Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ Pull requests and issues from anyone who is not a member of the organization wil
## For organization members

- Follow the [branch, metadata, and integration workflow](../docs/development.md#branch-and-integration-workflow).
- Publish only the current work branch and open its PR to `dev`.
- Humans review and merge; agents never write protected branches or merge their own PRs.
- Publish only the current branch and use its exact derived PR base: ordinary/workstream work targets
`dev`, program groups target `flow`, and slices target their matching parent.
- Treat `dev`, `flow`, `master`, and `main` as protected. Agents may merge only an approved, current,
green intermediate PR through `scripts/dev/workstream`; humans merge every final PR into `dev`.
- Preserve merge ancestry and branch/PR evidence. The required hosted protections and exact program
routes are in [Workstreams and programs](../docs/workstreams.md).

If you have questions about using the lab locally, start with the
[README](../README.md) and [documentation map](../docs/README.md). There is no
Expand Down
155 changes: 150 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ concurrency:

on:
push:
branches: [dev, master, main]
branches: [dev, flow, master, main]
pull_request:
branches: [dev, master, main, 'work/**']
branches: [dev, flow, master, main, 'work/**', 'group/**']
merge_group:
types: [checks_requested]

Expand All @@ -23,6 +23,8 @@ jobs:
timeout-minutes: 15
outputs:
diff-base: ${{ steps.diff-base.outputs.base }}
tested-head: ${{ steps.diff-base.outputs.head }}
classification: ${{ steps.fast-gate.outputs.classification }}
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
Expand All @@ -31,17 +33,97 @@ jobs:
- name: Install shellcheck
run: sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck

- name: Validate pull request topology
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }}
REPOSITORY: ${{ github.repository }}
run: |
if [ "$EVENT_NAME" != pull_request ]; then
exit 0
fi
if [ "$PR_HEAD_REPOSITORY" != "$REPOSITORY" ]; then
printf '::error title=Invalid PR repository::cross-repository PRs are not accepted\n'
exit 1
fi

component='[a-z0-9][a-z0-9-]{0,47}'
group='[gb][0-9]+[a-z]?-[a-z0-9][a-z0-9-]*'
valid_group() {
[ "${#1}" -le 48 ] && [[ "$1" =~ ^$group$ ]]
}
case "$PR_BASE_REF" in
flow)
group_name="${PR_HEAD_REF#group/}"
[ "$PR_HEAD_REF" = "group/$group_name" ] && valid_group "$group_name"
;;
group/*)
group_name="${PR_BASE_REF#group/}"
valid_group "$group_name" &&
[[ "$PR_HEAD_REF" =~ ^slice/group/$group_name/$component$ ]]
;;
work/*)
work_name="${PR_BASE_REF#work/}"
[[ "$work_name" =~ ^$component$ ]] &&
[[ "$PR_HEAD_REF" =~ ^slice/$work_name/$component$ ]]
;;
dev)
[[ ! "$PR_HEAD_REF" =~ ^(group|slice)/ ]]
;;
master | main)
[[ ! "$PR_HEAD_REF" =~ ^(group|slice)/ ]]
;;
*) false ;;
esac || {
printf '::error title=Invalid PR topology::%s cannot target %s\n' \
"$PR_HEAD_REF" "$PR_BASE_REF"
exit 1
}

- name: Resolve committed diff base
id: diff-base
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
PUSH_AFTER_SHA: ${{ github.event.after }}
REF_NAME: ${{ github.ref_name }}
MERGE_GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }}
EXPECTED_HEAD_SHA: ${{ github.sha }}
run: |
sha_pattern='^([0-9a-f]{40}|[0-9a-f]{64})$'
head="$(git rev-parse HEAD)"
if [[ ! "$EXPECTED_HEAD_SHA" =~ $sha_pattern ]] ||
[[ "$EXPECTED_HEAD_SHA" =~ ^0+$ ]] ||
[ "$head" != "$EXPECTED_HEAD_SHA" ]; then
printf '::error title=Unexpected tested head::expected %s, checked out %s\n' \
"${EXPECTED_HEAD_SHA:-<empty>}" "${head:-<empty>}"
exit 125
fi

case "$EVENT_NAME" in
pull_request) base="$PR_BASE_SHA" ;;
push) base="$PUSH_BEFORE_SHA" ;;
push)
if [[ "$PUSH_BEFORE_SHA" =~ ^0+$ ]]; then
if ! git fetch --no-tags origin \
'+refs/heads/dev:refs/remotes/origin/dev'; then
printf '::error title=Missing bootstrap authority::cannot resolve origin/dev\n'
exit 125
fi
dev_head="$(GIT_NO_REPLACE_OBJECTS=1 git rev-parse --verify 'origin/dev^{commit}')"
if [ "$REF_NAME" = flow ] && [ "$PUSH_AFTER_SHA" = "$head" ] &&
[ "$head" = "$dev_head" ]; then
base="$head"
else
printf '::error title=Invalid branch creation::flow bootstrap must equal current origin/dev\n'
exit 125
fi
else
base="$PUSH_BEFORE_SHA"
fi
;;
merge_group) base="$MERGE_GROUP_BASE_SHA" ;;
*)
printf '::error title=Unsupported CI event::%s has no deterministic diff base\n' \
Expand All @@ -50,7 +132,6 @@ jobs:
;;
esac

sha_pattern='^([0-9a-f]{40}|[0-9a-f]{64})$'
if [[ ! "$base" =~ $sha_pattern ]] || [[ "$base" =~ ^0+$ ]]; then
printf '::error title=Invalid CI diff base::event supplied %s\n' \
"${base:-<empty>}"
Expand All @@ -67,18 +148,28 @@ jobs:
exit 125
fi

head="$(git rev-parse HEAD)"
printf 'base=%s\n' "$base" >> "$GITHUB_OUTPUT"
printf 'head=%s\n' "$head" >> "$GITHUB_OUTPUT"

- name: Fast security gate
id: fast-gate
env:
AGENT_LAB_DIFF_BASE: ${{ steps.diff-base.outputs.base }}
CI_LOG_DIR: ${{ runner.temp }}/agent-lab-ci
run: |
set +e
set -o pipefail
mkdir -p "$CI_LOG_DIR"
./scripts/dev/ci-fast 2>&1 | tee "$CI_LOG_DIR/fast.log"
rc=$?
case "$rc" in
0) classification=success ;;
1) classification=assertion-failure ;;
125) classification=infrastructure ;;
*) classification=unexpected ;;
esac
printf 'classification=%s\n' "$classification" >> "$GITHUB_OUTPUT"
exit "$rc"

- name: Summarize fast gate
if: ${{ always() }}
Expand Down Expand Up @@ -109,16 +200,43 @@ jobs:
name: Static
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
tested-head: ${{ steps.identity.outputs.head }}
classification: ${{ steps.static-gate.outputs.classification }}
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5

- name: Bind tested checkout
id: identity
env:
EXPECTED_HEAD_SHA: ${{ github.sha }}
run: |
head="$(git rev-parse HEAD)"
if [ "$head" != "$EXPECTED_HEAD_SHA" ]; then
printf '::error title=Unexpected tested head::expected %s, checked out %s\n' \
"$EXPECTED_HEAD_SHA" "$head"
exit 125
fi
printf 'head=%s\n' "$head" >> "$GITHUB_OUTPUT"

- name: Static configuration gate
id: static-gate
env:
CI_LOG_DIR: ${{ runner.temp }}/agent-lab-ci
run: |
set +e
set -o pipefail
mkdir -p "$CI_LOG_DIR"
./tools/validate.sh --strict 2>&1 | tee "$CI_LOG_DIR/static.log"
rc=$?
case "$rc" in
0) classification=success ;;
1) classification=assertion-failure ;;
125) classification=infrastructure ;;
*) classification=unexpected ;;
esac
printf 'classification=%s\n' "$classification" >> "$GITHUB_OUTPUT"
exit "$rc"

- name: Summarize static gate
if: ${{ always() }}
Expand All @@ -144,9 +262,25 @@ jobs:
name: Docker security
runs-on: ubuntu-latest
timeout-minutes: 45
outputs:
tested-head: ${{ steps.identity.outputs.head }}
classification: ${{ steps.docker-gate.outputs.classification }}
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5

- name: Bind tested checkout
id: identity
env:
EXPECTED_HEAD_SHA: ${{ github.sha }}
run: |
head="$(git rev-parse HEAD)"
if [ "$head" != "$EXPECTED_HEAD_SHA" ]; then
printf '::error title=Unexpected tested head::expected %s, checked out %s\n' \
"$EXPECTED_HEAD_SHA" "$head"
exit 125
fi
printf 'head=%s\n' "$head" >> "$GITHUB_OUTPUT"

- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4

- name: Build cache-aware devbox
Expand All @@ -165,9 +299,19 @@ jobs:
AGENT_LAB_DEVBOX_PREBUILT: 1
CI_LOG_DIR: ${{ runner.temp }}/agent-lab-ci
run: |
set +e
set -o pipefail
mkdir -p "$CI_LOG_DIR"
./scripts/dev/docker-gate 2>&1 | tee "$CI_LOG_DIR/docker.log"
rc=$?
case "$rc" in
0) classification=success ;;
1) classification=assertion-failure ;;
125) classification=infrastructure ;;
*) classification=unexpected ;;
esac
printf 'classification=%s\n' "$classification" >> "$GITHUB_OUTPUT"
exit "$rc"

- name: Summarize Docker gate
if: ${{ always() }}
Expand Down Expand Up @@ -201,4 +345,5 @@ jobs:
- name: Reduce required gate results
env:
CI_NEEDS_JSON: ${{ toJSON(needs) }}
CI_EXPECTED_HEAD: ${{ github.sha }}
run: ./scripts/dev/required-gates
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ concurrency:

on:
push:
branches: [dev, master, main]
branches: [dev, flow, master, main]
pull_request:
branches: [dev, master, main, 'work/**']
branches: [dev, flow, master, main, 'work/**', 'group/**']
merge_group:
types: [checks_requested]
schedule:
- cron: "0 6 * * 1"

jobs:
analyze:
name: Analyze
name: CodeQL
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
Expand Down
12 changes: 10 additions & 2 deletions .serena/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ ignore_all_files_in_gitignore: true
# Maps the language key to the options.
# The settings are considered only if the project is trusted (see global configuration to define trusted projects).
# See https://oraios.github.io/serena/02-usage/050_configuration.html#language-server-specific-settings
ls_specific_settings: {}
ls_specific_settings:
bash:
bash_language_server_version: "5.6.0"

# list of workspace folder paths (LSP backend only).
# These folders will be used to build up Serena's symbol index.
Expand Down Expand Up @@ -154,7 +156,13 @@ initial_prompt: >-
dedicated no-network Serena container. AGENTS.md and docs/serena.md are
canonical; Serena memories are optional development assistance, never
repository authority. Never inspect or modify credentials, tokens, GitHub
authentication, Git attribution, or unrelated host state.
authentication, Git attribution, or unrelated host state. Before changing
code, establish branch and worktree state with the host-side
./scripts/dev/brief and ./scripts/dev/changed commands. Serena does not
establish Git or GitHub authority. For flow, group, or slice work, follow
AGENTS.md and docs/workstreams.md and use ./scripts/dev/workstream for
integration. Use ordinary tools for prose, configuration, and extensionless
Bash rails.

# time budget (seconds) per tool call for the retrieval of additional symbol information
# such as docstrings or parameter information.
Expand Down
Loading
Loading