fix(tribunal): thirteen review fixes, an infra lens, and site/docs registration#170
Merged
Conversation
The harness's own signal is authoritative; a hook subprocess is not guaranteed to start inside the project (/ca:doctor, /ca:preview run elsewhere too), and rev-parse from a foreign cwd can resolve to the plugin's marketplace clone. Env-first is also cheaper; one git spawn saved per hook invocation. Every test harness that spawns hooks into fixture repos now pins or strips the variable — a value leaking in from a live Claude session would point every guard at the developer's real repo, not the fixture.
pre-bash's COMMIT_RE captured args with [^|;&]*, which stops at the
first `;`, `|`, or `&` even inside a quoted -m string or a heredoc
body. A commit message containing `diff-scoped; nothing` truncated
there; the unterminated `$(cat <<'EOF'` fragment defeated the heredoc
stripper, message words leaked into the pathspec parse, and a token
like `/ca:checkpoint)` made `git diff HEAD -- ...` fatal ("outside
repository") — so H-09b failed CLOSED on a clean, already-reviewed
commit (the 2026-07-01 "flaky hook"; it was deterministic per message
shape, not timing).
Three-part fix, no gate weakening: (1) heredoc bodies are stripped
from the whole command before matching, with the raw command kept as
a fallback matcher so a heredoc fed TO a shell (`bash <<EOF`) is
still guarded; (2) the args capture is quote-aware, consuming quoted
strings whole while still stopping at unquoted separators; (3) the
fail-closed block message now carries git's actual stderr, so a
future read failure is diagnosable in one look.
CHANGELOG: Fix a false fail-closed H-09b/H-14 block on commits whose
message body contains `;`, `|`, `&`, or a `git -C` mention (heredoc
and quoted -m forms); block messages now include the underlying git
error.
Payload change (hooks fix) requires the bump; the overrides.log line is this session's /ca:dev entry, committed per the append-only audit-trail rule (ORCHESTRATOR §7).
finding-record.md promised "at most one discardable partial line" lost on a mid-write kill, but the mechanism was read-whole-file + rewrite (agents have Write, no append) — a kill could truncate the lens's entire findings file. Findings now write as findings/<lens>/<id>.json, one file each; a kill risks only the in-flight file. Re-dispatched lenses continue numbering from the highest NNN on disk and never rewrite an existing file. All 14 surfaces updated (skill, schemas, report, command, 10 agents); triage/run logs stay append-only jsonl.
The gate was referenced six times across SKILL.md, triage.md, issue-filing.md, and report.md but never given a value; every run had to invent it. It now lives once in triage.md: fileable at final_confidence >=0.5 for critical/high (below that a critical becomes decision-required, never silently dropped), >=0.7 for medium, >=0.75 for low (the pre-existing low rule, folded in).
SKILL.md hard-ruled "read tech-stack.md or STOP" for the tracker command while issue-filing.md offered a gh fallback, and no tech-stack template ever scaffolded the field — every real repo hit the STOP. Now: a documented tracker in tech-stack.md wins; an undocumented tracker on a GitHub origin defaults to `gh issue create`; STOP only when neither holds. context-creation and decompose now scaffold the tracker field so the contract is real going forward. Test/lint/secrets commands keep the strict STOP.
report.md demanded model/token actuals and telemetry demanded lens_exposure.surface_seen, but no on-disk schema carried them — the "deterministic from the logs" claim was false, and a resumed run lost every completed lens's exposure denominator. run/v1 gains a lens-completed event carrying surface_seen/findings/model; the report header and telemetry now read models and exposure from run.jsonl and treat token actuals as best-effort (null when unobserved), since subagent spend is not reliably observable. run/v1 also carries an optional per-lens tokens field, so observed spend lands in the log rather than nowhere.
…oles Resume was keyed to wave numbers no file defined — two sessions could partition the roster differently and break resume. A default partition now lives in cost-and-models.md (aligned with its model tiers), Phase 1 records the chosen partition in the run-started event, and resume reads the recorded partition, never re-deriving it. Ordering fixes: plans/phase-<n>.md is written before the wave-triaged event is emitted, and a run dir whose run.jsonl lacks run-started restarts Phase 0/1 fresh (finding files stand; triage dedups).
RUN_ID embeds the UTC date and the Phase 0 resume check looked for "today's" run dir, so a run interrupted before midnight was unresumable minutes later — against the skill's own resumes-from- disk promise. Phase 0 now scans reports/ for the most recent run dir matching the scope, resumes it when incomplete and younger than 7 days, asks the user when incomplete but older (findings from a drifted tree must not silently merge), and starts fresh when complete. RUN_ID keeps its creation date on resume.
test-fidelity's "Severity" heading assigned category values — renamed to Category. finding/v1's observed field is now defined (directly observed/reproduced vs inferred; triage weighs observed higher at equal confidence). --tag is declared in the command's argument-hint. The routing-table trigger reads "on-demand", not "periodic" (checkpoint owns periodic). Telemetry's repo slug gets canonical casing; bare /adr references become /ca:adr.
Phases 0, 3, 5, and 6 restated cost-and-models.md, triage.md, issue-filing.md, and telemetry.md nearly in full, against the skill's own load-on-demand mandate — double context per run and double-edit drift risk (this review's fixes already had to land facts twice). Each phase body is now its gate, its load-bearing rules, and a leaf pointer; every cut fact was verified present in (or moved into) its leaf. Gates, hard rules, and Phases 1/2/4 are untouched.
The evidence-or-drop and write-on-discovery rules were restated near-verbatim in all ten lens files; finding-record.md owns them and each lens now carries one pointer line. The agent files keep their one-sentence reminders deliberately — an agent may be dispatched with nothing else in context. The >5/>10 structural thresholds now live only in ai-markers.md, and the type-escape- hatch list only in typesafety.md (test-fidelity points at it with its test-scope qualifier).
An aborted run was indistinguishable from a crashed one, so the resume-by-scope check would offer to resume a run the user explicitly killed until the 7-day staleness gate aged it out. run/v1 gains run-aborted (optional detail = reason); the orchestrator logs it when told to abandon, and Phase 0 treats it as terminal.
cost-and-models notes claude-fable-5 above Opus and dates its
roster ("substitute the current flagship"); the per-role
model/effort table is marked advisory (agents inherit; no
per-dispatch effort control exists). checkpoint's "when not to
use" now points up at /ca:tribunal. The .codearbiter/reports/ run
dir is registered in the state-store enumerations. ai-markers
gains the AI-commit identification heuristic (trailers + message
shape). telemetry defines issues_found (post-triage keeps) and
skill_version (plugin.json).
A whole-codebase audit had no lens for pipeline and deploy surface: workflow injection and token permissions, unpinned actions, cache poisoning, artifact provenance, container/base-image posture, IaC and deploy-manifest drift, release automation. The checkpoint fleet covers this via security-reviewer; the tribunal roster now does too. Eleventh lens + tribunal-infra-reviewer, Sonnet tier, wave 3, scope-dropped when a repo has no CI/IaC surface. Also adds ai-markers.md to the architecture reviewer's required reading (its lens file points there for the structural thresholds). CHANGELOG: /ca:tribunal gains an infra lens (CI/CD, containers, IaC, deploy config) — eleven lenses total.
The tribunal lane shipped without the outer docs learning it exists; the reference section regenerates from plugin frontmatter (picking up the command, skill, and lens-reviewer agents, now eleven lenses with infra), and the curated overview/architecture surfaces now place it beside /ca:checkpoint — the lean periodic sweep vs the rare, deep, resumable, non-gating audit.
Twelve separately-landed fixes left seams; a full-pack read reconciles them — stale findings-layout wording, count drift, partition/gate restatements, resume contradictions — so the pack reads as one document again.
The infra lens is a feat; the payload-scoped SemVer bump from the released 2.7.x line is minor. README badge synced (the 2.7.1 CI lesson); the overrides.log line is this session's DEV: exit, appended per the append-only audit-trail rule.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A full review of the newly-landed tribunal skill (accuracy, efficiency, thoroughness, integration) surfaced 13 issues; each was decided interactively by the maintainer and landed as its own commit. Highlights:
Correctness of the resumability story
findings/<lens>/<lens>-NNN.json) — the jsonl "at most one line lost" claim was false under the Read+Write mechanism; a kill could truncate a lens's whole findings file. Re-dispatched lenses continue numbering from disk.run-abortedmarks deliberate abandons terminal; the wave partition is recorded inrun-startedand read back, never re-derived; plans write beforewave-triaged.Contracts that were referenced but never defined
decision-required, ≥0.7 medium, ≥0.75 low), defined once in triage.md.ghfallback → STOP), and context-creation/decompose now scaffold the field.run.jsonl(lens-completed), so report.md's "deterministic from the logs" claim is now true.Efficiency
Coverage
tribunal-infra-reviewer, Sonnet tier, wave 3, scope-dropped when a repo has no CI surface.Version: 2.7.1 → 2.8.0 (the infra lens is a feat; payload-scoped SemVer).
Verification
check-plugin-refs.pyandcheck_badge_consistency.pygreen at every commit.npm test169/169,npm run build,npm run link-auditall green.https://claude.ai/code/session_01PVTCDji6bEuf9SifQ8tfsa