altimate-receipts 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/receipt/assert.ts","../src/report/badge.ts","../src/report/diff.ts","../src/report/eval.ts","../src/report/log.ts","../src/report/sarif.ts","../src/report/stats.ts","../src/share/handoff.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { deriveFindings } from \"./findings/findings.js\";\nimport type { DerivedSummary } from \"./findings/spans.js\";\nimport { deriveSpans } from \"./findings/spans.js\";\nimport {\n type Assertion,\n assertExitCode,\n evaluateAsserts,\n loadAsserts,\n renderAssertResults,\n} from \"./receipt/assert.js\";\nimport { type Receipt, type ReceiptScope, buildReceipt } from \"./receipt/build.js\";\nimport { canonicalize } from \"./receipt/canonical.js\";\nimport { badgeEndpoint } from \"./report/badge.js\";\nimport { renderCard, renderList } from \"./report/card.js\";\nimport { diffReceipts, renderDiff } from \"./report/diff.js\";\nimport {\n type FieldRow,\n firedCategories,\n renderFieldScan,\n summarizeFieldScan,\n} from \"./report/eval.js\";\nimport {\n collectGuardrails,\n renderGuardrailsBlock,\n upsertGuardrailsSection,\n} from \"./report/guardrails.js\";\nimport { loadReceiptHistory, renderLog } from \"./report/log.js\";\nimport { toSarif } from \"./report/sarif.js\";\nimport { deriveTargets } from \"./report/sessions.js\";\nimport { computeStats, renderStats } from \"./report/stats.js\";\nimport { computeTrends, renderTrends, upsertTrendsSection } from \"./report/trends.js\";\nimport { copyToClipboard } from \"./share/clipboard.js\";\nimport { buildHandoff, renderHandoffMarkdown } from \"./share/handoff.js\";\nimport { renderShareMarkdown } from \"./share/markdown.js\";\nimport { redactReceipt } from \"./share/redact.js\";\nimport { toDsseEnvelope } from \"./sign/envelope.js\";\nimport { compareToTranscript, rederiveFromTranscript } from \"./sign/rederive.js\";\nimport { verifyBundle } from \"./sign/verify.js\";\nimport { applyDiffScope, changedFiles, inDiff } from \"./trace/diffScope.js\";\nimport {\n anyDetected,\n inRepo,\n listSessions,\n loadSession,\n rootsHint,\n selectForBranch,\n selectSummary,\n} from \"./trace/load.js\";\nimport { agentIds } from \"./trace/registry.js\";\nimport { sliceByBranch } from \"./trace/slice.js\";\nimport type { AgentSource, Session, SessionSummary } from \"./trace/types.js\";\nimport { getVersion } from \"./version.js\";\n\nconst HELP = `\n๐Ÿงพ receipts โ€” proof, not vibes\n\n A deterministic, cross-agent Report Card of what your coding agent actually did.\n Reads the agent's own transcript locally. No account, no upload, no model calls.\n\nUsage\n receipts [selector] Print the Agent Report Card for a session\n receipts --list List recent sessions (then: receipts <n>)\n receipts --json [selector] Emit the Receipt object (in-toto Statement)\n receipts --share [selector] Print a redacted, paste-ready Markdown summary\n receipts --handoff [selector] Print a verifiable handoff brief (done/open/risk/next/verify)\n receipts guardrails [sel] Paste-ready prevention rules (AGENTS.md / CLAUDE.md)\n from the findings (--last N to aggregate sessions)\n receipts trends Cross-session digest: grades, recurring findings,\n and evidence over your last N sessions (default 10)\n receipts pr Write this PR's redacted Receipt to .receipts/\n (diff-scoped: only this change's findings)\n receipts envelope <receipt> Wrap a Receipt as an unsigned DSSE envelope\n receipts verify <bundle> Verify a Receipt (+ --transcript to prove fidelity)\n receipts diff [<a> <b>] What changed between two Receipts (no args: last two; --json)\n receipts log [dir] List the committed receipts in .receipts/ (--last N)\n receipts stats [dir] Dogfooding scoreboard: how often it ran + what it caught\n receipts eval Flag-rate of the detectors over your real local sessions (--last N, --json)\n receipts badge [receipt] shields.io endpoint JSON for a README/PR badge (--out f)\n receipts sarif [receipt] SARIF 2.1.0 for GitHub code-scanning (inline + Security tab; --out f)\n receipts init Scaffold the PR-check workflow into this repo (1-command adopt)\n receipts rederive <file> Reproduce the canonical Receipt from a transcript\n receipts assert [selector] Check the receipt against committed .receipts/asserts.json (CI gate)\n receipts mcp Start the MCP server (stdio) for IDEs/agents\n\n selector: a list number (e.g. 3), a session id, or part of the title.\n With no selector, the most recent session is used.\n\nOptions\n --list List recent sessions and exit\n --agent <name> Limit to one agent: claude-code | codex | cursor | openclaw\n --json Emit the Receipt as JSON (no card)\n --compact With --json, emit canonical (sorted, minified) JSON\n --share Emit a redacted Markdown summary for sharing\n --redact With --json, redact secrets from the Receipt\n --out <path> With --json, write to a file instead of stdout\n --base <ref> With pr, the diff base to scope against (default: main)\n --branch <name> With pr, fall back to a branch slice (default: current)\n --whole-session With pr, use the whole session (no scoping)\n --last <n> With guardrails / trends, span the last n sessions\n --copy Also copy --share / --json output to the clipboard\n --no-color Disable ANSI color (also honors NO_COLOR)\n -v, --version Print the version and exit\n -h, --help Print this help and exit\n\nSigning is done in CI by the \"Verified-by: Receipts\" GitHub Action (Sigstore\nkeyless via GitHub Artifact Attestations). See docs/verified-by.md.\n\nReceipts reports what an agent DID โ€” not whether it was correct. Your tests are\nthe oracle for success. Evidence, not judgement.\n\nNote: a Receipt can contain titles, file paths, and command snippets from the\ntranscript (possibly secrets). Plain --json is local only; use --share or\n--json --redact to mask secrets before the output leaves your machine.\n\nDocs: https://github.com/AltimateAI/altimate-receipts\n`;\n\ntype Command =\n | \"envelope\"\n | \"verify\"\n | \"pr\"\n | \"mcp\"\n | \"rederive\"\n | \"guardrails\"\n | \"trends\"\n | \"diff\"\n | \"log\"\n | \"stats\"\n | \"eval\"\n | \"badge\"\n | \"sarif\"\n | \"init\"\n | \"assert\";\nconst COMMANDS = new Set<Command>([\n \"envelope\",\n \"verify\",\n \"pr\",\n \"mcp\",\n \"rederive\",\n \"guardrails\",\n \"trends\",\n \"diff\",\n \"log\",\n \"stats\",\n \"eval\",\n \"badge\",\n \"sarif\",\n \"init\",\n \"assert\",\n]);\n\ninterface ParsedArgs {\n help: boolean;\n version: boolean;\n list: boolean;\n json: boolean;\n compact: boolean;\n share: boolean;\n handoff: boolean;\n redact: boolean;\n copy: boolean;\n color: boolean;\n wholeSession: boolean;\n agent?: AgentSource;\n out?: string;\n branchScope?: string;\n base?: string;\n transcript?: string;\n last?: number;\n command?: Command;\n file?: string;\n /** second positional (e.g. the `b` receipt for `receipts diff <a> <b>`) */\n second?: string;\n selector?: string;\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args = argv.slice(2);\n const parsed: ParsedArgs = {\n help: false,\n version: false,\n list: false,\n json: false,\n compact: false,\n share: false,\n handoff: false,\n redact: false,\n copy: false,\n wholeSession: false,\n color: !process.env.NO_COLOR && process.stdout.isTTY === true,\n };\n const positionals: string[] = [];\n for (let i = 0; i < args.length; i++) {\n const a = args[i];\n if (a === \"-h\" || a === \"--help\") {\n parsed.help = true;\n } else if (a === \"-v\" || a === \"--version\") {\n parsed.version = true;\n } else if (a === \"--list\") {\n parsed.list = true;\n } else if (a === \"--json\") {\n parsed.json = true;\n } else if (a === \"--compact\") {\n parsed.compact = true;\n } else if (a === \"--share\") {\n parsed.share = true;\n } else if (a === \"--handoff\") {\n parsed.handoff = true;\n } else if (a === \"--redact\") {\n parsed.redact = true;\n } else if (a === \"--copy\") {\n parsed.copy = true;\n } else if (a === \"--out\") {\n parsed.out = args[++i];\n } else if (a === \"--branch\") {\n parsed.branchScope = args[++i];\n } else if (a === \"--base\") {\n parsed.base = args[++i];\n } else if (a === \"--transcript\") {\n parsed.transcript = args[++i];\n } else if (a === \"--last\") {\n const n = Number(args[++i]);\n if (Number.isFinite(n) && n > 0) {\n parsed.last = Math.floor(n);\n }\n } else if (a === \"--whole-session\") {\n parsed.wholeSession = true;\n } else if (a === \"--agent\") {\n const next = args[i + 1];\n if (next && agentIds().includes(next as AgentSource)) {\n parsed.agent = next as AgentSource;\n i++;\n }\n } else if (a === \"--no-color\") {\n parsed.color = false;\n } else if (a === \"--color\") {\n parsed.color = true;\n } else if (!a.startsWith(\"-\")) {\n positionals.push(a);\n }\n }\n if (positionals[0] && COMMANDS.has(positionals[0] as Command)) {\n parsed.command = positionals[0] as Command;\n parsed.file = positionals[1];\n parsed.second = positionals[2];\n } else {\n parsed.selector = positionals[0];\n }\n return parsed;\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const args = parseArgs(argv);\n\n if (args.version) {\n process.stdout.write(`${getVersion()}\\n`);\n return 0;\n }\n if (args.help) {\n process.stdout.write(`${HELP}\\n`);\n return 0;\n }\n\n if (args.command === \"envelope\") {\n return runEnvelope(args.file);\n }\n if (args.command === \"verify\") {\n return runVerify(args.file, { transcript: args.transcript, branch: args.branchScope });\n }\n if (args.command === \"diff\") {\n return runDiff(args.file, args.second, { json: args.json, out: args.out });\n }\n if (args.command === \"log\") {\n return runLog(args.file, { json: args.json, last: args.last, out: args.out });\n }\n if (args.command === \"stats\") {\n return runStats(args.file, { json: args.json, out: args.out });\n }\n if (args.command === \"eval\") {\n return runEval({ json: args.json, limit: args.last, agent: args.agent });\n }\n if (args.command === \"badge\") {\n return runBadge(args.file, { out: args.out });\n }\n if (args.command === \"sarif\") {\n return runSarif(args.file, { out: args.out });\n }\n if (args.command === \"init\") {\n return runInit();\n }\n if (args.command === \"rederive\") {\n return runRederive(args.file, {\n branch: args.branchScope,\n redact: args.redact,\n compact: args.compact,\n });\n }\n if (args.command === \"guardrails\") {\n // for `guardrails`, the positional (args.file) is a session selector\n return runGuardrails({\n selector: args.file,\n agent: args.agent,\n last: args.last,\n out: args.out,\n copy: args.copy,\n json: args.json,\n });\n }\n if (args.command === \"trends\") {\n return runTrends({\n selector: args.file,\n agent: args.agent,\n last: args.last,\n out: args.out,\n copy: args.copy,\n json: args.json,\n color: args.color,\n });\n }\n if (args.command === \"pr\") {\n return runPr({\n out: args.out,\n branch: args.branchScope,\n base: args.base,\n wholeSession: args.wholeSession,\n });\n }\n if (args.command === \"assert\") {\n return runAssert({ selector: args.file, agent: args.agent, json: args.json });\n }\n if (args.command === \"mcp\") {\n // Dynamic import keeps the MCP SDK out of every other code path.\n const { startStdio } = await import(\"./mcp/server.js\");\n await startStdio();\n // Stay alive while the transport serves stdio; resolve when the client\n // closes the input stream (so the process exits cleanly).\n await new Promise<void>((resolve) => {\n process.stdin.once(\"close\", resolve);\n process.stdin.once(\"end\", resolve);\n });\n return 0;\n }\n\n if (!(await anyDetected())) {\n process.stderr.write(\n `No agent transcripts found under ${rootsHint()}.\\nRun a coding-agent session first, then try again.\\n`,\n );\n return 1;\n }\n\n const sessions = await listSessions(args.agent);\n\n if (args.list) {\n process.stdout.write(renderList(sessions, { color: args.color }));\n return 0;\n }\n\n const summary = selectSummary(sessions, args.selector);\n if (!summary) {\n process.stderr.write(\n args.selector\n ? `No session matched \"${args.selector}\". Try \\`receipts --list\\`.\\n`\n : \"No sessions found.\\n\",\n );\n return 1;\n }\n\n const session = await loadSession(summary);\n if (!session) {\n process.stderr.write(`Could not read session: ${summary.id}\\n`);\n return 1;\n }\n\n const derived = deriveSpans(session);\n const findings = deriveFindings(derived);\n\n if (args.json) {\n let receipt = await buildReceipt(session, derived, findings);\n if (args.redact) {\n receipt = redactReceipt(receipt);\n }\n const out = args.compact ? canonicalize(receipt) : JSON.stringify(receipt, null, 2);\n if (args.out) {\n writeFileSync(args.out, `${out}\\n`);\n process.stderr.write(`Receipt written to ${args.out}\\n`);\n return 0;\n }\n emit(out, args.copy, \"Receipt\");\n return 0;\n }\n\n if (args.share) {\n const md = renderShareMarkdown({ summary, session, derived, findings });\n emit(md.trimEnd(), args.copy, \"Shareable summary\");\n return 0;\n }\n\n if (args.handoff) {\n const receipt = redactReceipt(await buildReceipt(session, derived, findings));\n const md = renderHandoffMarkdown(buildHandoff(receipt, findings));\n emit(md.trimEnd(), args.copy, \"Handoff\");\n return 0;\n }\n\n process.stdout.write(renderCard({ summary, derived, findings }, { color: args.color }));\n return 0;\n}\n\nfunction git(args: string[]): string {\n const r = spawnSync(\"git\", args, { encoding: \"utf8\" });\n return r.status === 0 ? r.stdout.trim() : \"\";\n}\n\n/**\n * `receipts pr` โ€” find the session that built the current git branch (matching\n * gitBranch + repo root from the transcript), and write its redacted Receipt to\n * `.receipts/<branch>.json` so the \"Verified-by: Receipts\" workflow can sign it.\n */\n/** How many recent in-repo sessions to scan when the branch session didn't produce the\n * diff (the integration-branch / squash-merge case). Bounds the cost of the fallback. */\nconst PR_SELECT_SCAN = 150;\n\n/** A loaded session + its derived evidence, returned by the `pr` session picker. */\ninterface PickedSession {\n summary: SessionSummary;\n session: Session;\n derived: DerivedSummary;\n}\n\n/** How many of `files` (the diff) a session's edits touched โ€” the evidence that this\n * session actually produced (part of) the change. */\nexport function diffOverlap(derived: DerivedSummary, files: readonly string[]): number {\n return derived.filesChanged.filter((f) => inDiff(f.path, files)).length;\n}\n\n/**\n * Pick the session that backs a diff-scoped `receipts pr`. A diff-scoped receipt is about\n * *who produced this change*, so the right session is the one whose edits **overlap the\n * diff** โ€” not merely one carrying the branch tag. The branch-matched session is tried\n * first (cheap, the common feature-branch case); only when it didn't touch the diff (an\n * integration/release branch whose work was merged from feature branches, or a squash\n * workflow โ€” where the branch tag carries only unrelated sessions) do we scan recent\n * in-repo sessions for the real author. Evidence-based: only a session that edited a diff\n * file can win, so this never mis-attributes an unrelated session's work (cf. M56). Returns\n * the branch session (even at 0 overlap) as an honest last resort, or null if none.\n */\nasync function pickForDiff(\n all: SessionSummary[],\n branch: string,\n repoRoot: string | undefined,\n files: readonly string[],\n): Promise<PickedSession | null> {\n const load = async (sum: SessionSummary): Promise<PickedSession | null> => {\n const session = await loadSession(sum);\n if (!session) {\n return null;\n }\n return { summary: sum, session, derived: deriveSpans(session) };\n };\n\n // 1) cheap path: the branch-matched session, if it actually produced the diff.\n const primarySum = selectForBranch(all, branch, repoRoot);\n const primary = primarySum ? await load(primarySum) : null;\n if (primary && diffOverlap(primary.derived, files) > 0) {\n return primary;\n }\n\n // 2) the branch session didn't touch the diff โ†’ find the session that did, among the\n // most-recent in-repo sessions (bounded). Most-recent-first, so ties keep the newest.\n let best: PickedSession | null = null;\n let bestScore = 0;\n const recent = all.filter((s) => inRepo(s.projectPath, repoRoot)).slice(0, PR_SELECT_SCAN);\n for (const sum of recent) {\n const cand = await load(sum);\n if (!cand) {\n continue;\n }\n const score = diffOverlap(cand.derived, files);\n if (score > bestScore) {\n best = cand;\n bestScore = score;\n }\n }\n return best ?? primary;\n}\n\nasync function runPr(opts: {\n out?: string;\n branch?: string;\n base?: string;\n wholeSession?: boolean;\n}): Promise<number> {\n const branch = opts.branch || git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const repoRoot = git([\"rev-parse\", \"--show-toplevel\"]);\n if (!branch || branch === \"HEAD\") {\n process.stderr.write(\"receipts pr: not on a git branch (use --branch <name>).\\n\");\n return 1;\n }\n\n // Diff-scope by default: the receipt reflects only this PR's change. The changed\n // file set is recorded in `predicate.scope` so the receipt stays re-derivable\n // (SPEC-0013). Fall back to a branch slice, then the whole session, and say which.\n const diff = opts.wholeSession ? null : changedFiles(opts.base);\n const all = await listSessions();\n const picked = diff\n ? await pickForDiff(all, branch, repoRoot || undefined, diff.files)\n : await (async () => {\n const sum = selectForBranch(all, branch, repoRoot || undefined);\n return sum ? { summary: sum, session: await loadSession(sum), derived: null } : null;\n })();\n\n if (!picked || !picked.session) {\n process.stderr.write(\n `receipts pr: no agent session found for branch \"${branch}\" in this repo.\\nBuild the branch with a coding agent first, or run \\`receipts --list\\`.\\n`,\n );\n return 1;\n }\n const { summary, session } = picked;\n\n let scopedSession = session;\n let derived = picked.derived ?? deriveSpans(session);\n let findings = deriveFindings(derived);\n let scope: ReceiptScope = { kind: \"session\" };\n let scopeNote = \"whole session\";\n\n if (diff) {\n const sd = applyDiffScope(derived, findings, diff.files);\n derived = sd.derived;\n findings = sd.findings;\n scope = { kind: \"diff\", base: diff.base, files: diff.files };\n scopeNote = `diff vs ${diff.base} (${diff.files.length} file${diff.files.length === 1 ? \"\" : \"s\"})`;\n } else if (!opts.wholeSession) {\n const slice = sliceByBranch(session, branch);\n if (slice) {\n scopedSession = slice;\n derived = deriveSpans(slice);\n findings = deriveFindings(derived);\n scope = { kind: \"branch\", branch };\n scopeNote = `branch ${branch} (no git diff)`;\n } else {\n scopeNote = \"whole session (no diff / branch tags)\";\n }\n }\n\n const receipt = redactReceipt(await buildReceipt(scopedSession, derived, findings, { scope }));\n\n const safe = branch.replace(/[/\\\\]/g, \"-\");\n const dir = join(repoRoot || \".\", \".receipts\");\n const out = opts.out ?? join(dir, `${safe}.json`);\n mkdirSync(dir, { recursive: true });\n writeFileSync(out, `${JSON.stringify(receipt, null, 2)}\\n`);\n git([\"add\", out]); // best-effort stage\n\n const rel = repoRoot ? relative(repoRoot, out) : out;\n process.stderr.write(\n `receipts pr: wrote ${rel} (Grade ${receipt.predicate.grade}, ${scopeNote}) from \"${summary.title ?? \"untitled\"}\".\\n`,\n );\n return 0;\n}\n\n/**\n * `receipts guardrails [selector] [--last N]` โ€” turn findings into a paste-ready\n * prevention block (AGENTS.md / CLAUDE.md). Aggregates the deduped guardrailRules.\n */\nasync function runGuardrails(opts: {\n selector?: string;\n agent?: AgentSource;\n last?: number;\n out?: string;\n copy?: boolean;\n json?: boolean;\n}): Promise<number> {\n if (!(await anyDetected())) {\n process.stderr.write(`No agent transcripts found under ${rootsHint()}.\\n`);\n return 1;\n }\n\n const derivations = await deriveTargets({\n agent: opts.agent,\n last: opts.last,\n selector: opts.selector,\n });\n if (derivations.length === 0) {\n process.stderr.write(\"guardrails: no matching session.\\n\");\n return 1;\n }\n const findingSets = derivations.map((d) => d.findings);\n\n const rules = collectGuardrails(findingSets);\n const block = renderGuardrailsBlock(rules, opts.json ? \"json\" : \"md\");\n\n if (opts.out) {\n const existing = existsSync(opts.out) ? readFileSync(opts.out, \"utf8\") : \"\";\n writeFileSync(opts.out, upsertGuardrailsSection(existing, block));\n process.stderr.write(\n `guardrails: wrote ${rules.length} rule(s) to ${opts.out} (from ${findingSets.length} session${findingSets.length === 1 ? \"\" : \"s\"}).\\n`,\n );\n return 0;\n }\n\n emit(block, opts.copy ?? false, \"Guardrails\");\n if (opts.last) {\n process.stderr.write(`(from the last ${findingSets.length} sessions)\\n`);\n }\n return 0;\n}\n\n/**\n * `receipts trends [--last N]` โ€” a cross-session digest: grade movement, the finding\n * kinds that recur most, and evidence totals over your last N sessions. Reuses the\n * same per-session derivation as the Report Card; deterministic, zero model calls.\n */\nasync function runTrends(opts: {\n selector?: string;\n agent?: AgentSource;\n last?: number;\n out?: string;\n copy?: boolean;\n json?: boolean;\n color?: boolean;\n}): Promise<number> {\n if (!(await anyDetected())) {\n process.stderr.write(`No agent transcripts found under ${rootsHint()}.\\n`);\n return 1;\n }\n\n // A trend needs a window: default to the last 10 sessions. An explicit selector\n // pins a single session; --last N overrides both.\n const requested = opts.last && opts.last > 0 ? opts.last : opts.selector ? 1 : 10;\n const derivations = await deriveTargets(\n opts.last && opts.last > 0\n ? { agent: opts.agent, last: opts.last }\n : opts.selector\n ? { agent: opts.agent, selector: opts.selector }\n : { agent: opts.agent, last: 10 },\n );\n if (derivations.length === 0) {\n process.stderr.write(\"trends: no matching sessions.\\n\");\n return 1;\n }\n\n // deriveTargets is most-recent-first; the digest reads oldest โ†’ newest.\n const inputs = derivations\n .slice()\n .reverse()\n .map((d) => ({ derived: d.derived, findings: d.findings }));\n const trends = computeTrends(inputs, requested);\n\n if (opts.out) {\n const block = renderTrends(trends, \"md\");\n const existing = existsSync(opts.out) ? readFileSync(opts.out, \"utf8\") : \"\";\n writeFileSync(opts.out, upsertTrendsSection(existing, block));\n process.stderr.write(\n `trends: wrote section to ${opts.out} (from ${trends.window.used} sessions).\\n`,\n );\n return 0;\n }\n\n if (opts.json) {\n emit(renderTrends(trends, \"json\"), opts.copy ?? false, \"Trends\");\n return 0;\n }\n\n process.stdout.write(renderTrends(trends, \"card\", { color: opts.color }));\n if (opts.copy) {\n const ok = copyToClipboard(renderTrends(trends, \"card\", { color: false }));\n process.stderr.write(\n ok ? \"Trends copied to clipboard.\\n\" : \"Clipboard unavailable โ€” copy the output above.\\n\",\n );\n }\n return 0;\n}\n\n/** `receipts envelope <receipt.json>` โ€” wrap a Receipt as an unsigned DSSE envelope. */\nfunction runEnvelope(file?: string): number {\n if (!file) {\n process.stderr.write(\"Usage: receipts envelope <receipt.json>\\n\");\n return 1;\n }\n try {\n const receipt = JSON.parse(readFileSync(file, \"utf8\"));\n process.stdout.write(`${JSON.stringify(toDsseEnvelope(receipt), null, 2)}\\n`);\n return 0;\n } catch (err) {\n process.stderr.write(`Could not read ${file}: ${err instanceof Error ? err.message : err}\\n`);\n return 1;\n }\n}\n\n/** `receipts verify <bundle> [--transcript <t> --branch b]` โ€” structural + re-derivation. */\nasync function runVerify(\n file?: string,\n opts: { transcript?: string; branch?: string } = {},\n): Promise<number> {\n if (!file) {\n process.stderr.write(\"Usage: receipts verify <bundle.json> [--transcript <t> [--branch b]]\\n\");\n return 1;\n }\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(file, \"utf8\"));\n } catch (err) {\n process.stderr.write(`Could not read ${file}: ${err instanceof Error ? err.message : err}\\n`);\n return 1;\n }\n const result = verifyBundle(input);\n if (!result.ok) {\n process.stderr.write(\"โœ— Invalid Receipt:\\n\");\n for (const e of result.errors) {\n process.stderr.write(` - ${e}\\n`);\n }\n return 1;\n }\n\n const sig = result.signed\n ? `signed${result.rekorLogIndex !== undefined ? ` ยท Rekor #${result.rekorLogIndex}` : \"\"}`\n : \"unsigned\";\n process.stdout.write(`โœ“ Valid Receipt โ€” Grade ${result.grade} ยท ${sig}\\n`);\n if (result.signer) {\n process.stdout.write(` signer: ${result.signer}\\n`);\n }\n\n // Re-derivation: prove the Receipt is faithful to its transcript (L1).\n if (opts.transcript && result.receipt) {\n const cmp = await compareToTranscript(result.receipt, opts.transcript, { branch: opts.branch });\n if (!cmp.rederived) {\n process.stderr.write(\" โœ— could not re-derive from the supplied transcript\\n\");\n return 1;\n }\n if (!cmp.matches) {\n process.stderr.write(\n \" โœ— re-derivation MISMATCH โ€” the Receipt does not match its transcript (possibly hand-edited)\\n\",\n );\n return 1;\n }\n process.stdout.write(\" โœ“ re-derived โ€” faithful to the transcript (L1)\\n\");\n return 0;\n }\n\n process.stdout.write(\n \" Note: structural check only. Pass --transcript to prove fidelity (L1); `gh attestation verify` for full Sigstore/Rekor.\\n\",\n );\n return 0;\n}\n\n/** `receipts diff <a.json> <b.json>` โ€” what changed between two receipts (M51). */\nfunction runDiff(\n fileA?: string,\n fileB?: string,\n opts: { json?: boolean; out?: string } = {},\n): number {\n let pathA = fileA;\n let pathB = fileB;\n // No args โ†’ \"what changed since the last run\": diff the two most recent committed\n // receipts in .receipts/ (composes `log`'s history with `diff`). A = older, B = newest.\n if (!pathA && !pathB) {\n const hist = loadReceiptHistory(\".receipts\");\n if (hist.length < 2) {\n process.stderr.write(\n `receipts diff: need two receipts. Found ${hist.length} in .receipts/ โ€” pass two explicitly: receipts diff <a.json> <b.json>.\\n`,\n );\n return 1;\n }\n pathA = join(\".receipts\", `${hist[1].name}.json`); // second-newest = baseline\n pathB = join(\".receipts\", `${hist[0].name}.json`); // newest = new\n process.stdout.write(`receipts diff: ${hist[1].name} โ†’ ${hist[0].name} (most recent two)\\n\\n`);\n }\n if (!pathA || !pathB) {\n process.stderr.write(\n \"Usage: receipts diff [<receiptA.json> <receiptB.json>] [--json] [--out <f>]\\n\" +\n \" with no args, diffs the two most recent receipts in .receipts/\\n\",\n );\n return 1;\n }\n const read = (f: string): Receipt | null => {\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(f, \"utf8\"));\n } catch (err) {\n process.stderr.write(`Could not read ${f}: ${err instanceof Error ? err.message : err}\\n`);\n return null;\n }\n const res = verifyBundle(input);\n if (!res.ok || !res.receipt) {\n process.stderr.write(`โœ— ${f} is not a valid Receipt:\\n`);\n for (const e of res.errors) process.stderr.write(` - ${e}\\n`);\n return null;\n }\n return res.receipt;\n };\n const a = read(pathA);\n const b = read(pathB);\n if (!a || !b) return 1;\n\n const delta = diffReceipts(a, b);\n const output = opts.json ? `${JSON.stringify(delta, null, 2)}\\n` : renderDiff(delta);\n if (opts.out) {\n writeFileSync(opts.out, output);\n process.stdout.write(`receipts diff: wrote ${opts.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\n/** `receipts log [dir]` โ€” list the committed receipts in `.receipts/` (M52). */\nfunction runLog(dir?: string, opts: { json?: boolean; last?: number; out?: string } = {}): number {\n const all = loadReceiptHistory(dir ?? \".receipts\");\n const shown = opts.last ? all.slice(0, opts.last) : all;\n const output = opts.json ? `${JSON.stringify(shown, null, 2)}\\n` : renderLog(shown, all.length);\n if (opts.out) {\n writeFileSync(opts.out, output);\n process.stdout.write(`receipts log: wrote ${opts.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\n/** `receipts stats [dir]` โ€” dogfooding scoreboard over the committed receipts (M53). */\nfunction runStats(dir?: string, opts: { json?: boolean; out?: string } = {}): number {\n const stats = computeStats(dir ?? \".receipts\");\n const output = opts.json ? `${JSON.stringify(stats, null, 2)}\\n` : renderStats(stats);\n if (opts.out) {\n writeFileSync(opts.out, output);\n process.stdout.write(`receipts stats: wrote ${opts.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\n/** `receipts badge` (M59) โ€” emit a shields.io endpoint JSON for a committed receipt (the\n * branch receipt by default), an at-a-glance factual state for a README/PR badge. States the\n * finding count, colors by worst severity; never a quality verdict (R2). Deterministic. */\nfunction runBadge(file?: string, opts: { out?: string } = {}): number {\n const repoRoot = git([\"rev-parse\", \"--show-toplevel\"]) || \".\";\n const branch = git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const path =\n file ??\n (branch && branch !== \"HEAD\"\n ? join(repoRoot, \".receipts\", `${branch.replace(/[/\\\\]/g, \"-\")}.json`)\n : undefined);\n if (!path || !existsSync(path)) {\n process.stderr.write(\n `receipts badge: no receipt found${path ? ` at ${path}` : \"\"}. Run \\`receipts pr\\` first, or pass a receipt path.\\n`,\n );\n return 1;\n }\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n process.stderr.write(`receipts badge: could not parse ${path}\\n`);\n return 1;\n }\n const res = verifyBundle(input);\n if (!res.ok || !res.receipt) {\n process.stderr.write(`receipts badge: ${path} is not a valid Receipt.\\n`);\n return 1;\n }\n const output = `${JSON.stringify(badgeEndpoint(res.receipt.predicate), null, 2)}\\n`;\n if (opts.out) {\n writeFileSync(opts.out, output);\n process.stdout.write(`receipts badge: wrote ${opts.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\n/** `receipts sarif` (M63) โ€” emit SARIF 2.1.0 for a committed receipt (the branch receipt by\n * default) so GitHub code-scanning can post findings inline + in the Security tab. Pure\n * transform; uploading is the user's CI step (see docs/sarif.md). */\nfunction runSarif(file?: string, opts: { out?: string } = {}): number {\n const repoRoot = git([\"rev-parse\", \"--show-toplevel\"]) || \".\";\n const branch = git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const path =\n file ??\n (branch && branch !== \"HEAD\"\n ? join(repoRoot, \".receipts\", `${branch.replace(/[/\\\\]/g, \"-\")}.json`)\n : undefined);\n if (!path || !existsSync(path)) {\n process.stderr.write(\n `receipts sarif: no receipt found${path ? ` at ${path}` : \"\"}. Run \\`receipts pr\\` first, or pass a receipt path.\\n`,\n );\n return 1;\n }\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n process.stderr.write(`receipts sarif: could not parse ${path}\\n`);\n return 1;\n }\n const res = verifyBundle(input);\n if (!res.ok || !res.receipt) {\n process.stderr.write(`receipts sarif: ${path} is not a valid Receipt.\\n`);\n return 1;\n }\n const output = `${JSON.stringify(toSarif(res.receipt), null, 2)}\\n`;\n if (opts.out) {\n writeFileSync(opts.out, output);\n process.stdout.write(`receipts sarif: wrote ${opts.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\n/** `receipts eval` โ€” field scan (M57): run the work-account detectors over your own real\n * local agent sessions and report how often each merge-surface category fires. A flag rate\n * the human interprets (a flag may be a true finding or an FP), never a verdict. Local-first\n * (reads only local sessions), deterministic, 0 model calls. `--last N` bounds the scan\n * (default 200, most-recent first). The labeled precision/recall corpus is a dev/CI artifact\n * (see `eval/corpus.json` + `test/eval.test.ts`), not shipped through this command. */\nasync function runEval(\n opts: { json?: boolean; limit?: number; agent?: AgentSource } = {},\n): Promise<number> {\n const limit = opts.limit && opts.limit > 0 ? opts.limit : 200;\n const summaries = (await listSessions(opts.agent)).slice(0, limit);\n const rows: FieldRow[] = [];\n for (const summary of summaries) {\n const session = await loadSession(summary);\n if (!session) {\n continue;\n }\n const { main, minor } = deriveFindings(deriveSpans(session));\n rows.push({\n title: summary.title ?? summary.id,\n categories: [...firedCategories([...main, ...minor])],\n });\n }\n const scan = summarizeFieldScan(rows);\n process.stdout.write(opts.json ? `${JSON.stringify(scan, null, 2)}\\n` : renderFieldScan(scan));\n return 0;\n}\n\n/** `receipts init` โ€” one-command integration: scaffold the quiet-mode \"Verified by\n * Receipts\" PR-check workflow into this repo, pinned to this CLI's version. Idempotent\n * (won't clobber an existing file). The single highest-friction step of adoption. */\nfunction runInit(): number {\n const v = getVersion();\n const tag = /^\\d+\\.\\d+\\.\\d+$/.test(v) ? `v${v}` : \"v0.2.2\";\n const dir = \".github/workflows\";\n const path = `${dir}/receipts.yml`;\n if (existsSync(path)) {\n process.stdout.write(`receipts init: ${path} already exists โ€” leaving it untouched.\\n`);\n return 0;\n }\n const content = `name: Verified by Receipts\n\n# Deterministic \"what did the coding agent actually do?\" check on PRs. Quiet + non-blocking\n# pilot: acts only when a branch commits an agent Receipt (.receipts/<branch>.json);\n# otherwise silent. Adds a new \"Receipts\" check only โ€” touches no existing workflow.\n# Docs: https://github.com/AltimateAI/altimate-receipts/blob/main/docs/onboarding-internal.md\n\non:\n pull_request:\n\npermissions:\n contents: read\n id-token: write # Sigstore keyless signing of the receipt\n attestations: write # record the attestation\n pull-requests: write # post the Receipts comment\n checks: write # post the Receipts check\n\njobs:\n receipts:\n uses: AltimateAI/altimate-receipts/.github/workflows/receipts.reusable.yml@${tag}\n with:\n require-receipt: false # never fail a PR that has no receipt (soft pilot)\n notify-when-missing: false # stay silent unless a receipt is present\n # block-on: \"\" # informational check; never blocks a merge\n`;\n mkdirSync(dir, { recursive: true });\n writeFileSync(path, content);\n process.stdout.write(\n [\n `receipts init: wrote ${path} (pinned to ${tag}, quiet + non-blocking).`,\n \" Commit it, open a PR, and the Receipts check runs on every PR.\",\n \" Generate receipts locally with the pre-push hook โ€” see docs/onboarding-internal.md.\",\n \"\",\n ].join(\"\\n\"),\n );\n return 0;\n}\n\n/** `receipts rederive <transcript>` โ€” reproduce the canonical Receipt from a transcript. */\nasync function runRederive(\n file?: string,\n opts: { branch?: string; redact?: boolean; compact?: boolean } = {},\n): Promise<number> {\n if (!file) {\n process.stderr.write(\"Usage: receipts rederive <transcript.jsonl> [--branch b] [--redact]\\n\");\n return 1;\n }\n const receipt = await rederiveFromTranscript(file, { branch: opts.branch, redact: opts.redact });\n if (!receipt) {\n process.stderr.write(`receipts rederive: could not read a session from ${file}\\n`);\n return 1;\n }\n const out = opts.compact ? canonicalize(receipt) : JSON.stringify(receipt, null, 2);\n process.stdout.write(`${out}\\n`);\n return 0;\n}\n\n/** `receipts assert [selector]` โ€” evaluate `.receipts/asserts.json` against the receipt\n * (a local CI gate the user controls). Exit non-zero iff an error-severity assertion fails\n * or the asserts file is malformed; a missing file is a clean no-op. */\nasync function runAssert(opts: {\n selector?: string;\n agent?: AgentSource;\n json?: boolean;\n}): Promise<number> {\n const repoRoot = git([\"rev-parse\", \"--show-toplevel\"]) || \".\";\n let asserts: Assertion[];\n try {\n asserts = loadAsserts(repoRoot);\n } catch (e) {\n process.stderr.write(`receipts assert: ${(e as Error).message}\\n`);\n return 2; // config error โ€” distinct from an assertion failure\n }\n if (asserts.length === 0) {\n process.stdout.write(`${renderAssertResults([])}\\n`);\n return 0; // absent file โ‡’ no-op\n }\n\n const summary = selectSummary(await listSessions(opts.agent), opts.selector);\n if (!summary) {\n process.stderr.write(\n opts.selector\n ? `No session matched \"${opts.selector}\". Try \\`receipts --list\\`.\\n`\n : \"No sessions found.\\n\",\n );\n return 1;\n }\n const session = await loadSession(summary);\n if (!session) {\n process.stderr.write(`Could not read session: ${summary.id}\\n`);\n return 1;\n }\n const derived = deriveSpans(session);\n const receipt = await buildReceipt(session, derived, deriveFindings(derived));\n const results = evaluateAsserts(receipt, asserts);\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n } else {\n process.stdout.write(`${renderAssertResults(results)}\\n`);\n }\n return assertExitCode(results);\n}\n\n/** Write `text` to stdout; if `copy`, also try the clipboard and note the result. */\nfunction emit(text: string, copy: boolean, label: string): void {\n process.stdout.write(`${text}\\n`);\n if (copy) {\n const ok = copyToClipboard(text);\n process.stderr.write(\n ok\n ? `\\n${label} copied to clipboard.\\n`\n : \"\\nClipboard unavailable โ€” copy the output above.\\n\",\n );\n }\n}\n\n// Run only when executed directly as the CLI โ€” not when imported by a test.\nconst entry = process.argv[1];\nconst isMain = entry !== undefined && import.meta.url === pathToFileURL(entry).href;\nif (isMain) {\n run(process.argv)\n .then((code) => process.exit(code))\n .catch((err: unknown) => {\n process.stderr.write(`receipts: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Receipt, ReceiptPredicate } from \"./build.js\";\n\n/**\n * Receipt assertions (M34, SPEC-0036) โ€” eval-as-code WITHOUT the model judge. A committed\n * `.receipts/asserts.json` of deterministic `{path, op, value}` checks is evaluated\n * mechanically against the just-derived receipt: the **user** supplies the oracle, and\n * Receipts only does exact comparison over evidence it already attests. Pure function of\n * the receipt + the committed file โ‡’ re-derivable; zero model calls; no quality verdict.\n */\n\nexport type AssertOp =\n | \"eq\"\n | \"ne\"\n | \"lt\"\n | \"lte\"\n | \"gt\"\n | \"gte\"\n | \"matches\"\n | \"in\"\n | \"empty\"\n | \"exists\";\n\nconst OPS = new Set<AssertOp>([\n \"eq\",\n \"ne\",\n \"lt\",\n \"lte\",\n \"gt\",\n \"gte\",\n \"matches\",\n \"in\",\n \"empty\",\n \"exists\",\n]);\n\nexport interface Assertion {\n /** dotted accessor into `predicate` (e.g. `evidence.costUsd`, `grade`) or a finding\n * selector (`findings.<id>` count, `findings.severity.<level>` count). */\n path: string;\n op: AssertOp;\n value?: unknown;\n /** `error` (default) gates the exit code; `warn` reports but does not fail. */\n severity?: \"error\" | \"warn\";\n}\n\nexport interface AssertResult {\n assertion: Assertion;\n pass: boolean;\n actual: unknown;\n /** a config/usage error (bad op, missing field for a comparison, โ€ฆ) โ€” never a silent pass */\n error?: string;\n}\n\n/** Resolve a dotted `path` into the receipt predicate, with finding selectors. */\nexport function resolvePath(predicate: ReceiptPredicate, path: string): unknown {\n if (path === \"findings\" || path.startsWith(\"findings.\")) {\n const rest = path === \"findings\" ? \"\" : path.slice(\"findings.\".length);\n if (rest === \"\") {\n return predicate.findings.length;\n }\n if (rest.startsWith(\"severity.\")) {\n const level = rest.slice(\"severity.\".length);\n return predicate.findings.filter((f) => f.severity === level).length;\n }\n // `findings.<id>` โ†’ count of findings whose id equals or is prefixed by it (so a\n // category like `destructive-git` matches `destructive-git-<span>`).\n return predicate.findings.filter((f) => f.id === rest || f.id.startsWith(`${rest}-`)).length;\n }\n // dotted get into the predicate (evidence.*, grade, scope.*, session.*)\n let cur: unknown = predicate;\n for (const key of path.split(\".\")) {\n if (cur == null || typeof cur !== \"object\") {\n return undefined;\n }\n cur = (cur as Record<string, unknown>)[key];\n }\n return cur;\n}\n\nconst isNum = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v);\nconst isEmpty = (v: unknown): boolean =>\n v == null ||\n v === \"\" ||\n v === 0 ||\n (Array.isArray(v) && v.length === 0) ||\n (typeof v === \"object\" && Object.keys(v as object).length === 0);\n\n/** Apply one operator; returns `{pass}` or `{error}` for a config/type misuse. */\nfunction applyOp(\n op: AssertOp,\n actual: unknown,\n value: unknown,\n): { pass: boolean } | { error: string } {\n const needNum = (): { error: string } | null =>\n isNum(actual) && isNum(value)\n ? null\n : { error: `op '${op}' needs a numeric field and value (got ${JSON.stringify(actual)})` };\n switch (op) {\n case \"exists\":\n return { pass: actual !== undefined && actual !== null };\n case \"empty\":\n return { pass: isEmpty(actual) };\n case \"eq\":\n return { pass: actual === value };\n case \"ne\":\n return { pass: actual !== value };\n case \"lt\":\n return needNum() ?? { pass: (actual as number) < (value as number) };\n case \"lte\":\n return needNum() ?? { pass: (actual as number) <= (value as number) };\n case \"gt\":\n return needNum() ?? { pass: (actual as number) > (value as number) };\n case \"gte\":\n return needNum() ?? { pass: (actual as number) >= (value as number) };\n case \"matches\": {\n if (typeof actual !== \"string\" || typeof value !== \"string\") {\n return { error: `op 'matches' needs a string field and a string pattern` };\n }\n try {\n return { pass: new RegExp(value).test(actual) };\n } catch (e) {\n return { error: `invalid regex '${value}': ${(e as Error).message}` };\n }\n }\n case \"in\":\n return Array.isArray(value)\n ? { pass: value.includes(actual) }\n : { error: `op 'in' needs an array value` };\n default:\n return { error: `unknown op '${op}'` };\n }\n}\n\n/** Validate + normalise one raw assertion entry; returns an error string when malformed. */\nfunction validateAssertion(raw: unknown): { assertion: Assertion } | { error: string } {\n if (!raw || typeof raw !== \"object\") {\n return { error: \"assertion must be an object\" };\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.path !== \"string\" || !r.path) {\n return { error: \"assertion.path must be a non-empty string\" };\n }\n if (typeof r.op !== \"string\" || !OPS.has(r.op as AssertOp)) {\n return { error: `assertion.op '${String(r.op)}' is not one of ${[...OPS].join(\"|\")}` };\n }\n if (r.severity !== undefined && r.severity !== \"error\" && r.severity !== \"warn\") {\n return { error: \"assertion.severity must be 'error' or 'warn'\" };\n }\n return {\n assertion: {\n path: r.path,\n op: r.op as AssertOp,\n value: r.value,\n severity: (r.severity as \"error\" | \"warn\") ?? \"error\",\n },\n };\n}\n\n/** Read `.receipts/asserts.json` (JSON-only v1, no new dependency). Returns `[]` when\n * absent (the command is then a no-op). Throws on malformed JSON / wrong shape. */\nexport function loadAsserts(repoRoot: string): Assertion[] {\n const path = join(repoRoot, \".receipts\", \"asserts.json\");\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch {\n return []; // absent โ‡’ no-op\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (e) {\n throw new Error(`.receipts/asserts.json is not valid JSON: ${(e as Error).message}`);\n }\n const list = Array.isArray(parsed)\n ? parsed\n : parsed &&\n typeof parsed === \"object\" &&\n Array.isArray((parsed as { asserts?: unknown }).asserts)\n ? (parsed as { asserts: unknown[] }).asserts\n : null;\n if (!list) {\n throw new Error(\".receipts/asserts.json must be an array or { asserts: [...] }\");\n }\n const out: Assertion[] = [];\n for (const raw of list) {\n const v = validateAssertion(raw);\n if (\"error\" in v) {\n throw new Error(`invalid assertion: ${v.error} (${JSON.stringify(raw)})`);\n }\n out.push(v.assertion);\n }\n return out;\n}\n\n/** Evaluate every assertion against the receipt โ€” pure, total, no model. */\nexport function evaluateAsserts(receipt: Receipt, asserts: readonly Assertion[]): AssertResult[] {\n return asserts.map((assertion) => {\n const actual = resolvePath(receipt.predicate, assertion.path);\n // a comparison op on a missing field is a config error, never a silent pass.\n if (\n actual === undefined &&\n assertion.op !== \"exists\" &&\n assertion.op !== \"empty\" &&\n assertion.op !== \"ne\"\n ) {\n return { assertion, pass: false, actual, error: `path '${assertion.path}' not found` };\n }\n const res = applyOp(assertion.op, actual, assertion.value);\n return \"error\" in res\n ? { assertion, pass: false, actual, error: res.error }\n : { assertion, pass: res.pass, actual };\n });\n}\n\n/** Exit code: non-zero iff an error-severity assertion failed or hit a config error. */\nexport function assertExitCode(results: readonly AssertResult[]): number {\n return results.some((r) => (!r.pass || r.error) && (r.assertion.severity ?? \"error\") === \"error\")\n ? 1\n : 0;\n}\n\n/** Human-readable report of the assertion run. */\nexport function renderAssertResults(results: readonly AssertResult[]): string {\n if (results.length === 0) {\n return \"receipts assert: no assertions (.receipts/asserts.json absent) โ€” nothing to check.\";\n }\n const lines = results.map((r) => {\n const { path, op, value, severity } = r.assertion;\n const expr = `${path} ${op}${value === undefined ? \"\" : ` ${JSON.stringify(value)}`}`;\n if (r.error) {\n return ` โš ๏ธ ERROR ${expr} โ€” ${r.error}`;\n }\n const tag = r.pass ? \" โœ… PASS \" : severity === \"warn\" ? \" ๐ŸŸก WARN \" : \" โŒ FAIL \";\n return `${tag} ${expr} (actual: ${JSON.stringify(r.actual)})`;\n });\n const failed = results.filter(\n (r) => !r.pass && (r.assertion.severity ?? \"error\") === \"error\",\n ).length;\n const warned = results.filter((r) => !r.pass && r.assertion.severity === \"warn\").length;\n const passed = results.filter((r) => r.pass).length;\n lines.push(\n ` ${passed} passed ยท ${failed} failed${warned ? ` ยท ${warned} warned` : \"\"} of ${results.length}`,\n );\n return lines.join(\"\\n\");\n}\n","import type { GradeLetter } from \"../findings/grade.js\";\n\n/**\n * `receipts badge` (M59) โ€” a [shields.io endpoint](https://shields.io/badges/endpoint-badge)\n * JSON for a repo's README/PR: an at-a-glance, **factual** state of the agent-work receipt.\n * It states the finding count (and colors by worst severity) โ€” never a quality verdict about\n * the code (R2). Pure function of the receipt's findings; deterministic; zero model calls.\n *\n * Hosting is the user's choice (commit the JSON + a raw URL, or publish it from CI); this only\n * emits the endpoint object. Works once a repo is public (shields.io must reach the URL).\n */\n\nexport interface ShieldsEndpoint {\n schemaVersion: 1;\n label: string;\n message: string;\n color: string;\n}\n\ntype Sev = \"critical\" | \"high\" | \"medium\" | \"low\";\nconst SEV_ORDER: readonly Sev[] = [\"critical\", \"high\", \"medium\", \"low\"];\n\n/** The worst severity present in a finding set, or undefined when empty. */\nexport function worstSeverity(findings: readonly { severity: Sev }[]): Sev | undefined {\n return SEV_ORDER.find((s) => findings.some((f) => f.severity === s));\n}\n\n/**\n * Build the shields.io endpoint object from a receipt predicate. Message is the finding\n * count (factual); color maps to the worst severity (clean โ†’ brightgreen, critical/high โ†’\n * red, medium โ†’ orange, low โ†’ yellow). The synthesized grade is deliberately NOT the\n * message โ€” the badge states what was found, not a verdict.\n */\nexport function badgeEndpoint(predicate: {\n grade?: GradeLetter;\n findings?: readonly { severity: Sev }[];\n}): ShieldsEndpoint {\n const findings = predicate.findings ?? [];\n const n = findings.length;\n const worst = worstSeverity(findings);\n const color =\n n === 0\n ? \"brightgreen\"\n : worst === \"critical\" || worst === \"high\"\n ? \"red\"\n : worst === \"medium\"\n ? \"orange\"\n : \"yellow\";\n const message = n === 0 ? \"no findings\" : `${n} finding${n === 1 ? \"\" : \"s\"}`;\n return { schemaVersion: 1, label: \"receipts\", message, color };\n}\n","import { formatCostAlways, formatTokens } from \"../findings/format.js\";\nimport type { Receipt, ReceiptFinding } from \"../receipt/build.js\";\n\n/**\n * Receipt-to-receipt diff (M51) โ€” \"what changed between two agent runs?\" A pure,\n * deterministic comparison of two receipts Receipts already emits (a re-run on the\n * same PR, last night's run vs tonight's, agent A vs agent B). It reports **deltas and\n * counts** โ€” files/edits/commands, cost/tokens, findings added/removed, the\n * test-observation flip, both grades โ€” and **never a judgement** (no \"better / worse /\n * regressed / improved\"). The reader decides; the diff states facts (SPEC-0000 R2).\n *\n * Deterministic ยท zero model calls ยท no schema change ยท same {a, b} โ†’ identical delta.\n */\n\nexport interface CountDelta {\n key: string;\n label: string;\n a: number;\n b: number;\n delta: number;\n}\n\nexport interface ReceiptDelta {\n grade: { a: string; b: string };\n counts: CountDelta[];\n cost: { a: number; b: number; delta: number };\n testsObserved: { a: boolean; b: boolean };\n findingsAdded: ReceiptFinding[];\n findingsRemoved: ReceiptFinding[];\n findingsCommon: number;\n scope: { a: string; b: string };\n}\n\n/** Stable cross-run identity for a finding. The raw `id` embeds span indices that\n * differ between runs, so identity is the human-stable (title + filePath) pair. */\nfunction findingKey(f: ReceiptFinding): string {\n return `${f.title}\u0000${f.filePath ?? \"\"}`;\n}\n\nfunction scopeLabel(r: Receipt): string {\n const s = r.predicate.scope;\n if (!s || s.kind === \"session\") return \"whole session\";\n if (s.kind === \"branch\") return `branch ${s.branch ?? \"?\"}`;\n return `diff (${(s.files ?? []).length} files${s.base ? ` vs ${s.base}` : \"\"})`;\n}\n\nexport function diffReceipts(a: Receipt, b: Receipt): ReceiptDelta {\n const ea = a.predicate.evidence;\n const eb = b.predicate.evidence;\n const count = (key: string, label: string, va: number, vb: number): CountDelta => ({\n key,\n label,\n a: va,\n b: vb,\n delta: vb - va,\n });\n const counts: CountDelta[] = [\n count(\"filesChanged\", \"files changed\", ea.filesChanged, eb.filesChanged),\n count(\"edits\", \"edits\", ea.edits, eb.edits),\n count(\"commands\", \"commands\", ea.commands, eb.commands),\n count(\"reads\", \"reads\", ea.reads, eb.reads),\n count(\"destructiveOps\", \"destructive ops\", ea.destructiveOps, eb.destructiveOps),\n count(\"tokens\", \"tokens\", ea.tokens.total, eb.tokens.total),\n ];\n\n const aKeys = new Set(a.predicate.findings.map(findingKey));\n const bKeys = new Set(b.predicate.findings.map(findingKey));\n const findingsAdded = b.predicate.findings.filter((f) => !aKeys.has(findingKey(f)));\n const findingsRemoved = a.predicate.findings.filter((f) => !bKeys.has(findingKey(f)));\n const findingsCommon = a.predicate.findings.filter((f) => bKeys.has(findingKey(f))).length;\n\n return {\n grade: { a: a.predicate.grade, b: b.predicate.grade },\n counts,\n cost: { a: ea.costUsd, b: eb.costUsd, delta: eb.costUsd - ea.costUsd },\n testsObserved: { a: ea.testsRan, b: eb.testsRan },\n findingsAdded,\n findingsRemoved,\n findingsCommon,\n scope: { a: scopeLabel(a), b: scopeLabel(b) },\n };\n}\n\nconst SEV_ICON: Record<string, string> = { critical: \"โ›”\", high: \"โš ๏ธ\", medium: \"๐Ÿ”\", low: \"ยท\" };\n\n/** Signed-delta string, neutral: \"+3\" / \"-2\" / \"ยฑ0\". No value judgement on direction. */\nfunction signed(n: number): string {\n if (n === 0) return \"ยฑ0\";\n return n > 0 ? `+${n}` : `${n}`;\n}\n\nfunction findingLines(fs: readonly ReceiptFinding[]): string[] {\n return fs.map((f) => {\n const loc = f.filePath ? ` (\\`${f.filePath}\\`)` : \"\";\n return ` ${SEV_ICON[f.severity] ?? \"ยท\"} ${f.title}${loc}`;\n });\n}\n\n/** Render the delta as plain text (A = baseline, B = new). Facts only. */\nexport function renderDiff(d: ReceiptDelta): string {\n const out: string[] = [];\n out.push(\"Receipt diff โ€” A (baseline) โ†’ B (new)\");\n out.push(\"\");\n out.push(`Grade: ${d.grade.a} โ†’ ${d.grade.b}`);\n out.push(`Scope: A ${d.scope.a} ยท B ${d.scope.b}`);\n out.push(\"\");\n out.push(\"Evidence:\");\n for (const c of d.counts) {\n out.push(` ${c.label}: ${c.a} โ†’ ${c.b} (${signed(c.delta)})`);\n }\n const cd = d.cost;\n const costDelta =\n cd.delta === 0 ? \"ยฑ0\" : (cd.delta > 0 ? \"+\" : \"-\") + formatCostAlways(Math.abs(cd.delta));\n out.push(` cost: ${formatCostAlways(cd.a)} โ†’ ${formatCostAlways(cd.b)} (${costDelta})`);\n out.push(\n ` tokens (total): ${formatTokens(d.counts.find((c) => c.key === \"tokens\")?.a ?? 0)} โ†’ ${formatTokens(d.counts.find((c) => c.key === \"tokens\")?.b ?? 0)}`,\n );\n const to = d.testsObserved;\n const toStr = (v: boolean) => (v ? \"observed\" : \"not observed\");\n out.push(` test command: ${toStr(to.a)} โ†’ ${toStr(to.b)}${to.a !== to.b ? \" (changed)\" : \"\"}`);\n out.push(\"\");\n out.push(\n `Findings: ${d.findingsAdded.length} only in B ยท ${d.findingsRemoved.length} only in A ยท ${d.findingsCommon} in both`,\n );\n if (d.findingsAdded.length) {\n out.push(\"\");\n out.push(\"Only in B (new):\");\n out.push(...findingLines(d.findingsAdded));\n }\n if (d.findingsRemoved.length) {\n out.push(\"\");\n out.push(\"Only in A (absent from B):\");\n out.push(...findingLines(d.findingsRemoved));\n }\n out.push(\"\");\n out.push(\"Deterministic ยท 0 model calls ยท evidence, not judgement.\");\n return `${out.join(\"\\n\")}\\n`;\n}\n","import type { AgentSource } from \"../trace/types.js\";\nimport { CHECK_CATALOG, checkForId } from \"./checks.js\";\n\n/**\n * `receipts eval` (M57) โ€” a precision/recall harness for the **work-account**, not the code.\n *\n * Receipts' thesis is that a human reviews the agent's *work* (a faithful, deterministic\n * account of what it did) instead of re-reading the agent's *output*. That only holds if the\n * account is trustworthy: one false alarm and the reviewer goes back to reading diffs. So the\n * near-zero-FP bar (SPEC-0000 R3) is existential โ€” and until now, unmeasured. This turns it\n * into a number: run the detectors over a hand-labeled corpus, compare what fired to the\n * ground truth, and compute precision/recall/F1.\n *\n * It is **dev/CI tooling, not the product path**: it adds no detector, calls no model (R1),\n * and renders no verdict about any code (R2) โ€” it measures *detector fidelity*. The unit of\n * scoring is (session ร— merge-surface category): each fixture's ground truth and the\n * detectors' output are both sets of {@link CHECK_CATALOG} keys (advisory cost/loop findings\n * are out of scope by construction โ€” they aren't in the catalog).\n */\n\n/** A finding, reduced to the one field the harness needs. */\nexport interface ScorableFinding {\n id: string;\n}\n\n/** The merge-surface category keys a finding set fired (reusing the existing taxonomy). */\nexport function firedCategories(findings: readonly ScorableFinding[]): Set<string> {\n const keys = new Set<string>();\n for (const f of findings) {\n const c = checkForId(f.id);\n if (c) {\n keys.add(c.key);\n }\n }\n return keys;\n}\n\n/**\n * The categories the curated corpus scores precision/recall over: the **deterministic\n * STATEMENT detectors** whose near-zero-FP we guarantee (SPEC-0000 R3). The heuristic,\n * confidence-weighted \"QUESTION\" detectors (blind/unverified edits, duplication, unfulfilled\n * promises, swallowed errors, stubbed impls โ€” see `findings.ts`) need full-session context to\n * be meaningful and fire as artifacts on minimal single-behavior fixtures, so they are out of\n * the curated precision claim. The field scan (`receipts eval`) exercises them over real\n * sessions, where they belong.\n */\nexport const SCORED_CATEGORIES: ReadonlySet<string> = new Set([\n \"destructive\",\n \"git-history\",\n \"secrets\",\n \"cicd\",\n \"lockfile\",\n \"tests\",\n \"weakening\",\n \"injection\",\n \"trojan\",\n \"malformed\",\n \"truncated\",\n \"tool-calls\",\n]);\n\n/** Restrict a set of category keys to the scored (deterministic) scope. */\nexport function scoped(keys: Iterable<string>): string[] {\n return [...keys].filter((k) => SCORED_CATEGORIES.has(k));\n}\n\n/** One labeled corpus row: a fixture and the categories that *should* fire ([] = clean). */\nexport interface CorpusEntry {\n fixture: string;\n /** merge-surface category keys (CHECK_CATALOG) expected to fire; empty โ‡’ clean session */\n expect: string[];\n /** adapter to load the fixture through (default claude-code) */\n source?: AgentSource;\n /** why this fixture is labeled this way (kept honest, human-readable) */\n note?: string;\n}\n\n/** The per-entry input to scoring: expected vs. actually-fired category keys. */\nexport interface ScoredEntry {\n fixture: string;\n expected: string[];\n fired: string[];\n /** fired but not expected โ€” the false positives that erode trust */\n fp: string[];\n /** expected but not fired โ€” the misses */\n fn: string[];\n}\n\nexport interface CategoryMetric {\n key: string;\n label: string;\n tp: number;\n fp: number;\n fn: number;\n precision: number;\n recall: number;\n f1: number;\n}\n\nexport interface EvalMetrics {\n entries: number;\n tp: number;\n fp: number;\n fn: number;\n precision: number;\n recall: number;\n f1: number;\n perCategory: CategoryMetric[];\n details: ScoredEntry[];\n}\n\n/** Precision/recall with an empty denominator = 1 (firing nothing on a clean session is\n * perfect, not undefined; missing nothing is perfect recall). */\nconst ratio = (num: number, denom: number): number => (denom === 0 ? 1 : num / denom);\nconst f1Of = (p: number, r: number): number => (p + r === 0 ? 0 : (2 * p * r) / (p + r));\n\n/**\n * Score a corpus run into a confusion matrix at (session ร— category) granularity. Pure: the\n * caller is responsible for loading fixtures and deriving findings; this only does the math,\n * so it is unit-testable without any I/O.\n */\nexport function scoreCorpus(\n results: readonly { fixture: string; expected: readonly string[]; fired: ReadonlySet<string> }[],\n): EvalMetrics {\n const label = new Map(CHECK_CATALOG.map((c) => [c.key, c.label] as const));\n const cat = new Map<string, { tp: number; fp: number; fn: number }>();\n const bump = (key: string, field: \"tp\" | \"fp\" | \"fn\") => {\n const row = cat.get(key) ?? { tp: 0, fp: 0, fn: 0 };\n row[field]++;\n cat.set(key, row);\n };\n\n let tp = 0;\n let fp = 0;\n let fn = 0;\n const details: ScoredEntry[] = [];\n\n for (const r of results) {\n const expected = new Set(r.expected);\n const fpKeys: string[] = [];\n const fnKeys: string[] = [];\n for (const key of r.fired) {\n if (expected.has(key)) {\n tp++;\n bump(key, \"tp\");\n } else {\n fp++;\n fpKeys.push(key);\n bump(key, \"fp\");\n }\n }\n for (const key of expected) {\n if (!r.fired.has(key)) {\n fn++;\n fnKeys.push(key);\n bump(key, \"fn\");\n }\n }\n details.push({\n fixture: r.fixture,\n expected: [...expected],\n fired: [...r.fired],\n fp: fpKeys,\n fn: fnKeys,\n });\n }\n\n const perCategory: CategoryMetric[] = [...cat.entries()]\n .map(([key, v]) => {\n const precision = ratio(v.tp, v.tp + v.fp);\n const recall = ratio(v.tp, v.tp + v.fn);\n return {\n key,\n label: label.get(key) ?? key,\n ...v,\n precision,\n recall,\n f1: f1Of(precision, recall),\n };\n })\n .sort((a, b) => b.tp + b.fn - (a.tp + a.fn) || a.label.localeCompare(b.label));\n\n const precision = ratio(tp, tp + fp);\n const recall = ratio(tp, tp + fn);\n return {\n entries: results.length,\n tp,\n fp,\n fn,\n precision,\n recall,\n f1: f1Of(precision, recall),\n perCategory,\n details,\n };\n}\n\nconst pct = (n: number): string => `${(100 * n).toFixed(1)}%`;\n\n/** Render the corpus confusion matrix as facts-only text (the trust artifact). */\nexport function renderEval(m: EvalMetrics): string {\n const out: string[] = [];\n out.push(`Receipts detector eval โ€” ${m.entries} labeled session${m.entries === 1 ? \"\" : \"s\"}`);\n out.push(\"\");\n out.push(\n `Precision ${pct(m.precision)} ยท Recall ${pct(m.recall)} ยท F1 ${pct(m.f1)} (TP ${m.tp} ยท FP ${m.fp} ยท FN ${m.fn})`,\n );\n out.push(\"\");\n if (m.perCategory.length) {\n out.push(\"By category:\");\n for (const c of m.perCategory) {\n out.push(\n ` ${c.label.padEnd(26)} P ${pct(c.precision).padStart(6)} R ${pct(c.recall).padStart(6)} (tp ${c.tp} fp ${c.fp} fn ${c.fn})`,\n );\n }\n }\n const fps = m.details.filter((d) => d.fp.length);\n const fns = m.details.filter((d) => d.fn.length);\n if (fps.length) {\n out.push(\"\", \"False positives (fired but should be clean):\");\n for (const d of fps) out.push(` ${d.fixture}: ${d.fp.join(\", \")}`);\n }\n if (fns.length) {\n out.push(\"\", \"Misses (expected but did not fire):\");\n for (const d of fns) out.push(` ${d.fixture}: ${d.fn.join(\", \")}`);\n }\n out.push(\"\", \"Deterministic ยท 0 model calls ยท measures detector fidelity, not code quality.\");\n return `${out.join(\"\\n\")}\\n`;\n}\n\n/** One real session's contribution to the field scan. */\nexport interface FieldRow {\n title: string;\n categories: string[];\n}\n\nexport interface FieldScan {\n scanned: number;\n flagged: number;\n byCategory: { key: string; label: string; sessions: number }[];\n rows: FieldRow[];\n}\n\n/** Aggregate a field scan over real local sessions: how often the work-account flags real\n * work, by category. A rate the human interprets โ€” never a verdict (a flag may be a true\n * finding or an FP). */\nexport function summarizeFieldScan(rows: readonly FieldRow[]): FieldScan {\n const label = new Map(CHECK_CATALOG.map((c) => [c.key, c.label] as const));\n const cat = new Map<string, number>();\n let flagged = 0;\n for (const r of rows) {\n if (r.categories.length) {\n flagged++;\n }\n for (const key of new Set(r.categories)) {\n cat.set(key, (cat.get(key) ?? 0) + 1);\n }\n }\n const byCategory = [...cat.entries()]\n .map(([key, sessions]) => ({ key, label: label.get(key) ?? key, sessions }))\n .sort((a, b) => b.sessions - a.sessions || a.label.localeCompare(b.label));\n return { scanned: rows.length, flagged, byCategory, rows: [...rows] };\n}\n\n/** Render the field scan as facts-only text. */\nexport function renderFieldScan(s: FieldScan): string {\n if (s.scanned === 0) {\n return \"No local agent sessions found to scan.\\n\";\n }\n const out: string[] = [];\n out.push(`Receipts field scan โ€” ${s.scanned} real local session${s.scanned === 1 ? \"\" : \"s\"}`);\n out.push(\"\");\n const rate = Math.round((100 * s.flagged) / s.scanned);\n out.push(`Flagged: ${s.flagged}/${s.scanned} sessions (${rate}%) carried โ‰ฅ1 merge-surface flag`);\n out.push(\"\");\n if (s.byCategory.length === 0) {\n out.push(\"No merge-surface category fired on any scanned session.\");\n } else {\n out.push(\"By category (sessions flagged):\");\n for (const c of s.byCategory) {\n out.push(` ${c.label.padEnd(26)} ${c.sessions}`);\n }\n }\n out.push(\n \"\",\n \"A flag may be a true finding or a false positive โ€” this is a flag rate you interpret,\",\n \"not a verdict. Deterministic ยท 0 model calls ยท reads only local sessions.\",\n );\n return `${out.join(\"\\n\")}\\n`;\n}\n","import { readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Severity } from \"../findings/findings.js\";\nimport { formatCostAlways } from \"../findings/format.js\";\nimport type { GradeLetter } from \"../findings/grade.js\";\nimport { verifyBundle } from \"../sign/verify.js\";\n\n/**\n * `receipts log` (M52) โ€” a chronological list of the committed receipts in `.receipts/`\n * (one line per receipt: date, grade, change-cost, finding count + top severity, scope,\n * name). The `git log` of receipts: the local, history-aware companion to `receipts diff`\n * (which compares two) and `receipts trends` (which aggregates sessions). It reads the\n * COMMITTED receipts, not live sessions, so it answers \"what receipts have we attached,\n * and what do they say?\" โ€” a view nothing else provides.\n *\n * Deterministic ยท zero model calls ยท local-first ยท lists recorded facts (each receipt's\n * own grade/cost/findings), never a synthesized judgement.\n */\n\nconst SEV_ICON: Record<Severity, string> = { critical: \"โ›”\", high: \"โš ๏ธ\", medium: \"๐Ÿ”\", low: \"ยท\" };\nconst SEV_RANK: Record<Severity, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n\nexport interface LogEntry {\n name: string;\n grade: GradeLetter;\n costUsd: number;\n findings: number;\n topSeverity?: Severity;\n scope: string;\n endedAt?: number;\n}\n\n/** Files in `.receipts/` that are config/examples, not receipts. */\nconst NON_RECEIPT = /(?:^|\\/)(?:asserts(?:\\.example)?|sample)\\.json$/i;\n\nfunction scopeLabel(\n scope: { kind: string; files?: string[]; branch?: string } | undefined,\n): string {\n if (!scope || scope.kind === \"session\") return \"session\";\n if (scope.kind === \"branch\") return `branch ${scope.branch ?? \"?\"}`;\n return `diff ${(scope.files ?? []).length}f`;\n}\n\nfunction isoDate(ms: number | undefined): string {\n if (!ms || !Number.isFinite(ms)) return \"โ€”\".padEnd(10);\n return new Date(ms).toISOString().slice(0, 10);\n}\n\n/** Load and validate the committed receipts under `dir`, most-recent first. */\nexport function loadReceiptHistory(dir: string): LogEntry[] {\n let files: string[];\n try {\n files = readdirSync(dir).filter((f) => f.endsWith(\".json\") && !NON_RECEIPT.test(f));\n } catch {\n return [];\n }\n const entries: LogEntry[] = [];\n for (const f of files) {\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(join(dir, f), \"utf8\"));\n } catch {\n continue;\n }\n const res = verifyBundle(input);\n if (!res.ok || !res.receipt) continue;\n const p = res.receipt.predicate;\n const fs = p.findings ?? [];\n let topSeverity: Severity | undefined;\n for (const x of fs) {\n if (!topSeverity || SEV_RANK[x.severity] < SEV_RANK[topSeverity]) topSeverity = x.severity;\n }\n entries.push({\n name: f.replace(/\\.json$/i, \"\"),\n grade: p.grade,\n costUsd: p.evidence.diffCostUsd ?? p.evidence.costUsd,\n findings: fs.length,\n topSeverity,\n scope: scopeLabel(p.scope),\n endedAt: p.session?.endedAt,\n });\n }\n // most-recent first; receipts without a timestamp sort last (by name, stable)\n entries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0) || a.name.localeCompare(b.name));\n return entries;\n}\n\n/** Render the history as an aligned text table (most-recent first). Facts only. */\nexport function renderLog(entries: readonly LogEntry[], total = entries.length): string {\n if (!entries.length) return \"No committed receipts found in .receipts/.\\n\";\n const rows = entries.map((e) => {\n const findings =\n e.findings === 0\n ? \"0\"\n : `${e.findings} ${e.topSeverity ? SEV_ICON[e.topSeverity] : \"\"}`.trim();\n return {\n date: isoDate(e.endedAt),\n grade: e.grade,\n cost: formatCostAlways(e.costUsd),\n findings,\n scope: e.scope,\n name: e.name,\n };\n });\n const w = (key: keyof (typeof rows)[number], head: string) =>\n Math.max(head.length, ...rows.map((r) => r[key].length));\n const wDate = w(\"date\", \"DATE\");\n const wGrade = Math.max(5, ...rows.map((r) => r.grade.length));\n const wCost = w(\"cost\", \"COST\");\n const wFind = w(\"findings\", \"FINDINGS\");\n const wScope = w(\"scope\", \"SCOPE\");\n const head = `${\"DATE\".padEnd(wDate)} ${\"GRADE\".padEnd(wGrade)} ${\"COST\".padEnd(wCost)} ${\"FINDINGS\".padEnd(wFind)} ${\"SCOPE\".padEnd(wScope)} RECEIPT`;\n const lines = rows.map(\n (r) =>\n `${r.date.padEnd(wDate)} ${r.grade.padEnd(wGrade)} ${r.cost.padEnd(wCost)} ${r.findings.padEnd(wFind)} ${r.scope.padEnd(wScope)} ${r.name}`,\n );\n const header = `Receipt history โ€” .receipts/ (${total} receipt${total === 1 ? \"\" : \"s\"}${entries.length < total ? `, showing ${entries.length}` : \"\"})`;\n return `${header}\\n\\n${head}\\n${lines.join(\"\\n\")}\\n\\n<cost = this change's cost (diff-scoped where available) ยท grade is each receipt's own recorded grade ยท evidence, not judgement>\\n`;\n}\n","import type { Receipt, ReceiptFinding } from \"../receipt/build.js\";\nimport { type CheckSeverity, checkForId } from \"./checks.js\";\n\n/**\n * `receipts sarif` (M63) โ€” render a receipt's findings as a SARIF 2.1.0 log so GitHub\n * code-scanning can post them **inline on the diff** and in the **Security tab** (the native\n * machine-findings surface). Unlocked by M62: file-anchored findings now carry `line`, so each\n * maps to a SARIF result with `region.startLine`. Pure transform of a verified receipt;\n * deterministic; zero model calls. It re-presents the same facts (R2) โ€” no new judgement.\n *\n * Uploading is the user's CI step (`github/codeql-action/upload-sarif`, needs\n * `security-events: write` + GHAS on private repos) โ€” see docs/sarif.md.\n */\n\nconst INFO_URI = \"https://github.com/AltimateAI/altimate-receipts\";\n\nexport interface SarifLog {\n $schema: string;\n version: \"2.1.0\";\n runs: SarifRun[];\n}\ninterface SarifRun {\n tool: { driver: { name: string; informationUri: string; version?: string; rules: SarifRule[] } };\n results: SarifResult[];\n}\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n defaultConfiguration: { level: SarifLevel };\n helpUri: string;\n}\ninterface SarifResult {\n ruleId: string;\n ruleIndex: number;\n level: SarifLevel;\n message: { text: string };\n locations?: {\n physicalLocation: {\n artifactLocation: { uri: string };\n region?: { startLine: number };\n };\n }[];\n partialFingerprints: { receiptsId: string };\n}\ntype SarifLevel = \"error\" | \"warning\" | \"note\";\n\n/** SARIF severity level for a finding's severity (the catalog/PR-comment mapping). */\nfunction levelOf(severity: CheckSeverity | undefined): SarifLevel {\n if (severity === \"critical\" || severity === \"high\") return \"error\";\n if (severity === \"medium\") return \"warning\";\n return \"note\";\n}\n\n/** Stable rule id for a finding: the merge-surface category key when it's in the catalog\n * (groups like the PR comment), else the finding-id prefix with the volatile span suffix\n * stripped (e.g. `claimed-commit-none-gen-3` โ†’ `claimed-commit-none`). */\nfunction ruleIdOf(id: string): string {\n const check = checkForId(id);\n if (check) return check.key;\n return id.replace(/-(?:tool|gen|span|s)-?\\d.*$/i, \"\") || id;\n}\n\n/** Map a finding's `filePath` to a repo-relative path: prefer the matching scope-file entry\n * (so code-scanning anchors correctly), else fall back to the basename. */\nfunction repoRelative(filePath: string, scopeFiles: readonly string[]): string {\n const base = filePath.split(\"/\").pop() ?? filePath;\n for (const sf of scopeFiles) {\n if (sf === filePath || sf.endsWith(`/${filePath}`) || filePath.endsWith(`/${sf}`)) return sf;\n if ((sf.split(\"/\").pop() ?? sf) === base) return sf;\n }\n return base;\n}\n\n/** Build a SARIF 2.1.0 log from a verified receipt. */\nexport function toSarif(receipt: Receipt): SarifLog {\n const p = receipt.predicate;\n const scopeFiles = p.scope?.files ?? [];\n const findings: ReceiptFinding[] = p.findings ?? [];\n\n // Collect rules (deduped by ruleId), tracking the worst level seen per rule.\n const ruleOrder: string[] = [];\n const rules = new Map<string, SarifRule>();\n const sevRank: Record<SarifLevel, number> = { error: 0, warning: 1, note: 2 };\n\n const results: SarifResult[] = findings.map((f) => {\n const ruleId = ruleIdOf(f.id);\n const level = levelOf(f.severity);\n const existing = rules.get(ruleId);\n if (!existing) {\n ruleOrder.push(ruleId);\n rules.set(ruleId, {\n id: ruleId,\n name: checkForId(f.id)?.label ?? ruleId,\n shortDescription: { text: checkForId(f.id)?.label ?? ruleId },\n defaultConfiguration: { level },\n helpUri: INFO_URI,\n });\n } else if (sevRank[level] < sevRank[existing.defaultConfiguration.level]) {\n existing.defaultConfiguration.level = level;\n }\n const uri = f.filePath ? repoRelative(f.filePath, scopeFiles) : undefined;\n const result: SarifResult = {\n ruleId,\n ruleIndex: ruleOrder.indexOf(ruleId),\n level,\n message: { text: f.detail ? `${f.title} โ€” ${f.detail}` : f.title },\n // Stable across commits: rule + path, never the volatile span id.\n partialFingerprints: { receiptsId: `${ruleId}::${uri ?? \"session\"}` },\n };\n if (uri) {\n result.locations = [\n {\n physicalLocation: {\n artifactLocation: { uri },\n ...(f.line ? { region: { startLine: f.line } } : {}),\n },\n },\n ];\n }\n return result;\n });\n\n // ruleIndex was assigned by first-seen order; finalize the rules array in that order.\n const ruleList = ruleOrder.map((id) => rules.get(id) as SarifRule);\n\n return {\n $schema: \"https://json.schemastore.org/sarif-2.1.0.json\",\n version: \"2.1.0\",\n runs: [\n {\n tool: {\n driver: {\n name: \"Receipts\",\n informationUri: INFO_URI,\n version: p.generator?.version,\n rules: ruleList,\n },\n },\n results,\n },\n ],\n };\n}\n","import { readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { GradeLetter } from \"../findings/grade.js\";\nimport { verifyBundle } from \"../sign/verify.js\";\nimport { checkForId } from \"./checks.js\";\n\n/**\n * `receipts stats` (M53) โ€” a dogfooding scoreboard over the committed receipts in\n * `.receipts/`. Answers the two questions a pilot owner asks: **how often did Receipts\n * run, and what did it catch?** It aggregates the receipts the tool already wrote โ€” how\n * many, the grade distribution, the flagged rate, and findings rolled up **by check\n * category** (which agent-failure modes actually show up here, ranked). Pure read + count\n * over local JSON; deterministic, zero model calls. It reports counts, never a verdict.\n *\n * This is the local measurement surface; an org-wide rollup (across repos) is a thin\n * scheduled job on top of the same per-repo numbers.\n */\n\nconst NON_RECEIPT = /(?:^|\\/)(?:asserts(?:\\.example)?|sample)\\.json$/i;\n\nexport interface ReceiptStats {\n /** how many valid committed receipts (โ‰ˆ how many PRs Receipts ran on) */\n receipts: number;\n /** files in the dir that weren't valid receipts (skipped) */\n skipped: number;\n /** receipts with โ‰ฅ1 finding */\n flagged: number;\n /** A/B/C/F counts */\n grades: Record<GradeLetter, number>;\n /** finding count rolled up by check category, ranked desc; label is human-readable */\n byCategory: { key: string; icon: string; label: string; findings: number; receipts: number }[];\n /** total findings across all receipts */\n totalFindings: number;\n}\n\n/** Aggregate the committed receipts under `dir` into a dogfooding scoreboard. */\nexport function computeStats(dir: string): ReceiptStats {\n let files: string[];\n try {\n files = readdirSync(dir).filter((f) => f.endsWith(\".json\") && !NON_RECEIPT.test(f));\n } catch {\n files = [];\n }\n const grades: Record<GradeLetter, number> = { A: 0, B: 0, C: 0, F: 0 };\n const cat = new Map<\n string,\n { icon: string; label: string; findings: number; receipts: number }\n >();\n let receipts = 0;\n let skipped = 0;\n let flagged = 0;\n let totalFindings = 0;\n\n for (const f of files) {\n let input: unknown;\n try {\n input = JSON.parse(readFileSync(join(dir, f), \"utf8\"));\n } catch {\n skipped++;\n continue;\n }\n const res = verifyBundle(input);\n if (!res.ok || !res.receipt) {\n skipped++;\n continue;\n }\n receipts++;\n const p = res.receipt.predicate;\n grades[p.grade] = (grades[p.grade] ?? 0) + 1;\n const findings = p.findings ?? [];\n if (findings.length) flagged++;\n totalFindings += findings.length;\n // which categories this receipt touched (count receipts once per category)\n const seen = new Set<string>();\n for (const finding of findings) {\n const c = checkForId(finding.id);\n if (!c) continue;\n const row = cat.get(c.key) ?? { icon: c.icon, label: c.label, findings: 0, receipts: 0 };\n row.findings++;\n if (!seen.has(c.key)) {\n row.receipts++;\n seen.add(c.key);\n }\n cat.set(c.key, row);\n }\n }\n\n const byCategory = [...cat.entries()]\n .map(([key, v]) => ({ key, ...v }))\n .sort((a, b) => b.findings - a.findings || a.label.localeCompare(b.label));\n\n return { receipts, skipped, flagged, grades, byCategory, totalFindings };\n}\n\n/** Render the scoreboard as plain text. Facts only. */\nexport function renderStats(s: ReceiptStats): string {\n if (s.receipts === 0) return \"No committed receipts found in .receipts/.\\n\";\n const out: string[] = [];\n out.push(\n `Receipts scoreboard โ€” ${s.receipts} receipt${s.receipts === 1 ? \"\" : \"s\"} in .receipts/`,\n );\n out.push(\"\");\n const pct = (n: number) => `${Math.round((100 * n) / s.receipts)}%`;\n out.push(\n `Grades: ๐ŸŸข A ${s.grades.A} ยท ๐ŸŸก B ${s.grades.B} ยท ๐ŸŸ  C ${s.grades.C} ยท ๐Ÿ”ด F ${s.grades.F}`,\n );\n out.push(`Flagged: ${s.flagged}/${s.receipts} receipts (${pct(s.flagged)}) carried โ‰ฅ1 finding`);\n out.push(\"\");\n if (s.byCategory.length === 0) {\n out.push(\"Problems caught: none โ€” every committed receipt was clean.\");\n } else {\n out.push(\n `Problems caught (${s.totalFindings} findings across ${s.byCategory.length} categories):`,\n );\n for (const c of s.byCategory) {\n out.push(\n ` ${c.icon} ${c.label.padEnd(26)} ${c.findings} finding${c.findings === 1 ? \"\" : \"s\"} in ${c.receipts} receipt${c.receipts === 1 ? \"\" : \"s\"}`,\n );\n }\n }\n if (s.skipped) {\n out.push(\"\", `<${s.skipped} non-receipt/invalid file${s.skipped === 1 ? \"\" : \"s\"} skipped>`);\n }\n out.push(\"\", \"Deterministic ยท 0 model calls ยท counts of recorded receipts, not a verdict.\");\n return `${out.join(\"\\n\")}\\n`;\n}\n","import type { FindingSet } from \"../findings/findings.js\";\nimport type { Receipt } from \"../receipt/build.js\";\nimport { redact } from \"./redact.js\";\n\n/**\n * Verifiable handoff brief (SPEC-0025 / M23). A pure projection of a session's Receipt +\n * findings into typed sections (DONE / OPEN / RISK / NEXT / PREVENT / VERIFY) the next\n * agent or human can read AND check (re-derive the subject hash). Deterministic, zero\n * model calls, no new schema. Evidence, not judgement: NEXT/PREVENT are the VERBATIM\n * fixPrompt/guardrailRule strings the findings engine already produced โ€” no invented\n * advice, no readiness verdict.\n */\n\nconst OPEN_IDS = new Set([\"unverified-change\", \"claimed-commit-none\", \"fake-green\"]);\n\nexport interface Handoff {\n subject: string;\n grade: string;\n done: { filesChanged: number; edits: number; commands: number; reads: number; testsRan: boolean };\n open: string[];\n risk: { severity: string; title: string }[];\n next: string[];\n prevent: string[];\n verify: string;\n}\n\nexport function buildHandoff(receipt: Receipt, findings: FindingSet): Handoff {\n const all = [...findings.main, ...findings.minor];\n const ev = receipt.predicate.evidence;\n return {\n subject: receipt.subject[0]?.digest.sha256 ?? \"\",\n grade: receipt.predicate.grade,\n done: {\n filesChanged: ev.filesChanged,\n edits: ev.edits,\n commands: ev.commands,\n reads: ev.reads,\n testsRan: ev.testsRan,\n },\n open: all.filter((f) => OPEN_IDS.has(f.id)).map((f) => redact(f.title)),\n risk: all\n .filter((f) => f.severity === \"high\" || f.severity === \"critical\")\n .map((f) => ({ severity: f.severity, title: redact(f.title) })),\n next: all\n .map((f) => f.fixPrompt)\n .filter((p): p is string => !!p)\n .map(redact),\n prevent: all\n .map((f) => f.guardrailRule)\n .filter((g): g is string => !!g)\n .map(redact),\n verify: `receipts rederive <transcript> # reproduces subject ${(receipt.subject[0]?.digest.sha256 ?? \"\").slice(0, 12)}โ€ฆ`,\n };\n}\n\nexport function renderHandoffMarkdown(h: Handoff): string {\n const lines: string[] = [];\n lines.push(`# Handoff โ€” Grade ${h.grade}`, \"\");\n lines.push(\n \"## โœ… Done\",\n `${h.done.filesChanged} files changed ยท ${h.done.edits} edits ยท ${h.done.commands} commands ยท ${h.done.reads} reads ยท tests ran: ${h.done.testsRan ? \"yes\" : \"no\"}`,\n \"\",\n );\n if (h.open.length) {\n lines.push(\"## ๐Ÿšง Open\", ...h.open.map((o) => `- ${o}`), \"\");\n }\n if (h.risk.length) {\n lines.push(\n \"## ๐Ÿ›ก๏ธ Risk\",\n ...h.risk.map((r) => `- **${r.severity.toUpperCase()}** ${r.title}`),\n \"\",\n );\n }\n if (h.next.length) {\n lines.push(\"## โญ๏ธ Next\", ...h.next.map((n) => `- ${n}`), \"\");\n }\n if (h.prevent.length) {\n lines.push(\"## ๐Ÿงท Prevent\", ...h.prevent.map((p) => `- ${p}`), \"\");\n }\n lines.push(\"## ๐Ÿ”Ž Verify\", `\\`${h.verify}\\``, \"\");\n return `${lines.join(\"\\n\").trimEnd()}\\n`;\n}\n"],"mappings":"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","names":["readFileSync","join","readFileSync","join","SEV_ICON","scopeLabel","readFileSync","join","head","readFileSync","readdirSync","join","NON_RECEIPT","readdirSync","readFileSync","join","join","readFileSync"]}
package/dist/index.js ADDED
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DSSE_PAYLOAD_TYPE,
4
+ branchesIn,
5
+ canonicalize,
6
+ categorize,
7
+ compareToTranscript,
8
+ copyToClipboard,
9
+ destructiveOutsideRepo,
10
+ envelopePae,
11
+ findingSurface,
12
+ pae,
13
+ rederiveFromTranscript,
14
+ renderShareMarkdown,
15
+ sliceByBranch,
16
+ toDsseEnvelope
17
+ } from "./chunk-SUAQDKUV.js";
18
+ import {
19
+ PREDICATE_TYPE,
20
+ adapterFor,
21
+ adapters,
22
+ agentIds,
23
+ anyDetected,
24
+ buildReceipt,
25
+ collectGuardrails,
26
+ deriveEvidence,
27
+ deriveFindings,
28
+ deriveSpans,
29
+ detectedAdapters,
30
+ formatCostAlways,
31
+ formatTokens,
32
+ getVersion,
33
+ gradeLetter,
34
+ hashTranscriptFile,
35
+ listSessions,
36
+ loadById,
37
+ loadSession,
38
+ redact,
39
+ redactReceipt,
40
+ renderCard,
41
+ renderGuardrailsBlock,
42
+ renderLedger,
43
+ renderList,
44
+ rootsHint,
45
+ selectForBranch,
46
+ selectSummary,
47
+ sha256Hex,
48
+ upsertGuardrailsSection,
49
+ validateReceiptShape,
50
+ verifyBundle
51
+ } from "./chunk-UHI6BGLE.js";
52
+
53
+ // src/report/prComment.ts
54
+ var CLASS_ORDER = [
55
+ "mutating",
56
+ "vcs-history",
57
+ "transport",
58
+ "test",
59
+ "build",
60
+ "read-only",
61
+ "opaque"
62
+ ];
63
+ var PR_COMMENT_MARKER = "<!-- verified-by-receipts -->";
64
+ var TRUST_DOC_URL = "https://github.com/AltimateAI/altimate-receipts/blob/main/docs/trust.md";
65
+ var ABOUT_DOC_URL = "https://github.com/AltimateAI/altimate-receipts/blob/main/docs/problems.md";
66
+ var EXPLAINER = `<sub>\u{1F916} A deterministic check that reads the coding agent's **own transcript** and reports what it changed, ran, and claimed on this PR \u2014 evidence, **not a code-quality verdict**. New here? [What the grade & checks mean \u203A](${ABOUT_DOC_URL})</sub>`;
67
+ var FEEDBACK_ISSUE_BASE = "https://github.com/AltimateAI/altimate-receipts/issues/new";
68
+ function feedbackLine(agent, grade, flagged) {
69
+ const findingLines = flagged.length ? flagged.slice(0, 8).map((f) => `- ${f.title} (\`${f.id}\`)`) : ["- (nothing was flagged \u2014 describe what you expected)"];
70
+ const body = [
71
+ "**Repo / PR:** __PR_URL__",
72
+ `**Agent:** ${agent} \xB7 **Grade:** ${grade}`,
73
+ "",
74
+ "**Flagged finding(s) being disputed:**",
75
+ ...findingLines,
76
+ "",
77
+ "**Why this is a false positive / noise:**",
78
+ "_(your notes \u2014 what should it have done instead?)_"
79
+ ].join("\n");
80
+ const title = flagged.length ? `False positive: ${flagged[0].title}` : "Receipts feedback";
81
+ const qs = `labels=${encodeURIComponent("false-positive,dogfooding")}&title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
82
+ const url = `${FEEDBACK_ISSUE_BASE}?${qs}`;
83
+ return `<sub>\u{1F4AC} Wrong call or noise? **[Report it \u2014 prefilled \u203A](${url})** (only the "why" is left to write) \xB7 or use the \u{1F642} reaction button on this comment to vote \u{1F44D} / \u{1F44E}. It tunes the checks.</sub>`;
84
+ }
85
+ var GRADE_DOT = { A: "\u{1F7E2}", B: "\u{1F7E1}", C: "\u{1F7E0}", F: "\u{1F534}" };
86
+ var VERDICT = {
87
+ A: "Safe to merge",
88
+ B: "Minor things to check",
89
+ C: "Needs a close review",
90
+ F: "Do not merge without review"
91
+ };
92
+ var CALLOUT = {
93
+ A: null,
94
+ B: "NOTE",
95
+ C: "WARNING",
96
+ F: "CAUTION"
97
+ };
98
+ var ICON = { critical: "\u26D4", high: "\u26A0\uFE0F", medium: "\u{1F50D}", low: "\xB7" };
99
+ var ORDER = { critical: 0, high: 1, medium: 2, low: 3 };
100
+ function renderPrComment(receipt, opts = {}) {
101
+ const p = receipt.predicate;
102
+ const ev = p.evidence;
103
+ const operatorCount = p.findings.filter((f) => findingSurface(f.id) === "operator").length;
104
+ const mergeFindings = p.findings.filter(
105
+ (f) => findingSurface(f.id) === "merge" && !(f.id.startsWith("destructive-") && destructiveOutsideRepo(f.title))
106
+ );
107
+ const g = gradeLetter(mergeFindings.filter((f) => f.confidence >= 0.5));
108
+ const main = mergeFindings.filter((f) => f.severity !== "low");
109
+ const cats = categorize(main);
110
+ const out = [];
111
+ out.push(PR_COMMENT_MARKER);
112
+ out.push(`### \u{1F9FE} Verified by Receipts \xB7 ${GRADE_DOT[g]} Grade ${g} \u2014 ${VERDICT[g]}`);
113
+ out.push("");
114
+ out.push(EXPLAINER);
115
+ out.push("");
116
+ if (main.length) {
117
+ const co = CALLOUT[g] ?? "WARNING";
118
+ const what = cats.flagged.length ? cats.flagged.map((fl) => fl.check.label).join(", ") : `${main.length} finding${main.length === 1 ? "" : "s"}`;
119
+ out.push(`> [!${co}]`);
120
+ out.push(
121
+ `> **${cats.flagged.length || main.length} of ${cats.total} checks flagged:** ${what}.`
122
+ );
123
+ out.push("");
124
+ const sorted = [...main].sort(
125
+ (a, b) => ORDER[a.severity] - ORDER[b.severity] || b.score - a.score
126
+ );
127
+ for (const f of sorted.slice(0, 12)) {
128
+ out.push(findingLine(f));
129
+ }
130
+ if (main.length > 12) {
131
+ out.push(`- _\u2026and ${main.length - 12} more \u2014 see the full breakdown_`);
132
+ }
133
+ out.push("");
134
+ }
135
+ out.push(statStrip(cats, ev, p));
136
+ out.push("");
137
+ const feedback = feedbackLine(p.session.agent, g, main);
138
+ out.push(fullBreakdown(p, ev, cats, operatorCount, opts, feedback));
139
+ return `${out.join("\n")}
140
+ `;
141
+ }
142
+ function costStat(ev) {
143
+ return ev.diffCostUsd != null ? `\u{1F4B0} \u2248 ${formatCostAlways(ev.diffCostUsd)} _(this change)_` : "";
144
+ }
145
+ function statStrip(cats, ev, p) {
146
+ const checks = cats.flagged.length ? `\u26A0\uFE0F **${cats.flagged.length}/${cats.total} flagged**` : `\u2705 **${cats.total}/${cats.total} checks clear**`;
147
+ const files = p.scope?.kind === "diff" ? p.scope.files ?? [] : [];
148
+ const parts = [checks];
149
+ if (files.length) parts.push(`\u{1F4C4} ${files.length} file${files.length === 1 ? "" : "s"}`);
150
+ parts.push(testsCell(ev));
151
+ const cost = costStat(ev);
152
+ if (cost) parts.push(cost);
153
+ parts.push(`_${p.session.agent}_`);
154
+ return parts.join(" \xB7 ");
155
+ }
156
+ function changedFilesBlock(files) {
157
+ if (files.length <= 12) {
158
+ return `**Changed** ${files.map((f) => `\`${f}\``).join(", ")}`;
159
+ }
160
+ const byDir = /* @__PURE__ */ new Map();
161
+ for (const f of files) {
162
+ const top = f.includes("/") ? `${f.split("/")[0]}/` : "(root)";
163
+ byDir.set(top, (byDir.get(top) ?? 0) + 1);
164
+ }
165
+ const dirs = [...byDir.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8).map(([d, n]) => `\`${d}\` ${n}`).join(" \xB7 ");
166
+ const moreDirs = byDir.size > 8 ? ` \xB7 _+${byDir.size - 8} more dirs_` : "";
167
+ const sample = files.slice(0, 60).map((f) => `\`${f}\``).join(", ");
168
+ const moreFiles = files.length > 60 ? ` _\u2026+${files.length - 60} more (full set in the receipt JSON)_` : "";
169
+ return [
170
+ `**Changed ${files.length} files** by area: ${dirs}${moreDirs}`,
171
+ "",
172
+ "<details><summary>file list</summary>",
173
+ "",
174
+ `${sample}${moreFiles}`,
175
+ "",
176
+ "</details>"
177
+ ].join("\n");
178
+ }
179
+ function fullBreakdown(p, ev, cats, operatorCount, opts, feedback) {
180
+ const inner = [];
181
+ const files = p.scope?.kind === "diff" ? p.scope.files ?? [] : [];
182
+ if (files.length) inner.push(changedFilesBlock(files), "");
183
+ const ledger = renderLedger(ev.claims ?? []);
184
+ if (ledger) inner.push(ledger, "");
185
+ inner.push(
186
+ `**Risk checks** \u2014 ${cats.flagged.length} flagged \xB7 ${cats.cleared.length} clear`,
187
+ "",
188
+ catalogTable(cats),
189
+ ""
190
+ );
191
+ const cl = diffCostLine(ev);
192
+ if (cl) inner.push(cl);
193
+ inner.push(`<sub>${effortLine(ev, operatorCount)}</sub>`);
194
+ const signed = opts.signed ? `\u{1F50F} Signed (Sigstore \u2192 Rekor)${opts.attestationUrl ? ` \xB7 [attestation](${opts.attestationUrl})` : ""} \xB7 ` : "";
195
+ inner.push(
196
+ `<sub>${signed}Re-derivable (L1: \`receipts verify <receipt> --transcript <t>\`) \xB7 deterministic \xB7 0 model calls \xB7 **evidence, not judgement** \xB7 [trust model](${TRUST_DOC_URL}).</sub>`
197
+ );
198
+ inner.push(feedback);
199
+ return [
200
+ "<details><summary>Full breakdown \u2014 files, checks, cost, provenance</summary>",
201
+ "",
202
+ ...inner,
203
+ "",
204
+ "</details>"
205
+ ].join("\n");
206
+ }
207
+ function diffCostLine(ev) {
208
+ if (ev.diffCostUsd == null) return null;
209
+ const turns = ev.diffTurns ?? 0;
210
+ const t = `${turns} turn${turns === 1 ? "" : "s"}`;
211
+ return `**Cost** \u2248 ${formatCostAlways(ev.diffCostUsd)} \xB7 ${formatTokens(ev.diffTokens ?? 0)} tokens \xB7 ${t} _(this change \u2014 upper bound; the turns that edited these files)_`;
212
+ }
213
+ function testsCell(ev) {
214
+ const tm = ev.testMetrics;
215
+ if (tm) {
216
+ const seg = [
217
+ tm.passed != null ? `${tm.passed} passed` : null,
218
+ tm.failed ? `**${tm.failed} failed**` : null,
219
+ tm.skipped ? `${tm.skipped} skipped` : null
220
+ ].filter(Boolean).join(", ");
221
+ const ok = !tm.failed;
222
+ return `${ok ? "\u2705" : "\u26A0\uFE0F"} ${seg || tm.exitStatus}`;
223
+ }
224
+ return ev.testsRan ? "\u2705 ran" : "\u2014 no test run detected";
225
+ }
226
+ function catalogTable(cats) {
227
+ const sev = new Map(cats.flagged.map((fl) => [fl.check.key, fl]));
228
+ const rows = [...cats.flagged.map((fl) => fl.check), ...cats.cleared].map((c) => {
229
+ const fl = sev.get(c.key);
230
+ const result = fl ? `${ICON[fl.severity]} ${fl.count} flagged` : "\u2705 clear";
231
+ return `| ${c.icon} ${c.label} | ${result} |`;
232
+ });
233
+ rows.sort((a, b) => (a.includes("\u2705 clear") ? 1 : 0) - (b.includes("\u2705 clear") ? 1 : 0));
234
+ return ["| Check | Result |", "| :-- | :-- |", ...rows].join("\n");
235
+ }
236
+ function effortLine(ev, operatorCount) {
237
+ const cbc = ev.commandsByClass;
238
+ const brk = cbc ? ` _(${CLASS_ORDER.filter((c) => cbc[c]).map((c) => `${cbc[c]} ${c}`).join(", ")})_` : "";
239
+ const op = operatorCount > 0 ? ` \xB7 ${operatorCount} efficiency/behaviour finding${operatorCount === 1 ? "" : "s"}` : "";
240
+ return `Session totals (the whole run, not this diff): ${ev.edits} edits \xB7 ${ev.commands} commands${brk} \xB7 ${formatCostAlways(ev.costUsd)} \xB7 ${formatTokens(ev.tokens.total)} tokens${op}.`;
241
+ }
242
+ function findingLine(f) {
243
+ const tag = f.impactLabel ? ` \u2014 ${f.impactLabel}` : "";
244
+ const loc = f.filePath ? ` (\`${f.filePath}${f.line ? `:${f.line}` : ""}\`)` : "";
245
+ const head = `- ${ICON[f.severity]} **${f.title}**${tag}${loc}`;
246
+ return f.detail ? `${head}
247
+ \u21B3 ${f.detail}` : head;
248
+ }
249
+ export {
250
+ DSSE_PAYLOAD_TYPE,
251
+ PREDICATE_TYPE,
252
+ PR_COMMENT_MARKER,
253
+ adapterFor,
254
+ adapters,
255
+ agentIds,
256
+ anyDetected,
257
+ branchesIn,
258
+ buildReceipt,
259
+ canonicalize,
260
+ collectGuardrails,
261
+ compareToTranscript,
262
+ copyToClipboard,
263
+ deriveEvidence,
264
+ deriveFindings,
265
+ deriveSpans,
266
+ detectedAdapters,
267
+ envelopePae,
268
+ getVersion,
269
+ gradeLetter,
270
+ hashTranscriptFile,
271
+ listSessions,
272
+ loadById,
273
+ loadSession,
274
+ pae,
275
+ redact,
276
+ redactReceipt,
277
+ rederiveFromTranscript,
278
+ renderCard,
279
+ renderGuardrailsBlock,
280
+ renderList,
281
+ renderPrComment,
282
+ renderShareMarkdown,
283
+ rootsHint,
284
+ selectForBranch,
285
+ selectSummary,
286
+ sha256Hex,
287
+ sliceByBranch,
288
+ toDsseEnvelope,
289
+ upsertGuardrailsSection,
290
+ validateReceiptShape,
291
+ verifyBundle
292
+ };
293
+ //# sourceMappingURL=index.js.map