@attalabs/vinaya 0.21.0 → 0.22.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.
Files changed (117) hide show
  1. package/README.md +3 -2
  2. package/aeg-root/enforcement.md +2 -1
  3. package/aeg-root/roles/archivist.md +1 -1
  4. package/aeg-root/roles/planner.md +1 -1
  5. package/aeg-root/templates/pr-report-template.md +2 -0
  6. package/aeg-root/tranche-model.md +3 -3
  7. package/dist/checks/bin/check-body-bare-digits.js +115 -9
  8. package/dist/checks/bin/check-branch-topology.js +111 -5
  9. package/dist/checks/bin/check-brief-shape.js +111 -5
  10. package/dist/checks/bin/check-changeset-coverage.js +113 -7
  11. package/dist/checks/bin/check-closes-n.js +111 -5
  12. package/dist/checks/bin/check-coherence.js +115 -9
  13. package/dist/checks/bin/check-dead-branch-push.js +111 -5
  14. package/dist/checks/bin/check-dispatch-readiness.js +116 -10
  15. package/dist/checks/bin/check-doc-coverage-push.js +116 -10
  16. package/dist/checks/bin/check-doc-coverage.js +116 -10
  17. package/dist/checks/bin/check-doctrine-portability.js +115 -9
  18. package/dist/checks/bin/check-evidence-fresh.js +111 -5
  19. package/dist/checks/bin/check-first-push-dispatch.js +113 -7
  20. package/dist/checks/bin/check-issue-assignment.js +111 -5
  21. package/dist/checks/bin/check-main-branch-refusal.js +111 -5
  22. package/dist/checks/bin/check-no-disk-state.js +111 -5
  23. package/dist/checks/bin/check-quoted-command.js +121 -12
  24. package/dist/checks/bin/check-reader-resolvable-prose.js +152 -20
  25. package/dist/checks/bin/check-registry-gates.js +131 -10
  26. package/dist/checks/bin/check-retired-vocabulary.js +144 -12
  27. package/dist/checks/bin/check-review-gate.js +113 -7
  28. package/dist/checks/bin/check-single-plan-pr.js +111 -5
  29. package/dist/checks/bin/check-test-plan.js +111 -5
  30. package/dist/checks/bin/check-token-collection-wired.js +113 -7
  31. package/dist/checks/bin/check-token-report.js +4096 -0
  32. package/dist/checks/bin/check-workspace-escape.js +113 -7
  33. package/dist/index.js +177 -104
  34. package/package.json +1 -1
  35. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  36. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  37. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  38. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  39. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  40. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  41. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  42. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  43. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  44. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  45. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  46. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  47. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  48. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  49. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  50. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  51. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  52. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  53. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  54. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  55. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  56. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  57. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  58. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  59. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  60. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
  61. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  62. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  63. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  64. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  65. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  66. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  67. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  68. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  69. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  70. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  71. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  72. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/1q96_modules_@clerk_nextjs_dist_esm_app-router_client_keyless-creator-reader_0lom2js.js +1 -1
  73. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0053k9k._.js +1 -1
  74. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
  75. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__02c71kv._.js +1 -1
  76. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0ozbaq0._.js → [root-of-the-server]__069-_41._.js} +1 -1
  77. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
  78. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
  79. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
  80. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
  81. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_03x_w6q._.js +1 -1
  82. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
  83. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
  84. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0o54suy._.js +1 -1
  85. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1-6rzip._.js +1 -1
  86. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1mrtj0f._.js +1 -1
  87. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
  88. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_06it6s-._.js +1 -1
  89. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
  90. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_animate_components_index_ts_186fje1._.js +1 -1
  91. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_brutal_components_index_ts_0n_lcc4._.js +1 -1
  92. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_retro_components_index_ts_0wvpm_z._.js +1 -1
  93. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_retro_components_index_ts_1_cfi48._.js +1 -1
  94. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  95. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  96. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  97. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
  98. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/00pi8vhg8w6gi.js +1 -0
  99. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0r4i_ks9z02bw.js → 03q0q9n6-xah8.js} +1 -1
  100. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0vc2u252q5q6o.js +1 -0
  101. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1k916ih3p4nsg.js → 13g16cu00g570.js} +1 -1
  102. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1hufpuody6vjv.js +1 -0
  103. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{2hmannd4bjhzy.js → 1sfxfunirkcr6.js} +1 -1
  104. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1t2kft7bxzuxn.js → 206ajg8f1a-_h.js} +1 -1
  105. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1hfhxjy577l5d.js → 267o-tsrnuwnv.js} +1 -1
  106. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{25kbt5k-xb2a5.js → 279qq4twinc97.js} +1 -1
  107. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{112g08xpx3kro.js → 2ka8dg687auhj.js} +1 -1
  108. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0up5x3jg-cwov.js → 2rn89uwtf2lwc.js} +1 -1
  109. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{2_k6j1o9q5nn4.js → 37hnluhzj9bei.js} +1 -1
  110. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3mqu_uhluy19i.css → 3qc67qhcvbg0o.css} +1 -1
  111. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1yqs2zgvwa4p1.js → 3zugx9esh2x51.js} +1 -1
  112. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0_jnwbarv-cqk.js +0 -1
  113. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1ybrihl5_aocy.js +0 -1
  114. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/3r5efmleneaco.js +0 -1
  115. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{crNCHQ9uAgKOYC6DKkZma → Fmyc42qzLwFcWWHLLNy-G}/_buildManifest.js +0 -0
  116. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{crNCHQ9uAgKOYC6DKkZma → Fmyc42qzLwFcWWHLLNy-G}/_clientMiddlewareManifest.js +0 -0
  117. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{crNCHQ9uAgKOYC6DKkZma → Fmyc42qzLwFcWWHLLNy-G}/_ssgManifest.js +0 -0
@@ -1788,6 +1788,99 @@ var DERIVED_STATUSES = [
1788
1788
  "incoherent"
1789
1789
  ];
1790
1790
  var DERIVABLE_STATUSES = DERIVED_STATUSES.filter((s) => s !== "backlog");
1791
+ // ../../packages/aeg-core/src/parse-ledger.ts
1792
+ function rowFromCells(cells) {
1793
+ if (cells.length < 7)
1794
+ return null;
1795
+ const phase = (cells[0] ?? "").trim();
1796
+ if (!phase)
1797
+ return null;
1798
+ return {
1799
+ phase,
1800
+ role: (cells[1] ?? "").trim(),
1801
+ agentModel: (cells[2] ?? "").trim(),
1802
+ tokensIn: parseIntCell(cells[3] ?? ""),
1803
+ tokensOut: parseIntCell(cells[4] ?? ""),
1804
+ cost: parseCostCell(cells[5] ?? ""),
1805
+ date: (cells[6] ?? "").trim()
1806
+ };
1807
+ }
1808
+ function parseIntCell(cell) {
1809
+ const trimmed = cell.replace(/`/g, "").trim();
1810
+ if (!trimmed || isEmDashOrDash(trimmed))
1811
+ return null;
1812
+ const normalized = trimmed.replace(/[,_\s]/g, "");
1813
+ if (!/^-?\d+$/.test(normalized))
1814
+ return null;
1815
+ return Number(normalized);
1816
+ }
1817
+ function parseCostCell(cell) {
1818
+ const trimmed = cell.replace(/`/g, "").trim();
1819
+ if (!trimmed || isEmDashOrDash(trimmed))
1820
+ return null;
1821
+ const normalized = trimmed.replace(/^\$/, "").replace(/[,_\s]/g, "");
1822
+ if (!/^-?\d+(\.\d+)?$/.test(normalized))
1823
+ return null;
1824
+ return Number(normalized);
1825
+ }
1826
+ function isEmDashOrDash(s) {
1827
+ const t = s.trim();
1828
+ return t === "—" || t === "-" || t === "–";
1829
+ }
1830
+ // ../../packages/aeg-core/src/parse-token-report.ts
1831
+ var TOKEN_REPORT_HEADING = /^\s*(?:#{1,6}\s*Token report\s*|\*\*Token report\*\*)\s*$/i;
1832
+ var INLINE_FIELD_LIST = /Phase:\s*([^|]+?)\s*\|\s*Role:\s*([^|]+?)\s*\|\s*Agent\/Model:\s*([^|]+?)\s*\|\s*Tokens in:\s*([^|]+?)\s*\|\s*Tokens out:\s*([^|]+?)\s*\|\s*Cost:\s*([^|]+?)\s*\|\s*Date:\s*(.+?)\s*$/im;
1833
+ function parseTokenReportEntries(body) {
1834
+ const lines = body.split(/\r?\n/);
1835
+ const headingIdxs = [];
1836
+ lines.forEach((line, i) => {
1837
+ if (TOKEN_REPORT_HEADING.test(line))
1838
+ headingIdxs.push(i);
1839
+ });
1840
+ const out = [];
1841
+ for (let h = 0;h < headingIdxs.length; h++) {
1842
+ const start = headingIdxs[h] + 1;
1843
+ const end = h + 1 < headingIdxs.length ? headingIdxs[h + 1] : lines.length;
1844
+ const section = lines.slice(start, end).join(`
1845
+ `);
1846
+ const tableRows = parseTableSection(section);
1847
+ if (tableRows.length > 0) {
1848
+ out.push(...tableRows);
1849
+ continue;
1850
+ }
1851
+ const inlineRow = parseInlineFieldList(section);
1852
+ if (inlineRow)
1853
+ out.push(inlineRow);
1854
+ }
1855
+ return out;
1856
+ }
1857
+ function parseTableSection(section) {
1858
+ const lines = section.split(/\r?\n/);
1859
+ let i = 0;
1860
+ for (;i < lines.length; i++) {
1861
+ if ((lines[i] ?? "").trim().startsWith("|"))
1862
+ break;
1863
+ }
1864
+ if (i + 1 >= lines.length)
1865
+ return [];
1866
+ i += 2;
1867
+ const out = [];
1868
+ for (;i < lines.length; i++) {
1869
+ const trimmed = (lines[i] ?? "").trim();
1870
+ if (!trimmed.startsWith("|"))
1871
+ break;
1872
+ const row = rowFromCells(splitTableRow(trimmed));
1873
+ if (row)
1874
+ out.push(row);
1875
+ }
1876
+ return out;
1877
+ }
1878
+ function parseInlineFieldList(section) {
1879
+ const m = section.match(INLINE_FIELD_LIST);
1880
+ if (!m)
1881
+ return null;
1882
+ return rowFromCells([m[1], m[2], m[3], m[4], m[5], m[6], m[7]]);
1883
+ }
1791
1884
  // ../../packages/aeg-core/src/report-tokens.ts
1792
1885
  var DASH_LOOKALIKES = {
1793
1886
  "-": "‑",
@@ -1796,6 +1889,7 @@ var DASH_LOOKALIKES = {
1796
1889
  };
1797
1890
  var DASH_CHARS = new Set(Object.keys(DASH_LOOKALIKES));
1798
1891
  // ../../packages/aeg-core/src/claude-code-transcript.ts
1892
+ import { createHash } from "node:crypto";
1799
1893
  function summarizeTranscript(jsonl) {
1800
1894
  const seen = new Set;
1801
1895
  const components = {
@@ -1844,7 +1938,14 @@ function numberOr(value, fallback) {
1844
1938
  function sanitizeKey(value) {
1845
1939
  return value.replace(/[^A-Za-z0-9]+/g, "-");
1846
1940
  }
1941
+ function collisionResistantKey(value) {
1942
+ const digest = createHash("sha256").update(value).digest("hex");
1943
+ return `${sanitizeKey(value)}-${digest}`;
1944
+ }
1847
1945
  function transcriptPointerPath(projectDir, tmpDir) {
1946
+ return `${tmpDir}/claude-transcript-${collisionResistantKey(projectDir)}.txt`;
1947
+ }
1948
+ function legacyTranscriptPointerPath(projectDir, tmpDir) {
1848
1949
  return `${tmpDir}/claude-transcript-${sanitizeKey(projectDir)}.txt`;
1849
1950
  }
1850
1951
  function resolvePointer(explicitTranscriptPath, deps) {
@@ -1852,13 +1953,15 @@ function resolvePointer(explicitTranscriptPath, deps) {
1852
1953
  return { path: explicitTranscriptPath, corroborated: true };
1853
1954
  const projectDir = deps.env.CLAUDE_PROJECT_DIR ?? deps.cwd;
1854
1955
  const tmpDir = deps.env.TMPDIR ?? "/tmp";
1855
- const pointerPath = transcriptPointerPath(projectDir, tmpDir);
1956
+ const primaryPointerPath = transcriptPointerPath(projectDir, tmpDir);
1957
+ const legacyPointerPath = legacyTranscriptPointerPath(projectDir, tmpDir);
1856
1958
  const currentSessionId = deps.env.CLAUDE_CODE_SESSION_ID;
1857
- if (!deps.exists(pointerPath)) {
1959
+ const pointerPath = deps.exists(primaryPointerPath) ? primaryPointerPath : deps.exists(legacyPointerPath) ? legacyPointerPath : undefined;
1960
+ if (!pointerPath) {
1858
1961
  return {
1859
1962
  pointerExisted: false,
1860
1963
  corroborated: false,
1861
- error: `No transcript pointer at ${pointerPath} and no --transcript given. ` + "Either this repo installs no track-transcript.sh Stop hook (lacking one is not a defect — " + "name the transcript directly instead), or no session has completed a turn yet."
1964
+ error: `No transcript pointer at ${primaryPointerPath} (nor its pre-migration name ${legacyPointerPath}) ` + "and no --transcript given. Either this repo installs no track-transcript.sh Stop hook (lacking one " + "is not a defect — name the transcript directly instead), or no session has completed a turn yet."
1862
1965
  };
1863
1966
  }
1864
1967
  let contents;
@@ -1933,6 +2036,9 @@ function isTokenCollectionWiringBroken(capability) {
1933
2036
  return false;
1934
2037
  return capability.reason !== "no-transcript-resolved";
1935
2038
  }
2039
+ // ../../packages/aeg-core/src/metering-io-guard.ts
2040
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from "node:fs";
2041
+ var GUARD_OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | fsConstants.O_NOFOLLOW;
1936
2042
  // ../../packages/aeg-core/src/file-classify.ts
1937
2043
  function isCodeFile(p) {
1938
2044
  if (p.endsWith(".md"))
@@ -2139,7 +2245,7 @@ function overrideActive(opts) {
2139
2245
  return false;
2140
2246
  }
2141
2247
  // ../../packages/aeg-core/src/premise-check.ts
2142
- import { createHash } from "node:crypto";
2248
+ import { createHash as createHash2 } from "node:crypto";
2143
2249
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
2144
2250
  function isPremiseHeader(line) {
2145
2251
  const stripped = line.replace(/[*#]/g, "").trim();
@@ -2184,7 +2290,7 @@ function checkPremises(assertions, fileReader) {
2184
2290
  } else if (a.kind === "absent" && content.includes(a.value)) {
2185
2291
  failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2186
2292
  } else if (a.kind === "sha256") {
2187
- const actual = createHash("sha256").update(content).digest("hex");
2293
+ const actual = createHash2("sha256").update(content).digest("hex");
2188
2294
  if (actual !== a.value.toLowerCase()) {
2189
2295
  failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2190
2296
  }
@@ -2,7 +2,7 @@
2
2
  // @bun
3
3
 
4
4
  // src/checks/bin/check-token-collection-wired.ts
5
- import { lstatSync, readFileSync } from "fs";
5
+ import { lstatSync, readFileSync as readFileSync2 } from "fs";
6
6
  // ../../packages/aeg-core/src/gate-audience.ts
7
7
  var GATE_AUDIENCE = {
8
8
  "check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
@@ -1792,6 +1792,99 @@ var DERIVED_STATUSES = [
1792
1792
  "incoherent"
1793
1793
  ];
1794
1794
  var DERIVABLE_STATUSES = DERIVED_STATUSES.filter((s) => s !== "backlog");
1795
+ // ../../packages/aeg-core/src/parse-ledger.ts
1796
+ function rowFromCells(cells) {
1797
+ if (cells.length < 7)
1798
+ return null;
1799
+ const phase = (cells[0] ?? "").trim();
1800
+ if (!phase)
1801
+ return null;
1802
+ return {
1803
+ phase,
1804
+ role: (cells[1] ?? "").trim(),
1805
+ agentModel: (cells[2] ?? "").trim(),
1806
+ tokensIn: parseIntCell(cells[3] ?? ""),
1807
+ tokensOut: parseIntCell(cells[4] ?? ""),
1808
+ cost: parseCostCell(cells[5] ?? ""),
1809
+ date: (cells[6] ?? "").trim()
1810
+ };
1811
+ }
1812
+ function parseIntCell(cell) {
1813
+ const trimmed = cell.replace(/`/g, "").trim();
1814
+ if (!trimmed || isEmDashOrDash(trimmed))
1815
+ return null;
1816
+ const normalized = trimmed.replace(/[,_\s]/g, "");
1817
+ if (!/^-?\d+$/.test(normalized))
1818
+ return null;
1819
+ return Number(normalized);
1820
+ }
1821
+ function parseCostCell(cell) {
1822
+ const trimmed = cell.replace(/`/g, "").trim();
1823
+ if (!trimmed || isEmDashOrDash(trimmed))
1824
+ return null;
1825
+ const normalized = trimmed.replace(/^\$/, "").replace(/[,_\s]/g, "");
1826
+ if (!/^-?\d+(\.\d+)?$/.test(normalized))
1827
+ return null;
1828
+ return Number(normalized);
1829
+ }
1830
+ function isEmDashOrDash(s) {
1831
+ const t = s.trim();
1832
+ return t === "—" || t === "-" || t === "–";
1833
+ }
1834
+ // ../../packages/aeg-core/src/parse-token-report.ts
1835
+ var TOKEN_REPORT_HEADING = /^\s*(?:#{1,6}\s*Token report\s*|\*\*Token report\*\*)\s*$/i;
1836
+ var INLINE_FIELD_LIST = /Phase:\s*([^|]+?)\s*\|\s*Role:\s*([^|]+?)\s*\|\s*Agent\/Model:\s*([^|]+?)\s*\|\s*Tokens in:\s*([^|]+?)\s*\|\s*Tokens out:\s*([^|]+?)\s*\|\s*Cost:\s*([^|]+?)\s*\|\s*Date:\s*(.+?)\s*$/im;
1837
+ function parseTokenReportEntries(body) {
1838
+ const lines = body.split(/\r?\n/);
1839
+ const headingIdxs = [];
1840
+ lines.forEach((line, i) => {
1841
+ if (TOKEN_REPORT_HEADING.test(line))
1842
+ headingIdxs.push(i);
1843
+ });
1844
+ const out = [];
1845
+ for (let h = 0;h < headingIdxs.length; h++) {
1846
+ const start = headingIdxs[h] + 1;
1847
+ const end = h + 1 < headingIdxs.length ? headingIdxs[h + 1] : lines.length;
1848
+ const section = lines.slice(start, end).join(`
1849
+ `);
1850
+ const tableRows = parseTableSection(section);
1851
+ if (tableRows.length > 0) {
1852
+ out.push(...tableRows);
1853
+ continue;
1854
+ }
1855
+ const inlineRow = parseInlineFieldList(section);
1856
+ if (inlineRow)
1857
+ out.push(inlineRow);
1858
+ }
1859
+ return out;
1860
+ }
1861
+ function parseTableSection(section) {
1862
+ const lines = section.split(/\r?\n/);
1863
+ let i = 0;
1864
+ for (;i < lines.length; i++) {
1865
+ if ((lines[i] ?? "").trim().startsWith("|"))
1866
+ break;
1867
+ }
1868
+ if (i + 1 >= lines.length)
1869
+ return [];
1870
+ i += 2;
1871
+ const out = [];
1872
+ for (;i < lines.length; i++) {
1873
+ const trimmed = (lines[i] ?? "").trim();
1874
+ if (!trimmed.startsWith("|"))
1875
+ break;
1876
+ const row = rowFromCells(splitTableRow(trimmed));
1877
+ if (row)
1878
+ out.push(row);
1879
+ }
1880
+ return out;
1881
+ }
1882
+ function parseInlineFieldList(section) {
1883
+ const m = section.match(INLINE_FIELD_LIST);
1884
+ if (!m)
1885
+ return null;
1886
+ return rowFromCells([m[1], m[2], m[3], m[4], m[5], m[6], m[7]]);
1887
+ }
1795
1888
  // ../../packages/aeg-core/src/report-tokens.ts
1796
1889
  var DASH_LOOKALIKES = {
1797
1890
  "-": "‑",
@@ -1800,6 +1893,7 @@ var DASH_LOOKALIKES = {
1800
1893
  };
1801
1894
  var DASH_CHARS = new Set(Object.keys(DASH_LOOKALIKES));
1802
1895
  // ../../packages/aeg-core/src/claude-code-transcript.ts
1896
+ import { createHash } from "node:crypto";
1803
1897
  function summarizeTranscript(jsonl) {
1804
1898
  const seen = new Set;
1805
1899
  const components = {
@@ -1848,7 +1942,14 @@ function numberOr(value, fallback) {
1848
1942
  function sanitizeKey(value) {
1849
1943
  return value.replace(/[^A-Za-z0-9]+/g, "-");
1850
1944
  }
1945
+ function collisionResistantKey(value) {
1946
+ const digest = createHash("sha256").update(value).digest("hex");
1947
+ return `${sanitizeKey(value)}-${digest}`;
1948
+ }
1851
1949
  function transcriptPointerPath(projectDir, tmpDir) {
1950
+ return `${tmpDir}/claude-transcript-${collisionResistantKey(projectDir)}.txt`;
1951
+ }
1952
+ function legacyTranscriptPointerPath(projectDir, tmpDir) {
1852
1953
  return `${tmpDir}/claude-transcript-${sanitizeKey(projectDir)}.txt`;
1853
1954
  }
1854
1955
  function resolvePointer(explicitTranscriptPath, deps) {
@@ -1856,13 +1957,15 @@ function resolvePointer(explicitTranscriptPath, deps) {
1856
1957
  return { path: explicitTranscriptPath, corroborated: true };
1857
1958
  const projectDir = deps.env.CLAUDE_PROJECT_DIR ?? deps.cwd;
1858
1959
  const tmpDir = deps.env.TMPDIR ?? "/tmp";
1859
- const pointerPath = transcriptPointerPath(projectDir, tmpDir);
1960
+ const primaryPointerPath = transcriptPointerPath(projectDir, tmpDir);
1961
+ const legacyPointerPath = legacyTranscriptPointerPath(projectDir, tmpDir);
1860
1962
  const currentSessionId = deps.env.CLAUDE_CODE_SESSION_ID;
1861
- if (!deps.exists(pointerPath)) {
1963
+ const pointerPath = deps.exists(primaryPointerPath) ? primaryPointerPath : deps.exists(legacyPointerPath) ? legacyPointerPath : undefined;
1964
+ if (!pointerPath) {
1862
1965
  return {
1863
1966
  pointerExisted: false,
1864
1967
  corroborated: false,
1865
- error: `No transcript pointer at ${pointerPath} and no --transcript given. ` + "Either this repo installs no track-transcript.sh Stop hook (lacking one is not a defect — " + "name the transcript directly instead), or no session has completed a turn yet."
1968
+ error: `No transcript pointer at ${primaryPointerPath} (nor its pre-migration name ${legacyPointerPath}) ` + "and no --transcript given. Either this repo installs no track-transcript.sh Stop hook (lacking one " + "is not a defect — name the transcript directly instead), or no session has completed a turn yet."
1866
1969
  };
1867
1970
  }
1868
1971
  let contents;
@@ -1937,6 +2040,9 @@ function isTokenCollectionWiringBroken(capability) {
1937
2040
  return false;
1938
2041
  return capability.reason !== "no-transcript-resolved";
1939
2042
  }
2043
+ // ../../packages/aeg-core/src/metering-io-guard.ts
2044
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from "node:fs";
2045
+ var GUARD_OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | fsConstants.O_NOFOLLOW;
1940
2046
  // ../../packages/aeg-core/src/file-classify.ts
1941
2047
  function isCodeFile(p) {
1942
2048
  if (p.endsWith(".md"))
@@ -2143,7 +2249,7 @@ function overrideActive(opts) {
2143
2249
  return false;
2144
2250
  }
2145
2251
  // ../../packages/aeg-core/src/premise-check.ts
2146
- import { createHash } from "node:crypto";
2252
+ import { createHash as createHash2 } from "node:crypto";
2147
2253
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
2148
2254
  function isPremiseHeader(line) {
2149
2255
  const stripped = line.replace(/[*#]/g, "").trim();
@@ -2188,7 +2294,7 @@ function checkPremises(assertions, fileReader) {
2188
2294
  } else if (a.kind === "absent" && content.includes(a.value)) {
2189
2295
  failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2190
2296
  } else if (a.kind === "sha256") {
2191
- const actual = createHash("sha256").update(content).digest("hex");
2297
+ const actual = createHash2("sha256").update(content).digest("hex");
2192
2298
  if (actual !== a.value.toLowerCase()) {
2193
2299
  failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2194
2300
  }
@@ -3961,7 +4067,7 @@ function main() {
3961
4067
  readFile: (path) => {
3962
4068
  if (!safeLstat(path).ok)
3963
4069
  throw new Error(`refusing to read ${path}: not a regular file owned by this user`);
3964
- return readFileSync(path, "utf8");
4070
+ return readFileSync2(path, "utf8");
3965
4071
  }
3966
4072
  };
3967
4073
  const capability = resolveMeteringCapability(deps);