Skip to content

feat(runs): offline coordinator decision audit (#595) - #649

Merged
solomonneas merged 3 commits into
mainfrom
feat/595-runs-audit
Aug 1, 2026
Merged

feat(runs): offline coordinator decision audit (#595)#649
solomonneas merged 3 commits into
mainfrom
feat/595-runs-audit

Conversation

@solomonneas

Copy link
Copy Markdown
Collaborator

Summary

  • Add brigade runs audit <run-id> as a read-only lifecycle-journal consumer (src/brigade/run_audit.py) that re-projects via project_run_snapshot, fingerprints coordinator-owned route/policy, dispatch, approval, adapter, and composed-prompt decisions, and stops at the first divergence.
  • Hard safety boundary: no writes to any run directory, no new event types, no changes to run_journal.py / run_events.py / run_projector.py / run_lifecycle.py, and no provider-adapter or subprocess construction.
  • CLI registration is a minimal hunk in cli/runs.py + thin runs_cmd.audit wrapper so it rebases cleanly beside concurrent runs: add durable cursors and idempotent live control on the lifecycle journal #604 work.

Acceptance criteria → tests

  • Golden run audits twice to byte-identical normalized events → test_golden_run_audits_twice_to_byte_identical_normalized_events
  • Changing a prompt template stops at first composed prompt → test_changing_prompt_template_stops_at_first_composed_prompt
  • Changing route selection / approval state stops at first decision → test_changing_route_selection_stops_at_first_coordinator_decision, test_changing_approval_state_stops_at_first_coordinator_decision
  • Audit path cannot construct provider adapter or subprocess → test_forbid_live_side_effects_sentinel
  • Missing/corrupt evidence reports exact artifact → test_missing_corrupt_evidence_reports_exact_artifact
  • Unsupported transports state coverage → test_unsupported_transport_states_coverage
  • Unsupported projector/schema versions stop with diagnostics → test_unsupported_projector_version_stops_with_compatibility_diagnostics
  • Legacy runs without journal report not_auditabletest_legacy_run_without_journal_reports_not_auditable
  • Private-data fixtures expose only safe summaries/fingerprints → test_private_data_fixtures_expose_only_safe_summaries
  • Receipt records source run, projector version, code revision, result, first divergence, evidence digests → test_receipt_records_required_fields

Test plan

  • brigade work verify run --target . --command "./scripts/verify" --capture brigade-work
  • Receipt: 20260801-034500-work-verify-13980f (exit=0)
  • External grader review before merge

Closes #595

Made with Cursor

Introduce brigade runs audit as a read-only lifecycle journal consumer that
re-projects runs, fingerprints coordinator-owned decisions, and reports the
first divergence without writing the run directory or constructing providers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • coderabbit-review

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: escoffier-labs/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e5870631-fb7b-4334-83ef-dac8b1090673

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@solomonneas solomonneas self-assigned this Aug 1, 2026
@solomonneas

Copy link
Copy Markdown
Collaborator Author

Grader review: APPROVE-WITH-CHANGES. All hard constraints verified: read-only (byte-compared), protected journal modules untouched, read_journal_bounded + validate_event only, fail-closed on chain errors, prompts reduced to fingerprints with a planted-secret test. No collision with #641 (your base already contains it). Two required changes before merge:

  1. Uncaught AuditError escapes audit_run via _safe_digests (run_audit.py:852, 904, 942, 967, 1017). Repro without a race: valid run.json, no journal, plan.json is a symlink -> the legacy-run return at :852 raises and runs_cmd.audit crashes with a traceback instead of a bounded not_auditable report, violating the module's own fail-closed contract. Wrap the digest computation or make _safe_digests return a diagnostic.
  2. repo-metadata CI is red because docs/command-inventory.md was not regenerated for the new 'brigade runs audit' subcommand (10 -> 11, add the line - see the feat(runs): durable cursors and idempotent live control (#604) #641 merge for the pattern).

Should-fix while in there (non-blocking): _read_json_object checks S_ISLNK but not S_ISREG (run_audit.py:253-263) so a FIFO at run.json blocks forever; _routing_drift has a dead inner condition (:721-723) so seat-order permutations are never reported; _error_report hardcodes sequence=1 (:883); exit codes 1 vs 2 for corrupt vs missing evidence deserve a doc line; note in the coverage docs that #641 control.* events are intentionally outside _COORDINATOR_EVENT_TYPES. Ping for re-grade after push.

solomonneas and others added 2 commits August 1, 2026 15:36
Wrap _safe_digests so symlinked or non-regular evidence cannot escape
audit_run as an uncaught AuditError. Add S_ISREG to _read_json_object,
fix seat-order routing drift detection, derive chain-error sequence from
the journal report, document control.* out-of-scope coverage, and
document CLI exit codes for match/diverge/not-auditable paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds brigade runs audit to docs/command-inventory.md (10 -> 11 paths)
so repo-metadata CI passes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@solomonneas

Copy link
Copy Markdown
Collaborator Author

Re-grade ready. Grader feedback from #issuecomment-5152790005 addressed in two commits on feat/595-runs-audit:

Required

  1. Uncaught AuditError via _safe_digests5abd7618: _safe_digests now catches AuditError per artifact (skips non-regular/symlinked sidecars instead of crashing audit_run). Regression: test_legacy_run_symlinked_plan_json_returns_bounded_not_auditable (valid run.json, no journal, symlinked plan.jsonnot_auditable, no traceback).
  2. docs/command-inventory.mdd7c2613a: regenerated (brigade runs 10→11; adds brigade runs audit).

Should-fix (same commit 5abd7618)

  • _read_json_object: S_ISREG guard (FIFO/non-regular no longer block forever).
  • _routing_drift: seat-order permutations now reported (not only set mismatches). Regression: test_seat_order_permutation_reports_routing_drift.
  • _error_report chain errors: sequence from _chain_error_sequence(report) instead of hardcoded 1.
  • CLI help: exit-code doc line (0 match, 1 diverge/corrupt, 2 not auditable / unresolved run).
  • Coverage note: #641 control.* events documented as intentionally outside _COORDINATOR_EVENT_TYPES.

Verification

  • ./scripts/verify via brigade work verify run --capture brigade-workpass (receipt 20260801-192546-work-verify-cde323, exit 0).
  • Targeted: pytest tests/test_run_audit.py — 15 passed.

Constraints unchanged: read-only audit; no edits to run_journal.py, run_events.py, run_projector.py, run_lifecycle.py.

@solomonneas

Copy link
Copy Markdown
Collaborator Author

Grader: APPROVE, merging. Both required changes verified: _safe_digests now catches AuditError per artifact so a symlinked plan.json yields a bounded not_auditable report instead of a CLI traceback (test_legacy_run_symlinked_plan_json_returns_bounded_not_auditable), and the command inventory is regenerated. All five should-fixes landed too, including the S_ISREG guard and the _routing_drift dead-condition fix with test_seat_order_permutation_reports_routing_drift. Read-only constraints held: no edits to run_journal.py, run_events.py, run_projector.py, or run_lifecycle.py. Receipt 20260801-192546-work-verify-cde323, CI green.

@solomonneas
solomonneas merged commit 549ac23 into main Aug 1, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

runs audit: offline coordinator decision audit from recorded lifecycle evidence

1 participant