@attalabs/vinaya 0.28.0 → 0.29.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 (138) hide show
  1. package/README.md +1 -1
  2. package/aeg-root/contracts/planner-developer.md +4 -1
  3. package/aeg-root/contracts/planner-operator.md +86 -0
  4. package/aeg-root/contracts/principal-operator.md +88 -0
  5. package/aeg-root/roles/developer.md +2 -1
  6. package/aeg-root/roles/operator.md +133 -0
  7. package/aeg-root/roles/planner.md +4 -0
  8. package/aeg-root/skills/aeg-context-packets/SKILL.md +123 -0
  9. package/aeg-root/skills/aeg-context-packets/examples/operator-start.md +30 -0
  10. package/aeg-root/templates/brief-template.md +6 -2
  11. package/dist/checks/bin/check-body-bare-digits.js +376 -16
  12. package/dist/checks/bin/check-branch-topology.js +403 -16
  13. package/dist/checks/bin/check-brief-shape.js +380 -19
  14. package/dist/checks/bin/check-changeset-coverage.js +673 -33
  15. package/dist/checks/bin/check-closes-n.js +403 -16
  16. package/dist/checks/bin/check-coherence.js +410 -16
  17. package/dist/checks/bin/check-dead-branch-push.js +369 -16
  18. package/dist/checks/bin/check-dispatch-readiness.js +410 -16
  19. package/dist/checks/bin/check-doc-coverage-push.js +670 -30
  20. package/dist/checks/bin/check-doc-coverage.js +672 -32
  21. package/dist/checks/bin/check-doctrine-no-procedures.js +376 -16
  22. package/dist/checks/bin/check-doctrine-portability.js +670 -30
  23. package/dist/checks/bin/check-evidence-fresh.js +762 -113
  24. package/dist/checks/bin/check-exec-bits.js +668 -28
  25. package/dist/checks/bin/check-first-push-dispatch.js +410 -16
  26. package/dist/checks/bin/check-issue-assignment.js +403 -16
  27. package/dist/checks/bin/check-issue-milestone-attach.js +369 -16
  28. package/dist/checks/bin/check-issue-objectives-numbering.js +369 -16
  29. package/dist/checks/bin/check-issue-parts-coverage.js +369 -16
  30. package/dist/checks/bin/check-issue-surface-globs.js +410 -16
  31. package/dist/checks/bin/check-issue-title-grammar.js +369 -16
  32. package/dist/checks/bin/check-issue-tranche-label.js +369 -16
  33. package/dist/checks/bin/check-main-branch-refusal.js +369 -16
  34. package/dist/checks/bin/check-no-disk-state.js +369 -16
  35. package/dist/checks/bin/check-pr-premise-reassert.js +376 -16
  36. package/dist/checks/bin/check-pr-report-density.js +369 -16
  37. package/dist/checks/bin/check-quoted-command.js +671 -31
  38. package/dist/checks/bin/check-reader-resolvable-prose.js +674 -34
  39. package/dist/checks/bin/check-registry-gates.js +369 -16
  40. package/dist/checks/bin/check-retired-vocabulary.js +669 -29
  41. package/dist/checks/bin/check-review-gate.js +391 -16
  42. package/dist/checks/bin/check-single-plan-pr.js +369 -16
  43. package/dist/checks/bin/check-surface-scope.js +403 -16
  44. package/dist/checks/bin/check-test-plan.js +369 -16
  45. package/dist/checks/bin/check-token-collection-wired.js +369 -16
  46. package/dist/checks/bin/check-token-report.js +382 -19
  47. package/dist/checks/bin/check-workspace-escape.js +668 -28
  48. package/dist/index.js +15307 -10932
  49. package/dist/lib/pre-push-select-tests.js +154 -11
  50. package/package.json +1 -1
  51. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  52. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  53. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  54. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error/page.js +2 -1
  55. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  56. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  57. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  58. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  59. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  61. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  62. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  63. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  64. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js +8 -7
  65. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  66. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  67. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  68. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js +8 -7
  69. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  70. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  71. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  72. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js +9 -8
  73. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  74. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  75. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  76. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js +9 -8
  77. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  78. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  79. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  80. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js +8 -7
  81. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  82. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  83. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +16 -4
  84. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js +10 -8
  85. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  86. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  87. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  88. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js +8 -7
  89. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  90. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  91. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  92. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js +8 -7
  93. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  94. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  95. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  96. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js +9 -8
  97. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  98. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  99. 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
  100. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__08f5pba._.js +3 -0
  101. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1o_0tjy._.js → [root-of-the-server]__0h9yhwx._.js} +2 -2
  102. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0053k9k._.js → [root-of-the-server]__0ls23oh._.js} +3 -2
  103. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0puovz5._.js → [root-of-the-server]__0nye8tb._.js} +3 -2
  104. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__18kqy4q._.js → [root-of-the-server]__0tfykr-._.js} +2 -2
  105. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0o771t1._.js → [root-of-the-server]__0th3gyp._.js} +3 -2
  106. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1-zcufa._.js +51 -0
  107. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0p8q38b._.js → [root-of-the-server]__11svemm._.js} +1 -1
  108. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__02c71kv._.js → [root-of-the-server]__140m1i_._.js} +2 -2
  109. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1bh2awk._.js +3 -0
  110. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0112h-k._.js → [root-of-the-server]__1gjqmhq._.js} +3 -2
  111. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1qmxez3._.js +4 -0
  112. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1r47dr7._.js +28 -0
  113. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
  114. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_01fv4fj._.js +1 -1
  115. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0gvm3og._.js → _096f46i._.js} +3 -2
  116. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0lwxg63._.js → _0af2one._.js} +3 -2
  117. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_1n0cnq-._.js → _0zf4d27._.js} +45 -2
  118. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_03x_w6q._.js → _1-wo68i._.js} +3 -2
  119. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_projects_[name]_tranches_[slug]_05ufo8i._.js +1 -12
  120. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1wdusod._.js +3 -0
  121. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{node_modules_1vo08dj._.js → node_modules_@clerk_nextjs_dist_esm_app-router_server-actions_1x7vfhn.js} +3 -4
  122. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_1khj-jh._.js +3 -0
  123. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  124. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  125. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  126. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +17 -5
  127. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3_9xytdmiv1xi.js → 25f3-jtiv8p5n.js} +4 -4
  128. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0bn8c8v5q429o.js → 27-6ym7lp2v8o.js} +1 -1
  129. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3-6a3tinbdb-7.js → 3daxns3o--9me.js} +1 -1
  130. package/studio-standalone/apps/vinaya-studio/web/tsconfig.json +12 -0
  131. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0z6dav-._.js +0 -51
  132. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__13rrmhr._.js +0 -3
  133. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__17h4sy8._.js +0 -45
  134. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +0 -3
  135. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_17sz44y._.js +0 -3
  136. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_buildManifest.js +0 -0
  137. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_clientMiddlewareManifest.js +0 -0
  138. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_ssgManifest.js +0 -0
@@ -1647,6 +1647,52 @@ var systemEnv3 = {
1647
1647
  ...process.env,
1648
1648
  PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
1649
1649
  };
1650
+ var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
1651
+ var cached;
1652
+ var inflight;
1653
+ async function resolveRepo(exec = defaultExec) {
1654
+ if (cached !== undefined)
1655
+ return cached;
1656
+ const fromEnv = process.env.AEG_REPO;
1657
+ if (fromEnv) {
1658
+ const parsed = parseOwnerRepo(fromEnv);
1659
+ if (parsed) {
1660
+ cached = parsed;
1661
+ return cached;
1662
+ }
1663
+ }
1664
+ if (inflight)
1665
+ return inflight;
1666
+ inflight = (async () => {
1667
+ try {
1668
+ const { stdout } = await exec();
1669
+ cached = parseGitRemoteUrl(stdout.trim());
1670
+ return cached;
1671
+ } catch (err) {
1672
+ const message = err instanceof Error ? err.message : String(err);
1673
+ console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
1674
+ return null;
1675
+ } finally {
1676
+ inflight = undefined;
1677
+ }
1678
+ })();
1679
+ return inflight;
1680
+ }
1681
+ function parseGitRemoteUrl(url) {
1682
+ const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
1683
+ if (ssh?.[1] && ssh[2])
1684
+ return { owner: ssh[1], repo: ssh[2] };
1685
+ const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
1686
+ if (https?.[1] && https[2])
1687
+ return { owner: https[1], repo: https[2] };
1688
+ return null;
1689
+ }
1690
+ function parseOwnerRepo(value) {
1691
+ const match = value.match(/^([^/]+)\/(.+)$/);
1692
+ if (!match?.[1] || !match[2])
1693
+ return null;
1694
+ return { owner: match[1], repo: match[2] };
1695
+ }
1650
1696
  // ../../packages/aeg-core/src/anchored-region.ts
1651
1697
  function anchoredRegionBounds(body, field) {
1652
1698
  const masked = maskCode(body);
@@ -1959,6 +2005,7 @@ var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\
1959
2005
  var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
1960
2006
  var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
1961
2007
  var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
2008
+ var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
1962
2009
  function firstFiveLines(comment) {
1963
2010
  return comment.split(`
1964
2011
  `).slice(0, 5).join(`
@@ -1994,6 +2041,15 @@ function extractPolicyDigest(comment) {
1994
2041
  const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
1995
2042
  return m ? m[1].toLowerCase() : null;
1996
2043
  }
2044
+ function firstThirteenLines(comment) {
2045
+ return comment.split(`
2046
+ `).slice(0, 13).join(`
2047
+ `);
2048
+ }
2049
+ function extractBaseSha(comment) {
2050
+ const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
2051
+ return m ? m[1].toLowerCase() : null;
2052
+ }
1997
2053
  var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
1998
2054
  function extractFindingSeverities(comment) {
1999
2055
  return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
@@ -2011,6 +2067,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2011
2067
  rulingOrdinal: null,
2012
2068
  briefHash: null,
2013
2069
  policyDigest: null,
2070
+ baseSha: null,
2014
2071
  findingSeverities: [],
2015
2072
  danglingNote: `no ${missingLabel} verdict comment found on this PR`
2016
2073
  };
@@ -2025,6 +2082,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2025
2082
  rulingOrdinal: null,
2026
2083
  briefHash: null,
2027
2084
  policyDigest: null,
2085
+ baseSha: null,
2028
2086
  findingSeverities: [],
2029
2087
  danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
2030
2088
  };
@@ -2036,6 +2094,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2036
2094
  rulingOrdinal: extractRulingOrdinal(latest),
2037
2095
  briefHash: extractBriefHash(latest),
2038
2096
  policyDigest: extractPolicyDigest(latest),
2097
+ baseSha: extractBaseSha(latest),
2039
2098
  findingSeverities: extractFindingSeverities(latest),
2040
2099
  danglingNote: null
2041
2100
  };
@@ -3949,7 +4008,11 @@ function briefHash(brief) {
3949
4008
  `).digest("hex");
3950
4009
  }
3951
4010
  function policyDigest(policy) {
3952
- return createHash4("sha256").update(JSON.stringify({ codeReviewThreshold: policy.codeReviewThreshold, securityThreshold: policy.securityThreshold })).digest("hex");
4011
+ return createHash4("sha256").update(JSON.stringify({
4012
+ codeReviewThreshold: policy.codeReviewThreshold,
4013
+ securityThreshold: policy.securityThreshold,
4014
+ maxRounds: policy.maxRounds
4015
+ })).digest("hex");
3953
4016
  }
3954
4017
  function isBoundToHead(echoed, headSha) {
3955
4018
  if (!echoed.headSha)
@@ -3965,8 +4028,12 @@ function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
3965
4028
  return false;
3966
4029
  return judged === current;
3967
4030
  }
3968
- function isBoundToPatch(echoed, headSha, patchIdOf) {
3969
- return isBoundToHead(echoed, headSha) || isBoundByPatchIdentity(echoed, headSha, patchIdOf);
4031
+ function isBoundToBase(echoed, currentBase) {
4032
+ if (currentBase === null)
4033
+ return true;
4034
+ if (!echoed.baseSha)
4035
+ return false;
4036
+ return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
3970
4037
  }
3971
4038
  function isBoundToObjectives(echoed, currentVersion) {
3972
4039
  if (currentVersion === null)
@@ -3987,14 +4054,18 @@ function isBoundToPolicy(echoed, currentDigest) {
3987
4054
  return echoed.policyDigest === currentDigest;
3988
4055
  }
3989
4056
  function compareManifest(echoed, current, patchIdOf) {
3990
- const head = isBoundToPatch(echoed, current.headSha, patchIdOf);
4057
+ const exactHead = isBoundToHead(echoed, current.headSha);
4058
+ const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
4059
+ const head = exactHead || patchHead;
4060
+ const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
3991
4061
  const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
3992
4062
  const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
3993
4063
  const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
3994
4064
  const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
3995
4065
  return {
3996
- bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
4066
+ bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
3997
4067
  head,
4068
+ base,
3998
4069
  briefHash: briefHashBound,
3999
4070
  objectivesVersion: objectivesVersion2,
4000
4071
  rulingOrdinal,
@@ -4046,6 +4117,7 @@ function checkReviewGate(input) {
4046
4117
  const securityClean = securityTextClean && securityPolicyClean;
4047
4118
  const currentManifest = {
4048
4119
  headSha: input.headSha,
4120
+ baseSha: input.baseSha ?? null,
4049
4121
  briefHash: input.briefHash ?? null,
4050
4122
  objectivesVersion: input.objectivesVersion,
4051
4123
  rulingOrdinal: input.rulingOrdinal,
@@ -4053,6 +4125,7 @@ function checkReviewGate(input) {
4053
4125
  };
4054
4126
  const codeReviewEchoed = {
4055
4127
  headSha: codeReview.headSha,
4128
+ baseSha: codeReview.baseSha,
4056
4129
  briefHash: codeReview.briefHash,
4057
4130
  objectivesVersion: codeReview.objectivesVersion,
4058
4131
  rulingOrdinal: codeReview.rulingOrdinal,
@@ -4060,6 +4133,7 @@ function checkReviewGate(input) {
4060
4133
  };
4061
4134
  const securityEchoed = {
4062
4135
  headSha: security.headSha,
4136
+ baseSha: security.baseSha,
4063
4137
  briefHash: security.briefHash,
4064
4138
  objectivesVersion: security.objectivesVersion,
4065
4139
  rulingOrdinal: security.rulingOrdinal,
@@ -4087,6 +4161,8 @@ function checkReviewGate(input) {
4087
4161
  problems.push(`code-reviewer verdict says APPROVE but carries a finding (${codeReviewPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's code-review policy threshold (${policy.codeReviewThreshold}) — a reviewer's own APPROVE never overrides policy`);
4088
4162
  } else if (!codeReviewBound) {
4089
4163
  problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
4164
+ } else if (!codeReviewBinding.base) {
4165
+ problems.push(`the newest code-review verdict was cast against base ${codeReview.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
4090
4166
  } else if (!codeReviewObjectivesBound) {
4091
4167
  problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
4092
4168
  } else if (!codeReviewRulingsBound) {
@@ -4102,6 +4178,8 @@ function checkReviewGate(input) {
4102
4178
  problems.push(`security-review verdict says PASS but carries a finding (${securityPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's security policy threshold (${policy.securityThreshold}) — a reviewer's own PASS never overrides policy`);
4103
4179
  } else if (!securityBound) {
4104
4180
  problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
4181
+ } else if (!securityBinding.base) {
4182
+ problems.push(`the newest security-review verdict was cast against base ${security.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
4105
4183
  } else if (!securityObjectivesBound) {
4106
4184
  problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
4107
4185
  } else if (!securityRulingsBound) {
@@ -4959,8 +5037,8 @@ var TaskToolErrorSchema = z.object({
4959
5037
  detail: z.string().optional()
4960
5038
  });
4961
5039
  var TaskToolRefSchema = z.union([
4962
- z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
4963
- z.object({ issue: z.number().int().positive() })
5040
+ z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
5041
+ z.object({ issue: z.number().int().positive() }).strict()
4964
5042
  ]);
4965
5043
  var MAX_PAGE_LIMIT = 100;
4966
5044
  var PageRequestSchema = z.object({
@@ -4974,7 +5052,7 @@ var ObservedSchema = z.object({
4974
5052
  });
4975
5053
  var TaskStatusInputSchema = z.object({
4976
5054
  task: TaskToolRefSchema.optional()
4977
- }).merge(PageRequestSchema);
5055
+ }).merge(PageRequestSchema).strict();
4978
5056
  var TaskStatusItemSchema = z.object({
4979
5057
  task: TaskToolRefSchema,
4980
5058
  issue: z.number().int().positive(),
@@ -4998,9 +5076,20 @@ var EscalationEvidenceSchema = z.object({
4998
5076
  reviewer: z.string().nullable(),
4999
5077
  security: z.string().nullable()
5000
5078
  });
5079
+ var EscalationRunIdentitySchema = z.object({
5080
+ runId: z.string(),
5081
+ pid: z.number().int().positive(),
5082
+ host: z.string()
5083
+ });
5084
+ var EscalationInputVersionsSchema = z.object({
5085
+ briefHash: z.string().nullable(),
5086
+ objectivesVersion: z.string().nullable(),
5087
+ rulingOrdinal: z.number().int().nonnegative(),
5088
+ policyDigest: z.string()
5089
+ });
5001
5090
  var TaskEscalationReadInputSchema = z.object({
5002
5091
  task: TaskToolRefSchema
5003
- }).merge(PageRequestSchema);
5092
+ }).merge(PageRequestSchema).strict();
5004
5093
  var TaskEscalationPacketSchema = z.object({
5005
5094
  reason: z.string(),
5006
5095
  detail: z.string().nullable(),
@@ -5008,7 +5097,9 @@ var TaskEscalationPacketSchema = z.object({
5008
5097
  evidence: EscalationEvidenceSchema.nullable(),
5009
5098
  attemptedRecovery: z.string(),
5010
5099
  requestedAuthority: RequestedAuthoritySchema,
5011
- permittedNextActions: z.array(z.string())
5100
+ permittedNextActions: z.array(z.string()),
5101
+ runIdentity: EscalationRunIdentitySchema.nullable(),
5102
+ inputVersions: EscalationInputVersionsSchema.nullable()
5012
5103
  }).merge(ObservedSchema);
5013
5104
  var TaskEscalationReadResultSchema = z.object({
5014
5105
  items: z.array(TaskEscalationPacketSchema),
@@ -5017,15 +5108,48 @@ var TaskEscalationReadResultSchema = z.object({
5017
5108
  var TaskStartInputSchema = z.object({
5018
5109
  tranche: z.string().min(1),
5019
5110
  id: z.string().min(1)
5111
+ }).strict();
5112
+ var TaskStartResultSchema = z.object({
5113
+ requestId: z.string().min(1),
5114
+ run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
5115
+ started: z.boolean(),
5116
+ startedAt: z.string(),
5117
+ mode: z.literal("attended")
5020
5118
  });
5021
5119
  var TaskResumeInputSchema = z.object({
5022
5120
  task: TaskToolRefSchema
5023
- });
5121
+ }).strict();
5024
5122
  var TaskCancelInputSchema = z.object({
5025
5123
  task: TaskToolRefSchema,
5026
5124
  reason: z.string().min(1)
5125
+ }).strict();
5126
+ var TaskResumeResultSchema = z.object({
5127
+ task: z.number().int().positive(),
5128
+ pr: z.number().int().positive(),
5129
+ escalationId: z.string().min(1),
5130
+ outcome: z.enum(["started", "already_resumed"]),
5131
+ authenticatedBy: z.string().min(1),
5132
+ authenticatedFrom: z.string().min(1)
5133
+ });
5134
+ var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
5135
+ var TaskCancelResultSchema = z.object({
5136
+ task: z.number().int().positive(),
5137
+ pr: z.number().int().positive(),
5138
+ escalationId: z.string().min(1),
5139
+ outcome: TaskCancelOutcomeSchema,
5140
+ authenticatedBy: z.string().min(1),
5141
+ authenticatedFrom: z.string().min(1),
5142
+ fencedEffectKeys: z.array(z.string())
5027
5143
  });
5028
- var NoResultSchema = z.never();
5144
+ var TASK_TOOL_NAMES = [
5145
+ "task_start",
5146
+ "task_status",
5147
+ "task_escalation_read",
5148
+ "task_resume",
5149
+ "task_cancel"
5150
+ ];
5151
+ var OPERATOR_STATUS_FOLLOW = "task_status_follow";
5152
+ var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
5029
5153
  // ../../packages/aeg-core/src/first-push-dispatch-gate.ts
5030
5154
  function parseTaskBranch(branch) {
5031
5155
  const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
@@ -5248,6 +5372,9 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
5248
5372
  }
5249
5373
  return findings;
5250
5374
  }
5375
+ // ../../packages/aeg-core/src/log/envelope.ts
5376
+ import { createHash as createHash5 } from "node:crypto";
5377
+
5251
5378
  // ../../packages/aeg-core/src/log/schema.ts
5252
5379
  import { z as z2 } from "zod";
5253
5380
  var ROLE_VALUES = [
@@ -5349,7 +5476,8 @@ var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
5349
5476
  }).strict(),
5350
5477
  z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
5351
5478
  z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
5352
- z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
5479
+ z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
5480
+ z2.object({ type: z2.literal("completed") }).strict()
5353
5481
  ]);
5354
5482
  var dispatchShared = {
5355
5483
  meta: HeaderMetaSchema,
@@ -5409,7 +5537,8 @@ var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
5409
5537
  round: z2.number().int(),
5410
5538
  head: z2.string(),
5411
5539
  all_approve: z2.boolean(),
5412
- blockers: z2.number().int().nonnegative()
5540
+ blockers: z2.number().int().nonnegative(),
5541
+ findings: z2.array(ReviewFindingSchema).optional()
5413
5542
  }).strict(),
5414
5543
  z2.object({
5415
5544
  ...loopShared,
@@ -5588,7 +5717,9 @@ var roleAttemptShared = {
5588
5717
  kind: z2.literal("role_attempt"),
5589
5718
  ...envelopeTail,
5590
5719
  actor: z2.string().nullable(),
5591
- attempt: z2.number().int().nullable()
5720
+ attempt: z2.number().int().nullable(),
5721
+ effect_id: z2.string(),
5722
+ model: z2.string().nullable()
5592
5723
  };
5593
5724
  var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
5594
5725
  z2.object({
@@ -5647,6 +5778,144 @@ var LogEventSchema = z2.union([
5647
5778
  HandoffEventSchema,
5648
5779
  EffectEventSchema
5649
5780
  ]);
5781
+
5782
+ // ../../packages/aeg-core/src/log/envelope.ts
5783
+ function isRole(value) {
5784
+ return value !== undefined && ROLE_VALUES.includes(value);
5785
+ }
5786
+ function actorIdFromEnv(role) {
5787
+ return role === undefined || role === "" ? null : role;
5788
+ }
5789
+ function lineageFieldFromEnv(value) {
5790
+ return value === undefined || value === "" ? null : value;
5791
+ }
5792
+ function attemptFromEnv(value) {
5793
+ if (value === undefined || value === "")
5794
+ return null;
5795
+ const n = Number(value);
5796
+ return Number.isInteger(n) ? n : null;
5797
+ }
5798
+ function provenanceFor(input) {
5799
+ if (input.provenance)
5800
+ return input.provenance;
5801
+ if (input.env.role || input.env.task)
5802
+ return "env_correlated";
5803
+ return "unavailable";
5804
+ }
5805
+ function issueFromTask(task) {
5806
+ if (task === undefined || task === "")
5807
+ return null;
5808
+ const n = Number(task);
5809
+ return Number.isInteger(n) ? n : null;
5810
+ }
5811
+ function roundFromEnv(round) {
5812
+ if (round === undefined || round === "")
5813
+ return;
5814
+ const n = Number(round);
5815
+ return Number.isInteger(n) ? n : undefined;
5816
+ }
5817
+ function buildHeader(input) {
5818
+ const role = isRole(input.env.role) ? input.env.role : "unattributed";
5819
+ const round = roundFromEnv(input.env.round);
5820
+ const subject = {
5821
+ issue: issueFromTask(input.env.task),
5822
+ role,
5823
+ ...round !== undefined ? { round } : {},
5824
+ ...input.subject ?? {}
5825
+ };
5826
+ return {
5827
+ meta: {
5828
+ schema: 2,
5829
+ ts: input.now.toISOString(),
5830
+ run_id: input.runId,
5831
+ seq: input.seq,
5832
+ repo: input.repo,
5833
+ vinaya: input.vinaya,
5834
+ doctrine: input.doctrine,
5835
+ host: input.host,
5836
+ machine: createHash5("sha256").update(input.hostname).digest("hex"),
5837
+ event_id: input.eventId,
5838
+ process_id: input.processId,
5839
+ actor_id: actorIdFromEnv(input.env.role),
5840
+ lineage: {
5841
+ run: lineageFieldFromEnv(input.env.run),
5842
+ attempt: attemptFromEnv(input.env.attempt),
5843
+ parent: lineageFieldFromEnv(input.env.parent)
5844
+ },
5845
+ input_versions: {
5846
+ objectives_version: input.inputVersions?.objectivesVersion ?? null,
5847
+ brief_hash: input.inputVersions?.briefHash ?? null,
5848
+ ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
5849
+ policy_digest: input.inputVersions?.policyDigest ?? null
5850
+ },
5851
+ provenance: provenanceFor(input)
5852
+ },
5853
+ subject
5854
+ };
5855
+ }
5856
+ // ../../packages/aeg-core/src/log/redact.ts
5857
+ var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
5858
+ var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
5859
+ var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
5860
+ var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
5861
+ var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
5862
+ var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
5863
+ var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
5864
+ var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
5865
+ var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
5866
+ var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
5867
+ var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
5868
+ var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
5869
+ var GENERIC_SECRET_ASSIGNMENT_PATTERN = /\b((?:secret|password|passwd|api[_-]?key|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[:=]\s*)[A-Za-z0-9+/_=-]{16,}\b/gi;
5870
+ function redactString(value, home) {
5871
+ let out = value.replace(GITHUB_TOKEN_PATTERN, "<redacted>").replace(CLASSIC_GITHUB_PAT_PATTERN, "$1<redacted>").replace(BEARER_TOKEN_PATTERN, "<redacted>").replace(AWS_ACCESS_KEY_PATTERN, "<redacted>").replace(SLACK_TOKEN_PATTERN, "<redacted>").replace(STRIPE_KEY_PATTERN, "<redacted>").replace(ANTHROPIC_KEY_PATTERN, "<redacted>").replace(OPENAI_KEY_PATTERN, "<redacted>").replace(NPM_TOKEN_PATTERN, "<redacted>").replace(JWT_PATTERN, "<redacted>").replace(PEM_BLOCK_PATTERN, "<redacted>").replace(BASIC_AUTH_URL_PATTERN, "$1<redacted>@").replace(GENERIC_SECRET_ASSIGNMENT_PATTERN, "$1<redacted>");
5872
+ if (home.length > 0 && out.startsWith(home)) {
5873
+ const rest = out.slice(home.length);
5874
+ if (rest === "" || rest.startsWith("/"))
5875
+ out = `~${rest}`;
5876
+ }
5877
+ return out;
5878
+ }
5879
+ function redact(value, home) {
5880
+ if (typeof value === "string")
5881
+ return redactString(value, home);
5882
+ if (Array.isArray(value))
5883
+ return value.map((v) => redact(v, home));
5884
+ if (value !== null && typeof value === "object") {
5885
+ const out = {};
5886
+ for (const [k, v] of Object.entries(value)) {
5887
+ out[k] = redact(v, home);
5888
+ }
5889
+ return out;
5890
+ }
5891
+ return value;
5892
+ }
5893
+ // ../../packages/aeg-core/src/log/store.ts
5894
+ function metaOf(obj) {
5895
+ if (obj === null || typeof obj !== "object")
5896
+ return null;
5897
+ const meta = obj.meta;
5898
+ if (meta === null || typeof meta !== "object")
5899
+ return null;
5900
+ return meta;
5901
+ }
5902
+ function recordIdentity(obj) {
5903
+ const meta = metaOf(obj);
5904
+ if (meta === null)
5905
+ return null;
5906
+ const eventId = meta.event_id;
5907
+ if (typeof eventId === "string" && eventId.length > 0)
5908
+ return eventId;
5909
+ const runId = meta.run_id;
5910
+ const seq = meta.seq;
5911
+ if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
5912
+ return `${runId}:${seq}`;
5913
+ }
5914
+ return null;
5915
+ }
5916
+
5917
+ // ../../packages/aeg-core/src/log/artifact.ts
5918
+ var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
5650
5919
  // ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
5651
5920
  var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
5652
5921
  // ../../packages/aeg-core/src/control-store/records.ts
@@ -5661,7 +5930,9 @@ var RunRecordSchema = z3.object({
5661
5930
  runId: z3.string().min(1),
5662
5931
  pid: z3.number().int().positive(),
5663
5932
  host: z3.string().min(1),
5664
- startedAt: isoTimestamp
5933
+ startedAt: isoTimestamp,
5934
+ childStartedAt: z3.string().min(1).nullable().optional(),
5935
+ childCommand: z3.string().min(1).nullable().optional()
5665
5936
  }).strict();
5666
5937
  var InputRecordSchema = z3.object({
5667
5938
  version: z3.literal(1),
@@ -5694,6 +5965,88 @@ var TransitionRecordSchema = z3.object({
5694
5965
  detail: z3.string().optional(),
5695
5966
  at: isoTimestamp
5696
5967
  }).strict();
5968
+ var ManifestRecordSchema = z3.object({
5969
+ version: z3.literal(1),
5970
+ kind: z3.literal("manifest"),
5971
+ task: taskId,
5972
+ round: epochNumber,
5973
+ repository: z3.string().min(1),
5974
+ pr: z3.number().int().positive(),
5975
+ branch: z3.string().min(1),
5976
+ baseSha: z3.string().min(1).nullable(),
5977
+ headSha: z3.string().min(1),
5978
+ briefHash: z3.string().min(1).nullable(),
5979
+ objectivesVersion: z3.string().min(1).nullable(),
5980
+ rulingOrdinal: epochNumber,
5981
+ policyDigest: z3.string().min(1),
5982
+ recordedAt: isoTimestamp
5983
+ }).strict();
5984
+ var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
5985
+ var LoopBudgetsSchema = z3.object({
5986
+ mechanicalRetries: z3.number().int().nonnegative(),
5987
+ reviewRounds: z3.number().int().nonnegative(),
5988
+ infrastructureRetries: z3.number().int().nonnegative()
5989
+ }).strict();
5990
+ var LoopStateRecordSchema = z3.object({
5991
+ version: z3.literal(1),
5992
+ kind: z3.literal("loop_state"),
5993
+ task: taskId,
5994
+ round: z3.number().int().positive(),
5995
+ phase: z3.string().min(1),
5996
+ pauseReason: z3.string().min(1).nullable(),
5997
+ budgets: LoopBudgetsSchema,
5998
+ heldResult: roundHeadIdentity.nullable(),
5999
+ deliveredFindings: roundHeadIdentity.nullable(),
6000
+ recordedAt: isoTimestamp
6001
+ }).strict();
6002
+ var EffectRecordSchema = z3.object({
6003
+ version: z3.literal(1),
6004
+ kind: z3.literal("effect"),
6005
+ task: taskId,
6006
+ key: z3.string().min(1),
6007
+ operation: z3.string().min(1),
6008
+ target: z3.string().min(1),
6009
+ inputVersion: z3.number().int().nonnegative(),
6010
+ payloadDigest: z3.string().min(1),
6011
+ status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
6012
+ url: z3.string().optional(),
6013
+ recordedAt: isoTimestamp
6014
+ }).strict();
6015
+ var EscalationRecordSchema = z3.object({
6016
+ version: z3.literal(1),
6017
+ kind: z3.literal("escalation"),
6018
+ task: taskId,
6019
+ escalationId: z3.string().min(1),
6020
+ round: epochNumber,
6021
+ head: z3.string().min(1),
6022
+ branch: z3.string().min(1),
6023
+ pr: z3.number().int().positive().nullable(),
6024
+ runId: z3.string().min(1),
6025
+ pid: z3.number().int().positive(),
6026
+ host: z3.string().min(1),
6027
+ agent: z3.string().min(1).optional(),
6028
+ reason: z3.string().min(1),
6029
+ detail: z3.string().optional(),
6030
+ evidence: z3.string().optional(),
6031
+ attemptedRecovery: z3.string().min(1),
6032
+ requestedDecision: z3.string().min(1),
6033
+ recipient: z3.string().min(1),
6034
+ briefHash: z3.string().min(1).nullable(),
6035
+ objectivesVersion: z3.string().min(1).nullable(),
6036
+ rulingOrdinal: epochNumber,
6037
+ policyDigest: z3.string().min(1),
6038
+ recordedAt: isoTimestamp
6039
+ }).strict();
6040
+ var ResolutionRecordSchema = z3.object({
6041
+ version: z3.literal(1),
6042
+ kind: z3.literal("resolution"),
6043
+ task: taskId,
6044
+ escalationId: z3.string().min(1),
6045
+ decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
6046
+ authenticatedBy: z3.string().min(1),
6047
+ authenticatedFrom: z3.string().min(1),
6048
+ consumedAt: isoTimestamp
6049
+ }).strict();
5697
6050
  // ../../packages/sources/src/commands.ts
5698
6051
  var COMMANDS = [
5699
6052
  {
@@ -5863,6 +6216,16 @@ var COMMANDS = [
5863
6216
  ],
5864
6217
  status: "shipped"
5865
6218
  },
6219
+ {
6220
+ name: "task-tools serve",
6221
+ description: "Run the task-operator MCP tool server over stdio — the command both runtime adapters register",
6222
+ details: [
6223
+ "Exposes the task-operator tool catalog (`packages/aeg-core/src/task-tools.ts`) to an agent runtime as one MCP server speaking newline-delimited JSON-RPC 2.0 (`initialize`/`tools/list`/`tools/call`). Claude registers it through the generated `.mcp.json`; Codex through its documented `~/.codex/config.toml` `[mcp_servers]` table — both point at this same command.",
6224
+ "stdout carries JSON-RPC and nothing else: any stray write from the CLI (a forge-read warning) is redirected to stderr, so the protocol stream is never corrupted.",
6225
+ "`task_status`/`task_escalation_read` read; `task_start` starts a run in attended mode only, requiring an authenticated caller from the invocation context (`VINAYA_MCP_CALLER`) and refusing without one — MCP is a transport, not authorization. `task_resume`/`task_cancel` require the same authenticated caller, plus a current Principal ruling read fresh from the run's own PR — never a caller-supplied approval; `task_resume` triggers the existing `dev-review-loop --resume` continuation exactly once per escalation, and `task_cancel` reports a truthful `confirmed`/`pending`/`uncertain` outcome, idempotently, across repeated calls. No unattended start until the worker-isolation boundary and a capability flag land."
6226
+ ],
6227
+ status: "shipped"
6228
+ },
5866
6229
  {
5867
6230
  name: "pr create",
5868
6231
  description: "Open a pull request after full brief-schema validation",
@@ -6007,6 +6370,30 @@ var COMMANDS = [
6007
6370
  ],
6008
6371
  status: "shipped"
6009
6372
  },
6373
+ {
6374
+ name: "log export-artifact",
6375
+ description: "Copy this run's own local outbox into a file, for the generated task-path workflow's own upload step",
6376
+ flags: [],
6377
+ details: [
6378
+ "Concatenates every `*.ndjson` file under `~/.vinaya/outbox/` into `<dest>`, verbatim — no filtering, no second redaction pass (lines are already redacted at `log()`'s own write boundary). Writes nothing when the outbox is empty, and exits 0 either way: no gate events this run is a legitimate outcome, never a failure.",
6379
+ "Runs inside the generated `vinaya-checks.yml` job, which holds no forge-write credential — this command never calls the forge. Both this step and the `actions/upload-artifact` step after it run `if: always()`, so a cancelled or failed job still exports whatever partial outbox it has."
6380
+ ],
6381
+ status: "shipped"
6382
+ },
6383
+ {
6384
+ name: "log collect-artifact",
6385
+ description: "Validate a downloaded task-log artifact and publish the valid records through the existing flush path",
6386
+ flags: [
6387
+ { flag: "--pr", description: "The pull request this artifact belongs to" },
6388
+ { flag: "--repo", description: "Expected `owner/repo` — a provenance cross-check against each record" }
6389
+ ],
6390
+ details: [
6391
+ "Runs inside the generated `vinaya-task-log-collector.yml` workflow — a `workflow_run`-triggered job on the default branch, holding the write credential the task-path job that produced the artifact never gets. `<path>` is already downloaded by that workflow, scoped to a specific, API-verified run id — a provenance guarantee this command never re-derives from the artifact bytes.",
6392
+ "Never executes, imports, or evaluates the artifact's content: every line is read as text and validated (schema, an 8 MiB whole-artifact size cap, redaction, and a repo cross-check) before anything is trusted. A rejected line becomes a named gap — printed, never a silent drop — and the artifact is never partially trusted past that check into executing anything.",
6393
+ "The valid, re-redacted survivors are appended into the same local outbox `vinaya log flush` would read for that PR's Issue, then published through the existing `flushOutbox` unmodified — reusing its chunking, its `<!-- aeg:log:… -->` marker, and its idempotent-retry read, rather than a second publisher. A retried collector run (a fresh runner, the same forge state) therefore dedupes for free: the marker already on the forge is acknowledged, never re-posted."
6394
+ ],
6395
+ status: "shipped"
6396
+ },
6010
6397
  {
6011
6398
  name: "milestone create",
6012
6399
  description: "Create a GitHub Milestone from a validated body",
@@ -6564,6 +6951,13 @@ var VinayaConfigSchema = z5.object({
6564
6951
  message: "must be at most 3600000 (1 hour)"
6565
6952
  });
6566
6953
  }
6954
+ }).optional(),
6955
+ logPublish: z5.object({
6956
+ issue: z5.number().int().positive().optional(),
6957
+ pr: z5.number().int().positive().optional(),
6958
+ maxChunksPerFlush: z5.number().int().positive().optional()
6959
+ }).refine((v) => !(v.issue !== undefined && v.pr !== undefined), {
6960
+ message: "logPublish: set at most one of issue/pr, not both"
6567
6961
  }).optional()
6568
6962
  });
6569
6963
  var GLOBAL_VINAYA_HOME = join(homedir(), ".vinaya");