| name | xcheck-audit |
| description | Launch an xcheck Auditor session - run the next queued audit pass and file evidence-backed findings. Use when the user invokes $xcheck-audit or /xcheck-audit, says "run a pass" or "audit pass", optionally with a pass id (e.g. P-03). |
xcheck launcher — Auditor
Thin launcher. The methodology lives in audit/XCHECK.md; this file only picks the charter and starts the role.
- Preflight.
audit/XCHECK.md and audit/AUDIT.md must exist. Missing → stop, point to xcheck bootstrap.md; AUDIT.md empty → suggest the xcheck-plan launcher.
- Read
audit/XCHECK.md fully. Your role: Auditor (§3 role card governs you). Note: the default agent for this role is Codex; running it in Claude is legitimate — any capable agent may play any role.
- Charter auto-pick: the first unchecked pass in the
audit/AUDIT.md pass queue. A user-supplied argument overrides: a pass id, or a dispute charter. A bare "disputed" is NOT a charter (§4 rule 1 needs an exact scope): resolve it to the explicit list of finding IDs currently in status disputed, announce that list, and for each named finding run the full §9 dispute round in this same session: (i) if that finding's ## Objection section is still empty, write exactly one round of objection into it (§3 Auditor mission; append-only, no agent ping-pong); if it ALREADY holds a round — left there by a prior sanctioned no-ruling entry — do NOT write a second one: leave it verbatim and carry that existing objection forward, because a re-write breaks the append-only rule and the §9 ping-pong bar. Then (ii) present that objection (existing or just-written) to the human and record their explicit ruling — accepted (human sides with the finding) or withdrawn (human sides against) — into that finding's frontmatter status and its audit/LEDGER.md row, closing the §5 disputed → accepted | withdrawn transition the Auditor/human owns (this is the Auditor's write surface per §3, not a triage write). You are the pen: record only the verbatim decision the human states; a finding the human does not rule on stays disputed and the session ends without writing its status — never infer, default, or batch a ruling. If none are disputed, report and stop. All passes checked and no argument → report the queue is empty and suggest the xcheck-status or xcheck-triage launcher.
- Announce the charter in one line (pass id, dimension, units, stop conditions), then execute the role exactly per XCHECK.md: copy
audit/templates/pass.md to start the pass report, audit/templates/finding.md per finding, respect max_findings_per_pass, write the mandatory coverage report, tick the pass checkbox, add ledger rows.
- Stop conditions are sacred (§4). Findings in the operator's working language; quotes verbatim in the material's language.
Lock discipline
audit/.lock serializes writing sessions (§4 rule 8) and is shared with the orchestrator (bin/xcheck), which acquires it atomically with open(O_CREAT|O_EXCL). Match that — never check-then-create (the gap between an existence check and a separate create lets two sessions both win):
- Acquire atomically: create
audit/.lock in one exclusive step that FAILS if the file already exists — e.g. (set -C; printf '%s' '{"pid": <pid or 0>, "role": "<Role>", "started": "<ISO>", "host": "<host>"}' > audit/.lock), where set -C (noclobber) makes the redirect fail atomically when the file exists. For pid, record a process id ONLY if it stays alive for your whole session (e.g. the orchestrator's own pid); a transient shell $$ dies the instant the acquire command returns — while your session keeps running — which would make your own live lock look stale and let another session steal it, so never record $$. An agent-CLI session has no session-long pid: record pid: 0. bin/xcheck reads pid: 0 as a live manual session (os.kill(0, 0) never reports it dead), so the lock stands until your owner-checked release removes it, or — if the session died — a human clears it with xcheck unlock --force. If acquisition fails, another writing session holds the lock — do not start; report the conflict to the human.
- Owner-checked release: hold the lock for the whole session; before deleting, re-read
audit/.lock and confirm its pid+started still match the lock you wrote — delete only then, and on every exit path including early stop. Never delete a lock you do not own.
- Stale lock: a lock carrying a real, dead
pid is stale — clear it with xcheck unlock, never silently steal it. A pid: 0 manual-session lock never reads as pid-dead, so xcheck unlock alone refuses it; clear it only with xcheck unlock --force, and only after the human confirms no writing session is active (§4 rule 8).