altimate-receipts 0.5.0 → 0.5.2

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.
@@ -2,6 +2,7 @@
2
2
  import {
3
3
  buildReceipt,
4
4
  commandOf,
5
+ cwdAtFirstGit,
5
6
  deriveEvidence,
6
7
  deriveFindings,
7
8
  deriveSpans,
@@ -18,7 +19,7 @@ import {
18
19
  redactReceipt,
19
20
  rewritesHistory,
20
21
  touchedPaths
21
- } from "./chunk-2QTR3AF4.js";
22
+ } from "./chunk-EYM5WETZ.js";
22
23
 
23
24
  // src/receipt/canonical.ts
24
25
  function canonicalize(value) {
@@ -257,7 +258,10 @@ function gitTouchesDiff(command, files) {
257
258
  }
258
259
  return false;
259
260
  }
260
- function keepUnderDiff(f, files, commandFor) {
261
+ function keepUnderDiff(f, files, commandFor, locusFor) {
262
+ if (locusFor?.(f) === "elsewhere") {
263
+ return false;
264
+ }
261
265
  if (isProcessFinding(f.id)) {
262
266
  return true;
263
267
  }
@@ -309,15 +313,34 @@ function narrowEffort(sliceDerived, files) {
309
313
  const eff = diffEffort(sliceDerived, files);
310
314
  return eff.turns > 0 ? eff : null;
311
315
  }
312
- function applyDiffScope(derived, findings, files) {
316
+ function applyDiffScope(derived, findings, files, projectPath) {
313
317
  const spanCmd = /* @__PURE__ */ new Map();
318
+ const spanCwd = /* @__PURE__ */ new Map();
314
319
  for (const s of derived.spans) {
315
320
  if (s.spanId) {
316
321
  spanCmd.set(s.spanId, commandOf(s.input));
322
+ if (s.cwd) {
323
+ spanCwd.set(s.spanId, s.cwd);
324
+ }
317
325
  }
318
326
  }
319
327
  const cmdOf = (f) => f.evidenceSpanId ? spanCmd.get(f.evidenceSpanId) : void 0;
320
- const keep = (f) => keepUnderDiff(f, files, cmdOf);
328
+ const locusOf = (f) => {
329
+ if (!projectPath || !f.evidenceSpanId) {
330
+ return void 0;
331
+ }
332
+ const base2 = spanCwd.get(f.evidenceSpanId);
333
+ const state = cwdAtFirstGit(spanCmd.get(f.evidenceSpanId) ?? "", base2);
334
+ if (state.kind === "unknown") {
335
+ return "elsewhere";
336
+ }
337
+ const at = state.kind === "known" ? state.path : base2;
338
+ if (!at) {
339
+ return void 0;
340
+ }
341
+ return at === projectPath || at.startsWith(`${projectPath}/`) ? "here" : "elsewhere";
342
+ };
343
+ const keep = (f) => keepUnderDiff(f, files, cmdOf, locusOf);
321
344
  const scopedFindings = {
322
345
  main: findings.main.filter(keep),
323
346
  minor: findings.minor.filter(keep)
@@ -404,7 +427,7 @@ async function rederiveFromTranscript(path, opts = {}) {
404
427
  let derived = deriveSpans(session);
405
428
  let findings = deriveFindings(derived);
406
429
  if (scope?.kind === "diff" && scope.files) {
407
- const scoped = applyDiffScope(derived, findings, scope.files);
430
+ const scoped = applyDiffScope(derived, findings, scope.files, session.projectPath);
408
431
  derived = scoped.derived;
409
432
  findings = scoped.findings;
410
433
  if (scope.branch) {
@@ -546,4 +569,4 @@ export {
546
569
  rederiveFromTranscript,
547
570
  compareToTranscript
548
571
  };
549
- //# sourceMappingURL=chunk-WISVSYA7.js.map
572
+ //# sourceMappingURL=chunk-GOLRNSZT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/receipt/canonical.ts","../src/share/clipboard.ts","../src/share/markdown.ts","../src/sign/envelope.ts","../src/trace/diffScope.ts","../src/findings/surface.ts","../src/trace/slice.ts","../src/sign/rederive.ts","../src/report/checks.ts"],"sourcesContent":["/**\n * Canonical JSON (RFC 8785-style): object keys sorted lexicographically, minimal\n * whitespace, arrays in order. Used now for deterministic hashing/equality and\n * reused verbatim as M4's DSSE signing payload, so a Receipt and its signature\n * always agree on the exact bytes.\n *\n * Scope note: this is a pragmatic subset — all numbers in a Receipt are integers\n * or values we round before emitting, so JSON.stringify's number formatting is\n * already stable. We do not implement RFC 8785's full number canonicalization.\n */\nexport function canonicalize(value: unknown): string {\n return serialize(value);\n}\n\nfunction serialize(value: unknown): string {\n if (value === null || typeof value === \"number\" || typeof value === \"boolean\") {\n return JSON.stringify(value);\n }\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(serialize).join(\",\")}]`;\n }\n if (typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n const body = keys.map((k) => `${JSON.stringify(k)}:${serialize(obj[k])}`).join(\",\");\n return `{${body}}`;\n }\n // undefined / function / symbol — not valid Receipt content\n return \"null\";\n}\n","import { spawnSync } from \"node:child_process\";\n\ninterface ClipboardTool {\n cmd: string;\n args: string[];\n}\n\n/** OS clipboard tools, by platform, in preference order. */\nfunction candidates(): ClipboardTool[] {\n if (process.platform === \"darwin\") {\n return [{ cmd: \"pbcopy\", args: [] }];\n }\n if (process.platform === \"win32\") {\n return [{ cmd: \"clip\", args: [] }];\n }\n // linux / other: Wayland first, then X11\n return [\n { cmd: \"wl-copy\", args: [] },\n { cmd: \"xclip\", args: [\"-selection\", \"clipboard\"] },\n { cmd: \"xsel\", args: [\"--clipboard\", \"--input\"] },\n ];\n}\n\n/**\n * Best-effort copy to the OS clipboard. Returns true on success, false if no tool\n * is available or the copy failed — the caller prints a note and still exits 0.\n * No npm dependency; shells out to the platform tool.\n */\nexport function copyToClipboard(text: string): boolean {\n for (const { cmd, args } of candidates()) {\n try {\n const res = spawnSync(cmd, args, { input: text, stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n if (!res.error && res.status === 0) {\n return true;\n }\n } catch {\n // try the next tool\n }\n }\n return false;\n}\n","import type { FindingSet, Severity } from \"../findings/findings.js\";\nimport { type GradeLetter, gradeLetter } from \"../findings/grade.js\";\nimport type { DerivedSummary } from \"../findings/spans.js\";\nimport { deriveEvidence } from \"../receipt/build.js\";\nimport type { Session, SessionSummary } from \"../trace/types.js\";\nimport { redact } from \"./redact.js\";\n\nconst VERDICT: Record<GradeLetter, string> = {\n F: \"DO NOT MERGE WITHOUT REVIEW\",\n C: \"NEEDS A CLOSE REVIEW\",\n B: \"MINOR THINGS TO CHECK\",\n A: \"LOOKS CLEAN\",\n};\n\nconst ICON: Record<Severity, string> = {\n critical: \"⛔\",\n high: \"⚠️\",\n medium: \"🔍\",\n low: \"·\",\n};\n\nconst base = (p: string): string => p.split(\"/\").pop() ?? p;\n\n/**\n * A redacted, paste-ready Markdown summary of a session — the `--share` artifact.\n * Pure function of the derived data; all user-text is passed through `redact()`.\n */\nexport function renderShareMarkdown(args: {\n summary: SessionSummary;\n session: Session;\n derived: DerivedSummary;\n findings: FindingSet;\n}): string {\n const { summary, session, derived, findings } = args;\n const { main, minor } = findings;\n const g = gradeLetter(main);\n const ev = deriveEvidence(session, derived);\n\n const counts =\n ([\"critical\", \"high\", \"medium\"] as const)\n .map((s) => {\n const n = main.filter((f) => f.severity === s).length;\n return n ? `${n} ${s}` : null;\n })\n .filter(Boolean)\n .join(\" · \") || \"no findings\";\n\n const title = redact(summary.title || \"untitled session\");\n const out: string[] = [];\n out.push(`## 🧾 Receipt — ${title} · Grade ${g}`);\n out.push(\"\");\n out.push(`**${VERDICT[g]}** · ${counts} · _${summary.source}_`);\n out.push(\"\");\n\n if (main.length) {\n out.push(\"### Findings\");\n const order: Record<Severity, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n const sorted = [...main].sort(\n (a, b) => order[a.severity] - order[b.severity] || b.score - a.score,\n );\n for (const f of sorted.slice(0, 12)) {\n const tag = f.impactLabel ? ` — ${redact(f.impactLabel)}` : \"\";\n const loc = f.filePath ? ` (\\`${redact(base(f.filePath))}\\`)` : \"\";\n out.push(`- ${ICON[f.severity]} **${redact(f.title)}**${tag}${loc}`);\n }\n if (minor.length) {\n out.push(`- _+${minor.length} minor (collapsed)_`);\n }\n out.push(\"\");\n }\n\n out.push(\"### Evidence\");\n out.push(\n `${ev.filesChanged} files · ${ev.edits} edits · ${ev.commands} commands · ` +\n `${ev.testsRan ? \"tests ran ✓\" : \"no test run detected\"} · ` +\n `${ev.destructiveOps} destructive ops`,\n );\n out.push(\"\");\n out.push(\"_Verified by Receipts · deterministic · 0 model calls · evidence, not judgement_\");\n return `${out.join(\"\\n\")}\\n`;\n}\n","import type { Receipt } from \"../receipt/build.js\";\nimport { canonicalize } from \"../receipt/canonical.js\";\n\n/** in-toto payloads ride in DSSE with this type. */\nexport const DSSE_PAYLOAD_TYPE = \"application/vnd.in-toto+json\";\n\nexport interface DsseSignature {\n sig: string;\n keyid?: string;\n}\n\nexport interface DsseEnvelope {\n payloadType: string;\n /** base64 of the canonical Receipt JSON */\n payload: string;\n signatures: DsseSignature[];\n}\n\n/**\n * DSSE Pre-Authentication Encoding (PAE) — the exact bytes a signer signs:\n * \"DSSEv1\" SP len(payloadType) SP payloadType SP len(payload) SP payload\n * Lengths count UTF-8 bytes; `payload` here is the raw (un-base64) payload.\n */\nexport function pae(payloadType: string, payload: string): Buffer {\n const typeBytes = Buffer.from(payloadType, \"utf8\");\n const bodyBytes = Buffer.from(payload, \"utf8\");\n const header = `DSSEv1 ${typeBytes.length} ${payloadType} ${bodyBytes.length} `;\n return Buffer.concat([Buffer.from(header, \"utf8\"), bodyBytes]);\n}\n\n/**\n * Wrap a Receipt as an UNSIGNED DSSE envelope. The payload is the canonical\n * Receipt JSON (so signature and content always agree on the exact bytes). The\n * signature array is filled by the signer (the GitHub Action), not here.\n */\nexport function toDsseEnvelope(receipt: Receipt): DsseEnvelope {\n const canonical = canonicalize(receipt);\n return {\n payloadType: DSSE_PAYLOAD_TYPE,\n payload: Buffer.from(canonical, \"utf8\").toString(\"base64\"),\n signatures: [],\n };\n}\n\n/** The PAE bytes for an envelope (what a verifier checks the signature against). */\nexport function envelopePae(env: DsseEnvelope): Buffer {\n const raw = Buffer.from(env.payload, \"base64\").toString(\"utf8\");\n return pae(env.payloadType, raw);\n}\n","import { spawnSync } from \"node:child_process\";\nimport { estimateCost } from \"../findings/cost.js\";\nimport type { Finding, FindingSet } from \"../findings/findings.js\";\nimport {\n cwdAtFirstGit,\n destroysGitData,\n isNoVerify,\n parseGitInvocations,\n rewritesHistory,\n touchedPaths,\n} from \"../findings/gitParse.js\";\nimport { type DerivedSummary, destructiveMatch } from \"../findings/spans.js\";\nimport { destructiveOutsideRepo, regenerableReceiptRm } from \"../findings/surface.js\";\nimport { commandOf, filePathOf, isEditTool } from \"../findings/toolRoles.js\";\n\n/**\n * Diff-scoping for `receipts pr` (SPEC-0013). The PR's changed-file set is read from\n * git at produce time and recorded in `predicate.scope.files`; every scoping decision\n * below is a pure function of that file list (+ the repo-root-free destructive\n * heuristic), so a verifier reproduces the exact scoped receipt from the recorded\n * `files` alone — no git at verify time. That's what keeps L1 re-derivation intact.\n */\n\nfunction git(args: string[], cwd?: string): string | null {\n const r = spawnSync(\"git\", args, { encoding: \"utf8\", cwd });\n return r.status === 0 ? r.stdout : null;\n}\n\nexport interface DiffResult {\n /** the ref the diff was taken against */\n base: string;\n /** changed files, sorted, repo-relative */\n files: string[];\n repoRoot: string;\n}\n\n/** Receipts' own bookkeeping dir. A receipt must NOT scope over `.receipts/` — else\n * committing the receipt changes the diff, which re-scopes the next receipt: an endless\n * regeneration loop in the pre-push hook. Excluded from the diff scope here AND in the\n * Action's scope-honesty check (action/verified-by.mjs) so the two stay consistent. */\nexport const RECEIPTS_DIR_RE = /(?:^|\\/)\\.receipts\\//;\n\n/**\n * The PR's changed files via `git diff --name-only <base>...HEAD`, sorted, with the\n * `.receipts/` bookkeeping dir excluded (see RECEIPTS_DIR_RE). `base` defaults to the\n * default branch (origin/HEAD → main). Returns null when no repo, base, or non-empty\n * diff is resolvable (caller falls back honestly).\n */\nexport function changedFiles(baseOverride?: string): DiffResult | null {\n const root = git([\"rev-parse\", \"--show-toplevel\"])?.trim();\n if (!root) {\n return null;\n }\n let base = baseOverride;\n if (!base) {\n const sym = git([\"symbolic-ref\", \"refs/remotes/origin/HEAD\"], root)?.trim();\n base = sym ? sym.replace(\"refs/remotes/\", \"\") : \"main\";\n }\n let out = git([\"diff\", \"--name-only\", `${base}...HEAD`], root);\n if (out === null && !baseOverride) {\n // base may be unfetched (e.g. origin/main absent locally) — try local main.\n out = git([\"diff\", \"--name-only\", \"main...HEAD\"], root);\n if (out !== null) {\n base = \"main\";\n }\n }\n if (out === null) {\n return null;\n }\n const files = out\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean)\n .filter((f) => !RECEIPTS_DIR_RE.test(f)) // a receipt never scopes over .receipts/\n .sort();\n if (files.length === 0) {\n return null; // nothing to scope to (or a receipts-only diff) → caller falls back\n }\n return { base, files, repoRoot: root };\n}\n\n/** Does a finding's file path belong to the changed-file set? Matches exact, path\n * suffix, or basename (a PR's diff is small; basename collisions are unlikely and\n * fail toward surfacing). */\nexport function inDiff(filePath: string, files: readonly string[]): boolean {\n const base = filePath.split(\"/\").pop();\n for (const d of files) {\n if (d === filePath || d.endsWith(`/${filePath}`) || filePath.endsWith(`/${d}`)) {\n return true;\n }\n if (base && d.split(\"/\").pop() === base) {\n return true;\n }\n }\n return false;\n}\n\n// Integrity findings that are about the *act*, not a path — kept regardless of the\n// diff (a `curl | sh`, a fabricated tool call, a `--no-verify` are merge-relevant\n// even though they name no changed file). `force-push` is NOT here: it's a git op\n// scoped by its touched paths below (it touches none ⇒ session hygiene, not a merge\n// risk for this change).\n// Path-free integrity findings kept regardless of the diff — a `curl|sh` or a\n// fabricated/malformed tool call is a session-integrity problem no matter which files\n// changed. `hook-bypass` is NOT here: it's scoped below (a `push --no-verify` only skips\n// pre-push hooks ⇒ session hygiene, not a merge risk for this diff).\nconst PROCESS_PREFIXES = [\"pipe-sh\", \"tool-fabricated\", \"tool-malformed-args\"];\nconst isProcessFinding = (id: string): boolean =>\n PROCESS_PREFIXES.some((p) => id === p || id.startsWith(`${p}-`));\nconst isDestructive = (id: string): boolean => id.startsWith(\"destructive-\");\nconst isGitProcess = (id: string): boolean =>\n id.startsWith(\"force-push\") || id.startsWith(\"destructive-git\");\n\n/** True when the **destructive** git op in this command touches a diff file. Only the\n * destructive / history-rewriting invocation is judged — a benign sibling clause in the\n * same compound command (e.g. `git add <diff-file> && git reset --hard <ref>`) must NOT\n * make the unrelated reset look diff-relevant. Ref/history/worktree-wide ops\n * (`reset --hard <branch>`, `push -f`, `branch -D`) have no touched path ⇒ false ⇒\n * session hygiene, not a merge risk for this change. */\n/** True when every `--no-verify` in this command is on a `push` (no `commit --no-verify`).\n * A `push --no-verify` skips only the pre-push hooks (no committed content changes), so it\n * is session hygiene, not a merge risk for this diff. A `commit --no-verify` skipped the\n * pre-commit checks on committed content ⇒ NOT push-only ⇒ kept. */\nfunction hookBypassIsPushOnly(command: string): boolean {\n const noVerify = parseGitInvocations(command).filter(isNoVerify);\n return noVerify.length > 0 && noVerify.every((inv) => inv.subcommand === \"push\");\n}\n\nfunction gitTouchesDiff(command: string, files: readonly string[]): boolean {\n for (const inv of parseGitInvocations(command)) {\n if (!destroysGitData(inv) && !rewritesHistory(inv)) {\n continue; // a `git add`/`commit`/`checkout <branch>` clause is not the destructive op\n }\n if (touchedPaths(inv).some((p) => inDiff(p, files))) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Keep a finding under a diff scope:\n * - path-free integrity findings (hook-bypass, pipe-sh, fabricated/malformed) — always,\n * - a git process/destructive op only when its touched paths fall in the diff\n * (`reset --hard <branch>`/`push -f` touch nothing ⇒ dropped to the session card),\n * - a non-git destructive whose target is a repo path (not a `$TMP`/`.receipts` scratch),\n * - any other finding about a changed file.\n * Pure function of the finding + the recorded file list (+ the finding's own command,\n * itself re-derived from the transcript) ⇒ reproducible at verify.\n */\nexport function keepUnderDiff(\n f: Pick<Finding, \"id\" | \"title\"> & { filePath?: string; evidenceSpanId?: string },\n files: readonly string[],\n commandFor?: (f: Pick<Finding, \"id\" | \"evidenceSpanId\">) => string | undefined,\n locusFor?: (f: Pick<Finding, \"id\" | \"evidenceSpanId\">) => \"here\" | \"elsewhere\" | undefined,\n): boolean {\n // Cross-repo bleed (SPEC-0069 addendum, observed live): a session that also ran\n // `git commit --no-verify` in ANOTHER repo (`cd /other && git commit --no-verify`)\n // must not flag THIS repo's diff receipt. The locus is resolved by the caller from\n // transcript data only (span cwd + cd tracking), so the drop re-derives with no\n // git at verify time; \"elsewhere\" includes unresolvable-cd uncertainty (under-claim).\n if (locusFor?.(f) === \"elsewhere\") {\n return false;\n }\n if (isProcessFinding(f.id)) {\n return true;\n }\n // hook-bypass: a `push --no-verify` skips only pre-push hooks (no code change) ⇒ session\n // hygiene, dropped from the diff; a `commit --no-verify` (or an unresolvable command) is\n // kept — it may have skipped pre-commit checks on the committed change.\n if (f.id === \"hook-bypass\" || f.id.startsWith(\"hook-bypass-\")) {\n const cmd = commandFor?.(f);\n return cmd ? !hookBypassIsPushOnly(cmd) : true;\n }\n // git ref/history surgery is a merge risk only if it touched a changed file.\n if (isGitProcess(f.id)) {\n const cmd = commandFor?.(f);\n return cmd ? gitTouchesDiff(cmd, files) : false;\n }\n if (isDestructive(f.id)) {\n // scratch (`/tmp`) and the tool's own regenerable `.receipts/*.json` are both\n // out-of-scope for \"did this change do damage?\" — drop either from the diff.\n if (destructiveOutsideRepo(f.title) || regenerableReceiptRm(f.title)) {\n return false;\n }\n // a git destructive (`git reset --hard <branch>`, `git rm`) only counts when it hit\n // the diff; a non-git filesystem removal (`rm -rf src/old`) keeps the repo-path\n // behaviour. The command comes from the span resolver, falling back to the title's\n // clause (`Destructive op: <cmd>`), so this holds even without a resolver.\n const cmd =\n commandFor?.(f) ?? f.title.replace(/^Destructive op:\\s*/i, \"\").replace(/\\s*×\\d+\\s*$/, \"\");\n if (/(^|[\\s;&|])git\\s/.test(cmd)) {\n return gitTouchesDiff(cmd, files);\n }\n return true;\n }\n return f.filePath ? inDiff(f.filePath, files) : false;\n}\n\nexport interface ScopedData {\n derived: DerivedSummary;\n findings: FindingSet;\n}\n\n/**\n * Cost/tokens of just the generation turns that edited a file in the diff — \"what\n * producing *this change* cost\", versus the whole-session total. Each edit tool span\n * links to the assistant turn that emitted it via `parentSpanId`; we collect those\n * generations and sum their recorded/estimated cost + tokens. Pure function of\n * `derived.spans` (re-derived from the transcript) + `files` ⇒ reproducible at verify.\n *\n * Honest bound: a turn that edited a diff file *and* others is counted whole, and the\n * turn's cost includes its shared context overhead — so this is an upper estimate of the\n * diff's marginal cost, not a precise split. It is always ≤ the session total and, in a\n * session that produced several PRs, far below it.\n */\nexport function diffEffort(\n derived: DerivedSummary,\n files: readonly string[],\n): { cost: number; tokens: number; turns: number } {\n const editedGens = new Set<string>();\n for (const s of derived.spans) {\n if (s.kind !== \"tool\" || !s.parentSpanId || !isEditTool(s.name)) {\n continue;\n }\n const fp = filePathOf(s.input);\n if (fp && inDiff(fp, files)) {\n editedGens.add(s.parentSpanId);\n }\n }\n let cost = 0;\n let tokens = 0;\n for (const s of derived.spans) {\n if (s.kind === \"generation\" && editedGens.has(s.spanId)) {\n // recorded cost when present, else estimate from the turn's tokens + model (the\n // generation span's name is the model id) — the same basis as the session total.\n cost += s.cost || estimateCost(s.tokens, s.name);\n tokens += s.tokens?.total ?? 0;\n }\n }\n return { cost, tokens, turns: editedGens.size };\n}\n\n/**\n * Branch-narrowed effort (SPEC-0068 R4): in a session that produced several PRs, the\n * whole-session `diffEffort` counts every turn that ever touched a hot file (cli.ts,\n * README) — observed 26× inflation on a marathon session. When the session carries the\n * receipt branch's turns, the honest bound is branch turns ∩ diff-file edits. Returns\n * null when there is no slice or the slice has zero diff-file-editing turns (e.g.\n * Bash-only writes) — callers then keep the whole-session bound and must NOT record\n * `scope.branch`, so the receipt always states how its effort was computed. Shared by\n * produce (`receipts pr`) and verify (rederive) so the bytes match (L1).\n */\nexport function narrowEffort(\n sliceDerived: DerivedSummary | null,\n files: readonly string[],\n): { cost: number; tokens: number; turns: number } | null {\n if (!sliceDerived) {\n return null;\n }\n const eff = diffEffort(sliceDerived, files);\n return eff.turns > 0 ? eff : null;\n}\n\n/**\n * Apply a diff scope to derived evidence + findings. Scopes the risk-relevant\n * evidence (`filesChanged`, `destructiveOps`) to the change and computes the diff's own\n * cost (`diffCostUsd`/`diffTokens`/`diffTurns`); leaves whole-session effort metrics\n * (`edits`/`commands`/`reads`/total tokens/cost) intact for the footer. Deterministic;\n * uses only `files` so re-derivation reproduces it from `predicate.scope.files`.\n */\nexport function applyDiffScope(\n derived: DerivedSummary,\n findings: FindingSet,\n files: readonly string[],\n projectPath?: string,\n): ScopedData {\n // evidenceSpanId → the span's command/cwd, so a git process/destructive finding can\n // be attributed to the diff by its touched paths and its repo. Built from\n // `derived.spans` (re-derived from the transcript) so the scope stays a pure\n // function of (derived, findings, files, projectPath) — all transcript-derived.\n const spanCmd = new Map<string, string>();\n const spanCwd = new Map<string, string>();\n for (const s of derived.spans) {\n if (s.spanId) {\n spanCmd.set(s.spanId, commandOf(s.input));\n if (s.cwd) {\n spanCwd.set(s.spanId, s.cwd);\n }\n }\n }\n const cmdOf = (f: Pick<Finding, \"evidenceSpanId\">): string | undefined =>\n f.evidenceSpanId ? spanCmd.get(f.evidenceSpanId) : undefined;\n // Did this finding's command actually run in the session's own project?\n // `cwdAtFirstGit` tracks `cd` clauses inside compounds; outside or uncertain ⇒\n // \"elsewhere\" (another repo's process risk — drop from the diff receipt).\n const locusOf = (f: Pick<Finding, \"evidenceSpanId\">): \"here\" | \"elsewhere\" | undefined => {\n if (!projectPath || !f.evidenceSpanId) {\n return undefined;\n }\n const base = spanCwd.get(f.evidenceSpanId);\n const state = cwdAtFirstGit(spanCmd.get(f.evidenceSpanId) ?? \"\", base);\n if (state.kind === \"unknown\") {\n return \"elsewhere\";\n }\n const at = state.kind === \"known\" ? state.path : base;\n if (!at) {\n return undefined;\n }\n return at === projectPath || at.startsWith(`${projectPath}/`) ? \"here\" : \"elsewhere\";\n };\n const keep = (f: Finding): boolean => keepUnderDiff(f, files, cmdOf, locusOf);\n const scopedFindings: FindingSet = {\n main: findings.main.filter(keep),\n minor: findings.minor.filter(keep),\n };\n const filesChanged = derived.filesChanged.filter((fc) => inDiff(fc.path, files));\n const destructiveCount = derived.spans\n .filter((s) => s.destructive)\n .filter((s) => {\n const cmd = commandOf(s.input);\n const clause = destructiveMatch(cmd) ?? cmd;\n if (destructiveOutsideRepo(clause) || regenerableReceiptRm(clause)) {\n return false;\n }\n // git ref/history surgery that touched no changed file isn't this diff's damage.\n if (/(^|[\\s;&|])git\\s/.test(cmd)) {\n return gitTouchesDiff(cmd, files);\n }\n return true;\n }).length;\n const eff = diffEffort(derived, files);\n return {\n derived: {\n ...derived,\n filesChanged,\n destructiveCount,\n diffCostUsd: eff.cost,\n diffTokens: eff.tokens,\n diffTurns: eff.turns,\n },\n findings: scopedFindings,\n };\n}\n","/**\n * Which surface a finding belongs to. The **merge gate** (the PR comment) is about\n * the *merged artifact* — what a reviewer must check before merging. The **operator**\n * view (the `receipts` card and `receipts trends`) is about *how the agent worked* —\n * efficiency, cost, loops, retries. One source of truth, shared by the PR-comment\n * renderer and its standalone Action mirror.\n */\n\n/** Kinds that describe agent behaviour/efficiency, not the merged change. */\nconst OPERATOR_KINDS = new Set([\n \"loop\",\n \"bottleneck\",\n \"cost-concentration\",\n \"cache-opportunity\",\n \"model-downgrade\",\n]);\n\nexport type Surface = \"merge\" | \"operator\";\n\nexport function findingSurface(id: string): Surface {\n // `errcluster-<tool>` (\"X failed N× before succeeding\") is an efficiency signal.\n if (OPERATOR_KINDS.has(id) || id.startsWith(\"errcluster-\")) {\n return \"operator\";\n }\n return \"merge\";\n}\n\n/**\n * True when a destructive finding's target is a **scratch path** (a `$VAR`, `/tmp`,\n * `/var/folders`, or `~`), so it can't be a merge risk and shouldn't gate the PR.\n * Parsed from the finding title's clause (the `destructiveMatch` output, e.g.\n * `Destructive op: rm -rf \"$TMP\"`). Conservative: only returns true when **every**\n * `rm`/`rmdir` operand is clearly non-repo — `rm -rf ./src`, `rm -rf build`,\n * `git reset --hard`, `DROP TABLE` are all kept (return false).\n */\nexport function destructiveOutsideRepo(title: string): boolean {\n const clause = title.replace(/^Destructive op:\\s*/i, \"\").replace(/\\s*×\\d+\\s*$/, \"\");\n // Only filesystem removals carry a path target we can judge; git/SQL/infra\n // destructives act on the repo or an external system → never \"outside repo\".\n const m = clause.match(/^\\s*(rm|rmdir)\\b(.*)$/i);\n if (!m) {\n return false;\n }\n const operands = m[2].split(/\\s+/).filter((t) => t && !t.startsWith(\"-\"));\n if (operands.length === 0) {\n return false;\n }\n const scratch = (t: string): boolean => {\n const p = t.replace(/^[\"']|[\"']$/g, \"\");\n return (\n /\\$/.test(p) ||\n p.startsWith(\"/tmp\") ||\n p.startsWith(\"/var/folders\") ||\n p.startsWith(\"/private/var/folders\") ||\n p.startsWith(\"~\")\n );\n };\n return operands.every(scratch);\n}\n\n/**\n * True when a destructive finding deletes only the tool's **own regenerable Receipt\n * artifact** (`rm .receipts/<branch>.json`), e.g. when regenerating it against a\n * corrected base. Like {@link destructiveOutsideRepo} this is a scope-layer carve-out:\n * a `.receipts/*.json` is inside the repo but is rewritten by `receipts pr`, so it\n * isn't a merge risk in the change under review. Conservative: only `rm`/`rmdir` whose\n * **every** operand is a `.receipts/<name>.json` file — a mixed command\n * (`rm .receipts/x.json src/app.ts`) or the whole dir (`rm -rf .receipts`) returns\n * false and keeps flagging.\n */\nexport function regenerableReceiptRm(title: string): boolean {\n const clause = title.replace(/^Destructive op:\\s*/i, \"\").replace(/\\s*×\\d+\\s*$/, \"\");\n const m = clause.match(/^\\s*(rm|rmdir)\\b(.*)$/i);\n if (!m) {\n return false;\n }\n const operands = m[2].split(/\\s+/).filter((t) => t && !t.startsWith(\"-\"));\n if (operands.length === 0) {\n return false;\n }\n // a flat `.receipts/<name>.json` file (receipts are one-per-branch, not nested) —\n // the dir itself (`.receipts`, `.receipts/`) has no `.json` operand, so it's kept.\n const receiptJson = (t: string): boolean =>\n /(?:^|\\/)\\.receipts\\/[^/]+\\.json$/.test(t.replace(/^[\"']|[\"']$/g, \"\"));\n return operands.every(receiptJson);\n}\n","import type { Session, SessionMessage } from \"./types.js\";\n\n/** The distinct branches that appear across a session's messages, in first-seen order. */\nexport function branchesIn(session: Session): string[] {\n const seen: string[] = [];\n for (const m of session.messages) {\n if (m.gitBranch && !seen.includes(m.gitBranch)) {\n seen.push(m.gitBranch);\n }\n }\n return seen;\n}\n\n/**\n * Assign every message an effective branch: its own `gitBranch`, else the nearest\n * preceding tagged branch (carry-forward); leading untagged messages take the\n * first branch that appears. Deterministic.\n */\nfunction effectiveBranches(messages: SessionMessage[]): (string | undefined)[] {\n const firstTagged = messages.find((m) => m.gitBranch)?.gitBranch;\n let current = firstTagged;\n return messages.map((m) => {\n if (m.gitBranch) {\n current = m.gitBranch;\n }\n return current;\n });\n}\n\n/**\n * Slice a session down to the messages belonging to `branch` (non-contiguous\n * visits included), recomputing the per-session `digestSource` over the slice so\n * the Receipt's subject digest is scoped to this branch's work. Deterministic.\n *\n * Returns null when the branch isn't present in the session at all.\n */\nexport function sliceByBranch(session: Session, branch: string): Session | null {\n if (!branchesIn(session).includes(branch)) {\n return null;\n }\n const eff = effectiveBranches(session.messages);\n const messages = session.messages.filter((_, i) => eff[i] === branch);\n if (messages.length === 0) {\n return null;\n }\n const timestamps = messages\n .map((m) => m.timestamp)\n .filter((t): t is number => typeof t === \"number\");\n const startedAt = timestamps.length ? Math.min(...timestamps) : session.startedAt;\n const endedAt = timestamps.length ? Math.max(...timestamps) : session.endedAt;\n\n return {\n ...session,\n id: `${session.id}#${branch}`,\n gitBranch: branch,\n startedAt,\n endedAt,\n messages,\n // Scope the subject digest to this branch's slice (reproducible by re-slicing).\n digestSource: JSON.stringify({ id: session.id, branch, messages }),\n };\n}\n","import { deriveFindings } from \"../findings/findings.js\";\nimport { deriveSpans } from \"../findings/spans.js\";\nimport { type Receipt, type ReceiptScope, buildReceipt } from \"../receipt/build.js\";\nimport { canonicalize } from \"../receipt/canonical.js\";\nimport { redactReceipt } from \"../share/redact.js\";\nimport { applyDiffScope, narrowEffort } from \"../trace/diffScope.js\";\nimport { loadById } from \"../trace/load.js\";\nimport { sliceByBranch } from \"../trace/slice.js\";\nimport type { AgentSource } from \"../trace/types.js\";\n\nexport interface RederiveOptions {\n /** agent that produced the transcript (default: claude-code) */\n source?: AgentSource;\n /** scope to one branch's turns before deriving */\n branch?: string;\n /** the committed receipt's recorded scope — re-applied so the re-derivation\n * matches a scoped receipt byte-for-byte (SPEC-0013 L1). Its `files`/`branch`\n * come from the receipt, so no git is needed at verify time. */\n scope?: ReceiptScope;\n /** apply secret redaction (to compare against a redacted committed Receipt) */\n redact?: boolean;\n}\n\n/**\n * Re-run the deterministic engine on a transcript file to reproduce its Receipt.\n * Because the pipeline is deterministic, a verifier with the transcript gets the\n * exact same Receipt — that's what proves a committed Receipt is faithful and not\n * fabricated (SPEC-0009 Part B, L1). When the committed receipt was scoped\n * (SPEC-0013), the same recorded scope is re-applied so the bytes still match.\n */\nexport async function rederiveFromTranscript(\n path: string,\n opts: RederiveOptions = {},\n): Promise<Receipt | null> {\n const loaded = await loadById(opts.source ?? \"claude-code\", path);\n if (!loaded) {\n return null;\n }\n // Resolve scope: the recorded `predicate.scope` takes precedence; fall back to a\n // bare `--branch` for pre-SPEC-0013 (branch-only) receipts.\n const scope = opts.scope;\n const branch = scope?.kind === \"branch\" ? scope.branch : opts.branch;\n const session = branch ? (sliceByBranch(loaded, branch) ?? loaded) : loaded;\n\n let derived = deriveSpans(session);\n let findings = deriveFindings(derived);\n if (scope?.kind === \"diff\" && scope.files) {\n const scoped = applyDiffScope(derived, findings, scope.files, session.projectPath);\n derived = scoped.derived;\n findings = scoped.findings;\n if (scope.branch) {\n // SPEC-0068 R4: the receipt declares branch-narrowed effort — recompute it the\n // same way (branch turns ∩ diff-file edits) so the byte-compare holds.\n const slice = sliceByBranch(loaded, scope.branch);\n const eff = narrowEffort(slice ? deriveSpans(slice) : null, scope.files);\n if (eff) {\n derived = {\n ...derived,\n diffCostUsd: eff.cost,\n diffTokens: eff.tokens,\n diffTurns: eff.turns,\n };\n }\n }\n }\n\n const receipt = await buildReceipt(session, derived, findings, { scope });\n return opts.redact ? redactReceipt(receipt) : receipt;\n}\n\nexport interface RederiveCompare {\n /** the re-derivation produced a Receipt at all */\n rederived: boolean;\n /** the committed Receipt byte-equals the re-derivation (faithful, not fabricated) */\n matches: boolean;\n}\n\n/**\n * Compare a committed Receipt against a fresh re-derivation from its transcript.\n * `matches` true ⇒ the Receipt is the deterministic function of that transcript.\n */\nexport async function compareToTranscript(\n committed: Receipt,\n transcriptPath: string,\n opts: RederiveOptions = {},\n): Promise<RederiveCompare> {\n // Re-apply the committed receipt's own recorded scope so a scoped receipt\n // re-derives byte-for-byte (the basis is in the receipt, so no git is needed).\n const fresh = await rederiveFromTranscript(transcriptPath, {\n redact: true,\n ...opts,\n scope: committed.predicate.scope,\n });\n if (!fresh) {\n return { rederived: false, matches: false };\n }\n return { rederived: true, matches: canonicalize(committed) === canonicalize(fresh) };\n}\n","/**\n * The catalog of merge-surface checks the engine runs on every diff. The PR comment\n * lists it so a reviewer sees *what was mechanically scanned for* — the cleared checks\n * are the trust surface (\"a deterministic auditor looked for these and found nothing\"),\n * the flagged ones point at the Findings above. This is a render-time partition of the\n * existing finding ids — it adds no detector and makes no judgement: \"cleared\" means\n * **no detector fired on this diff**, never \"this code is good\" (SPEC-0000 R2).\n *\n * Keep this in lock-step with the detectors: every merge-surface finding id prefix MUST\n * map to a category here (the `categorize` self-check throws in dev if one doesn't), so\n * the catalog never silently under-claims or claims a check that doesn't run.\n */\n\nexport interface Check {\n key: string;\n icon: string;\n label: string;\n /** matches the finding-id prefixes this category covers */\n prefixes: string[];\n}\n\n/** Ordered by review priority. Operator/efficiency findings (loop, errcluster, …) are\n * deliberately absent — they live on the `receipts` card, not the merge gate. */\nexport const CHECK_CATALOG: readonly Check[] = [\n {\n key: \"destructive\",\n icon: \"🛡️\",\n label: \"destructive ops\",\n prefixes: [\"destructive\", \"file-shrink\"],\n },\n {\n key: \"git-history\",\n icon: \"🌿\",\n label: \"git-history safety\",\n prefixes: [\"force-push\", \"history-rewrite\"],\n },\n { key: \"secrets\", icon: \"🔑\", label: \"secret leaks\", prefixes: [\"secret\"] },\n { key: \"cicd\", icon: \"⚙️\", label: \"CI/CD tampering\", prefixes: [\"ci-cd-touch\"] },\n { key: \"lockfile\", icon: \"📦\", label: \"lockfile integrity\", prefixes: [\"lockfile-edit\"] },\n {\n key: \"tests\",\n icon: \"🧪\",\n label: \"test integrity\",\n prefixes: [\n \"fake-green\",\n \"test-focus\",\n \"test-skipped\",\n \"test-trivialised\",\n \"grader-edit\",\n \"eval-override\",\n ],\n },\n {\n key: \"weakening\",\n icon: \"🔓\",\n label: \"config/safety weakening\",\n prefixes: [\"config-weaken\", \"hook-bypass\", \"pipe-sh\"],\n },\n {\n key: \"blind-edits\",\n icon: \"👁️\",\n label: \"blind / unverified edits\",\n prefixes: [\"blind-edit\", \"unverified-change\", \"edit-reversion\"],\n },\n { key: \"injection\", icon: \"💉\", label: \"prompt-injection\", prefixes: [\"prompt-injection\"] },\n { key: \"trojan\", icon: \"🕵️\", label: \"hidden unicode\", prefixes: [\"trojan-source\"] },\n {\n key: \"duplication\",\n icon: \"📋\",\n label: \"duplicated code\",\n prefixes: [\"dup-file\", \"duplicated-code\"],\n },\n { key: \"swallowed\", icon: \"🤫\", label: \"swallowed errors\", prefixes: [\"error-swallowed\"] },\n { key: \"stubbed\", icon: \"🚧\", label: \"stubbed implementation\", prefixes: [\"impl-stubbed\"] },\n { key: \"malformed\", icon: \"🧱\", label: \"malformed artifacts\", prefixes: [\"malformed-artifact\"] },\n { key: \"truncated\", icon: \"✂️\", label: \"truncated turns\", prefixes: [\"truncated-turn\"] },\n {\n key: \"promises\",\n icon: \"🤝\",\n label: \"unfulfilled claims\",\n prefixes: [\"claimed-commit-none\", \"unfulfilled-promise\"],\n },\n {\n key: \"tool-calls\",\n icon: \"🧬\",\n label: \"tool-call integrity\",\n prefixes: [\"tool-fabricated\", \"tool-malformed-args\"],\n },\n] as const;\n\n/** A finding id matches a category if it equals or `<prefix>-`-starts one of its prefixes. */\nfunction matches(id: string, check: Check): boolean {\n return check.prefixes.some((p) => id === p || id.startsWith(`${p}-`));\n}\n\n/** The catalog check a finding id belongs to (for cross-receipt rollups), or undefined. */\nexport function checkForId(id: string): Check | undefined {\n return CHECK_CATALOG.find((c) => matches(id, c));\n}\n\nexport type CheckSeverity = \"critical\" | \"high\" | \"medium\" | \"low\";\nconst SEV_RANK: Record<CheckSeverity, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n\nexport interface FlaggedCheck {\n check: Check;\n count: number;\n /** worst severity among the findings that matched this category */\n severity: CheckSeverity;\n}\n\nexport interface CategorizedChecks {\n /** categories with ≥1 merge finding on this diff, each with count + worst severity */\n flagged: FlaggedCheck[];\n /** categories that ran and found nothing — the trust surface */\n cleared: Check[];\n /** total categories in the catalog */\n total: number;\n}\n\n/**\n * Partition the catalog against a set of (merge-surface) findings. A category is\n * `flagged` when ≥1 finding matches it (carrying the count + worst severity), else\n * `cleared`. The order of {@link CHECK_CATALOG} is preserved in both lists.\n */\nexport function categorize(\n findings: readonly { id: string; severity?: CheckSeverity }[],\n): CategorizedChecks {\n const flagged: FlaggedCheck[] = [];\n const cleared: Check[] = [];\n for (const check of CHECK_CATALOG) {\n const hits = findings.filter((f) => matches(f.id, check));\n if (hits.length > 0) {\n const severity = hits\n .map((f) => f.severity ?? \"high\")\n .sort((a, b) => SEV_RANK[a] - SEV_RANK[b])[0];\n flagged.push({ check, count: hits.length, severity });\n } else {\n cleared.push(check);\n }\n }\n return { flagged, cleared, total: CHECK_CATALOG.length };\n}\n"],"mappings":"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","names":["spawnSync","spawnSync","base"]}