@attalabs/vinaya 0.22.0 → 0.23.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 (188) hide show
  1. package/README.md +13 -3
  2. package/aeg-root/contracts/archivist-tranche-archivist.md +2 -2
  3. package/aeg-root/contracts/brief-developer.md +1 -0
  4. package/aeg-root/contracts/developer-reviewer.md +3 -3
  5. package/aeg-root/contracts/reviewer-archivist.md +3 -3
  6. package/aeg-root/enforcement.md +26 -20
  7. package/aeg-root/process.md +8 -4
  8. package/aeg-root/roles/archivist.md +2 -2
  9. package/aeg-root/roles/brief-author.md +9 -3
  10. package/aeg-root/roles/developer.md +63 -31
  11. package/aeg-root/roles/planner.md +1 -1
  12. package/aeg-root/roles/principal.md +14 -0
  13. package/aeg-root/roles/reviewer.md +32 -15
  14. package/aeg-root/roles/security.md +15 -5
  15. package/aeg-root/skills/aeg/SKILL.md +9 -5
  16. package/aeg-root/skills/aeg-roles/SKILL.md +2 -2
  17. package/aeg-root/skills/brief-authoring/SKILL.md +39 -27
  18. package/aeg-root/state-machine.md +9 -11
  19. package/aeg-root/templates/brief-template.md +6 -6
  20. package/aeg-root/templates/pr-report-template.md +10 -7
  21. package/aeg-root/tranche-model.md +6 -2
  22. package/dist/checks/bin/check-body-bare-digits.js +552 -139
  23. package/dist/checks/bin/check-branch-topology.js +603 -144
  24. package/dist/checks/bin/check-brief-shape.js +593 -142
  25. package/dist/checks/bin/check-changeset-coverage.js +935 -161
  26. package/dist/checks/bin/check-closes-n.js +603 -144
  27. package/dist/checks/bin/check-coherence.js +614 -147
  28. package/dist/checks/bin/check-dead-branch-push.js +552 -139
  29. package/dist/checks/bin/check-dispatch-readiness.js +612 -145
  30. package/dist/checks/bin/check-doc-coverage-push.js +689 -218
  31. package/dist/checks/bin/check-doc-coverage.js +689 -218
  32. package/dist/checks/bin/check-doctrine-no-procedures.js +4794 -0
  33. package/dist/checks/bin/check-doctrine-portability.js +684 -146
  34. package/dist/checks/bin/check-evidence-fresh.js +994 -174
  35. package/dist/checks/bin/check-exec-bits.js +4931 -0
  36. package/dist/checks/bin/check-first-push-dispatch.js +603 -144
  37. package/dist/checks/bin/check-issue-assignment.js +603 -144
  38. package/dist/checks/bin/check-main-branch-refusal.js +552 -139
  39. package/dist/checks/bin/check-no-disk-state.js +552 -139
  40. package/dist/checks/bin/check-pr-report-density.js +4461 -0
  41. package/dist/checks/bin/check-quoted-command.js +621 -155
  42. package/dist/checks/bin/check-reader-resolvable-prose.js +617 -154
  43. package/dist/checks/bin/check-registry-gates.js +595 -144
  44. package/dist/checks/bin/check-retired-vocabulary.js +617 -154
  45. package/dist/checks/bin/check-review-gate.js +670 -141
  46. package/dist/checks/bin/check-single-plan-pr.js +552 -139
  47. package/dist/checks/bin/check-test-plan.js +553 -140
  48. package/dist/checks/bin/check-token-collection-wired.js +552 -139
  49. package/dist/checks/bin/check-token-report.js +552 -139
  50. package/dist/checks/bin/check-workspace-escape.js +985 -145
  51. package/dist/index.js +8500 -5518
  52. package/package.json +1 -1
  53. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/actions.ts +173 -0
  54. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/anchored-region.ts +113 -0
  55. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/archive-task.ts +206 -0
  56. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/baseline-capture.ts +65 -0
  57. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/blast-radius-domains.ts +192 -0
  58. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/branch-topology-gate.ts +85 -0
  59. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/brief-validation.ts +511 -0
  60. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/claude-code-transcript.ts +460 -0
  61. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/coherence-checks.ts +787 -0
  62. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/dead-branch-push-audit.ts +55 -0
  63. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/dead-branch-push-guard.ts +77 -0
  64. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/derive-section7.ts +66 -0
  65. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/derive-tranche.ts +94 -0
  66. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/diagram-model.ts +372 -0
  67. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/direct-main-push.ts +39 -0
  68. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/dispatch-gate.ts +224 -0
  69. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/doc-owners.ts +314 -0
  70. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/build-doc-nav.ts +38 -0
  71. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/docs-coherence.ts +136 -0
  72. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/index.ts +29 -0
  73. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/legacy-anchors.ts +48 -0
  74. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/nav-helpers.ts +17 -0
  75. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/node-route.ts +134 -0
  76. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/parse-doc.ts +43 -0
  77. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/published-prose.ts +306 -0
  78. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/surfaced-manifest.ts +89 -0
  79. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/docs/types.ts +33 -0
  80. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/doctrine-portability.ts +170 -0
  81. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/doctrine-source.ts +23 -0
  82. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/ensure-label.ts +28 -0
  83. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/file-classify.ts +51 -0
  84. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/first-push-dispatch-gate.ts +80 -0
  85. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/gate-audience.ts +168 -0
  86. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/index.ts +301 -0
  87. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/issue-assignment.ts +102 -0
  88. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/issue-validation.ts +746 -0
  89. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/leftover-detection.ts +68 -0
  90. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/local-anchor-coverage.ts +245 -0
  91. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/main-branch-refusal.ts +64 -0
  92. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/manifest-validity.ts +81 -0
  93. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/markdown-table.ts +76 -0
  94. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/metering-io-guard.ts +119 -0
  95. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/milestone-validation.ts +240 -0
  96. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/no-disk-state.ts +50 -0
  97. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/parse-ledger.ts +77 -0
  98. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/parse-registry.ts +105 -0
  99. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/parse-token-report.ts +165 -0
  100. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/parse-tranche.ts +183 -0
  101. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/pr-tier.ts +81 -0
  102. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/premise-check.ts +125 -0
  103. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/quoted-command.ts +275 -0
  104. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/reader-resolvable-prose.ts +320 -0
  105. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/registry-checks.ts +255 -0
  106. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/registry-parse.ts +164 -0
  107. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/registry-scaffold.ts +216 -0
  108. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/report-tokens.ts +261 -0
  109. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/retired-vocabulary.ts +163 -0
  110. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/review-gate.ts +269 -0
  111. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/single-plan-pr.ts +73 -0
  112. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/state-machine-model.ts +269 -0
  113. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/state-source.ts +14 -0
  114. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/status-block.ts +8 -0
  115. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/sum-ledger.ts +26 -0
  116. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/symbol-collisions.ts +78 -0
  117. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/test-plan-gate.ts +104 -0
  118. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/test-plan-section.ts +65 -0
  119. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/types.ts +174 -0
  120. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/verdict-extraction.ts +140 -0
  121. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/vocabulary-citation.ts +114 -0
  122. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/waiver-label.ts +52 -0
  123. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/workspace-escape.ts +172 -0
  124. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  125. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  126. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  127. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  128. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  129. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  130. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  132. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  133. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  134. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  135. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  136. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  137. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +1 -1
  138. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  139. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  140. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  141. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  142. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  143. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  144. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  145. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  146. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  147. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  148. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  149. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  150. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
  151. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  152. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  153. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  154. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  155. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  156. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  157. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  158. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  159. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  160. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  161. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  162. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/[root-of-the-server]__02a-3g8._.js +1 -1
  163. 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
  164. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0053k9k._.js +1 -1
  165. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
  166. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
  167. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
  168. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
  169. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__069-_41._.js → [root-of-the-server]__1mcitst._.js} +1 -1
  170. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
  171. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_03x_w6q._.js +1 -1
  172. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
  173. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
  174. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1fqw88f._.js +1 -1
  175. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
  176. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
  177. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  178. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  179. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  180. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
  181. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{37hnluhzj9bei.js → 0jer_drkl1e4r.js} +4 -4
  182. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{267o-tsrnuwnv.js → 20x-t0a0v129z.js} +1 -1
  183. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1hufpuody6vjv.js → 2ou_81ahqw31e.js} +1 -1
  184. package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
  185. /package/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/{aeg-core → vinaya/studio-standalone/_node_modules/@attalabs/aeg-core}/bin/verify-coherence.ts +0 -0
  186. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{Fmyc42qzLwFcWWHLLNy-G → 5xy_GA7G5KRuE3HDumIiw}/_buildManifest.js +0 -0
  187. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{Fmyc42qzLwFcWWHLLNy-G → 5xy_GA7G5KRuE3HDumIiw}/_clientMiddlewareManifest.js +0 -0
  188. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{Fmyc42qzLwFcWWHLLNy-G → 5xy_GA7G5KRuE3HDumIiw}/_ssgManifest.js +0 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Path classifiers shared by the tier-derivation and doc-owners checks.
3
+ * Pure string predicates — no I/O.
4
+ */
5
+
6
+ /**
7
+ * Decision archives: frozen records of what was decided, not documentation.
8
+ * Touching one must never satisfy C3's code-requires-docs pairing, carry a
9
+ * tier signal, or be held to a spec's `Status:` block.
10
+ *
11
+ * Recognized by filename suffix, never by an enumerated path list. An earlier
12
+ * form of this predicate hardcoded each consumer's archive by full path, which
13
+ * put specific product names inside a package that ships to adopters who have
14
+ * neither. The suffix is the actual rule — a file named `…decisions-legacy.md`
15
+ * is an archive in any repo — and it subsumes every path that list held, so
16
+ * the coupling was removable with no behavior change.
17
+ *
18
+ * The historical failure the path list was added to prevent (renaming an
19
+ * archive out of recognition) is not re-opened: the earlier rule required a
20
+ * `-decisions-legacy.md` suffix and so missed a top-level `decisions-legacy.md`
21
+ * with no prefix, which is why the list existed at all. Matching the bare
22
+ * suffix covers both shapes.
23
+ */
24
+ export function isFrozenArchive(p: string): boolean {
25
+ return p.endsWith('decisions-legacy.md')
26
+ }
27
+
28
+ export function isDocFile(p: string): boolean {
29
+ return (
30
+ (p.startsWith('aeg-root/') && p.endsWith('.md')) ||
31
+ (p.startsWith('aeg-project/') && p.endsWith('.md')) ||
32
+ (p.includes('/aeg-project/') && p.endsWith('.md')) ||
33
+ (p.startsWith('.vinaya/') && p.endsWith('.md')) ||
34
+ (p.startsWith('docs/') && p.endsWith('.md') && !isFrozenArchive(p)) ||
35
+ (p.startsWith('apps/') && p.includes('/specs/') && p.endsWith('.md') && !isFrozenArchive(p)) ||
36
+ (p.startsWith('.claude/skills/') && p.endsWith('.md')) ||
37
+ /^(apps|packages)\/[^/]+\/README\.md$/.test(p) ||
38
+ p === 'docs-index.md' ||
39
+ p === 'README.md' ||
40
+ p === 'CLAUDE.md'
41
+ )
42
+ }
43
+
44
+ export function isCodeFile(p: string): boolean {
45
+ if (p.endsWith('.md')) return false
46
+ return /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|sql|css)$/.test(p)
47
+ }
48
+
49
+ export function isSpecFile(p: string): boolean {
50
+ return p.startsWith('apps/') && p.includes('/specs/') && p.endsWith('.md') && !isFrozenArchive(p)
51
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * First-push dispatch gate (aeg-governance-hardening task 25, #365). Pure —
3
+ * no `fs`, no `gh`/`git` shell-outs. The CLI shim (`bin/check-first-push-
4
+ * dispatch.ts`, wired into `.husky/pre-push`) runs the UNCHANGED
5
+ * `verify-dispatch.ts` gate mode once on a `task/<tranche>/<n>` branch's
6
+ * first push, maps its exit/output to a `DispatchReadinessFact`, and passes
7
+ * it in here.
8
+ *
9
+ * Mechanizes `roles/developer.md`'s entry-gate items 3–7 at the earliest
10
+ * possible moment — the first push — instead of relying on the Developer to
11
+ * run `verify-dispatch.ts` by hand before Step 0. Subsequent pushes (once a
12
+ * PR exists) skip the gate: dispatch readiness was validated once, and
13
+ * re-blocking mid-task on a sibling's later state change would strand
14
+ * in-flight work.
15
+ *
16
+ * `UNKNOWN` (forge unreachable — `verify-dispatch.ts`'s own `severity:infra`
17
+ * marker, printed when repo/token resolution fails) maps to `allow`, the
18
+ * same deliberate fail-open choice `dead-branch-push-guard.ts` already makes
19
+ * for the sibling gate: a guard that can block *all* pushes on a
20
+ * transient forge-reachability issue is worse than the bug it fixes. See
21
+ * `aeg-root/enforcement.md`.
22
+ */
23
+
24
+ /** A `task/<tranche>/<n>` branch parses to its two topology coordinates; anything else does not. */
25
+ export function parseTaskBranch(branch: string): { tranche: string; taskId: string } | null {
26
+ const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch)
27
+ return m ? { tranche: m[1] as string, taskId: m[2] as string } : null
28
+ }
29
+
30
+ export type DispatchReadinessFact = 'READY' | 'NOT_READY' | 'UNKNOWN'
31
+
32
+ export type FirstPushDispatchGateInput = {
33
+ /** The branch being pushed. */
34
+ branch: string
35
+ /** Whether a PR already exists for this branch — the hook's existing C5/ detection, reused, never re-derived here. */
36
+ prExists: boolean
37
+ /** verify-dispatch's classified result. Irrelevant (never read) when the branch is not a task branch or a PR already exists. */
38
+ readiness: DispatchReadinessFact
39
+ }
40
+
41
+ export type FirstPushDispatchGateVerdict = 'allow' | 'refuse'
42
+
43
+ export type FirstPushDispatchGateResult = { verdict: FirstPushDispatchGateVerdict; reason: string }
44
+
45
+ export function checkFirstPushDispatchGate(input: FirstPushDispatchGateInput): FirstPushDispatchGateResult {
46
+ const { branch, prExists, readiness } = input
47
+
48
+ if (parseTaskBranch(branch) === null) {
49
+ return {
50
+ verdict: 'allow',
51
+ reason: `Branch \`${branch}\` is not a task/<tranche>/<n> branch — the first-push dispatch gate only applies to task branches.`
52
+ }
53
+ }
54
+
55
+ if (prExists) {
56
+ return {
57
+ verdict: 'allow',
58
+ reason: `Branch \`${branch}\` already has an open PR — dispatch readiness was already validated on its first push; later pushes are not re-blocked by a sibling task's state change.`
59
+ }
60
+ }
61
+
62
+ if (readiness === 'UNKNOWN') {
63
+ return {
64
+ verdict: 'allow',
65
+ reason: `verify-dispatch could not reach the forge for \`${branch}\` (repo/token unresolvable) — failing OPEN rather than blocking the push on a transient issue.`
66
+ }
67
+ }
68
+
69
+ if (readiness === 'NOT_READY') {
70
+ return {
71
+ verdict: 'refuse',
72
+ reason: `verify-dispatch reports NOT READY for \`${branch}\` — see the failing predicate printed above.`
73
+ }
74
+ }
75
+
76
+ return {
77
+ verdict: 'allow',
78
+ reason: `verify-dispatch reports READY TO DISPATCH for \`${branch}\`.`
79
+ }
80
+ }
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Who each governance gate under `packages/aeg-core/bin/` is FOR.
3
+ *
4
+ * The problem this closes: this repository holds two parallel worlds — the
5
+ * gates it runs on itself (`packages/aeg-core/bin/*`) and the checks an
6
+ * adopter runs through the published CLI (`apps/cli/src/checks/bin/*`) — and
7
+ * nothing asserted a relationship between them. Membership of the shipped set
8
+ * was defined by ABSENCE from `coreCheckRegistry()`, which means a deliberate
9
+ * exclusion and a forgotten port left exactly the same trace.
10
+ *
11
+ * `reader-resolvable-prose` is the instructive case, and the reason this file
12
+ * exists. That call was made carefully and its reasoning written up well — in
13
+ * a paragraph of prose inside `registry.ts`. It is right, and it is invisible
14
+ * to tooling. A good decision and an unmade decision looked identical, so the
15
+ * next one might simply not get made.
16
+ *
17
+ * So `internal` is a thing you must SAY, with a reason, rather than something
18
+ * you can forget to notice. `gate-audience.test.ts` enumerates the bin
19
+ * directory and fails when a gate is in neither column.
20
+ *
21
+ * **This is deliberately NOT a field on `CheckSpec`.** Adopter-defined checks
22
+ * in `vinaya.config.json` produce that same shape (`lib/config.ts`), so an
23
+ * `audience` field there would push an internal-governance concept into
24
+ * adopter-facing config, where it means nothing and cannot be answered.
25
+ * The question is about THIS repo's own bins, so the declaration lives here.
26
+ *
27
+ * Adding a gate to `bin/` and nothing else is now a failing build, naming the
28
+ * file. That is the whole mechanism; deciding which column a given gate
29
+ * belongs in stays a human judgement, which is the point.
30
+ */
31
+
32
+ /** A gate that adopters run, and the `coreCheckRegistry()` name it ships
33
+ * under. `ring` mirrors `apps/cli/src/checks/registry.ts`'s `CORE_CHECK_RING`
34
+ * value for that same name — duplicated here, not imported, because
35
+ * `aeg-core` cannot import `apps/cli` (see this file's own module comment on
36
+ * the dependency-cycle constraint `coreCheckRegistry()` runs into). Kept
37
+ * from drifting by `registry-ring-parity.test.ts` (`apps/cli`), which is the
38
+ * only place both sides are in scope at once — same shape as
39
+ * `shipped-bin-audience.test.ts`'s existing `shippedAs` cross-check. This is
40
+ * the "registry-derived fact" `registry-scaffold.ts` reads to place a stub
41
+ * row for an aeg-core-bin G2 candidate that IS registry-backed; a candidate
42
+ * with no entry here gets no stub (see `registry-scaffold.ts`). */
43
+ export type ShippedGate = { shippedAs: string | string[]; ring: 0 | 1 | 2 }
44
+ /** A gate this repo runs on itself, and why it cannot or should not ship. */
45
+ export type InternalGate = { internal: string }
46
+ export type GateAudience = ShippedGate | InternalGate
47
+
48
+ /**
49
+ * Keyed by basename (no extension) of each `packages/aeg-core/bin/*.ts` that
50
+ * is a GATE — something that inspects a repo and passes or fails. Non-gate
51
+ * tooling in the same directory (forge writers, one-shot reporters) is listed
52
+ * in `NON_GATE_BINS` below rather than given a fake audience.
53
+ */
54
+ export const GATE_AUDIENCE: Record<string, GateAudience> = {
55
+ 'check-branch-topology': { shippedAs: 'branch-topology', ring: 0 },
56
+ 'check-first-push-dispatch': { shippedAs: 'first-push-dispatch', ring: 0 },
57
+ 'check-no-disk-state': { shippedAs: 'no-disk-state', ring: 0 },
58
+ 'verify-brief': { shippedAs: 'brief-shape', ring: 0 },
59
+ 'verify-coherence': { shippedAs: 'coherence', ring: 0 },
60
+ 'verify-dispatch': { shippedAs: 'dispatch-readiness', ring: 0 },
61
+ 'verify-docs': { shippedAs: ['doc-coverage', 'doc-coverage-push'], ring: 0 },
62
+ 'verify-registry': { shippedAs: 'registry-gates', ring: 0 },
63
+ 'verify-review-gate': { shippedAs: 'review-gate', ring: 1 },
64
+ 'verify-single-plan-pr': { shippedAs: 'single-plan-pr', ring: 0 },
65
+ 'verify-test-plan': { shippedAs: 'test-plan', ring: 1 },
66
+
67
+ 'check-direct-main-push': {
68
+ internal:
69
+ 'Reaches adopters through `vinaya audit --only=direct-push`, not the check registry: it is a ring-2 sweep over merge history keyed on `GITHUB_SHA`, run by the generated archivist job on push to the default branch. It has no diff to key on, so there is nothing for `vinaya check` to run it against.'
70
+ },
71
+ 'check-push-target': {
72
+ internal:
73
+ 'A pre-push hook helper: it takes a branch name as `argv[2]` and answers one `gh pr list --head <branch>` question, for a caller that already knows which ref is being pushed. Adopters reach the same question through the registered `dead-branch-push`, which resolves the branch itself when `BRANCH` is unset. Registering this one too would add a second entry answering an identical forge query with a worse interface.'
74
+ },
75
+ 'verify-task': {
76
+ internal:
77
+ "A composite that shells this repo's own `typecheck`/`lint`/`test`/`build` scripts by name. Those names are this monorepo's toolchain (bun + turbo + biome), not an adopter's; the shipped equivalent of its intent is `vinaya check --all`, which is portable by construction."
78
+ }
79
+ }
80
+
81
+ /**
82
+ * The other half, and the one the motivating case actually lives in.
83
+ *
84
+ * `reader-resolvable-prose` has no bin under `packages/aeg-core/bin/` at all —
85
+ * its logic is `src/reader-resolvable-prose.ts` and its only executable is
86
+ * `apps/cli/src/checks/bin/check-reader-resolvable-prose.ts`. So the map above
87
+ * would never have seen it, and an earlier revision of this file claimed it as
88
+ * the reason the file exists while leaving it uncovered. Review caught that;
89
+ * this is the fix, not a re-wording.
90
+ *
91
+ * Enumerating the SHIPPED check bins asks the question that case actually
92
+ * poses: here is an executable adopters could run — is it registered, and if
93
+ * not, why not? `coreCheckRegistry()` lives in `apps/cli`, which `aeg-core`
94
+ * cannot import without closing a dependency cycle, so the declaration lives
95
+ * here and `apps/cli`'s own suite does the asserting.
96
+ *
97
+ * `check-reader-resolvable-prose`/`check-retired-vocabulary` (task 7, Issue
98
+ * #56): both used to live here as `internal` — hardcoded monorepo-specific
99
+ * doctrine paths made them unreachable through an adopter's own registry.
100
+ * Both are now config-driven (`vinaya.config.json`'s `proseGates`) and
101
+ * registered in `coreCheckRegistry()` as `reader-resolvable-prose` /
102
+ * `retired-vocabulary`, so neither belongs in this map any more — this repo's
103
+ * own `shipped-bin-audience.test.ts` refuses a bin declared in BOTH places.
104
+ */
105
+ export const SHIPPED_BIN_AUDIENCE: Record<string, GateAudience> = {}
106
+
107
+ /**
108
+ * `name` -> `ring` for every check registered in `coreCheckRegistry()` whose
109
+ * bin lives under `apps/cli/src/checks/bin/` — the direct analogue of
110
+ * `ShippedGate.ring` above, for the OTHER directory. Mirrors
111
+ * `apps/cli/src/checks/registry.ts`'s `CORE_CHECK_RING` — duplicated, not
112
+ * imported, for the identical dependency-cycle reason `ShippedGate.ring`'s
113
+ * own comment gives: `aeg-core` cannot import `apps/cli`. This is the
114
+ * registry-derived fact `registry-scaffold.ts` reads to place a stub row for
115
+ * an `apps/cli/src/checks/bin/` G2 candidate; a bin whose stripped name has
116
+ * no entry here gets no stub — same no-guess discipline `classify()`
117
+ * already applies to `packages/aeg-core/bin/` candidates via
118
+ * `GATE_AUDIENCE`. Kept from drifting by `shipped-bin-audience.test.ts`
119
+ * (`apps/cli`)'s own ring-parity block, the only place both sides are in
120
+ * scope at once — same shape as this file's `ShippedGate.ring` check.
121
+ */
122
+ export const CLI_CHECK_RING: Readonly<Record<string, 0 | 1 | 2>> = {
123
+ 'brief-shape': 0,
124
+ 'doc-coverage': 0,
125
+ coherence: 0,
126
+ 'dispatch-readiness': 0,
127
+ 'closes-n': 1,
128
+ 'single-plan-pr': 0,
129
+ 'test-plan': 1,
130
+ 'body-bare-digits': 1,
131
+ 'no-disk-state': 0,
132
+ 'registry-gates': 0,
133
+ 'review-gate': 1,
134
+ 'branch-topology': 0,
135
+ 'dead-branch-push': 0,
136
+ 'first-push-dispatch': 0,
137
+ 'doc-coverage-push': 0,
138
+ 'issue-assignment': 0,
139
+ 'evidence-fresh': 1,
140
+ 'reader-resolvable-prose': 0,
141
+ 'retired-vocabulary': 0,
142
+ 'doctrine-portability': 0,
143
+ 'workspace-escape': 0,
144
+ 'changeset-coverage': 0,
145
+ 'quoted-command': 0,
146
+ 'main-branch-refusal': 0,
147
+ 'token-collection-wired': 0,
148
+ 'token-report': 1
149
+ }
150
+
151
+ /**
152
+ * Files in `bin/` that are not gates and therefore have no audience: forge
153
+ * writers and one-shot reporters. Listed explicitly rather than pattern-matched
154
+ * so a NEW file cannot slip through by being named unlike a gate.
155
+ */
156
+ export const NON_GATE_BINS = [
157
+ 'archive-task',
158
+ 'assign-task-issue',
159
+ 'dead-branch-audit',
160
+ 'eval-agent-compliance',
161
+ 'open-issue',
162
+ 'open-pr',
163
+ 'report-tokens'
164
+ ] as const
165
+
166
+ export function isShipped(a: GateAudience): a is ShippedGate {
167
+ return 'shippedAs' in a
168
+ }
@@ -0,0 +1,301 @@
1
+ export * from './types'
2
+ export type { StateSource } from './state-source'
3
+ export type { DoctrineContent, DoctrineSource } from './doctrine-source'
4
+ export { CLI_CHECK_RING, GATE_AUDIENCE, NON_GATE_BINS, SHIPPED_BIN_AUDIENCE, isShipped } from './gate-audience'
5
+ export type { GateAudience, InternalGate, ShippedGate } from './gate-audience'
6
+ export { ANCHOR_FIELDS, anchoredRegion, anchoredRegionBounds } from './anchored-region'
7
+ export type { AnchorField } from './anchored-region'
8
+ export { parseRegistry } from './parse-registry'
9
+ export {
10
+ CROSS_CUTTING_CANDIDATES,
11
+ deriveBuiltinCrossCuttingDefaults,
12
+ deriveWorkspacePackageDomains,
13
+ parsePnpmWorkspaceYaml
14
+ } from './blast-radius-domains'
15
+ export { parseTranche } from './parse-tranche'
16
+ export { deriveTranche } from './derive-tranche'
17
+ export { parseLedger, rowFromCells } from './parse-ledger'
18
+ export { sumLedger } from './sum-ledger'
19
+ export { aggregateTaskTokenRows, parseTokenReportEntries, parseTokensLines } from './parse-token-report'
20
+ export type { TokenSourcePr } from './parse-token-report'
21
+ export { formatBreakdown, formatTokenReportRow, formatTokensLine } from './report-tokens'
22
+ export type { TokenReportRowInput, TokensLineInput, TranscriptSummary, UsageComponents } from './report-tokens'
23
+ // The Claude Code collection adapter (`tranche-model.md` §12 layer 2) — one
24
+ // host's way to produce a `TranscriptSummary`, exported beside the portable
25
+ // renderers it feeds, never as a requirement of the contract.
26
+ export {
27
+ isTokenCollectionWiringBroken,
28
+ resolveMeteringCapability,
29
+ summarizeTranscript
30
+ } from './claude-code-transcript'
31
+ export type { MeteringCapability, MeteringCapabilityDeps, MeteringIncapableReason } from './claude-code-transcript'
32
+ // The hardened deps every real caller of `resolveMeteringCapability` should
33
+ // build from (`#313`) — a sibling module, not part of the pure adapter above.
34
+ export { hardenedMeteringDeps, isTrustedMeteringStat } from './metering-io-guard'
35
+ export { declarationsIn, findCollisions } from './symbol-collisions'
36
+ export type { SymbolCollision, SymbolDeclaration } from './symbol-collisions'
37
+ export { isCodeFile, isDocFile, isSpecFile } from './file-classify'
38
+ export { hasStatusBlock } from './status-block'
39
+ export {
40
+ classifyDocOwnersManifest,
41
+ DOC_OWNERS_PATH,
42
+ evaluateC5,
43
+ globToRegex,
44
+ isMechanicallyNeutralDiff,
45
+ isUrlPointer,
46
+ parseDocOwners,
47
+ pointerToPath,
48
+ readDocAcks,
49
+ readDocNeutrals
50
+ } from './doc-owners'
51
+ export type { C5Result, DocAck, DocNeutral, DocOwnersBinding, DocOwnersManifestState } from './doc-owners'
52
+ export {
53
+ isPrincipal,
54
+ isWaiverLabelActorVerified,
55
+ PRINCIPAL_ALLOWLIST,
56
+ WAIVER_LABEL,
57
+ WAIVER_LABEL_REVIEW
58
+ } from './waiver-label'
59
+ export { deriveSection7, globsOverlap } from './derive-section7'
60
+ export type { Section7Match } from './derive-section7'
61
+ export { checkManifestValidity, parseNoDocRules } from './manifest-validity'
62
+ export type { NoDocRule } from './manifest-validity'
63
+ export { evaluateVocabularyCitation } from './vocabulary-citation'
64
+ export type {
65
+ VocabularyCheckResult,
66
+ VocabularyFinding,
67
+ VocabularyHit,
68
+ VocabularyPattern
69
+ } from './vocabulary-citation'
70
+ export { deriveTierFromDiff, overrideActive, readTierFromPrBody, TIER_FIELD } from './pr-tier'
71
+ export {
72
+ checkAutonomyClause,
73
+ checkBriefSections,
74
+ checkClosesN as checkBriefClosesN,
75
+ checkDocUpdateList,
76
+ checkForField,
77
+ checkForgeTitle,
78
+ checkPlanPrNoCloses,
79
+ checkPremiseCoverage,
80
+ checkPrincipalPlaceholder,
81
+ checkProjectField,
82
+ checkStopConditions,
83
+ checkSurfaceMap,
84
+ checkTestPlan,
85
+ checkTestPlanExclusivity,
86
+ checkTierField,
87
+ checkWorktreeStep0,
88
+ COMMIT_TYPE_STYLE,
89
+ COMMIT_TYPES,
90
+ headerRegion,
91
+ inferBranchFromBody,
92
+ isBriefShaped,
93
+ isTaskBranch
94
+ } from './brief-validation'
95
+ export type { BriefSectionResult, BriefSectionsOptions } from './brief-validation'
96
+ export {
97
+ checkA1,
98
+ checkA2,
99
+ checkA3,
100
+ checkClosesN,
101
+ checkD1,
102
+ checkL1,
103
+ checkL2,
104
+ checkL3,
105
+ checkL4,
106
+ checkL5,
107
+ checkR1,
108
+ checkT1,
109
+ checkT2,
110
+ checkT3,
111
+ COHERENCE_ENFORCED_FROM,
112
+ extractClosesReferences,
113
+ isGrandfathered,
114
+ R1_GRANDFATHERED_ISSUES,
115
+ scopeT2ToPlanPr
116
+ } from './coherence-checks'
117
+ export type { CheckFailure, CheckResult, ForgeIssue, TrancheFile, TaskEntry } from './coherence-checks'
118
+ export {
119
+ buildProvenanceBlock,
120
+ extractIssue,
121
+ hasProvenance,
122
+ isEligibleForProvenance,
123
+ taskRefFromBranch
124
+ } from './archive-task'
125
+ export type { MergedPrFacts } from './archive-task'
126
+ export { extractCodeReviewVerdict, extractSecurityReviewVerdict } from './verdict-extraction'
127
+ export type { VerdictExtraction } from './verdict-extraction'
128
+ export {
129
+ CHANGESET_RELEASE_BRANCH,
130
+ checkReviewGate,
131
+ DEFAULT_RELEASE_ACTOR,
132
+ isChangesetsReleasePr,
133
+ isReviewGateExemptBranch
134
+ } from './review-gate'
135
+ export type { ReviewGateComment, ReviewGateInput, ReviewGateResult, ReviewGateVerdict } from './review-gate'
136
+ export {
137
+ checkBlastRadiusScope,
138
+ checkConflictCompleteness,
139
+ checkIssueRationale,
140
+ checkIssueType,
141
+ checkNoBriefContent,
142
+ checkProjectsRegistered,
143
+ checkRationaleNamesDocs,
144
+ declaredProjects,
145
+ isTaskIssueLabelSet
146
+ } from './issue-validation'
147
+ export type { IssueSectionResult, ProjectPath, TaskIssueFacts } from './issue-validation'
148
+ export { findHeadingLine, findTable, rowToRecord } from './markdown-table'
149
+ export type { ParsedTable, TableRow } from './markdown-table'
150
+ export { deriveDiagramModel } from './diagram-model'
151
+ export type {
152
+ DiagramConfig,
153
+ DiagramEdge,
154
+ DiagramFinding,
155
+ DiagramModel,
156
+ DiagramNode,
157
+ DiagramNodeKind,
158
+ RenderState
159
+ } from './diagram-model'
160
+ export { parseEnforcementRegistry } from './registry-parse'
161
+ export type { GateRing, GateRow } from './registry-parse'
162
+ export { checkG1, checkG2, checkG3, checkG4, checkG5, checkG6 } from './registry-checks'
163
+ export type { RegistryCheckResult, RegistryCheckStatus, RegistryFinding } from './registry-checks'
164
+ export { applyScaffoldPlan, computeScaffoldPlan, PLACEHOLDER } from './registry-scaffold'
165
+ export type { ScaffoldPlan, ScaffoldSkip, ScaffoldStub } from './registry-scaffold'
166
+ export { ACTIONS, CROSSING_KEYWORDS } from './actions'
167
+ export type { Action, ActionCrossing } from './actions'
168
+ export {
169
+ DERIVABLE_STATUSES,
170
+ DERIVATION_RULES,
171
+ DERIVED_STATUSES,
172
+ deriveStatusFromModel,
173
+ FORGE_FACT_INPUTS
174
+ } from './state-machine-model'
175
+ export type { DerivationRule, ForgeFactInput } from './state-machine-model'
176
+ export { checkPremises, parsePremiseBlock } from './premise-check'
177
+ export type { PremiseAssertion, PremiseCheckResult } from './premise-check'
178
+ export { classifyLeftover } from './leftover-detection'
179
+ export type { LeftoverInput, LeftoverResult, LeftoverVerdict } from './leftover-detection'
180
+ export { checkDeadBranchPush } from './dead-branch-push-guard'
181
+ export type {
182
+ DeadBranchPushInput,
183
+ DeadBranchPushResult,
184
+ DeadBranchPushVerdict,
185
+ PrStateFact
186
+ } from './dead-branch-push-guard'
187
+ export { captureBaseline, compareToBaseline } from './baseline-capture'
188
+ export type { BaselineComparison, BaselineEntry, BaselineToolComparison } from './baseline-capture'
189
+ export { checkDoctrinePortability } from './doctrine-portability'
190
+ export type { PortabilityFinding, PortabilitySourceFile } from './doctrine-portability'
191
+ export {
192
+ checkReaderResolvableProse,
193
+ checkUndefinedVocabulary,
194
+ checkUnresolvableReferences,
195
+ classifyProseFile,
196
+ legacySlugPattern,
197
+ parseGlossaryTerms,
198
+ stripNonProse
199
+ } from './reader-resolvable-prose'
200
+ export type { ProseFileClass, ProseFinding, ProseSourceFile } from './reader-resolvable-prose'
201
+ export {
202
+ checkQuotedCommandStaleness,
203
+ evaluateCitedQuotes,
204
+ findCitedQuotes,
205
+ isValidCitedFilePath
206
+ } from './quoted-command'
207
+ export type { CitedQuote, QuotedCommandFinding, QuotedCommandSourceFile } from './quoted-command'
208
+ export {
209
+ PATTERN_EXEMPT,
210
+ RETIRED_EXEMPT_SUBSTRINGS,
211
+ RETIRED_PATTERNS,
212
+ scanRetiredVocabulary
213
+ } from './retired-vocabulary'
214
+ export type { VocabFinding, VocabSourceFile } from './retired-vocabulary'
215
+ export { checkLocalAnchorCoverage } from './local-anchor-coverage'
216
+ export type {
217
+ AnchorCoverageFinding,
218
+ AnchorCoverageScope,
219
+ AnchorSourceFile,
220
+ LocalAnchorCoverageOptions,
221
+ LocalAnchorCoverageResult
222
+ } from './local-anchor-coverage'
223
+ export { checkDispatchReadiness } from './dispatch-gate'
224
+ export type {
225
+ DispatchConflictsWithFact,
226
+ DispatchDependsOnFact,
227
+ DispatchEdgeFact,
228
+ DispatchGateInput,
229
+ DispatchIssueFact,
230
+ DispatchPriorTrancheFact,
231
+ DispatchPriorTaskFact,
232
+ DispatchResult
233
+ } from './dispatch-gate'
234
+ export { checkSinglePlanPr, trancheSlugFromTopologyPath, touchesAnyTopology } from './single-plan-pr'
235
+ export type { OpenPrFiles } from './single-plan-pr'
236
+ export { isNewDiskStateFile } from './no-disk-state'
237
+ export type { DiskStateFileStatus } from './no-disk-state'
238
+ export { checkDirectMainPush } from './direct-main-push'
239
+ export type { DirectMainPushFact, DirectMainPushResult } from './direct-main-push'
240
+ export { checkMainBranchRefusal } from './main-branch-refusal'
241
+ export type { MainBranchRefusalFinding, MainBranchRefusalReason } from './main-branch-refusal'
242
+ export { ensureLabelExists, LABEL_COLOR } from './ensure-label'
243
+ export type { LabelExistenceIo } from './ensure-label'
244
+ export { findDeadBranchPushes } from './dead-branch-push-audit'
245
+ export type { DeadBranchFact, DeadBranchPush } from './dead-branch-push-audit'
246
+ export { checkBranchTopology, taskBranchTopologyFields } from './branch-topology-gate'
247
+ export type { BranchTopologyInput, BranchTopologyResult, BranchTopologyVerdict } from './branch-topology-gate'
248
+ export { checkFirstPushDispatchGate, parseTaskBranch } from './first-push-dispatch-gate'
249
+ export type {
250
+ DispatchReadinessFact,
251
+ FirstPushDispatchGateInput,
252
+ FirstPushDispatchGateResult,
253
+ FirstPushDispatchGateVerdict
254
+ } from './first-push-dispatch-gate'
255
+ export { decideIssueAssignment } from './issue-assignment'
256
+ export type { IssueAssignmentDecision, IssueAssignmentInput } from './issue-assignment'
257
+ export { locateTestPlanSection } from './test-plan-section'
258
+ export type { TestPlanSection } from './test-plan-section'
259
+ export { evaluateTestPlanGate } from './test-plan-gate'
260
+ export type { TestPlanGateResult, TestPlanGateVerdict } from './test-plan-gate'
261
+ export {
262
+ AEG_BLOCKED_LABEL,
263
+ buildBranchName,
264
+ fetchForgeFacts,
265
+ fetchForgeTasksByLabel,
266
+ fetchOpenIssuesByLabel,
267
+ fetchTaskIssueRefs,
268
+ findTrancheSlug,
269
+ hasLabel,
270
+ trancheLabel,
271
+ trancheSlugLengthError,
272
+ trancheSlugOf,
273
+ LABEL_MAX_LENGTH,
274
+ LABEL_NAMESPACE,
275
+ LABELS,
276
+ label,
277
+ mapForgeFacts,
278
+ matchesLabel,
279
+ projectsFromBody
280
+ } from '@attalabs/aeg-forge-state'
281
+ export type { Label, LabelCategory, LabelForm, LabelKey } from '@attalabs/aeg-forge-state'
282
+ export type {
283
+ FetchForgeFactsInput,
284
+ ForgeFactsSnapshot,
285
+ PrRef,
286
+ RawTaskFacts,
287
+ TaskIssueRef,
288
+ TaskRef
289
+ } from '@attalabs/aeg-types'
290
+ export { checkAdoptable, checkMilestoneShape, releaseFieldFromBody } from './milestone-validation'
291
+ export type {
292
+ AdoptFacts,
293
+ AdoptResult,
294
+ AdoptSlugFacts,
295
+ AdoptTargetFacts,
296
+ MilestoneIntent,
297
+ MilestoneShapeResult,
298
+ ReleaseField
299
+ } from './milestone-validation'
300
+ export { findWorkspaceEscapes } from './workspace-escape'
301
+ export type { WorkspaceEscapeFinding, WorkspaceEscapeReason, WorkspaceEscapeSourceFile } from './workspace-escape'