{"slug":"tribunal-3","title":"tribunal","summary":"The deep, rarely-convened whole-codebase audit lane. Routed to when the user invokes $ca-tribunal. Seven gated phases — cost/model, map, roster dispatch, triage, report, approval+filing, telemetry. Costs on the order of millions of tokens; proceeds only after the user acknowledge","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-08-24T16:57:07.860901Z","repo":{"url":"https://github.com/arbiterForge/codeArbiter","stars":145,"forks":7,"license":"AGPL-3.0","updatedAt":"2026-09-18T06:55:41Z"},"bodyHtml":"<hr>\n<h2>name: tribunal\ndescription: The deep, rarely-convened whole-codebase audit lane. Routed to when the user invokes $ca-tribunal. Seven gated phases — cost/model, map, roster dispatch, triage, report, approval+filing, telemetry. Costs on the order of millions of tokens; proceeds only after the user acknowledges the estimate; never a required gate; nothing filed or sent without explicit authorization.</h2>\n<h1>tribunal</h1>\n<p>The deepest, most expensive review codeArbiter offers — convened rarely, on demand, never as a gate. Routed to when the user invokes <code>$ca-tribunal</code>. Eleven specialist lenses judge the codebase; every finding persists to its own file (plus append-only triage/run logs) under a run dir that survives compaction and disconnects, so the run resumes from disk.</p>\n<h2>Pre-flight</h2>\n<p>Read these, or STOP and surface the gap — never guess a command or a path:</p>\n<ul>\n<li><code>&lt;project-root&gt;/.codearbiter/tech-stack.md</code> — stack, async model, concurrency primitives, test/lint/secrets commands, and, when documented, the tracker command. Stop if the test/lint/secrets commands are missing; do not guess.</li>\n<li><code>&lt;project-root&gt;/.codearbiter/CONTEXT.md</code> — the <code>stage:</code> maturity value and domain vocabulary.</li>\n<li><code>&lt;project-root&gt;/.codearbiter/coding-standards.md</code> — the conventions lenses judge against.</li>\n<li><code>&lt;project-root&gt;/.codearbiter/security-controls.md</code> — trust boundaries, approved crypto/secret stores; feeds the appsec and secrets lenses. Absent on some repos — proceed without the security lenses' control-file checks if so.</li>\n<li>A git repository must be present.</li>\n<li>The reference set under <code>${CLAUDE_PLUGIN_ROOT}/routines/tribunal/references/</code> — each is cited at its phase, loaded on demand. Do not preload them.</li>\n</ul>\n<h2>Phase 0 — Cost, model &amp; resume · gate: STOP</h2>\n<p>This lane is expensive. Orient and get explicit go-ahead before dispatching anything.</p>\n<ul>\n<li><strong>Resume check.</strong> Scan <code>.codearbiter/reports/</code> for the most recent run dir matching the current scope-slug, any date — never just today's. If none, skip to sizing. If found, check completion: incomplete (no <code>report-written</code> event in its <code>run.jsonl</code>) means either resumable or stale, judged by that run dir's latest <code>run.jsonl</code> timestamp. A run whose <code>run.jsonl</code> carries <code>run-aborted</code> is terminal — never offered for resume; a fresh run starts. Younger than 7 days → recover position with the cheap cursor scan in <code>references/schemas.md</code> (grep the last <code>wave-triaged</code>, do not read finding bodies) and offer to resume at the first un-triaged wave instead of restarting; skip the estimate. Older than 7 days → STOP and ask the user to resume anyway or start fresh — the codebase may have drifted under the findings, and stale-tree findings must not silently merge with fresh ones. Complete → start a fresh run.</li>\n<li><strong>Abandon.</strong> If the user tells the orchestrator to abandon the run, log a <code>run-aborted</code> event to <code>run.jsonl</code> before stopping.</li>\n<li><strong>Cost acknowledgment.</strong> Size the job, compute the token band, recommend the model (highest-reasoning available, high effort), and offer the cost-control levers. Present the band plainly; nothing dispatches until the user acknowledges it and confirms the model.</li>\n<li>Establish <code>RUN_ID</code> = <code>&lt;UTC-date&gt;-&lt;scope-slug&gt;</code> on a fresh run; create <code>.codearbiter/reports/&lt;run-id&gt;/</code>; open <code>run.jsonl</code>. On resume, reuse the existing <code>RUN_ID</code> as-is — the date is the run's creation date and never changes on resume.</li>\n<li>Procedure: <code>references/cost-and-models.md</code> — load now.</li>\n</ul>\n<p>Gate: the user has acknowledged the estimated cost and confirmed the model. An unacknowledged run does not pass.</p>\n<h2>Phase 1 — Map + judgment overlay · gate: BLOCK</h2>\n<p>Map before reviewing; the map decides what gets scrutiny.</p>\n<ul>\n<li>Produce the inventory (inline, or on a large repo dispatch the optional cheap mappers per <code>references/cost-and-models.md</code>): file tree, language breakdown, entry points/routes, core-logic and shared-utility locations, dependency and integration surface. Write <code>inventory.md</code>.</li>\n<li>Apply the judgment overlay in <code>references/ai-markers.md</code>: risk-rank directories (untrusted input, money, auth, PII, churn = highest), mark trust boundaries, record AI-authorship markers and an iteration-depth estimate. High-marker / high-iteration areas carry a scrutiny boost and a small severity prior.</li>\n<li>Choose the active lenses — the roster IS the set of cards under <code>references/lenses/</code>; the active set is that roster minus any lens whose concern is absent from scope (no migrations → drop the migration lens). Record launched/skipped as <code>run.jsonl</code> events.</li>\n<li>Choose the wave partition — the default in <code>references/cost-and-models.md</code>, or a repartition for cause — and record it in the <code>run-started</code> event (<code>references/schemas.md</code>); resume reads this recorded partition, never re-derives it.</li>\n</ul>\n<p>Gate: <code>inventory.md</code> written with the risk/boundary/marker overlay, and the active-lens set recorded.</p>\n<h2>Phase 2 — Roster dispatch (dual output: finding files + summary) · gate: BLOCK</h2>\n<p>Dispatch one <code>tribunal-lens-reviewer</code> per active lens, in the wave partition recorded at Phase 1 (default in <code>references/cost-and-models.md</code>) at the concurrency from <code>references/cost-and-models.md</code> (≤5 in flight). Each dispatch carries the assignment block from the agent's Assignment Format — its FIRST line is the title <code>Tribunal lens: &lt;lens-slug&gt; — &lt;scope summary&gt;</code> — naming the lens slug, the scope slice, the run dir, and the findings dir, on the model/effort from <code>references/cost-and-models.md</code>. The agent itself reads its own mandate (<code>references/lenses/&lt;lens&gt;.md</code>, including that card's Required-reading docs) and the finding contract (<code>references/finding-record.md</code>), and loads neither the other lenses' mandates nor the orchestrator schemas. The orchestrator reads <code>references/finding-record.md</code> to read findings at triage, and consults a lens mandate only to adjudicate that lens's finding.</p>\n<ul>\n<li>Each dispatched lens reviewer writes each finding to its own file <code>findings/&lt;lens&gt;/&lt;finding-id&gt;.json</code> the moment it is found — one file per finding, never a batched write at the end (write contract: <code>references/finding-record.md</code>).</li>\n<li><strong>Evidence-or-drop.</strong> Every finding cites a concrete <code>path:line</code> and the minimal snippet. An absence claim — \"no handler\", \"no teardown\", \"missing validation\" — requires reading the whole unit, never a truncated window.</li>\n<li>Specialists never dispatch further subagents. Update each wave's status in <code>run.jsonl</code> as it flushes.</li>\n<li>When a lens's summary returns, record a <code>lens-completed</code> event in <code>run.jsonl</code> with <code>surface_seen</code>/<code>findings</code>/<code>model</code> taken from the agent's summary, plus <code>tokens</code> when the orchestrator can observe that lens's spend.</li>\n<li><strong>Codex usage receipt.</strong> If the current host has no subagent dispatch capability and a lens must run inline, record <code>tokens_status: unavailable</code> and <code>tokens_reason: host-usage-unsupported</code>. If dispatch succeeds but returns no usable thread ID, record <code>tokens_status: unavailable</code> and <code>tokens_reason: host-result-missing</code>. Otherwise capture the returned agent thread ID on the <code>lens-launched</code> event. After that lens completes, resolve the installed plugin root from this routine's own loaded <code>SKILL.md</code> path (ordinary shell calls do not inherit a plugin-root environment variable) and run <code>hooks/tribunal-usage.py observe --thread-id &lt;agent-thread-id&gt;</code>. The helper reads only metadata and cumulative token-count events from the exact agent session. On <code>status: observed</code>, copy its integer <code>tokens</code> and component <code>token_usage</code>, set <code>tokens_status: observed</code>, and copy <code>source</code> as <code>tokens_source</code> into <code>lens-completed</code>. On <code>status: unavailable</code>, omit <code>tokens</code>, set <code>tokens_status: unavailable</code>, and copy <code>reason</code> as <code>tokens_reason</code>; never turn a parser or capability failure into an unexplained omission. Codex session JSONL is explicitly not a stable extension interface, so this recovery remains best-effort and every changed-format path must degrade to a reason, not block the tribunal.</li>\n</ul>\n<p>Gate: every active lens has flushed its <code>findings/&lt;lens&gt;/</code> files, and each wave's status is recorded.</p>\n<h2>Phase 3 — Triage &amp; per-wave planning · gate: BLOCK</h2>\n<p>Triage per wave from disk as soon as it flushes; do not wait for the whole run.</p>\n<ul>\n<li><strong>Calibrate independently.</strong> Set <code>final_severity</code>/<code>final_confidence</code> from the evidence yourself — the lens's values are provisional input; every critical/high carries a <code>counter_argument</code>.</li>\n<li><strong>Decide per finding, logged.</strong> Each finding gets one decision from the vocabulary, appended as one line to <code>triage.jsonl</code>. Below the confidence gate after calibration → <code>investigate</code> (medium/low) or <code>decision-required</code> (critical/high) — never dropped silently.</li>\n<li><strong>Plan the wave.</strong> Write <code>plans/phase-&lt;n&gt;.md</code> for its kept (<code>keep</code>/<code>combine</code>) work.</li>\n<li>Procedure: <code>references/triage.md</code> — load now.</li>\n</ul>\n<p>Gate: every wave's findings triaged into <code>triage.jsonl</code> and a <code>plans/phase-&lt;n&gt;.md</code> written for its kept work.</p>\n<h2>Phase 4 — Report · gate: BLOCK</h2>\n<p>Regenerate <code>report.md</code> and <code>manifest.yaml</code> from the two logs per <code>references/report.md</code> — projections, never hand-authored. Task-list-structured (not prose): findings grouped by <strong>calibrated</strong> severity then type, each with id, <code>path:line</code>, one-line description, remediation shape, triage decision, and a link to its phase plan; <code>decision-required</code> in its own section; a launched/skipped-lens summary; an investigate appendix. Apply <code>${CLAUDE_PLUGIN_ROOT}/includes/anti-slop-design/</code> (<code>core</code> + <code>medium-documents</code>) to the prose.</p>\n<p>State plainly that critical/high are blocking-severity findings — work that should block shipping the affected code — but that this lane is not itself a gate and blocks nothing.</p>\n<p>Gate: <code>report.md</code> regenerated from the logs and presented. No issues created.</p>\n<h2>Phase 5 — Approval &amp; issue filing · gate: BLOCK</h2>\n<p>Findings become GitHub issues only on explicit selection and authorization. Silence or ambiguity → file nothing; \"looks good\" is not authorization.</p>\n<ul>\n<li><strong>Dedup first.</strong> Skip findings already carrying an <code>issue_ref</code> in <code>triage.jsonl</code>, then dedup against the tracker — this lane reruns over time and will re-find the same issues.</li>\n<li><strong>Default is hand-off.</strong> Write and print <code>issue-commands.sh</code>; execute only on explicit approval, writing each <code>issue_ref</code> back into <code>triage.jsonl</code>.</li>\n<li>Findings file as GitHub issues, never <code>open-tasks.md</code> — a periodic-review finding must survive PR abandonment.</li>\n<li>Procedure: <code>references/issue-filing.md</code> — load now.</li>\n</ul>\n<p>Gate: either <code>issue-commands.sh</code> written and printed, or — on approval — issues filed with the id→result table and <code>issue_ref</code> recorded. Nothing filed without explicit selection; no duplicates against the tracker.</p>\n<h2>Phase 6 — Telemetry · gate: STOP</h2>\n<p>Optional, opt-in KPI feedback to refine the skill and the estimator — off by default, sent only on explicit per-run authorization.</p>\n<ul>\n<li><strong>Scrub.</strong> The payload is aggregates and per-lens exposure counts only — no code, paths, or finding text; no repo identity unless the user adds <code>--tag</code>.</li>\n<li><strong>Show before send.</strong> Write the payload to the run dir and show it in full; state plainly that it posts publicly to the codeArbiter repo. Default: hand the user the ready command; post only on explicit approval.</li>\n<li>Procedure: <code>references/telemetry.md</code> — load now.</li>\n</ul>\n<p>Gate: the payload is shown, and it is either handed to the user as a command or — on approval — posted. No telemetry leaves without per-run authorization.</p>\n<h2>Hard rules</h2>\n<ul>\n<li>MUST NOT proceed past Phase 0 without the user acknowledging the estimated token cost — this lane can cost millions of tokens.</li>\n<li>MUST NOT edit, refactor, format, or commit project code — writes are confined to <code>.codearbiter/reports/&lt;run-id&gt;/</code> until the filing gate.</li>\n<li>MUST NOT act as a required gate or block a merge, commit, or other workflow — critical/high are blocking-severity findings, not a pipeline halt.</li>\n<li>MUST NOT record a finding without a concrete <code>path:line</code> and a minimal evidence snippet.</li>\n<li>MUST NOT assert an absence without reading the whole relevant unit — partial-window absence claims do not pass.</li>\n<li>MUST NOT let a lens's provisional severity/confidence stand as final — calibrate at triage; every critical/high carries a <code>counter_argument</code>.</li>\n<li>MUST NOT mutate the append-only logs — <code>manifest.yaml</code>, <code>report.md</code>, and <code>plans/</code> are regenerated from them, never hand-edited.</li>\n<li>MUST NOT file an issue below the confidence gate or without explicit selection and authorization; findings file as GitHub issues, never <code>open-tasks.md</code>.</li>\n<li>MUST NOT create a duplicate issue — skip findings carrying an <code>issue_ref</code>, and dedup against the tracker by <code>dedup_key</code>/title before filing.</li>\n<li>MUST NOT author or scaffold an ADR — <code>decision-required</code> findings file as a discussion issue; ADRs are authored only via <code>$ca-adr</code> with user attribution.</li>\n<li>MUST NOT send telemetry without explicit per-run authorization, and MUST NOT include code, file paths, finding text, or repo identity (absent an explicit <code>--tag</code>) in the payload — KPI aggregates only.</li>\n<li>MUST NOT guess the test, lint, or secrets-scan command — read <code>tech-stack.md</code> or STOP. For the tracker: use <code>tech-stack.md</code> if it documents one; else default to <code>gh issue create</code> on a GitHub origin; else STOP.</li>\n<li>MUST NOT dispatch a subagent from within a dispatched specialist — only the orchestrator dispatches.</li>\n</ul>\n","files":[{"path":"references/ai-markers.md","sizeBytes":1758,"isText":true},{"path":"references/cost-and-models.md","sizeBytes":3879,"isText":true},{"path":"references/finding-record.md","sizeBytes":3362,"isText":true},{"path":"references/issue-filing.md","sizeBytes":2864,"isText":true},{"path":"references/lenses/appsec.md","sizeBytes":1535,"isText":true},{"path":"references/lenses/architecture.md","sizeBytes":1663,"isText":true},{"path":"references/lenses/coverage.md","sizeBytes":859,"isText":true},{"path":"references/lenses/infra.md","sizeBytes":1605,"isText":true},{"path":"references/lenses/migration.md","sizeBytes":1138,"isText":true},{"path":"references/lenses/observability.md","sizeBytes":911,"isText":true},{"path":"references/lenses/performance.md","sizeBytes":900,"isText":true},{"path":"references/lenses/reliability.md","sizeBytes":1575,"isText":true},{"path":"references/lenses/secrets-supply.md","sizeBytes":1255,"isText":true},{"path":"references/lenses/test-fidelity.md","sizeBytes":1625,"isText":true},{"path":"references/lenses/typesafety.md","sizeBytes":1071,"isText":true},{"path":"references/report.md","sizeBytes":2029,"isText":true},{"path":"references/schemas.md","sizeBytes":6003,"isText":true},{"path":"references/telemetry.md","sizeBytes":4738,"isText":true},{"path":"references/triage.md","sizeBytes":3826,"isText":true},{"path":"SKILL.md","sizeBytes":13844,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"notes-only","suspicious":0,"notes":3,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-02T09:49:35.799772Z","sha256":"77D0E0E2AC1DE26A9CFED338A0D2104229E0C640869D0098CD97D057094EB5FA","sizeBytes":29719},"review":null,"source":{"repositoryUrl":"https://github.com/arbiterForge/codeArbiter","path":"plugins/ca-codex/routines/tribunal","license":"AGPL-3.0","commit":"46c0eb3833c3f00eba18fdadd77d43c773370a9c","subtreeSha":"BBAA92DC5998ECBD3336C342E39FF73BF1D2ACA70BC3EC55D23C15E3EB122FB0","lastSyncedAt":"2026-09-18T13:47:38.553461Z"},"reviewedAt":"2026-09-02T09:51:03.158893Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/arbiterForge/codeArbiter/tree/main/plugins/ca-codex/routines/tribunal"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install arbiterforge-codearbiter@llmmart"},{"target":"git","command":"git clone https://github.com/arbiterForge/codeArbiter.git"}]}