tribunal
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
Install
npx skills add https://github.com/arbiterForge/codeArbiter/tree/main/plugins/ca-pi/routines/tribunal
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install arbiterforge-codearbiter@llmmart
git clone https://github.com/arbiterForge/codeArbiter.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole arbiterforge/codearbiter collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
tribunal
The deepest, most expensive review codeArbiter offers — convened rarely, on demand, never as a gate. Routed to when the user invokes /ca-tribunal. 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.
Pre-flight
Read these, or STOP and surface the gap — never guess a command or a path:
<project-root>/.codearbiter/tech-stack.md— 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.<project-root>/.codearbiter/CONTEXT.md— thestage:maturity value and domain vocabulary.<project-root>/.codearbiter/coding-standards.md— the conventions lenses judge against.<project-root>/.codearbiter/security-controls.md— 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.- A git repository must be present.
- The reference set under
<plugin-root>/routines/tribunal/references/— each is cited at its phase, loaded on demand. Do not preload them.
Phase 0 — Cost, model & resume · gate: STOP
This lane is expensive. Orient and get explicit go-ahead before dispatching anything.
- Resume check. Scan
.codearbiter/reports/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 (noreport-writtenevent in itsrun.jsonl) means either resumable or stale, judged by that run dir's latestrun.jsonltimestamp. A run whoserun.jsonlcarriesrun-abortedis terminal — never offered for resume; a fresh run starts. Younger than 7 days → recover position with the cheap cursor scan inreferences/schemas.md(grep the lastwave-triaged, 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. - Abandon. If the user tells the orchestrator to abandon the run, log a
run-abortedevent torun.jsonlbefore stopping. - Cost acknowledgment. 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.
- Establish
RUN_ID=<UTC-date>-<scope-slug>on a fresh run; create.codearbiter/reports/<run-id>/; openrun.jsonl. On resume, reuse the existingRUN_IDas-is — the date is the run's creation date and never changes on resume. - Procedure:
references/cost-and-models.md— load now.
Gate: the user has acknowledged the estimated cost and confirmed the model. An unacknowledged run does not pass.
Phase 1 — Map + judgment overlay · gate: BLOCK
Map before reviewing; the map decides what gets scrutiny.
- Produce the inventory (inline, or on a large repo dispatch the optional cheap mappers per
references/cost-and-models.md): file tree, language breakdown, entry points/routes, core-logic and shared-utility locations, dependency and integration surface. Writeinventory.md. - Apply the judgment overlay in
references/ai-markers.md: 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. - Choose the active lenses — the roster IS the set of cards under
references/lenses/; the active set is that roster minus any lens whose concern is absent from scope (no migrations → drop the migration lens). Record launched/skipped asrun.jsonlevents. - Choose the wave partition — the default in
references/cost-and-models.md, or a repartition for cause — and record it in therun-startedevent (references/schemas.md); resume reads this recorded partition, never re-derives it.
Gate: inventory.md written with the risk/boundary/marker overlay, and the active-lens set recorded.
Phase 2 — Roster dispatch (dual output: finding files + summary) · gate: BLOCK
Dispatch one tribunal-lens-reviewer per active lens, in the wave partition recorded at Phase 1 (default in references/cost-and-models.md) at the concurrency from references/cost-and-models.md (≤5 in flight). Each dispatch carries the assignment block from the agent's Assignment Format — its FIRST line is the title Tribunal lens: <lens-slug> — <scope summary> — naming the lens slug, the scope slice, the run dir, and the findings dir, on the model/effort from references/cost-and-models.md. The agent itself reads its own mandate (references/lenses/<lens>.md, including that card's Required-reading docs) and the finding contract (references/finding-record.md), and loads neither the other lenses' mandates nor the orchestrator schemas. The orchestrator reads references/finding-record.md to read findings at triage, and consults a lens mandate only to adjudicate that lens's finding.
- Each dispatched lens reviewer writes each finding to its own file
findings/<lens>/<finding-id>.jsonthe moment it is found — one file per finding, never a batched write at the end (write contract:references/finding-record.md). - Evidence-or-drop. Every finding cites a concrete
path:lineand the minimal snippet. An absence claim — "no handler", "no teardown", "missing validation" — requires reading the whole unit, never a truncated window. - Specialists never dispatch further subagents. Update each wave's status in
run.jsonlas it flushes. - When a lens's summary returns, record a
lens-completedevent inrun.jsonlwithsurface_seen/findings/modeltaken from the agent's summary, plustokenswhen the orchestrator can observe that lens's spend.
Gate: every active lens has flushed its findings/<lens>/ files, and each wave's status is recorded.
Phase 3 — Triage & per-wave planning · gate: BLOCK
Triage per wave from disk as soon as it flushes; do not wait for the whole run.
- Calibrate independently. Set
final_severity/final_confidencefrom the evidence yourself — the lens's values are provisional input; every critical/high carries acounter_argument. - Decide per finding, logged. Each finding gets one decision from the vocabulary, appended as one line to
triage.jsonl. Below the confidence gate after calibration →investigate(medium/low) ordecision-required(critical/high) — never dropped silently. - Plan the wave. Write
plans/phase-<n>.mdfor its kept (keep/combine) work. - Procedure:
references/triage.md— load now.
Gate: every wave's findings triaged into triage.jsonl and a plans/phase-<n>.md written for its kept work.
Phase 4 — Report · gate: BLOCK
Regenerate report.md and manifest.yaml from the two logs per references/report.md — projections, never hand-authored. Task-list-structured (not prose): findings grouped by calibrated severity then type, each with id, path:line, one-line description, remediation shape, triage decision, and a link to its phase plan; decision-required in its own section; a launched/skipped-lens summary; an investigate appendix. Apply <plugin-root>/includes/anti-slop-design/ (core + medium-documents) to the prose.
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.
Gate: report.md regenerated from the logs and presented. No issues created.
Phase 5 — Approval & issue filing · gate: BLOCK
Findings become GitHub issues only on explicit selection and authorization. Silence or ambiguity → file nothing; "looks good" is not authorization.
- Dedup first. Skip findings already carrying an
issue_refintriage.jsonl, then dedup against the tracker — this lane reruns over time and will re-find the same issues. - Default is hand-off. Write and print
issue-commands.sh; execute only on explicit approval, writing eachissue_refback intotriage.jsonl. - Findings file as GitHub issues, never
open-tasks.md— a periodic-review finding must survive PR abandonment. - Procedure:
references/issue-filing.md— load now.
Gate: either issue-commands.sh written and printed, or — on approval — issues filed with the id→result table and issue_ref recorded. Nothing filed without explicit selection; no duplicates against the tracker.
Phase 6 — Telemetry · gate: STOP
Optional, opt-in KPI feedback to refine the skill and the estimator — off by default, sent only on explicit per-run authorization.
- Scrub. The payload is aggregates and per-lens exposure counts only — no code, paths, or finding text; no repo identity unless the user adds
--tag. - Show before send. 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.
- Procedure:
references/telemetry.md— load now.
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.
Hard rules
- MUST NOT proceed past Phase 0 without the user acknowledging the estimated token cost — this lane can cost millions of tokens.
- MUST NOT edit, refactor, format, or commit project code — writes are confined to
.codearbiter/reports/<run-id>/until the filing gate. - 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.
- MUST NOT record a finding without a concrete
path:lineand a minimal evidence snippet. - MUST NOT assert an absence without reading the whole relevant unit — partial-window absence claims do not pass.
- MUST NOT let a lens's provisional severity/confidence stand as final — calibrate at triage; every critical/high carries a
counter_argument. - MUST NOT mutate the append-only logs —
manifest.yaml,report.md, andplans/are regenerated from them, never hand-edited. - MUST NOT file an issue below the confidence gate or without explicit selection and authorization; findings file as GitHub issues, never
open-tasks.md. - MUST NOT create a duplicate issue — skip findings carrying an
issue_ref, and dedup against the tracker bydedup_key/title before filing. - MUST NOT author or scaffold an ADR —
decision-requiredfindings file as a discussion issue; ADRs are authored only via/ca-adrwith user attribution. - MUST NOT send telemetry without explicit per-run authorization, and MUST NOT include code, file paths, finding text, or repo identity (absent an explicit
--tag) in the payload — KPI aggregates only. - MUST NOT guess the test, lint, or secrets-scan command — read
tech-stack.mdor STOP. For the tracker: usetech-stack.mdif it documents one; else default togh issue createon a GitHub origin; else STOP. - MUST NOT dispatch a subagent from within a dispatched specialist — only the orchestrator dispatches.
Files (codearbiter)
-
references
-
lenses
-
appsec.md 1.5 KB
# appsec — lens mandate Executed by `tribunal-lens-reviewer` under the `appsec` assignment. Write contract + evidence discipline: `finding-record.md` — every finding needs `path:line` evidence; write it the moment it's found. ## Scope emphasis The assigned path slice, weighted to trust-boundary crossings and request handlers. ## Required reading - `<project-root>/.codearbiter/security-controls.md` — trust boundaries and approved patterns; and `inventory.md` in the run dir for marked trust boundaries. ## Checklist - Injection surface: user-controlled input reaching SQL (string concatenation, CWE-89), shell execution, filesystem path resolution, HTML/template rendering (XSS, CWE-79), or deserialization. Concatenating input into any query or command is critical regardless of how "clean" the input looks. - Resource-level authorization: for every route/endpoint, is the authenticated user verified to own *this* resource? Missing resource-level authz (IDOR) is the highest-yield critical class and near-invisible to SAST. - Missing input boundary validation (CWE-20): inputs used without null/type/range checks at boundaries. - JWT: signature, expiry, issuer, and algorithm validated; no algorithm confusion. - CORS: wildcard `*` origins. SSRF: server-side fetches of user-controlled URLs. ## Exposure Count of sink sites inspected (query construction, command exec, path resolution, HTML/template render, deserialization). ## Out of scope Secrets/crypto/deps (secrets-supply); generic error handling (reliability). -
architecture.md 1.6 KB
# architecture — lens mandate Executed by `tribunal-lens-reviewer` under the `architecture` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis The assigned path slice plus the `inventory.md` import/caller map. Coupling, dead code, abstraction quality, module sizing. ## Required reading - `<plugin-root>/routines/tribunal/references/ai-markers.md` — the structural thresholds the lens checklist cites. - `<project-root>/.codearbiter/coding-standards.md` — the conventions structure is judged against; `inventory.md` in the run dir — the import/caller map. ## Checklist - Orphan/dead modules: zero active callers; a module tested but never called in production is dead code masquerading as live. - Pattern consistency: identify the primary pattern and verify it holds across all modules; deviating modules are typically later-added where context was lost. - Cosmetic abstractions: an interface/abstract class whose removal changes no behavior, or with a single implementation adding no isolation. The diagnostic is whether it *encapsulates* complexity or merely *relocates* it — relocation creates leaky layers that force consumers to know internals. - Dead code paths: unreachable branches, functions whose return is never consumed, imported symbols never referenced. - God modules, over-consumed shared dependencies — structural thresholds: `ai-markers.md`. Monolith accretion in oversized files. ## Exposure Count of modules in the import/caller map (`inventory.md`). ## Out of scope Conformance to accepted ADRs — that is `architecture-drift-reviewer`, a different agent. Do not re-flag ADR drift. -
coverage.md 859 B
# coverage — lens mandate Executed by `tribunal-lens-reviewer` under the `coverage` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis Source-and-test pairs on risk paths in the assigned slice (auth, money, data-mutation, error handling). ## Required reading - `<project-root>/.codearbiter/tech-stack.md` — test and coverage invocations; `inventory.md` in the run dir — the risk overlay. ## Checklist - Coverage gaps on risk paths (auth, money, data-mutation, error handling). - Missing edge-case/property coverage; the empty/null/single-item and zero-value cases. - Tests asserting implementation detail rather than observable behavior. ## Exposure Count of risk paths examined (`inventory.md` risk overlay). ## Out of scope Tests validating fiction (test-fidelity); the underlying bug itself (reliability). -
infra.md 1.6 KB
# infra — lens mandate Executed by `tribunal-lens-reviewer` under the `infra` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis CI workflows, Dockerfiles/compose, IaC and deploy manifests, release automation in the assigned slice. ## Required reading - `<project-root>/.codearbiter/security-controls.md` — trust boundaries and approved secret stores; `<project-root>/.codearbiter/tech-stack.md` — deploy targets and CI conventions. ## Checklist - CI/CD workflows: untrusted input (PR titles, branch names, comments) interpolated into `run:` steps; excessive workflow/token `permissions`; third-party actions pinned to tags, not SHAs; fork-writable cache keys (poisoning); artifacts promoted without provenance; masked failures (swallowed exit codes) ahead of a publish step. - Container posture: base image unpinned or of unvetted provenance; running as root; secrets baked into layers or build args. - IaC/deploy manifests: drift between environments; missing resource limits; services exposed wider than intended. - Release automation: publish/tag steps ungated by branch or tag protections. ## Categories & severity `security` for exploitable pipeline issues (injection, token overreach, cache poisoning); `dependency` for provenance/pinning; `reliability` for deploy-config correctness. Exploitable-from-fork is critical/high. ## Exposure Count of workflows + Dockerfiles/compose files + IaC/deploy manifests examined. ## Out of scope Supply-chain risk of app dependencies (secrets-supply) — this lens owns the pipeline and deploy surface itself. -
migration.md 1.1 KB
# migration — lens mandate Executed by `tribunal-lens-reviewer` under the `migration` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis Migration files in the assigned slice, cross-referenced against schema and query code. ## Required reading - `<project-root>/.codearbiter/security-controls.md` — data-classification categories; `<project-root>/.codearbiter/tech-stack.md` — ORM/schema conventions. ## Checklist - Reversibility: rollback/down path present; destructive ops (DROP, TRUNCATE) guarded; NOT NULL added without DEFAULT/backfill; single-step rename that breaks queries mid-deploy. - Data-classification annotation present for tables holding sensitive data (PII, credentials, payment, audit). - Immutability: edits to an already-committed migration (schema divergence across environments). - Index concurrency on large tables; locks that block production traffic. - Schema-to-code drift, backfill correctness, operation ordering, unguarded destructive operations. ## Exposure Count of migration files reviewed. ## Out of scope Application-level data handling (appsec/secrets). -
observability.md 911 B
# observability — lens mandate Executed by `tribunal-lens-reviewer` under the `observability` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis The assigned path slice, weighted to critical paths and boundaries. ## Required reading - `<project-root>/.codearbiter/tech-stack.md` — logging/tracing/metrics stack; `inventory.md` in the run dir — the boundary map. ## Checklist - Missing or inconsistent structured logging on critical paths. - Absent tracing / correlation IDs across service or async boundaries. - No metrics on critical paths; audit-trail gaps for security-relevant events. - Sensitive-data-in-logs is flagged once, by the secrets lens — do not double-report it here. ## Exposure Count of boundary crossings / critical paths inspected (`inventory.md` boundary map). ## Out of scope Whether the logged operation is itself correct (reliability). -
performance.md 900 B
# performance — lens mandate Executed by `tribunal-lens-reviewer` under the `performance` assignment. Write contract + evidence discipline: `finding-record.md`; flag a signature only where the path is plausibly hot — no speculative micro-optimization. ## Scope emphasis The assigned path slice, weighted to hot paths and data access. ## Required reading - `<project-root>/.codearbiter/tech-stack.md` — data layer, ORM, and cache conventions. ## Checklist - N+1 queries and per-iteration IO in loops. - Redundant hot-path work; recomputation that could be hoisted or memoized. - Query/index shape: filters/sorts on unindexed columns; over-fetching. - Missing or incorrect caching; cache keys that never invalidate or collide. - Blocking IO on latency-critical paths. ## Exposure Count of hot-path/data-access sites inspected. ## Out of scope Correctness of the logic itself (reliability). -
reliability.md 1.5 KB
# reliability — lens mandate Executed by `tribunal-lens-reviewer` under the `reliability` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis The assigned path slice: async correctness, error propagation, races, resource lifecycle, boundary conditions, orphan state. ## Required reading - `<project-root>/.codearbiter/tech-stack.md` — async model and concurrency primitives. ## Checklist - Async inventory: every `await`, `Promise`, and `.then()` chain has a `.catch`/`try-catch`. - Error-propagation trace: for every `catch`, what happens next. Acceptable — rethrow, typed fallback, central handler, or a state update notifying the caller. Unacceptable — log-and-return-`undefined`, or swallow entirely. Flag every catch that does not propagate a meaningful signal. - Race surface: two+ async operations writing shared state (component state, globals, filesystem, DB rows) without locking/serialization; handlers that fire before a prior invocation completes; polling loops without cancellation; message handlers mutating state without queueing. - Resource lifecycle: every subscription, listener, connection, or timer set up in an init hook has a teardown in cleanup/unmount. - Boundary conditions: empty, null, single-item collections; zero-value numerics; null API responses. - Orphan state: state written conditionally but read unconditionally; mutation after unmount (stale closure). ## Exposure Count of async sites (await/Promise/then) inspected. ## Out of scope Performance (performance); injection/authz (appsec). -
secrets-supply.md 1.2 KB
# secrets-supply — lens mandate Executed by `tribunal-lens-reviewer` under the `secrets-supply` assignment. Write contract + evidence discipline: `finding-record.md`. ## Scope emphasis Source, config, `.env*`, and dependency manifests/lockfiles in the assigned slice. ## Required reading - `<project-root>/.codearbiter/security-controls.md` — approved secret store and crypto; `<project-root>/.codearbiter/tech-stack.md` — dependency manifests. ## Checklist - Literal secrets in source or `.env.example` — JWT/signing keys, API keys, DB connection strings, OAuth secrets, passwords (CWE-798). `.env.example` populated with real values is a common AI regression. - Weak/misused crypto (CWE-327): MD5/SHA-1 for password hashing; `Math.random()` for tokens instead of a CSPRNG. - Cleartext transmission: HTTP where HTTPS is required; credentials in query strings or bodies. - Secrets/PII in logs; debug flags active without an environment gate. - Supply chain: hallucinated/slopsquatted package names; dependency overuse (large trees from small features); pins current at training time but now deprecated or vulnerable. ## Exposure Count of dependencies examined + config/secret-bearing files scanned. ## Out of scope Injection/authz (appsec). -
test-fidelity.md 1.6 KB
# test-fidelity — lens mandate Executed by `tribunal-lens-reviewer` under the `test-fidelity` assignment. Write contract + evidence discipline: `finding-record.md`. Report observable state only; do not assert "written because the producer was absent" unless a comment says so. ## Scope emphasis Test files and fixtures in the assigned slice. Doubles, fabricated literals, escape hatches, temporariness confessions. ## Required reading - `<project-root>/.codearbiter/tech-stack.md` — mock patterns, fixture/factory conventions, the real producers (serializers, DTOs, queries). ## Checklist - Tests validating fiction: mocks/stubs/fabricated literals that should now be sourced from a real producer. Signals: `vi.mock`/`jest.mock`, `mockReturnValue`/`mockResolvedValue`/`mockImplementation`, `sinon.stub`, manual doubles, large inline domain-typed literals in fixtures/`beforeEach`. - Type-escape hatches hiding drift from the compiler: the typesafety lens's escape-hatch list (`typesafety.md`), scoped to test code. - Temporariness confessions: `TODO`/`FIXME`/`HACK`, "stub until X exists/ready/implemented". - Cross-reference: does a real producer now exist (factory/builder, serializer/DTO, query/seed, the real module behind the mock)? Side-by-side drift evidence — missing now-required field, stale enum, wrong nullability — raises confidence. ## Category `maintainability` by default; rises to `reliability` if the drift could let a real defect through — a test validating fiction actively masks regressions. ## Exposure Count of test doubles/fixtures examined. ## Out of scope Coverage gaps (coverage). -
typesafety.md 1 KB
# typesafety — lens mandate Executed by `tribunal-lens-reviewer` under the `typesafety` assignment. Write contract + evidence discipline: `finding-record.md`. Skip entirely if the language has no static type system. ## Scope emphasis The assigned path slice, weighted to public interfaces and module boundaries. Skip entirely if the language has no static type system. ## Required reading - `<project-root>/.codearbiter/coding-standards.md` — typing conventions; `<project-root>/.codearbiter/tech-stack.md` — whether the project is statically typed. ## Checklist - Footgun public interfaces: easy to call wrong, no defaults, silent coercion. - Weak/implicit typing where the language supports better; `any` where a real type exists. - Type-escape hatches: `as any`, `as unknown as X`, `@ts-ignore`, `@ts-expect-error`, untyped fixtures. - Unhelpful error messages; undocumented invariants; naming-convention drift within a unit. ## Exposure Count of public interfaces / exported signatures inspected. ## Out of scope Test-double typing drift (test-fidelity).
-
-
ai-markers.md 1.7 KB
# AI-authorship markers & judgment overlay The orchestrator's Phase 1 overlay on the raw inventory. These signals risk-rank scope and set severity priors; they are not findings themselves. ## Structural map For each module, record what it exports, imports, and is called by. Flag modules importing from >5 sources (likely god module) and modules imported by >10 consumers (critical shared dependency — highest audit priority). ## AI-authorship markers Signals that raise scrutiny on a file or directory: - Excessive inline comments narrating trivial logic. - Stale `TODO:`/`FIXME:` never resolved. - Near-duplicate functions separated by 100+ lines (lost-context duplication). - Convention switches mid-file — camelCase to snake_case, a pattern used then abandoned. - Naming-convention drift within a unit. ## Iteration-depth estimate Inspect git history. A large surface with few commits, or long runs of AI commits without human edits, indicates high AI-generation ratio and a higher feedback-loop-degradation prior — code more secure at step 1 than at the final state. Identify AI commits via `Co-Authored-By: Claude` / AI-tool trailers and characteristic generated message shapes (uniform conventional-commit bodies with bullet lists) — a heuristic signal, not proof. Raise scrutiny on the highest-iteration areas. ## Risk ranking & trust boundaries Rank directories: highest = untrusted input, money movement, auth, PII, high churn. Mark trust boundaries explicitly — these feed the appsec lens directly. ## Effect on triage A finding in a high-marker or high-iteration area carries a small upward severity prior at calibration. The prior never manufactures a finding — it only adjusts one that already cleared evidence-or-drop. -
cost-and-models.md 3.8 KB
# Cost estimate, model recommendation & concurrency ## Sizing commands Prefer `tokei` or `cloc` if present; else `git ls-files | xargs wc -l`. Capture total LOC, file count, and the top languages. Read `tech-stack.md` for the language set first. ## v0 token estimate (crude, self-calibrating) An order-of-magnitude band, not a quote. Refined over runs by the `tokens_estimated`/`tokens_actual` telemetry pair. ``` repo_tokens = LOC * 10 # ~8-12 tokens/line; 10 default per_lens = repo_tokens * 0.5 * 3 # 0.5 coverage fraction * 3 read+reason+write on high-reasoning lenses_total = per_lens * active_lens_count mapping = repo_tokens * 1.2 total_point = mapping + lenses_total band = [total_point * 0.5, total_point * 2] ``` Present the band, the inputs, and that high-reasoning output tokens dominate. On a large repo this is routinely millions of tokens — say so. ## Model recommendation (state at Phase 0) Drive this lane with the highest-reasoning model available at high effort. A cheap model inflates false positives, and this lane files real issues. Every lens runs the same agent (`tribunal-lens-reviewer`); the tier varies per LENS at dispatch time: | Lens (or role) | Model | Effort | |---|---|---| | orchestrator (the skill) | Opus 4.8 | high | | appsec | Opus 4.8 | high | | reliability | Opus 4.8 | high | | architecture | Opus 4.8 | high | | secrets-supply | Sonnet 5 | high | | migration | Sonnet 5 | high | | test-fidelity | Sonnet 5 | high | | performance | Sonnet 5 | medium | | observability | Sonnet 5 | medium | | typesafety | Sonnet 5 | medium | | coverage | Sonnet 5 | medium | | infra | Sonnet 5 | medium | | optional mappers (`map-structure`, `map-deps`) | Haiku 4.5 | low | Advisory only: `tribunal-lens-reviewer` ships `model: inherit`; a dispatch-time override takes an alias (`haiku`/`sonnet`/`opus`/`fable`), not a pinned ID, and there is no per-dispatch effort control. This table guides the orchestrator's dispatch choices — it is not mechanically enforced. API strings: `claude-opus-4-8`, `claude-sonnet-5`, `claude-haiku-4-5-20251001` — as of authoring; substitute the current flagship. `claude-fable-5` now sits above Opus as the highest-reasoning flagship. On proprietary code all tiers must be approved (Anthropic) models — never an external worker. ## Default wave partition The default dispatch order (Phase 2), aligned with the model tiers above: | Wave | Lenses | |---|---| | 1 | appsec, architecture, reliability | | 2 | secrets-supply, migration, test-fidelity | | 3 | coverage, infra, observability, performance, typesafety | A lens dropped from the roster at Phase 1 (scope-inapplicable) is simply absent from its wave — no renumbering. Phase 0/1 MAY choose a different partition for cause (e.g. a migration-heavy repo pulling `migration` into wave 1), but whichever partition is used MUST be recorded in `run-started` (`schemas.md`) — resume reads the recorded partition, never re-derives it. ## Concurrency & cost control Concurrency ≤5 lenses in flight regardless of roster size — the roster is a budget, not a simultaneous-dispatch target. Cost levers offered at Phase 0: narrow scope to a subtree; trim the Tier-2 lenses (`performance`, `observability`, `typesafety`); lower concurrency. ## Optional mappers On a large/sprawling repo, offload raw file-reading to two cheap mapper subagents so it stays out of the orchestrator's retained context: `map-structure` (tree, languages, entry points, core/shared/test locations, churn) and `map-deps` (manifests, lockfiles, integration surface, env/secret-usage surface). On a small repo, map inline and skip them. Either way, produce the same `inventory.md`. These are the only subagents beyond the lens reviewer, and they carry no `tribunal-` prefix because they are generic extractors, not judges. -
finding-record.md 3.3 KB
# Finding record — the agent write contract Every tribunal lens agent emits findings in this format; the orchestrator reads them at triage. This is the only schema an agent needs — triage/run schemas are orchestrator-only (`schemas.md`). ## Write rule Write each finding as its own file — `findings/<lens>/<finding-id>.json` (e.g. `findings/appsec/appsec-001.json`), one `finding/v1` JSON object per file — in the run directory the orchestrator gives you, the moment it is found. Never a batched write at the end. Durability comes from the one-file-one-finding layout: a process killed mid-write risks only the file being written; every previously written finding is already safe on disk. (There is no append tool; a read-then-rewrite of a shared per-lens jsonl would put the lens's whole findings file at risk on every write — that layout is rejected.) **Mechanism:** use `Write` only. Never use a Bash shell command to write finding content — arbitrary `evidence` text (quotes, backticks, embedded newlines) will corrupt a shell-escaped write. Never `Write` over an existing finding file. This is safe without locking: you are the only writer under `findings/<lens>/` — no other agent touches your lens's directory. **Numbering on (re-)dispatch:** before your first write, Glob `findings/<lens>/` — files may already exist if a prior attempt at this lens died partway. Continue numbering from the highest existing `NNN`; never renumber, rewrite, or delete an existing finding file. Prior findings stand; the orchestrator's triage dedups any overlap. ## finding/v1 ```json {"schema":"finding/v1","id":"<lens>-NNN","lens":"<lens>","title":"<imperative,specific>","category":"security|reliability|performance|architecture|observability|maintainability|testing|dependency|migration","severity":"critical|high|medium|low","confidence":0.0,"observed":true,"locations":[{"path":"src/...","lines":"42-58"}],"evidence":"<minimal snippet + 1-2 sentences>","impact":"<what breaks / cost>","recommendation":"<remediation shape, not a patch>","acceptance_criteria":["<verifiable close condition>"],"effort":"S|M|L","depends_on":["<id>"],"dedup_key":"<lens>:<normalized-path>:<slug>","created_at":"<iso8601>"} ``` Minimum required: `locations` (path + lines), `evidence`, `recommendation`. Set `lens` to your own lens name; set `category` to the finding's class, which may differ from your lens (the secrets-supply lens may file a `dependency` finding). `severity`/`confidence` are **provisional** — the orchestrator recalibrates at triage; do not treat your own scores as final. `observed` is `true` when the failure/behavior was directly observed or reproduced (test run, executed path, live config) and `false` when inferred from reading code; triage weighs observed findings above inferred ones at the same confidence. ## id & dedup_key `id`: `<lens>-NNN`, sequential per lens (`appsec-001`, `appsec-002`, …). `dedup_key`: `<lens>:<path-normalized-to-repo-root>:<short-slug-of-title>` — the orchestrator dedups on this plus overlapping `locations`, and it rides into any filed issue body as a searchable comment. ## Evidence discipline Concrete `path:line` + minimal snippet on every finding. An absence claim — "no handler", "no teardown", "missing validation" — requires reading the whole relevant unit, never a truncated window. -
issue-filing.md 2.8 KB
# Issue filing Findings become GitHub issues only on explicit selection and authorization. Use the tracker command documented in `tech-stack.md` if present; otherwise default to `gh issue create` on a GitHub origin; otherwise STOP. This lane reruns over time, so filing is **idempotent** — never create a duplicate. ## Selection File only findings the user explicitly selects ("all keep+combine critical/high", or specific ids). Silence or ambiguity → file nothing. Offer `decision-required` findings as a **separate** opt-in (discussion issues), so design questions don't masquerade as fix tickets. ## What is eligible `keep` (one issue each) and `combine` groups (one issue per `group_id`), only above the confidence gate (defined in `triage.md`). `duplicate` / `false-positive` / `defer` / `accept-risk` / `investigate` never file. `decision-required` files as a discussion/ADR-candidate issue framed as a question — never a fix ticket, and **never by authoring an ADR** (ADRs come only from `/ca-adr`, user-attributed). ## Dedup — before generating any body 1. Skip any finding already carrying an `issue_ref` in `triage.jsonl` (filed on a prior run recorded in this log). 2. For every remaining selected finding, search the tracker for an open issue carrying its `dedup_key` or matching title (e.g. `gh issue list --search "<dedup_key>"`). The `dedup_key` rides in each body as an HTML comment, so it is searchable. If found, skip and record it as a duplicate in the filing report — do not re-file. ## Body — `bodies/<finding-id>.md`, generated lazily, approved-only ``` # <title> **Severity:** <final_severity> | **Confidence:** <final_confidence> | **Effort:** <effort> **Where:** <path:lines, one per line> **Evidence:** <minimal snippet + what is observed> **Impact:** <what breaks / what it costs> **Recommendation:** <remediation shape> **Acceptance criteria:** - <verifiable close condition> <!-- dedup_key: <dedup_key> · finding: <id> --> ``` `decision-required` variant: frame as **Question / Options / Evidence** — the decision and its trade-offs, not a remediation. Anti-slop applies (no em-dash sentence separators, no filler, no fabricated precision). ## Filing procedure - **Default (no execution):** write `issue-commands.sh` with one line per issue: `gh issue create --title "<title>" --label "<final_severity>" --body-file bodies/<finding-id>.md` (`decision-required` labelled distinctly, e.g. `--label discussion`). Print the list. Stop. - **On explicit approval:** run each command; capture the issue URL; write it to `triage.jsonl` as `issue_ref`. - **Report** a table: finding/group id → created URL, or skipped (duplicate), or failed (with the error). Never silently drop a failure. Findings file as GitHub issues, never `open-tasks.md` — a periodic-review finding must survive PR abandonment. -
report.md 1.9 KB
# Report projection `report.md` is a projection of the logs, regenerated in Phase 4 — never hand-authored, never a source of truth. Rebuild it fully from `findings/*/*.json` + `triage.jsonl` on every run and on resume; it is deterministic from the logs. Task-list-structured, not prose. ## Structure - **Header** — run-id, scope, date, models used (from `run.jsonl`), the token estimate from Phase 0 vs. actuals (summed from `lens-completed` `tokens` in `run.jsonl` when present; best-effort, since the orchestrator cannot always observe subagent spend), and a launched/skipped-lens summary with the skip reason per lens. - **Findings** — grouped by **calibrated** `final_severity` (critical to low), then by lens/type within each severity. Each entry on one line: `id` · `path:line(s)` · one-line description · remediation shape · triage `decision` · link to `plans/phase-<n>.md`. Only `keep`/`combine` findings appear here. - **Decisions needed** — a separate section for `decision-required` findings, each as its question + options. These need a decision, not a fix; do not fold them into the severity list. - **Investigate appendix** — medium/low findings below the confidence gate after calibration (defined in `triage.md`; below-gate critical/high land in Decisions needed instead); `id` + `path:line` + one terse line each. Preserved, not filed. - **Blocking-severity note** — one line: critical/high should block shipping the affected code, but this lane is not a gate and blocks nothing. ## Anti-slop Apply `core` (no em-dash sentence separators, no filler/AI cadence, no fabricated precision) and `medium-documents`. Every count comes from the logs — never invent a number to make the report "feel precise." ## Relationship to `manifest.yaml` `manifest.yaml` is the machine-readable run snapshot (a projection of `run.jsonl`); `report.md` is the human view. Both regenerate from the logs; neither is edited by hand. -
schemas.md 4.8 KB
# Orchestrator schemas & artifact layout The finding record (what agents emit) is in `finding-record.md`. This file holds the orchestrator-only logs and the run layout. Source of truth = the per-finding files (`findings/<lens>/<finding-id>.json`) plus the two append-only logs (`triage.jsonl`, `run.jsonl`); everything else is a projection regenerable from them. Write each record as it is produced — never batch. ## Artifact tree ``` .codearbiter/reports/<run-id>/ # run-id = <UTC-date>-<scope-slug> run.jsonl # APPEND-ONLY run-state events; resume source of truth manifest.yaml # projection of run.jsonl (regenerable snapshot) inventory.md # map + risk/boundary/marker overlay findings/<lens>/<finding-id>.json # one finding per file, written on discovery # (crash-durable: a kill risks only the in-flight file; # per-lens dirs, so no write contention) triage.jsonl # APPEND-ONLY, one decision/line bodies/<finding-id>.md # issue body, lazy, approved-only plans/phase-<n>.md # per-wave path plan (projection) report.md # final human-readable (projection) issue-commands.sh # ready-to-run gh issue create commands telemetry.json # KPI payload, opt-in ``` ## triage/v1 — one object per line in `triage.jsonl` ```json {"schema":"triage/v1","id":"<finding-id>","decision":"keep|combine|duplicate|false-positive|defer|accept-risk|decision-required|investigate","final_severity":"critical|high|medium|low","final_confidence":0.0,"counter_argument":"<steelman; required for critical+high>","rationale":"<why>","group_id":"<when combine>","duplicate_of":"<finding-id, when duplicate>","issue_ref":"<filled after filing>","decided_at":"<iso8601>"} ``` `final_*` override the provisional self-scores everywhere downstream. `issue_ref` closes the finding→issue loop and makes re-runs idempotent. ## run/v1 — one state event per line in `run.jsonl` ```json {"schema":"run/v1","event":"run-started|lens-launched|lens-skipped|lens-completed|wave-flushed|wave-triaged|report-written|issues-filed|telemetry-sent|run-aborted","wave":1,"lens":"<lens>","detail":"<optional>","surface_seen":0,"findings":0,"model":"<model>","tokens":0,"at":"<iso8601>"} ``` `run-aborted` records a deliberate abandon (optional `detail` = reason) and marks the run terminal. A `lens-completed` event carries `surface_seen` (int — the lens's Exposure denominator), `findings` (int — count the lens emitted), and `model` (the model the lens ran on, as dispatched); `model` also appears on `lens-launched`. `tokens` (int, optional) records the lens's observed token spend when the orchestrator can see it; null/omitted when unobserved. The `run-started` event's `detail` carries the chosen wave partition — the lens list per wave (default or repartitioned-for-cause, per `cost-and-models.md`). This is the single record of the partition; nothing else derives or re-derives it. ## Resume — read the cursor, never the finding bodies `run.jsonl` is the coarse state log — one line per wave/lens transition, tens of lines even across retries, not the per-finding logs. Resume reads the cursor, not the whole run, and never re-hydrates completed work: 0. **No `run-started`.** A run dir present but with no `run-started` event in `run.jsonl` is a Phase-0/1 death — restart Phase 0/1 fresh (`inventory.md` and lens selection are cheap to rebuild); any finding files already on disk stand and are deduped at triage as normal. 1. **Position.** The resume point is fixed by the last triaged wave: `grep '"event":"wave-triaged"' run.jsonl | tail -1` returns it while reading only matching lines. If none, resume at wave 1. 2. **Plan.** Read the wave partition from the `run-started` event's `detail` — the recorded partition, never re-derived — via `manifest.yaml` (a small projection) or, if it is missing or stale, `run.jsonl` directly. Both are bounded reads — never a full-file scan for the plan. 3. **Re-enter** Phase 2/3 for waves after the last triaged one only. 4. **Do not load** already-triaged waves' `findings/<lens>/` files or `triage.jsonl` into context — they are authoritative on disk. A later wave's dedup that needs a specific prior id fetches it by targeted `grep` across `findings/`, never a full read. 5. **Ordering.** `plans/phase-<n>.md` is written before the `wave-triaged` event for that wave is emitted — the event asserts the plan exists. `manifest.yaml` is a convenience snapshot regenerated from `run.jsonl`; it accelerates the plan read but is never authoritative — a corrupt or stale manifest falls back to the append-only log. ## dedup_key & ids `id`: `<lens>-NNN`, sequential per lens. `dedup_key`: `<lens>:<path-normalized-to-repo-root>:<short-slug-of-title>`. Dedup matches on `dedup_key` and overlapping `locations`. -
telemetry.md 3.7 KB
# Telemetry (opt-in, KPI-only) Optional feedback that refines the skill and calibrates the estimator, pooled across contributors. The target is the public codeArbiter repo, so a shared corpus needs a shared destination — which is safe only because the payload is boring by construction: aggregates and per-lens exposure counts, never anything that identifies a codebase or exposes a weakness. Off by default; sent only on explicit per-run authorization. ## Hard scrubbing The payload carries integers and enums only. It MUST NOT contain code, file paths, finding titles or text, commit hashes, or remote URLs. Repo identity is omitted by default; a contributor who wants to self-tag their submission for their own cross-run tracking may add `--tag <label>`, and only then does `tag` appear. `run_id` is a fresh random value, not derived from the repo. ## Why exposure counts, not raw findings A raw finding count is uninterpretable alone: it is base-rate x detector-sensitivity x exposure, and you cannot invert the product from one number. "0 SQL-injection findings" reads as both "nobody concatenates SQL" and "our appsec lens is blind" — and those resolve oppositely. The per-lens `surface_seen` denominator disambiguates: 0 against a large surface is a blind-spot alarm; 0 against no surface is correctly uninformative. `false_positives` (from the decision log) separates a silent lens from a noisy one. These fields let the corpus *flag* blind-vs-rare; they cannot *confirm* it — that needs ground truth (a seeded-vulnerability canary or a semgrep/CodeQL cross-check), which is a separate self-test, not a payload field. Reading the corpus is the maintainer's judgment, not skill behavior — and a suspicious zero in a security lens defaults to suspecting the detector, never to dialing the lens back, because those costs are asymmetric. ## Payload — `telemetry.json` ```json {"schema":"telemetry/v1","skill_version":"<x.y.z>","run_id":"<random>","at":"<iso8601>","tag":"<omitted unless --tag>","loc_total":0,"loc_by_language":{"<lang>":0},"files_scanned":0,"primary_language":"<lang>","lenses_run":0,"lenses_skipped":0,"model_orchestrator":"<api-string>","models_by_tier":{"opus":0,"sonnet":0,"haiku":0},"tokens_estimated":0,"tokens_actual":null,"lens_exposure":{"<lens>":{"ran":true,"surface_seen":0,"findings":0,"false_positives":0}},"issues_found":0,"severity_breakdown":{"critical":0,"high":0,"medium":0,"low":0},"decision_breakdown":{"keep":0,"combine":0,"duplicate":0,"false_positive":0,"defer":0,"accept_risk":0,"decision_required":0,"investigate":0},"issues_filed":0,"run_duration_sec":0} ``` `lens_exposure` is the field that makes the corpus interpretable; `surface_seen` and `model_orchestrator`/`models_by_tier` are sourced from `run.jsonl` `lens-launched`/`lens-completed` events, not hand-tallied. `tokens_estimated` vs `tokens_actual` calibrates the cost estimate (a guardrail, not a measure of review quality); `tokens_actual` sums `run.jsonl` `lens-completed` `tokens` when present, and is otherwise optional/best-effort — null when the orchestrator could not observe subagent spend. `issues_found` is the post-triage kept count (the `keep` + `combine` decision groups), distinct from the per-lens raw `findings` counts in `lens_exposure`. `skill_version` is read from `plugin.json`, not hand-set. ## Send procedure - Write `telemetry.json`; show it in full. - State plainly, in one line: these aggregates post publicly to the codeArbiter repo; they carry no code, paths, or finding text, and no repo identity unless you added `--tag`. - **Default:** print `gh issue create --repo arbiterForge/codeArbiter --label telemetry --title "run-metrics <at>" --body-file telemetry.json`. Stop. - **On explicit approval:** run it; record a `telemetry-sent` event in `run.jsonl`. -
triage.md 3.7 KB
# Triage & calibration Triage per wave from disk. The orchestrator's calibrated values are final and override every provisional self-score downstream. ## Dedup Before calibrating, dedup each new finding against all findings already on disk — match by `dedup_key` and by overlapping locations. A match decides as `duplicate` (`duplicate_of` set), distinct from `combine`. ## Severity rubric (impact x likelihood) - **critical** — exploitable security hole, data loss/corruption, or an outage path reachable with realistic input. - **high** — serious correctness/security weakness, latent but plausible; or a systemic architectural defect amplifying other risk. - **medium** — real defect/debt, limited blast radius or lower likelihood. - **low** — minor quality, polish, or DX improvement. ## Calibration For each finding, set `final_severity`/`final_confidence` from the evidence directly — the lens's values are provisional input. For every critical/high, record a `counter_argument` — the strongest case it is lower or a false positive; if compelling, downgrade or reclassify. Calibration is bidirectional: promote under-rated findings too. Optional for criticals: dispatch a fresh-context adversary that sees only the finding + code and tries to refute it, to defeat anchoring. ## Severity priors Apply as priors on findings that already cleared evidence-or-drop, never to manufacture one: resource-level authz / IDOR → high or critical; injection with reachable user input → high or critical; literal secret → high or critical; async operation with no handler on a critical path → high. A high-marker/high-iteration location (per `ai-markers.md`) nudges one level at most. ## Confidence gate The bar a finding's `final_confidence` must clear to file, tiered by severity — an uncertain critical is too costly to bury silently, so it gets a lower bar and a softer landing than a low: | `final_severity` | gate | below the gate | | --- | --- | --- | | critical / high | ≥0.5 | → `decision-required`, framed as a question, never dropped silently | | medium | ≥0.7 | → `investigate` | | low | ≥0.75 | → `investigate` | ## Low-severity discipline A `low` is kept only above the confidence gate (≥0.75, see above) with a concrete, actionable remediation. Beyond ~5 lows per lens, aggregate the remainder into a single rollup finding that still lists each `path:line`. ## Decision vocabulary (into `triage.jsonl`) - **keep** — actionable fix; files as its own issue. - **combine** — real, merged with siblings under a shared `group_id`; one issue. - **duplicate** — identical to a recorded finding (`duplicate_of`); distinct from combine. - **false-positive** — not real; `rationale` required (this tunes future-run noise down — keep it). - **defer** — real, out of scope/priority now; preserved, not filed this run. - **accept-risk** — real, consciously not fixing; the risk-acceptance trail. - **decision-required** — real and significant, but the response is an ADR-grade design choice, not a clear fix; files as a discussion, not a fix ticket. - **investigate** — undecided, or a medium/low below the confidence gate after calibration; never filed. Below the confidence gate after calibration: medium/low → `investigate`; critical/high → `decision-required` (see Confidence gate above — never dropped silently). ADR-grade questions also → `decision-required`. ## Per-wave plan `plans/phase-<n>.md` covers only `keep`/`combine`, grouped by type (lens/category/`group_id`): shared remediation approach, ordered sequence, cross-group `depends_on`, rolled-up acceptance criteria. Roadmap level only — no per-finding code steps. A `decision-required` item gets a one-line "ADR-candidate — resolve via `/ca-adr`" pointer, never an authored ADR.
-
-
SKILL.md 11.7 KB
--- name: tribunal description: 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. --- # tribunal The deepest, most expensive review codeArbiter offers — convened rarely, on demand, never as a gate. Routed to when the user invokes `/ca-tribunal`. 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. ## Pre-flight Read these, or STOP and surface the gap — never guess a command or a path: - `<project-root>/.codearbiter/tech-stack.md` — 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. - `<project-root>/.codearbiter/CONTEXT.md` — the `stage:` maturity value and domain vocabulary. - `<project-root>/.codearbiter/coding-standards.md` — the conventions lenses judge against. - `<project-root>/.codearbiter/security-controls.md` — 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. - A git repository must be present. - The reference set under `<plugin-root>/routines/tribunal/references/` — each is cited at its phase, loaded on demand. Do not preload them. ## Phase 0 — Cost, model & resume · gate: STOP This lane is expensive. Orient and get explicit go-ahead before dispatching anything. - **Resume check.** Scan `.codearbiter/reports/` 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 `report-written` event in its `run.jsonl`) means either resumable or stale, judged by that run dir's latest `run.jsonl` timestamp. A run whose `run.jsonl` carries `run-aborted` is terminal — never offered for resume; a fresh run starts. Younger than 7 days → recover position with the cheap cursor scan in `references/schemas.md` (grep the last `wave-triaged`, 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. - **Abandon.** If the user tells the orchestrator to abandon the run, log a `run-aborted` event to `run.jsonl` before stopping. - **Cost acknowledgment.** 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. - Establish `RUN_ID` = `<UTC-date>-<scope-slug>` on a fresh run; create `.codearbiter/reports/<run-id>/`; open `run.jsonl`. On resume, reuse the existing `RUN_ID` as-is — the date is the run's creation date and never changes on resume. - Procedure: `references/cost-and-models.md` — load now. Gate: the user has acknowledged the estimated cost and confirmed the model. An unacknowledged run does not pass. ## Phase 1 — Map + judgment overlay · gate: BLOCK Map before reviewing; the map decides what gets scrutiny. - Produce the inventory (inline, or on a large repo dispatch the optional cheap mappers per `references/cost-and-models.md`): file tree, language breakdown, entry points/routes, core-logic and shared-utility locations, dependency and integration surface. Write `inventory.md`. - Apply the judgment overlay in `references/ai-markers.md`: 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. - Choose the active lenses — the roster IS the set of cards under `references/lenses/`; 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 `run.jsonl` events. - Choose the wave partition — the default in `references/cost-and-models.md`, or a repartition for cause — and record it in the `run-started` event (`references/schemas.md`); resume reads this recorded partition, never re-derives it. Gate: `inventory.md` written with the risk/boundary/marker overlay, and the active-lens set recorded. ## Phase 2 — Roster dispatch (dual output: finding files + summary) · gate: BLOCK Dispatch one `tribunal-lens-reviewer` per active lens, in the wave partition recorded at Phase 1 (default in `references/cost-and-models.md`) at the concurrency from `references/cost-and-models.md` (≤5 in flight). Each dispatch carries the assignment block from the agent's Assignment Format — its FIRST line is the title `Tribunal lens: <lens-slug> — <scope summary>` — naming the lens slug, the scope slice, the run dir, and the findings dir, on the model/effort from `references/cost-and-models.md`. The agent itself reads its own mandate (`references/lenses/<lens>.md`, including that card's Required-reading docs) and the finding contract (`references/finding-record.md`), and loads neither the other lenses' mandates nor the orchestrator schemas. The orchestrator reads `references/finding-record.md` to read findings at triage, and consults a lens mandate only to adjudicate that lens's finding. - Each dispatched lens reviewer writes each finding to its own file `findings/<lens>/<finding-id>.json` the moment it is found — one file per finding, never a batched write at the end (write contract: `references/finding-record.md`). - **Evidence-or-drop.** Every finding cites a concrete `path:line` and the minimal snippet. An absence claim — "no handler", "no teardown", "missing validation" — requires reading the whole unit, never a truncated window. - Specialists never dispatch further subagents. Update each wave's status in `run.jsonl` as it flushes. - When a lens's summary returns, record a `lens-completed` event in `run.jsonl` with `surface_seen`/`findings`/`model` taken from the agent's summary, plus `tokens` when the orchestrator can observe that lens's spend. Gate: every active lens has flushed its `findings/<lens>/` files, and each wave's status is recorded. ## Phase 3 — Triage & per-wave planning · gate: BLOCK Triage per wave from disk as soon as it flushes; do not wait for the whole run. - **Calibrate independently.** Set `final_severity`/`final_confidence` from the evidence yourself — the lens's values are provisional input; every critical/high carries a `counter_argument`. - **Decide per finding, logged.** Each finding gets one decision from the vocabulary, appended as one line to `triage.jsonl`. Below the confidence gate after calibration → `investigate` (medium/low) or `decision-required` (critical/high) — never dropped silently. - **Plan the wave.** Write `plans/phase-<n>.md` for its kept (`keep`/`combine`) work. - Procedure: `references/triage.md` — load now. Gate: every wave's findings triaged into `triage.jsonl` and a `plans/phase-<n>.md` written for its kept work. ## Phase 4 — Report · gate: BLOCK Regenerate `report.md` and `manifest.yaml` from the two logs per `references/report.md` — projections, never hand-authored. Task-list-structured (not prose): findings grouped by **calibrated** severity then type, each with id, `path:line`, one-line description, remediation shape, triage decision, and a link to its phase plan; `decision-required` in its own section; a launched/skipped-lens summary; an investigate appendix. Apply `<plugin-root>/includes/anti-slop-design/` (`core` + `medium-documents`) to the prose. 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. Gate: `report.md` regenerated from the logs and presented. No issues created. ## Phase 5 — Approval & issue filing · gate: BLOCK Findings become GitHub issues only on explicit selection and authorization. Silence or ambiguity → file nothing; "looks good" is not authorization. - **Dedup first.** Skip findings already carrying an `issue_ref` in `triage.jsonl`, then dedup against the tracker — this lane reruns over time and will re-find the same issues. - **Default is hand-off.** Write and print `issue-commands.sh`; execute only on explicit approval, writing each `issue_ref` back into `triage.jsonl`. - Findings file as GitHub issues, never `open-tasks.md` — a periodic-review finding must survive PR abandonment. - Procedure: `references/issue-filing.md` — load now. Gate: either `issue-commands.sh` written and printed, or — on approval — issues filed with the id→result table and `issue_ref` recorded. Nothing filed without explicit selection; no duplicates against the tracker. ## Phase 6 — Telemetry · gate: STOP Optional, opt-in KPI feedback to refine the skill and the estimator — off by default, sent only on explicit per-run authorization. - **Scrub.** The payload is aggregates and per-lens exposure counts only — no code, paths, or finding text; no repo identity unless the user adds `--tag`. - **Show before send.** 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. - Procedure: `references/telemetry.md` — load now. 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. ## Hard rules - MUST NOT proceed past Phase 0 without the user acknowledging the estimated token cost — this lane can cost millions of tokens. - MUST NOT edit, refactor, format, or commit project code — writes are confined to `.codearbiter/reports/<run-id>/` until the filing gate. - 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. - MUST NOT record a finding without a concrete `path:line` and a minimal evidence snippet. - MUST NOT assert an absence without reading the whole relevant unit — partial-window absence claims do not pass. - MUST NOT let a lens's provisional severity/confidence stand as final — calibrate at triage; every critical/high carries a `counter_argument`. - MUST NOT mutate the append-only logs — `manifest.yaml`, `report.md`, and `plans/` are regenerated from them, never hand-edited. - MUST NOT file an issue below the confidence gate or without explicit selection and authorization; findings file as GitHub issues, never `open-tasks.md`. - MUST NOT create a duplicate issue — skip findings carrying an `issue_ref`, and dedup against the tracker by `dedup_key`/title before filing. - MUST NOT author or scaffold an ADR — `decision-required` findings file as a discussion issue; ADRs are authored only via `/ca-adr` with user attribution. - MUST NOT send telemetry without explicit per-run authorization, and MUST NOT include code, file paths, finding text, or repo identity (absent an explicit `--tag`) in the payload — KPI aggregates only. - MUST NOT guess the test, lint, or secrets-scan command — read `tech-stack.md` or STOP. For the tracker: use `tech-stack.md` if it documents one; else default to `gh issue create` on a GitHub origin; else STOP. - MUST NOT dispatch a subagent from within a dispatched specialist — only the orchestrator dispatches.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.