@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
@@ -1644,6 +1644,52 @@ var systemEnv3 = {
1644
1644
  ...process.env,
1645
1645
  PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
1646
1646
  };
1647
+ var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
1648
+ var cached;
1649
+ var inflight;
1650
+ async function resolveRepo(exec = defaultExec) {
1651
+ if (cached !== undefined)
1652
+ return cached;
1653
+ const fromEnv = process.env.AEG_REPO;
1654
+ if (fromEnv) {
1655
+ const parsed = parseOwnerRepo(fromEnv);
1656
+ if (parsed) {
1657
+ cached = parsed;
1658
+ return cached;
1659
+ }
1660
+ }
1661
+ if (inflight)
1662
+ return inflight;
1663
+ inflight = (async () => {
1664
+ try {
1665
+ const { stdout } = await exec();
1666
+ cached = parseGitRemoteUrl(stdout.trim());
1667
+ return cached;
1668
+ } catch (err) {
1669
+ const message = err instanceof Error ? err.message : String(err);
1670
+ console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
1671
+ return null;
1672
+ } finally {
1673
+ inflight = undefined;
1674
+ }
1675
+ })();
1676
+ return inflight;
1677
+ }
1678
+ function parseGitRemoteUrl(url) {
1679
+ const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
1680
+ if (ssh?.[1] && ssh[2])
1681
+ return { owner: ssh[1], repo: ssh[2] };
1682
+ const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
1683
+ if (https?.[1] && https[2])
1684
+ return { owner: https[1], repo: https[2] };
1685
+ return null;
1686
+ }
1687
+ function parseOwnerRepo(value) {
1688
+ const match = value.match(/^([^/]+)\/(.+)$/);
1689
+ if (!match?.[1] || !match[2])
1690
+ return null;
1691
+ return { owner: match[1], repo: match[2] };
1692
+ }
1647
1693
  // ../../packages/aeg-core/src/anchored-region.ts
1648
1694
  function anchoredRegionBounds(body, field) {
1649
1695
  const masked = maskCode(body);
@@ -1956,6 +2002,7 @@ var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\
1956
2002
  var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
1957
2003
  var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
1958
2004
  var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
2005
+ var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
1959
2006
  function firstFiveLines(comment) {
1960
2007
  return comment.split(`
1961
2008
  `).slice(0, 5).join(`
@@ -1991,6 +2038,15 @@ function extractPolicyDigest(comment) {
1991
2038
  const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
1992
2039
  return m ? m[1].toLowerCase() : null;
1993
2040
  }
2041
+ function firstThirteenLines(comment) {
2042
+ return comment.split(`
2043
+ `).slice(0, 13).join(`
2044
+ `);
2045
+ }
2046
+ function extractBaseSha(comment) {
2047
+ const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
2048
+ return m ? m[1].toLowerCase() : null;
2049
+ }
1994
2050
  var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
1995
2051
  function extractFindingSeverities(comment) {
1996
2052
  return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
@@ -2008,6 +2064,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2008
2064
  rulingOrdinal: null,
2009
2065
  briefHash: null,
2010
2066
  policyDigest: null,
2067
+ baseSha: null,
2011
2068
  findingSeverities: [],
2012
2069
  danglingNote: `no ${missingLabel} verdict comment found on this PR`
2013
2070
  };
@@ -2022,6 +2079,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2022
2079
  rulingOrdinal: null,
2023
2080
  briefHash: null,
2024
2081
  policyDigest: null,
2082
+ baseSha: null,
2025
2083
  findingSeverities: [],
2026
2084
  danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
2027
2085
  };
@@ -2033,6 +2091,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
2033
2091
  rulingOrdinal: extractRulingOrdinal(latest),
2034
2092
  briefHash: extractBriefHash(latest),
2035
2093
  policyDigest: extractPolicyDigest(latest),
2094
+ baseSha: extractBaseSha(latest),
2036
2095
  findingSeverities: extractFindingSeverities(latest),
2037
2096
  danglingNote: null
2038
2097
  };
@@ -3946,7 +4005,11 @@ function briefHash(brief) {
3946
4005
  `).digest("hex");
3947
4006
  }
3948
4007
  function policyDigest(policy) {
3949
- return createHash4("sha256").update(JSON.stringify({ codeReviewThreshold: policy.codeReviewThreshold, securityThreshold: policy.securityThreshold })).digest("hex");
4008
+ return createHash4("sha256").update(JSON.stringify({
4009
+ codeReviewThreshold: policy.codeReviewThreshold,
4010
+ securityThreshold: policy.securityThreshold,
4011
+ maxRounds: policy.maxRounds
4012
+ })).digest("hex");
3950
4013
  }
3951
4014
  function isBoundToHead(echoed, headSha) {
3952
4015
  if (!echoed.headSha)
@@ -3962,8 +4025,12 @@ function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
3962
4025
  return false;
3963
4026
  return judged === current;
3964
4027
  }
3965
- function isBoundToPatch(echoed, headSha, patchIdOf) {
3966
- return isBoundToHead(echoed, headSha) || isBoundByPatchIdentity(echoed, headSha, patchIdOf);
4028
+ function isBoundToBase(echoed, currentBase) {
4029
+ if (currentBase === null)
4030
+ return true;
4031
+ if (!echoed.baseSha)
4032
+ return false;
4033
+ return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
3967
4034
  }
3968
4035
  function isBoundToObjectives(echoed, currentVersion) {
3969
4036
  if (currentVersion === null)
@@ -3984,14 +4051,18 @@ function isBoundToPolicy(echoed, currentDigest) {
3984
4051
  return echoed.policyDigest === currentDigest;
3985
4052
  }
3986
4053
  function compareManifest(echoed, current, patchIdOf) {
3987
- const head = isBoundToPatch(echoed, current.headSha, patchIdOf);
4054
+ const exactHead = isBoundToHead(echoed, current.headSha);
4055
+ const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
4056
+ const head = exactHead || patchHead;
4057
+ const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
3988
4058
  const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
3989
4059
  const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
3990
4060
  const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
3991
4061
  const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
3992
4062
  return {
3993
- bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
4063
+ bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
3994
4064
  head,
4065
+ base,
3995
4066
  briefHash: briefHashBound,
3996
4067
  objectivesVersion: objectivesVersion2,
3997
4068
  rulingOrdinal,
@@ -4043,6 +4114,7 @@ function checkReviewGate(input) {
4043
4114
  const securityClean = securityTextClean && securityPolicyClean;
4044
4115
  const currentManifest = {
4045
4116
  headSha: input.headSha,
4117
+ baseSha: input.baseSha ?? null,
4046
4118
  briefHash: input.briefHash ?? null,
4047
4119
  objectivesVersion: input.objectivesVersion,
4048
4120
  rulingOrdinal: input.rulingOrdinal,
@@ -4050,6 +4122,7 @@ function checkReviewGate(input) {
4050
4122
  };
4051
4123
  const codeReviewEchoed = {
4052
4124
  headSha: codeReview.headSha,
4125
+ baseSha: codeReview.baseSha,
4053
4126
  briefHash: codeReview.briefHash,
4054
4127
  objectivesVersion: codeReview.objectivesVersion,
4055
4128
  rulingOrdinal: codeReview.rulingOrdinal,
@@ -4057,6 +4130,7 @@ function checkReviewGate(input) {
4057
4130
  };
4058
4131
  const securityEchoed = {
4059
4132
  headSha: security.headSha,
4133
+ baseSha: security.baseSha,
4060
4134
  briefHash: security.briefHash,
4061
4135
  objectivesVersion: security.objectivesVersion,
4062
4136
  rulingOrdinal: security.rulingOrdinal,
@@ -4084,6 +4158,8 @@ function checkReviewGate(input) {
4084
4158
  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`);
4085
4159
  } else if (!codeReviewBound) {
4086
4160
  problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
4161
+ } else if (!codeReviewBinding.base) {
4162
+ 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)`);
4087
4163
  } else if (!codeReviewObjectivesBound) {
4088
4164
  problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
4089
4165
  } else if (!codeReviewRulingsBound) {
@@ -4099,6 +4175,8 @@ function checkReviewGate(input) {
4099
4175
  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`);
4100
4176
  } else if (!securityBound) {
4101
4177
  problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
4178
+ } else if (!securityBinding.base) {
4179
+ 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)`);
4102
4180
  } else if (!securityObjectivesBound) {
4103
4181
  problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
4104
4182
  } else if (!securityRulingsBound) {
@@ -4956,8 +5034,8 @@ var TaskToolErrorSchema = z.object({
4956
5034
  detail: z.string().optional()
4957
5035
  });
4958
5036
  var TaskToolRefSchema = z.union([
4959
- z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
4960
- z.object({ issue: z.number().int().positive() })
5037
+ z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
5038
+ z.object({ issue: z.number().int().positive() }).strict()
4961
5039
  ]);
4962
5040
  var MAX_PAGE_LIMIT = 100;
4963
5041
  var PageRequestSchema = z.object({
@@ -4971,7 +5049,7 @@ var ObservedSchema = z.object({
4971
5049
  });
4972
5050
  var TaskStatusInputSchema = z.object({
4973
5051
  task: TaskToolRefSchema.optional()
4974
- }).merge(PageRequestSchema);
5052
+ }).merge(PageRequestSchema).strict();
4975
5053
  var TaskStatusItemSchema = z.object({
4976
5054
  task: TaskToolRefSchema,
4977
5055
  issue: z.number().int().positive(),
@@ -4995,9 +5073,20 @@ var EscalationEvidenceSchema = z.object({
4995
5073
  reviewer: z.string().nullable(),
4996
5074
  security: z.string().nullable()
4997
5075
  });
5076
+ var EscalationRunIdentitySchema = z.object({
5077
+ runId: z.string(),
5078
+ pid: z.number().int().positive(),
5079
+ host: z.string()
5080
+ });
5081
+ var EscalationInputVersionsSchema = z.object({
5082
+ briefHash: z.string().nullable(),
5083
+ objectivesVersion: z.string().nullable(),
5084
+ rulingOrdinal: z.number().int().nonnegative(),
5085
+ policyDigest: z.string()
5086
+ });
4998
5087
  var TaskEscalationReadInputSchema = z.object({
4999
5088
  task: TaskToolRefSchema
5000
- }).merge(PageRequestSchema);
5089
+ }).merge(PageRequestSchema).strict();
5001
5090
  var TaskEscalationPacketSchema = z.object({
5002
5091
  reason: z.string(),
5003
5092
  detail: z.string().nullable(),
@@ -5005,7 +5094,9 @@ var TaskEscalationPacketSchema = z.object({
5005
5094
  evidence: EscalationEvidenceSchema.nullable(),
5006
5095
  attemptedRecovery: z.string(),
5007
5096
  requestedAuthority: RequestedAuthoritySchema,
5008
- permittedNextActions: z.array(z.string())
5097
+ permittedNextActions: z.array(z.string()),
5098
+ runIdentity: EscalationRunIdentitySchema.nullable(),
5099
+ inputVersions: EscalationInputVersionsSchema.nullable()
5009
5100
  }).merge(ObservedSchema);
5010
5101
  var TaskEscalationReadResultSchema = z.object({
5011
5102
  items: z.array(TaskEscalationPacketSchema),
@@ -5014,15 +5105,48 @@ var TaskEscalationReadResultSchema = z.object({
5014
5105
  var TaskStartInputSchema = z.object({
5015
5106
  tranche: z.string().min(1),
5016
5107
  id: z.string().min(1)
5108
+ }).strict();
5109
+ var TaskStartResultSchema = z.object({
5110
+ requestId: z.string().min(1),
5111
+ run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
5112
+ started: z.boolean(),
5113
+ startedAt: z.string(),
5114
+ mode: z.literal("attended")
5017
5115
  });
5018
5116
  var TaskResumeInputSchema = z.object({
5019
5117
  task: TaskToolRefSchema
5020
- });
5118
+ }).strict();
5021
5119
  var TaskCancelInputSchema = z.object({
5022
5120
  task: TaskToolRefSchema,
5023
5121
  reason: z.string().min(1)
5122
+ }).strict();
5123
+ var TaskResumeResultSchema = z.object({
5124
+ task: z.number().int().positive(),
5125
+ pr: z.number().int().positive(),
5126
+ escalationId: z.string().min(1),
5127
+ outcome: z.enum(["started", "already_resumed"]),
5128
+ authenticatedBy: z.string().min(1),
5129
+ authenticatedFrom: z.string().min(1)
5130
+ });
5131
+ var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
5132
+ var TaskCancelResultSchema = z.object({
5133
+ task: z.number().int().positive(),
5134
+ pr: z.number().int().positive(),
5135
+ escalationId: z.string().min(1),
5136
+ outcome: TaskCancelOutcomeSchema,
5137
+ authenticatedBy: z.string().min(1),
5138
+ authenticatedFrom: z.string().min(1),
5139
+ fencedEffectKeys: z.array(z.string())
5024
5140
  });
5025
- var NoResultSchema = z.never();
5141
+ var TASK_TOOL_NAMES = [
5142
+ "task_start",
5143
+ "task_status",
5144
+ "task_escalation_read",
5145
+ "task_resume",
5146
+ "task_cancel"
5147
+ ];
5148
+ var OPERATOR_STATUS_FOLLOW = "task_status_follow";
5149
+ var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
5026
5150
  // ../../packages/aeg-core/src/first-push-dispatch-gate.ts
5027
5151
  function parseTaskBranch(branch) {
5028
5152
  const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
@@ -5245,6 +5369,9 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
5245
5369
  }
5246
5370
  return findings;
5247
5371
  }
5372
+ // ../../packages/aeg-core/src/log/envelope.ts
5373
+ import { createHash as createHash5 } from "node:crypto";
5374
+
5248
5375
  // ../../packages/aeg-core/src/log/schema.ts
5249
5376
  import { z as z2 } from "zod";
5250
5377
  var ROLE_VALUES = [
@@ -5346,7 +5473,8 @@ var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
5346
5473
  }).strict(),
5347
5474
  z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
5348
5475
  z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
5349
- z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
5476
+ z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
5477
+ z2.object({ type: z2.literal("completed") }).strict()
5350
5478
  ]);
5351
5479
  var dispatchShared = {
5352
5480
  meta: HeaderMetaSchema,
@@ -5406,7 +5534,8 @@ var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
5406
5534
  round: z2.number().int(),
5407
5535
  head: z2.string(),
5408
5536
  all_approve: z2.boolean(),
5409
- blockers: z2.number().int().nonnegative()
5537
+ blockers: z2.number().int().nonnegative(),
5538
+ findings: z2.array(ReviewFindingSchema).optional()
5410
5539
  }).strict(),
5411
5540
  z2.object({
5412
5541
  ...loopShared,
@@ -5585,7 +5714,9 @@ var roleAttemptShared = {
5585
5714
  kind: z2.literal("role_attempt"),
5586
5715
  ...envelopeTail,
5587
5716
  actor: z2.string().nullable(),
5588
- attempt: z2.number().int().nullable()
5717
+ attempt: z2.number().int().nullable(),
5718
+ effect_id: z2.string(),
5719
+ model: z2.string().nullable()
5589
5720
  };
5590
5721
  var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
5591
5722
  z2.object({
@@ -5644,6 +5775,144 @@ var LogEventSchema = z2.union([
5644
5775
  HandoffEventSchema,
5645
5776
  EffectEventSchema
5646
5777
  ]);
5778
+
5779
+ // ../../packages/aeg-core/src/log/envelope.ts
5780
+ function isRole(value) {
5781
+ return value !== undefined && ROLE_VALUES.includes(value);
5782
+ }
5783
+ function actorIdFromEnv(role) {
5784
+ return role === undefined || role === "" ? null : role;
5785
+ }
5786
+ function lineageFieldFromEnv(value) {
5787
+ return value === undefined || value === "" ? null : value;
5788
+ }
5789
+ function attemptFromEnv(value) {
5790
+ if (value === undefined || value === "")
5791
+ return null;
5792
+ const n = Number(value);
5793
+ return Number.isInteger(n) ? n : null;
5794
+ }
5795
+ function provenanceFor(input) {
5796
+ if (input.provenance)
5797
+ return input.provenance;
5798
+ if (input.env.role || input.env.task)
5799
+ return "env_correlated";
5800
+ return "unavailable";
5801
+ }
5802
+ function issueFromTask(task) {
5803
+ if (task === undefined || task === "")
5804
+ return null;
5805
+ const n = Number(task);
5806
+ return Number.isInteger(n) ? n : null;
5807
+ }
5808
+ function roundFromEnv(round) {
5809
+ if (round === undefined || round === "")
5810
+ return;
5811
+ const n = Number(round);
5812
+ return Number.isInteger(n) ? n : undefined;
5813
+ }
5814
+ function buildHeader(input) {
5815
+ const role = isRole(input.env.role) ? input.env.role : "unattributed";
5816
+ const round = roundFromEnv(input.env.round);
5817
+ const subject = {
5818
+ issue: issueFromTask(input.env.task),
5819
+ role,
5820
+ ...round !== undefined ? { round } : {},
5821
+ ...input.subject ?? {}
5822
+ };
5823
+ return {
5824
+ meta: {
5825
+ schema: 2,
5826
+ ts: input.now.toISOString(),
5827
+ run_id: input.runId,
5828
+ seq: input.seq,
5829
+ repo: input.repo,
5830
+ vinaya: input.vinaya,
5831
+ doctrine: input.doctrine,
5832
+ host: input.host,
5833
+ machine: createHash5("sha256").update(input.hostname).digest("hex"),
5834
+ event_id: input.eventId,
5835
+ process_id: input.processId,
5836
+ actor_id: actorIdFromEnv(input.env.role),
5837
+ lineage: {
5838
+ run: lineageFieldFromEnv(input.env.run),
5839
+ attempt: attemptFromEnv(input.env.attempt),
5840
+ parent: lineageFieldFromEnv(input.env.parent)
5841
+ },
5842
+ input_versions: {
5843
+ objectives_version: input.inputVersions?.objectivesVersion ?? null,
5844
+ brief_hash: input.inputVersions?.briefHash ?? null,
5845
+ ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
5846
+ policy_digest: input.inputVersions?.policyDigest ?? null
5847
+ },
5848
+ provenance: provenanceFor(input)
5849
+ },
5850
+ subject
5851
+ };
5852
+ }
5853
+ // ../../packages/aeg-core/src/log/redact.ts
5854
+ var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
5855
+ var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
5856
+ var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
5857
+ var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
5858
+ var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
5859
+ var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
5860
+ var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
5861
+ var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
5862
+ var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
5863
+ var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
5864
+ var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
5865
+ var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
5866
+ 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;
5867
+ function redactString(value, home) {
5868
+ 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>");
5869
+ if (home.length > 0 && out.startsWith(home)) {
5870
+ const rest = out.slice(home.length);
5871
+ if (rest === "" || rest.startsWith("/"))
5872
+ out = `~${rest}`;
5873
+ }
5874
+ return out;
5875
+ }
5876
+ function redact(value, home) {
5877
+ if (typeof value === "string")
5878
+ return redactString(value, home);
5879
+ if (Array.isArray(value))
5880
+ return value.map((v) => redact(v, home));
5881
+ if (value !== null && typeof value === "object") {
5882
+ const out = {};
5883
+ for (const [k, v] of Object.entries(value)) {
5884
+ out[k] = redact(v, home);
5885
+ }
5886
+ return out;
5887
+ }
5888
+ return value;
5889
+ }
5890
+ // ../../packages/aeg-core/src/log/store.ts
5891
+ function metaOf(obj) {
5892
+ if (obj === null || typeof obj !== "object")
5893
+ return null;
5894
+ const meta = obj.meta;
5895
+ if (meta === null || typeof meta !== "object")
5896
+ return null;
5897
+ return meta;
5898
+ }
5899
+ function recordIdentity(obj) {
5900
+ const meta = metaOf(obj);
5901
+ if (meta === null)
5902
+ return null;
5903
+ const eventId = meta.event_id;
5904
+ if (typeof eventId === "string" && eventId.length > 0)
5905
+ return eventId;
5906
+ const runId = meta.run_id;
5907
+ const seq = meta.seq;
5908
+ if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
5909
+ return `${runId}:${seq}`;
5910
+ }
5911
+ return null;
5912
+ }
5913
+
5914
+ // ../../packages/aeg-core/src/log/artifact.ts
5915
+ var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
5647
5916
  // ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
5648
5917
  var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
5649
5918
  // ../../packages/aeg-core/src/control-store/records.ts
@@ -5658,7 +5927,9 @@ var RunRecordSchema = z3.object({
5658
5927
  runId: z3.string().min(1),
5659
5928
  pid: z3.number().int().positive(),
5660
5929
  host: z3.string().min(1),
5661
- startedAt: isoTimestamp
5930
+ startedAt: isoTimestamp,
5931
+ childStartedAt: z3.string().min(1).nullable().optional(),
5932
+ childCommand: z3.string().min(1).nullable().optional()
5662
5933
  }).strict();
5663
5934
  var InputRecordSchema = z3.object({
5664
5935
  version: z3.literal(1),
@@ -5691,6 +5962,88 @@ var TransitionRecordSchema = z3.object({
5691
5962
  detail: z3.string().optional(),
5692
5963
  at: isoTimestamp
5693
5964
  }).strict();
5965
+ var ManifestRecordSchema = z3.object({
5966
+ version: z3.literal(1),
5967
+ kind: z3.literal("manifest"),
5968
+ task: taskId,
5969
+ round: epochNumber,
5970
+ repository: z3.string().min(1),
5971
+ pr: z3.number().int().positive(),
5972
+ branch: z3.string().min(1),
5973
+ baseSha: z3.string().min(1).nullable(),
5974
+ headSha: z3.string().min(1),
5975
+ briefHash: z3.string().min(1).nullable(),
5976
+ objectivesVersion: z3.string().min(1).nullable(),
5977
+ rulingOrdinal: epochNumber,
5978
+ policyDigest: z3.string().min(1),
5979
+ recordedAt: isoTimestamp
5980
+ }).strict();
5981
+ var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
5982
+ var LoopBudgetsSchema = z3.object({
5983
+ mechanicalRetries: z3.number().int().nonnegative(),
5984
+ reviewRounds: z3.number().int().nonnegative(),
5985
+ infrastructureRetries: z3.number().int().nonnegative()
5986
+ }).strict();
5987
+ var LoopStateRecordSchema = z3.object({
5988
+ version: z3.literal(1),
5989
+ kind: z3.literal("loop_state"),
5990
+ task: taskId,
5991
+ round: z3.number().int().positive(),
5992
+ phase: z3.string().min(1),
5993
+ pauseReason: z3.string().min(1).nullable(),
5994
+ budgets: LoopBudgetsSchema,
5995
+ heldResult: roundHeadIdentity.nullable(),
5996
+ deliveredFindings: roundHeadIdentity.nullable(),
5997
+ recordedAt: isoTimestamp
5998
+ }).strict();
5999
+ var EffectRecordSchema = z3.object({
6000
+ version: z3.literal(1),
6001
+ kind: z3.literal("effect"),
6002
+ task: taskId,
6003
+ key: z3.string().min(1),
6004
+ operation: z3.string().min(1),
6005
+ target: z3.string().min(1),
6006
+ inputVersion: z3.number().int().nonnegative(),
6007
+ payloadDigest: z3.string().min(1),
6008
+ status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
6009
+ url: z3.string().optional(),
6010
+ recordedAt: isoTimestamp
6011
+ }).strict();
6012
+ var EscalationRecordSchema = z3.object({
6013
+ version: z3.literal(1),
6014
+ kind: z3.literal("escalation"),
6015
+ task: taskId,
6016
+ escalationId: z3.string().min(1),
6017
+ round: epochNumber,
6018
+ head: z3.string().min(1),
6019
+ branch: z3.string().min(1),
6020
+ pr: z3.number().int().positive().nullable(),
6021
+ runId: z3.string().min(1),
6022
+ pid: z3.number().int().positive(),
6023
+ host: z3.string().min(1),
6024
+ agent: z3.string().min(1).optional(),
6025
+ reason: z3.string().min(1),
6026
+ detail: z3.string().optional(),
6027
+ evidence: z3.string().optional(),
6028
+ attemptedRecovery: z3.string().min(1),
6029
+ requestedDecision: z3.string().min(1),
6030
+ recipient: z3.string().min(1),
6031
+ briefHash: z3.string().min(1).nullable(),
6032
+ objectivesVersion: z3.string().min(1).nullable(),
6033
+ rulingOrdinal: epochNumber,
6034
+ policyDigest: z3.string().min(1),
6035
+ recordedAt: isoTimestamp
6036
+ }).strict();
6037
+ var ResolutionRecordSchema = z3.object({
6038
+ version: z3.literal(1),
6039
+ kind: z3.literal("resolution"),
6040
+ task: taskId,
6041
+ escalationId: z3.string().min(1),
6042
+ decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
6043
+ authenticatedBy: z3.string().min(1),
6044
+ authenticatedFrom: z3.string().min(1),
6045
+ consumedAt: isoTimestamp
6046
+ }).strict();
5694
6047
  // ../../packages/sources/src/commands.ts
5695
6048
  var COMMANDS = [
5696
6049
  {
@@ -5860,6 +6213,16 @@ var COMMANDS = [
5860
6213
  ],
5861
6214
  status: "shipped"
5862
6215
  },
6216
+ {
6217
+ name: "task-tools serve",
6218
+ description: "Run the task-operator MCP tool server over stdio — the command both runtime adapters register",
6219
+ details: [
6220
+ "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.",
6221
+ "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.",
6222
+ "`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."
6223
+ ],
6224
+ status: "shipped"
6225
+ },
5863
6226
  {
5864
6227
  name: "pr create",
5865
6228
  description: "Open a pull request after full brief-schema validation",
@@ -6004,6 +6367,30 @@ var COMMANDS = [
6004
6367
  ],
6005
6368
  status: "shipped"
6006
6369
  },
6370
+ {
6371
+ name: "log export-artifact",
6372
+ description: "Copy this run's own local outbox into a file, for the generated task-path workflow's own upload step",
6373
+ flags: [],
6374
+ details: [
6375
+ "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.",
6376
+ "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."
6377
+ ],
6378
+ status: "shipped"
6379
+ },
6380
+ {
6381
+ name: "log collect-artifact",
6382
+ description: "Validate a downloaded task-log artifact and publish the valid records through the existing flush path",
6383
+ flags: [
6384
+ { flag: "--pr", description: "The pull request this artifact belongs to" },
6385
+ { flag: "--repo", description: "Expected `owner/repo` — a provenance cross-check against each record" }
6386
+ ],
6387
+ details: [
6388
+ "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.",
6389
+ "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.",
6390
+ "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."
6391
+ ],
6392
+ status: "shipped"
6393
+ },
6007
6394
  {
6008
6395
  name: "milestone create",
6009
6396
  description: "Create a GitHub Milestone from a validated body",