@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
@@ -1820,6 +1820,99 @@ var DERIVED_STATUSES = [
1820
1820
  "incoherent"
1821
1821
  ];
1822
1822
  var DERIVABLE_STATUSES = DERIVED_STATUSES.filter((s) => s !== "backlog");
1823
+ // ../../packages/aeg-core/src/parse-ledger.ts
1824
+ function rowFromCells(cells) {
1825
+ if (cells.length < 7)
1826
+ return null;
1827
+ const phase = (cells[0] ?? "").trim();
1828
+ if (!phase)
1829
+ return null;
1830
+ return {
1831
+ phase,
1832
+ role: (cells[1] ?? "").trim(),
1833
+ agentModel: (cells[2] ?? "").trim(),
1834
+ tokensIn: parseIntCell(cells[3] ?? ""),
1835
+ tokensOut: parseIntCell(cells[4] ?? ""),
1836
+ cost: parseCostCell(cells[5] ?? ""),
1837
+ date: (cells[6] ?? "").trim()
1838
+ };
1839
+ }
1840
+ function parseIntCell(cell) {
1841
+ const trimmed = cell.replace(/`/g, "").trim();
1842
+ if (!trimmed || isEmDashOrDash(trimmed))
1843
+ return null;
1844
+ const normalized = trimmed.replace(/[,_\s]/g, "");
1845
+ if (!/^-?\d+$/.test(normalized))
1846
+ return null;
1847
+ return Number(normalized);
1848
+ }
1849
+ function parseCostCell(cell) {
1850
+ const trimmed = cell.replace(/`/g, "").trim();
1851
+ if (!trimmed || isEmDashOrDash(trimmed))
1852
+ return null;
1853
+ const normalized = trimmed.replace(/^\$/, "").replace(/[,_\s]/g, "");
1854
+ if (!/^-?\d+(\.\d+)?$/.test(normalized))
1855
+ return null;
1856
+ return Number(normalized);
1857
+ }
1858
+ function isEmDashOrDash(s) {
1859
+ const t = s.trim();
1860
+ return t === "—" || t === "-" || t === "–";
1861
+ }
1862
+ // ../../packages/aeg-core/src/parse-token-report.ts
1863
+ var TOKEN_REPORT_HEADING = /^\s*(?:#{1,6}\s*Token report\s*|\*\*Token report\*\*)\s*$/i;
1864
+ 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;
1865
+ function parseTokenReportEntries(body) {
1866
+ const lines = body.split(/\r?\n/);
1867
+ const headingIdxs = [];
1868
+ lines.forEach((line, i) => {
1869
+ if (TOKEN_REPORT_HEADING.test(line))
1870
+ headingIdxs.push(i);
1871
+ });
1872
+ const out = [];
1873
+ for (let h = 0;h < headingIdxs.length; h++) {
1874
+ const start = headingIdxs[h] + 1;
1875
+ const end = h + 1 < headingIdxs.length ? headingIdxs[h + 1] : lines.length;
1876
+ const section = lines.slice(start, end).join(`
1877
+ `);
1878
+ const tableRows = parseTableSection(section);
1879
+ if (tableRows.length > 0) {
1880
+ out.push(...tableRows);
1881
+ continue;
1882
+ }
1883
+ const inlineRow = parseInlineFieldList(section);
1884
+ if (inlineRow)
1885
+ out.push(inlineRow);
1886
+ }
1887
+ return out;
1888
+ }
1889
+ function parseTableSection(section) {
1890
+ const lines = section.split(/\r?\n/);
1891
+ let i = 0;
1892
+ for (;i < lines.length; i++) {
1893
+ if ((lines[i] ?? "").trim().startsWith("|"))
1894
+ break;
1895
+ }
1896
+ if (i + 1 >= lines.length)
1897
+ return [];
1898
+ i += 2;
1899
+ const out = [];
1900
+ for (;i < lines.length; i++) {
1901
+ const trimmed = (lines[i] ?? "").trim();
1902
+ if (!trimmed.startsWith("|"))
1903
+ break;
1904
+ const row = rowFromCells(splitTableRow(trimmed));
1905
+ if (row)
1906
+ out.push(row);
1907
+ }
1908
+ return out;
1909
+ }
1910
+ function parseInlineFieldList(section) {
1911
+ const m = section.match(INLINE_FIELD_LIST);
1912
+ if (!m)
1913
+ return null;
1914
+ return rowFromCells([m[1], m[2], m[3], m[4], m[5], m[6], m[7]]);
1915
+ }
1823
1916
  // ../../packages/aeg-core/src/report-tokens.ts
1824
1917
  var DASH_LOOKALIKES = {
1825
1918
  "-": "‑",
@@ -1828,6 +1921,7 @@ var DASH_LOOKALIKES = {
1828
1921
  };
1829
1922
  var DASH_CHARS = new Set(Object.keys(DASH_LOOKALIKES));
1830
1923
  // ../../packages/aeg-core/src/claude-code-transcript.ts
1924
+ import { createHash } from "node:crypto";
1831
1925
  function summarizeTranscript(jsonl) {
1832
1926
  const seen = new Set;
1833
1927
  const components = {
@@ -1876,7 +1970,14 @@ function numberOr(value, fallback) {
1876
1970
  function sanitizeKey(value) {
1877
1971
  return value.replace(/[^A-Za-z0-9]+/g, "-");
1878
1972
  }
1973
+ function collisionResistantKey(value) {
1974
+ const digest = createHash("sha256").update(value).digest("hex");
1975
+ return `${sanitizeKey(value)}-${digest}`;
1976
+ }
1879
1977
  function transcriptPointerPath(projectDir, tmpDir) {
1978
+ return `${tmpDir}/claude-transcript-${collisionResistantKey(projectDir)}.txt`;
1979
+ }
1980
+ function legacyTranscriptPointerPath(projectDir, tmpDir) {
1880
1981
  return `${tmpDir}/claude-transcript-${sanitizeKey(projectDir)}.txt`;
1881
1982
  }
1882
1983
  function resolvePointer(explicitTranscriptPath, deps) {
@@ -1884,13 +1985,15 @@ function resolvePointer(explicitTranscriptPath, deps) {
1884
1985
  return { path: explicitTranscriptPath, corroborated: true };
1885
1986
  const projectDir = deps.env.CLAUDE_PROJECT_DIR ?? deps.cwd;
1886
1987
  const tmpDir = deps.env.TMPDIR ?? "/tmp";
1887
- const pointerPath = transcriptPointerPath(projectDir, tmpDir);
1988
+ const primaryPointerPath = transcriptPointerPath(projectDir, tmpDir);
1989
+ const legacyPointerPath = legacyTranscriptPointerPath(projectDir, tmpDir);
1888
1990
  const currentSessionId = deps.env.CLAUDE_CODE_SESSION_ID;
1889
- if (!deps.exists(pointerPath)) {
1991
+ const pointerPath = deps.exists(primaryPointerPath) ? primaryPointerPath : deps.exists(legacyPointerPath) ? legacyPointerPath : undefined;
1992
+ if (!pointerPath) {
1890
1993
  return {
1891
1994
  pointerExisted: false,
1892
1995
  corroborated: false,
1893
- 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."
1996
+ 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."
1894
1997
  };
1895
1998
  }
1896
1999
  let contents;
@@ -1965,6 +2068,9 @@ function isTokenCollectionWiringBroken(capability) {
1965
2068
  return false;
1966
2069
  return capability.reason !== "no-transcript-resolved";
1967
2070
  }
2071
+ // ../../packages/aeg-core/src/metering-io-guard.ts
2072
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from "node:fs";
2073
+ var GUARD_OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | fsConstants.O_NOFOLLOW;
1968
2074
  // ../../packages/aeg-core/src/file-classify.ts
1969
2075
  function isCodeFile(p) {
1970
2076
  if (p.endsWith(".md"))
@@ -2171,7 +2277,7 @@ function overrideActive(opts) {
2171
2277
  return false;
2172
2278
  }
2173
2279
  // ../../packages/aeg-core/src/premise-check.ts
2174
- import { createHash } from "node:crypto";
2280
+ import { createHash as createHash2 } from "node:crypto";
2175
2281
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
2176
2282
  function isPremiseHeader(line) {
2177
2283
  const stripped = line.replace(/[*#]/g, "").trim();
@@ -2216,7 +2322,7 @@ function checkPremises(assertions, fileReader) {
2216
2322
  } else if (a.kind === "absent" && content.includes(a.value)) {
2217
2323
  failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2218
2324
  } else if (a.kind === "sha256") {
2219
- const actual = createHash("sha256").update(content).digest("hex");
2325
+ const actual = createHash2("sha256").update(content).digest("hex");
2220
2326
  if (actual !== a.value.toLowerCase()) {
2221
2327
  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.`);
2222
2328
  }
@@ -1791,6 +1791,99 @@ var DERIVED_STATUSES = [
1791
1791
  "incoherent"
1792
1792
  ];
1793
1793
  var DERIVABLE_STATUSES = DERIVED_STATUSES.filter((s) => s !== "backlog");
1794
+ // ../../packages/aeg-core/src/parse-ledger.ts
1795
+ function rowFromCells(cells) {
1796
+ if (cells.length < 7)
1797
+ return null;
1798
+ const phase = (cells[0] ?? "").trim();
1799
+ if (!phase)
1800
+ return null;
1801
+ return {
1802
+ phase,
1803
+ role: (cells[1] ?? "").trim(),
1804
+ agentModel: (cells[2] ?? "").trim(),
1805
+ tokensIn: parseIntCell(cells[3] ?? ""),
1806
+ tokensOut: parseIntCell(cells[4] ?? ""),
1807
+ cost: parseCostCell(cells[5] ?? ""),
1808
+ date: (cells[6] ?? "").trim()
1809
+ };
1810
+ }
1811
+ function parseIntCell(cell) {
1812
+ const trimmed = cell.replace(/`/g, "").trim();
1813
+ if (!trimmed || isEmDashOrDash(trimmed))
1814
+ return null;
1815
+ const normalized = trimmed.replace(/[,_\s]/g, "");
1816
+ if (!/^-?\d+$/.test(normalized))
1817
+ return null;
1818
+ return Number(normalized);
1819
+ }
1820
+ function parseCostCell(cell) {
1821
+ const trimmed = cell.replace(/`/g, "").trim();
1822
+ if (!trimmed || isEmDashOrDash(trimmed))
1823
+ return null;
1824
+ const normalized = trimmed.replace(/^\$/, "").replace(/[,_\s]/g, "");
1825
+ if (!/^-?\d+(\.\d+)?$/.test(normalized))
1826
+ return null;
1827
+ return Number(normalized);
1828
+ }
1829
+ function isEmDashOrDash(s) {
1830
+ const t = s.trim();
1831
+ return t === "—" || t === "-" || t === "–";
1832
+ }
1833
+ // ../../packages/aeg-core/src/parse-token-report.ts
1834
+ var TOKEN_REPORT_HEADING = /^\s*(?:#{1,6}\s*Token report\s*|\*\*Token report\*\*)\s*$/i;
1835
+ 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;
1836
+ function parseTokenReportEntries(body) {
1837
+ const lines = body.split(/\r?\n/);
1838
+ const headingIdxs = [];
1839
+ lines.forEach((line, i) => {
1840
+ if (TOKEN_REPORT_HEADING.test(line))
1841
+ headingIdxs.push(i);
1842
+ });
1843
+ const out = [];
1844
+ for (let h = 0;h < headingIdxs.length; h++) {
1845
+ const start = headingIdxs[h] + 1;
1846
+ const end = h + 1 < headingIdxs.length ? headingIdxs[h + 1] : lines.length;
1847
+ const section = lines.slice(start, end).join(`
1848
+ `);
1849
+ const tableRows = parseTableSection(section);
1850
+ if (tableRows.length > 0) {
1851
+ out.push(...tableRows);
1852
+ continue;
1853
+ }
1854
+ const inlineRow = parseInlineFieldList(section);
1855
+ if (inlineRow)
1856
+ out.push(inlineRow);
1857
+ }
1858
+ return out;
1859
+ }
1860
+ function parseTableSection(section) {
1861
+ const lines = section.split(/\r?\n/);
1862
+ let i = 0;
1863
+ for (;i < lines.length; i++) {
1864
+ if ((lines[i] ?? "").trim().startsWith("|"))
1865
+ break;
1866
+ }
1867
+ if (i + 1 >= lines.length)
1868
+ return [];
1869
+ i += 2;
1870
+ const out = [];
1871
+ for (;i < lines.length; i++) {
1872
+ const trimmed = (lines[i] ?? "").trim();
1873
+ if (!trimmed.startsWith("|"))
1874
+ break;
1875
+ const row = rowFromCells(splitTableRow(trimmed));
1876
+ if (row)
1877
+ out.push(row);
1878
+ }
1879
+ return out;
1880
+ }
1881
+ function parseInlineFieldList(section) {
1882
+ const m = section.match(INLINE_FIELD_LIST);
1883
+ if (!m)
1884
+ return null;
1885
+ return rowFromCells([m[1], m[2], m[3], m[4], m[5], m[6], m[7]]);
1886
+ }
1794
1887
  // ../../packages/aeg-core/src/report-tokens.ts
1795
1888
  var DASH_LOOKALIKES = {
1796
1889
  "-": "‑",
@@ -1799,6 +1892,7 @@ var DASH_LOOKALIKES = {
1799
1892
  };
1800
1893
  var DASH_CHARS = new Set(Object.keys(DASH_LOOKALIKES));
1801
1894
  // ../../packages/aeg-core/src/claude-code-transcript.ts
1895
+ import { createHash } from "node:crypto";
1802
1896
  function summarizeTranscript(jsonl) {
1803
1897
  const seen = new Set;
1804
1898
  const components = {
@@ -1847,7 +1941,14 @@ function numberOr(value, fallback) {
1847
1941
  function sanitizeKey(value) {
1848
1942
  return value.replace(/[^A-Za-z0-9]+/g, "-");
1849
1943
  }
1944
+ function collisionResistantKey(value) {
1945
+ const digest = createHash("sha256").update(value).digest("hex");
1946
+ return `${sanitizeKey(value)}-${digest}`;
1947
+ }
1850
1948
  function transcriptPointerPath(projectDir, tmpDir) {
1949
+ return `${tmpDir}/claude-transcript-${collisionResistantKey(projectDir)}.txt`;
1950
+ }
1951
+ function legacyTranscriptPointerPath(projectDir, tmpDir) {
1851
1952
  return `${tmpDir}/claude-transcript-${sanitizeKey(projectDir)}.txt`;
1852
1953
  }
1853
1954
  function resolvePointer(explicitTranscriptPath, deps) {
@@ -1855,13 +1956,15 @@ function resolvePointer(explicitTranscriptPath, deps) {
1855
1956
  return { path: explicitTranscriptPath, corroborated: true };
1856
1957
  const projectDir = deps.env.CLAUDE_PROJECT_DIR ?? deps.cwd;
1857
1958
  const tmpDir = deps.env.TMPDIR ?? "/tmp";
1858
- const pointerPath = transcriptPointerPath(projectDir, tmpDir);
1959
+ const primaryPointerPath = transcriptPointerPath(projectDir, tmpDir);
1960
+ const legacyPointerPath = legacyTranscriptPointerPath(projectDir, tmpDir);
1859
1961
  const currentSessionId = deps.env.CLAUDE_CODE_SESSION_ID;
1860
- if (!deps.exists(pointerPath)) {
1962
+ const pointerPath = deps.exists(primaryPointerPath) ? primaryPointerPath : deps.exists(legacyPointerPath) ? legacyPointerPath : undefined;
1963
+ if (!pointerPath) {
1861
1964
  return {
1862
1965
  pointerExisted: false,
1863
1966
  corroborated: false,
1864
- 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."
1967
+ 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."
1865
1968
  };
1866
1969
  }
1867
1970
  let contents;
@@ -1936,6 +2039,9 @@ function isTokenCollectionWiringBroken(capability) {
1936
2039
  return false;
1937
2040
  return capability.reason !== "no-transcript-resolved";
1938
2041
  }
2042
+ // ../../packages/aeg-core/src/metering-io-guard.ts
2043
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from "node:fs";
2044
+ var GUARD_OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | fsConstants.O_NOFOLLOW;
1939
2045
  // ../../packages/aeg-core/src/file-classify.ts
1940
2046
  function isCodeFile(p) {
1941
2047
  if (p.endsWith(".md"))
@@ -2142,7 +2248,7 @@ function overrideActive(opts) {
2142
2248
  return false;
2143
2249
  }
2144
2250
  // ../../packages/aeg-core/src/premise-check.ts
2145
- import { createHash } from "node:crypto";
2251
+ import { createHash as createHash2 } from "node:crypto";
2146
2252
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
2147
2253
  function isPremiseHeader(line) {
2148
2254
  const stripped = line.replace(/[*#]/g, "").trim();
@@ -2187,7 +2293,7 @@ function checkPremises(assertions, fileReader) {
2187
2293
  } else if (a.kind === "absent" && content.includes(a.value)) {
2188
2294
  failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2189
2295
  } else if (a.kind === "sha256") {
2190
- const actual = createHash("sha256").update(content).digest("hex");
2296
+ const actual = createHash2("sha256").update(content).digest("hex");
2191
2297
  if (actual !== a.value.toLowerCase()) {
2192
2298
  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.`);
2193
2299
  }
@@ -4375,7 +4481,7 @@ function emitCheckError(error) {
4375
4481
 
4376
4482
  // src/lib/config.ts
4377
4483
  import { execFileSync as execFileSync2 } from "node:child_process";
4378
- import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
4484
+ import { existsSync, mkdirSync, readFileSync as readFileSync2, realpathSync, writeFileSync } from "node:fs";
4379
4485
  import { homedir } from "node:os";
4380
4486
  import { dirname, join, resolve } from "node:path";
4381
4487
  import { z as z2 } from "zod";
@@ -4668,7 +4774,7 @@ function loadConfig() {
4668
4774
  if (!path)
4669
4775
  return null;
4670
4776
  try {
4671
- const raw = JSON.parse(readFileSync(path, "utf-8"));
4777
+ const raw = JSON.parse(readFileSync2(path, "utf-8"));
4672
4778
  return stripGlobalOnlyKeys(VinayaConfigSchema.parse(raw), path);
4673
4779
  } catch {
4674
4780
  return null;
@@ -1791,6 +1791,99 @@ var DERIVED_STATUSES = [
1791
1791
  "incoherent"
1792
1792
  ];
1793
1793
  var DERIVABLE_STATUSES = DERIVED_STATUSES.filter((s) => s !== "backlog");
1794
+ // ../../packages/aeg-core/src/parse-ledger.ts
1795
+ function rowFromCells(cells) {
1796
+ if (cells.length < 7)
1797
+ return null;
1798
+ const phase = (cells[0] ?? "").trim();
1799
+ if (!phase)
1800
+ return null;
1801
+ return {
1802
+ phase,
1803
+ role: (cells[1] ?? "").trim(),
1804
+ agentModel: (cells[2] ?? "").trim(),
1805
+ tokensIn: parseIntCell(cells[3] ?? ""),
1806
+ tokensOut: parseIntCell(cells[4] ?? ""),
1807
+ cost: parseCostCell(cells[5] ?? ""),
1808
+ date: (cells[6] ?? "").trim()
1809
+ };
1810
+ }
1811
+ function parseIntCell(cell) {
1812
+ const trimmed = cell.replace(/`/g, "").trim();
1813
+ if (!trimmed || isEmDashOrDash(trimmed))
1814
+ return null;
1815
+ const normalized = trimmed.replace(/[,_\s]/g, "");
1816
+ if (!/^-?\d+$/.test(normalized))
1817
+ return null;
1818
+ return Number(normalized);
1819
+ }
1820
+ function parseCostCell(cell) {
1821
+ const trimmed = cell.replace(/`/g, "").trim();
1822
+ if (!trimmed || isEmDashOrDash(trimmed))
1823
+ return null;
1824
+ const normalized = trimmed.replace(/^\$/, "").replace(/[,_\s]/g, "");
1825
+ if (!/^-?\d+(\.\d+)?$/.test(normalized))
1826
+ return null;
1827
+ return Number(normalized);
1828
+ }
1829
+ function isEmDashOrDash(s) {
1830
+ const t = s.trim();
1831
+ return t === "—" || t === "-" || t === "–";
1832
+ }
1833
+ // ../../packages/aeg-core/src/parse-token-report.ts
1834
+ var TOKEN_REPORT_HEADING = /^\s*(?:#{1,6}\s*Token report\s*|\*\*Token report\*\*)\s*$/i;
1835
+ 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;
1836
+ function parseTokenReportEntries(body) {
1837
+ const lines = body.split(/\r?\n/);
1838
+ const headingIdxs = [];
1839
+ lines.forEach((line, i) => {
1840
+ if (TOKEN_REPORT_HEADING.test(line))
1841
+ headingIdxs.push(i);
1842
+ });
1843
+ const out = [];
1844
+ for (let h = 0;h < headingIdxs.length; h++) {
1845
+ const start = headingIdxs[h] + 1;
1846
+ const end = h + 1 < headingIdxs.length ? headingIdxs[h + 1] : lines.length;
1847
+ const section = lines.slice(start, end).join(`
1848
+ `);
1849
+ const tableRows = parseTableSection(section);
1850
+ if (tableRows.length > 0) {
1851
+ out.push(...tableRows);
1852
+ continue;
1853
+ }
1854
+ const inlineRow = parseInlineFieldList(section);
1855
+ if (inlineRow)
1856
+ out.push(inlineRow);
1857
+ }
1858
+ return out;
1859
+ }
1860
+ function parseTableSection(section) {
1861
+ const lines = section.split(/\r?\n/);
1862
+ let i = 0;
1863
+ for (;i < lines.length; i++) {
1864
+ if ((lines[i] ?? "").trim().startsWith("|"))
1865
+ break;
1866
+ }
1867
+ if (i + 1 >= lines.length)
1868
+ return [];
1869
+ i += 2;
1870
+ const out = [];
1871
+ for (;i < lines.length; i++) {
1872
+ const trimmed = (lines[i] ?? "").trim();
1873
+ if (!trimmed.startsWith("|"))
1874
+ break;
1875
+ const row = rowFromCells(splitTableRow(trimmed));
1876
+ if (row)
1877
+ out.push(row);
1878
+ }
1879
+ return out;
1880
+ }
1881
+ function parseInlineFieldList(section) {
1882
+ const m = section.match(INLINE_FIELD_LIST);
1883
+ if (!m)
1884
+ return null;
1885
+ return rowFromCells([m[1], m[2], m[3], m[4], m[5], m[6], m[7]]);
1886
+ }
1794
1887
  // ../../packages/aeg-core/src/report-tokens.ts
1795
1888
  var DASH_LOOKALIKES = {
1796
1889
  "-": "‑",
@@ -1799,6 +1892,7 @@ var DASH_LOOKALIKES = {
1799
1892
  };
1800
1893
  var DASH_CHARS = new Set(Object.keys(DASH_LOOKALIKES));
1801
1894
  // ../../packages/aeg-core/src/claude-code-transcript.ts
1895
+ import { createHash } from "node:crypto";
1802
1896
  function summarizeTranscript(jsonl) {
1803
1897
  const seen = new Set;
1804
1898
  const components = {
@@ -1847,7 +1941,14 @@ function numberOr(value, fallback) {
1847
1941
  function sanitizeKey(value) {
1848
1942
  return value.replace(/[^A-Za-z0-9]+/g, "-");
1849
1943
  }
1944
+ function collisionResistantKey(value) {
1945
+ const digest = createHash("sha256").update(value).digest("hex");
1946
+ return `${sanitizeKey(value)}-${digest}`;
1947
+ }
1850
1948
  function transcriptPointerPath(projectDir, tmpDir) {
1949
+ return `${tmpDir}/claude-transcript-${collisionResistantKey(projectDir)}.txt`;
1950
+ }
1951
+ function legacyTranscriptPointerPath(projectDir, tmpDir) {
1851
1952
  return `${tmpDir}/claude-transcript-${sanitizeKey(projectDir)}.txt`;
1852
1953
  }
1853
1954
  function resolvePointer(explicitTranscriptPath, deps) {
@@ -1855,13 +1956,15 @@ function resolvePointer(explicitTranscriptPath, deps) {
1855
1956
  return { path: explicitTranscriptPath, corroborated: true };
1856
1957
  const projectDir = deps.env.CLAUDE_PROJECT_DIR ?? deps.cwd;
1857
1958
  const tmpDir = deps.env.TMPDIR ?? "/tmp";
1858
- const pointerPath = transcriptPointerPath(projectDir, tmpDir);
1959
+ const primaryPointerPath = transcriptPointerPath(projectDir, tmpDir);
1960
+ const legacyPointerPath = legacyTranscriptPointerPath(projectDir, tmpDir);
1859
1961
  const currentSessionId = deps.env.CLAUDE_CODE_SESSION_ID;
1860
- if (!deps.exists(pointerPath)) {
1962
+ const pointerPath = deps.exists(primaryPointerPath) ? primaryPointerPath : deps.exists(legacyPointerPath) ? legacyPointerPath : undefined;
1963
+ if (!pointerPath) {
1861
1964
  return {
1862
1965
  pointerExisted: false,
1863
1966
  corroborated: false,
1864
- 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."
1967
+ 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."
1865
1968
  };
1866
1969
  }
1867
1970
  let contents;
@@ -1936,6 +2039,9 @@ function isTokenCollectionWiringBroken(capability) {
1936
2039
  return false;
1937
2040
  return capability.reason !== "no-transcript-resolved";
1938
2041
  }
2042
+ // ../../packages/aeg-core/src/metering-io-guard.ts
2043
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readFileSync } from "node:fs";
2044
+ var GUARD_OPEN_FLAGS = fsConstants.O_RDONLY | fsConstants.O_NONBLOCK | fsConstants.O_NOFOLLOW;
1939
2045
  // ../../packages/aeg-core/src/file-classify.ts
1940
2046
  function isCodeFile(p) {
1941
2047
  if (p.endsWith(".md"))
@@ -2142,7 +2248,7 @@ function overrideActive(opts) {
2142
2248
  return false;
2143
2249
  }
2144
2250
  // ../../packages/aeg-core/src/premise-check.ts
2145
- import { createHash } from "node:crypto";
2251
+ import { createHash as createHash2 } from "node:crypto";
2146
2252
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
2147
2253
  function isPremiseHeader(line) {
2148
2254
  const stripped = line.replace(/[*#]/g, "").trim();
@@ -2187,7 +2293,7 @@ function checkPremises(assertions, fileReader) {
2187
2293
  } else if (a.kind === "absent" && content.includes(a.value)) {
2188
2294
  failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2189
2295
  } else if (a.kind === "sha256") {
2190
- const actual = createHash("sha256").update(content).digest("hex");
2296
+ const actual = createHash2("sha256").update(content).digest("hex");
2191
2297
  if (actual !== a.value.toLowerCase()) {
2192
2298
  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.`);
2193
2299
  }