Merge pull request #547 from escoffier-labs/issue/501-route-decision-… #1082
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ci | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| code_graph: ${{ steps.filter.outputs.code_graph }} | |
| evidence_ledger: ${{ steps.filter.outputs.evidence_ledger }} | |
| notify: ${{ steps.filter.outputs.notify }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| code_graph: | |
| - 'engines/code-graph/**' | |
| - 'src/brigade/templates/components/manifest-v1.json' | |
| - '.github/workflows/ci.yml' | |
| evidence_ledger: | |
| - 'engines/evidence-ledger/**' | |
| - 'src/brigade/templates/components/manifest-v1.json' | |
| - '.github/workflows/ci.yml' | |
| notify: | |
| - 'stations/notify/**' | |
| - 'src/brigade/templates/components/manifest-v1.json' | |
| - '.github/workflows/ci.yml' | |
| code-graph-msrv: | |
| name: MSRV (Rust 1.85) | |
| needs: changes | |
| if: ${{ needs.changes.outputs.code_graph == 'true' }} | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: engines/code-graph | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@1.85.0 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: engines/code-graph | |
| - name: Check locked all-features build | |
| run: cargo check --locked --all-features | |
| code-graph-build-and-test: | |
| name: build-and-test | |
| needs: changes | |
| if: ${{ needs.changes.outputs.code_graph == 'true' }} | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: engines/code-graph | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: engines/code-graph | |
| - name: Format | |
| run: cargo fmt --check | |
| - name: Clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| - name: Test | |
| run: cargo test --all-features | |
| - name: Build (default, no-network) | |
| run: cargo build --release | |
| code-graph-feature-configurations: | |
| name: Feature configuration (${{ matrix.name }}) | |
| needs: changes | |
| if: ${{ needs.changes.outputs.code_graph == 'true' }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: no-default | |
| cargo_args: --no-default-features | |
| - name: default | |
| cargo_args: "" | |
| - name: watch-only | |
| cargo_args: --no-default-features --features watch | |
| - name: codesearch-only | |
| cargo_args: --no-default-features --features codesearch | |
| - name: miseledger-only | |
| cargo_args: --no-default-features --features miseledger | |
| - name: all-features | |
| cargo_args: --all-features | |
| defaults: | |
| run: | |
| working-directory: engines/code-graph | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: engines/code-graph | |
| - name: Check locked feature configuration | |
| run: cargo check --locked ${{ matrix.cargo_args }} | |
| code-graph-windows: | |
| name: Windows (stable, default features) | |
| needs: changes | |
| if: ${{ needs.changes.outputs.code_graph == 'true' }} | |
| runs-on: windows-latest | |
| defaults: | |
| run: | |
| working-directory: engines/code-graph | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: engines/code-graph | |
| - name: Test locked default features | |
| run: cargo test --locked | |
| evidence-ledger-test: | |
| needs: changes | |
| if: ${{ needs.changes.outputs.evidence_ledger == 'true' }} | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: engines/evidence-ledger | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: stable | |
| - run: go test ./... | |
| - run: go vet ./... | |
| - run: go install golang.org/x/vuln/cmd/govulncheck@v1.3.0 | |
| - run: govulncheck ./... | |
| - run: go build -o bin/miseledger ./cmd/miseledger | |
| - run: go build -o bin/sessionfind ./cmd/sessionfind | |
| - run: scripts/check_release_workflow.sh | |
| - run: scripts/smoke_archive.sh | |
| - run: scripts/smoke_mcp.sh | |
| - run: scripts/smoke_http.sh | |
| notify-build-and-test: | |
| name: notify-build-and-test (ubuntu-latest) | |
| needs: changes | |
| if: ${{ needs.changes.outputs.notify == 'true' }} | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: stations/notify | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| cache-dependency-path: stations/notify/go.sum | |
| - name: Build | |
| run: go build ./... | |
| - name: Vet | |
| run: go vet ./... | |
| - name: Test | |
| run: go test -race ./... | |
| - name: Setup stable Go for govulncheck | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: stable | |
| cache-dependency-path: stations/notify/go.sum | |
| - name: Install govulncheck | |
| run: go install golang.org/x/vuln/cmd/govulncheck@v1.3.0 | |
| - name: Vulncheck | |
| run: govulncheck ./... | |
| notify-windows: | |
| name: notify-build-and-test (windows-latest) | |
| needs: changes | |
| if: ${{ needs.changes.outputs.notify == 'true' }} | |
| runs-on: windows-latest | |
| defaults: | |
| run: | |
| working-directory: stations/notify | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| cache-dependency-path: stations/notify/go.sum | |
| - name: Build | |
| run: go build ./... | |
| - name: Vet | |
| run: go vet ./... | |
| - name: Test | |
| run: go test -race ./... | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev]" | |
| - name: Ruff check | |
| run: python -m ruff check . | |
| - name: Ruff format | |
| run: python -m ruff format --check . | |
| - name: Mypy | |
| run: python -m mypy | |
| - name: Version sync | |
| run: python scripts/version_sync.py --check | |
| - name: Managed snapshot | |
| run: python scripts/managed_snapshot.py --check | |
| test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python: ["3.10", "3.11", "3.12"] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| - name: Install | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev]" | |
| - name: Pytest | |
| if: matrix.python != '3.12' | |
| run: python -m pytest -q | |
| - name: Pytest with coverage gate | |
| if: matrix.python == '3.12' | |
| run: python -m pytest -q --cov=brigade --cov-report=term --cov-fail-under=78 | |
| component-manifest-provenance: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev]" | |
| - name: Exercise generated-release provenance contract | |
| run: python -m pytest tests/test_component_manifest_provenance.py -q | |
| content-guard: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| path: brigade | |
| - uses: actions/checkout@v5 | |
| with: | |
| repository: solomonneas/content-guard | |
| ref: v0.1.1 | |
| path: content-guard | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Scan | |
| run: | | |
| cd brigade | |
| PYTHONPATH=../content-guard/src python -m content_guard scan . \ | |
| --policy ../content-guard/policies/public-repo.json | |
| repo-metadata: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -e ".[dev]" | |
| - name: Command Inventory | |
| run: brigade roadmap commands --check | |
| env: | |
| BRIGADE_EXTRAS: "1" | |
| - name: Template Audit | |
| run: brigade security template-audit --target . --json | |
| install-from-source: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| combo: | |
| - name: "repo+claude" | |
| flags: "--depth repo --harnesses claude" | |
| - name: "repo+codex" | |
| flags: "--depth repo --harnesses codex" | |
| - name: "workspace+claude+openclaw" | |
| flags: "--depth workspace --harnesses claude,openclaw" | |
| - name: "workspace+codex+openclaw" | |
| flags: "--depth workspace --harnesses codex,openclaw" | |
| - name: "workspace+hermes" | |
| flags: "--depth workspace --harnesses hermes" | |
| - name: "kitchen-sink" | |
| flags: "--depth workspace --harnesses claude,codex,openclaw,hermes" | |
| - name: "workspace+none" | |
| flags: "--depth workspace --harnesses none" | |
| - name: "repo+claude+publisher" | |
| flags: "--depth repo --harnesses claude --include publisher" | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: pipx install | |
| run: | | |
| python -m pip install --upgrade pip pipx | |
| pipx install . | |
| brigade --version | |
| - name: Init + doctor | |
| run: | | |
| target="$(mktemp -d)" | |
| git init -q -b main "$target" | |
| brigade init --target "$target" ${{ matrix.combo.flags }} | |
| brigade doctor --target "$target" | |
| case "${{ matrix.combo.flags }}" in | |
| *hermes*) | |
| test -f "$target/.hermes/memory-handoffs/TEMPLATE.md" | |
| test -d "$target/.hermes/memory-handoffs/processed" | |
| test -f "$target/.brigade/hermes/workspace.harness.json" | |
| test -f "$target/.brigade/hermes/memory-handoff.harness.json" | |
| grep -q '"handoff_inbox": ".hermes/memory-handoffs"' "$target/.brigade/hermes/workspace.harness.json" | |
| grep -q '"inbox_dir": ".hermes/memory-handoffs"' "$target/.brigade/hermes/memory-handoff.harness.json" | |
| ! grep -R '.claude/memory-handoffs' "$target/.brigade/hermes" | |
| brigade handoff sources init --target "$target" --force | |
| brigade handoff draft --target "$target" --inbox hermes \ | |
| --title "Hermes CI smoke" \ | |
| --summary "Hermes can write a local Brigade handoff." \ | |
| --content "### Hermes CI smoke | |
| The Hermes inbox follows the shared Brigade handoff contract." | |
| brigade operator verify-harness --harness hermes --target "$target" | |
| ;; | |
| esac | |
| quickstart-smoke: | |
| name: quickstart-smoke (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: pipx install | |
| run: | | |
| python -m pip install --upgrade pip pipx | |
| pipx install . | |
| brigade --version | |
| - name: Quickstart (minimal default, Linux/macOS) | |
| if: runner.os != 'Windows' | |
| run: | | |
| target="$(mktemp -d)" | |
| git init -q -b main "$target" | |
| brigade operator quickstart --target "$target" --harnesses codex --json | |
| brigade operator doctor --target "$target" --profile local-operator --json | |
| test -f "$target/.brigade/config.json" | |
| test -d "$target/.codex/memory-handoffs" | |
| test -f "$target/.codex/skills/brigade-work/SKILL.md" | |
| test -f "$target/AGENTS.md" | |
| test ! -e "$target/tools" | |
| test ! -e "$target/rules" | |
| test ! -e "$target/INSTALL_FOR_AGENTS.md" | |
| - name: Quickstart (minimal default, PowerShell) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $target = Join-Path $env:RUNNER_TEMP "brigade-quickstart-minimal" | |
| git init -q -b main $target | |
| brigade operator quickstart --target $target --harnesses codex --json | |
| brigade operator doctor --target $target --profile local-operator --json | |
| if (-not (Test-Path (Join-Path $target ".brigade/config.json"))) { throw "missing Brigade config" } | |
| if (-not (Test-Path (Join-Path $target ".codex/memory-handoffs"))) { throw "missing Codex handoff inbox" } | |
| if (-not (Test-Path (Join-Path $target ".codex/skills/brigade-work/SKILL.md"))) { throw "missing brigade-work skill" } | |
| if (-not (Test-Path (Join-Path $target "AGENTS.md"))) { throw "missing AGENTS.md" } | |
| if (Test-Path (Join-Path $target "tools")) { throw "minimal install unexpectedly created tools" } | |
| if (Test-Path (Join-Path $target "rules")) { throw "minimal install unexpectedly created rules" } | |
| if (Test-Path (Join-Path $target "INSTALL_FOR_AGENTS.md")) { throw "minimal install unexpectedly created full-kit guide" } | |
| - name: Quickstart (--full, Linux/macOS) | |
| if: runner.os != 'Windows' | |
| run: | | |
| target="$(mktemp -d)" | |
| git init -q -b main "$target" | |
| brigade operator quickstart --target "$target" --harnesses codex --full --json | |
| brigade operator doctor --target "$target" --profile local-operator --json | |
| test -f "$target/.codex/skills/frontend/SKILL.md" | |
| test -f "$target/tools/antislop.md" | |
| test -f "$target/INSTALL_FOR_AGENTS.md" | |
| test -f "$target/rules/issue-tdd-loop.md" | |
| - name: Quickstart (--full, PowerShell) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $target = Join-Path $env:RUNNER_TEMP "brigade-quickstart-full" | |
| git init -q -b main $target | |
| brigade operator quickstart --target $target --harnesses codex --full --json | |
| brigade operator doctor --target $target --profile local-operator --json | |
| if (-not (Test-Path (Join-Path $target ".codex/skills/frontend/SKILL.md"))) { throw "missing frontend skill" } | |
| if (-not (Test-Path (Join-Path $target "tools/antislop.md"))) { throw "missing antislop tool" } | |
| if (-not (Test-Path (Join-Path $target "INSTALL_FOR_AGENTS.md"))) { throw "missing full-kit guide" } | |
| if (-not (Test-Path (Join-Path $target "rules/issue-tdd-loop.md"))) { throw "missing issue/TDD rule" } | |
| windows-native-acceptance: | |
| name: windows-native-acceptance | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Run Windows native acceptance (source install) | |
| shell: powershell | |
| run: | | |
| & "${{ github.workspace }}\scripts\windows-native-acceptance.ps1" -InstallMode source -RepoRoot "${{ github.workspace }}" |