@attalabs/vinaya 0.19.3 → 0.20.1

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 (112) hide show
  1. package/README.md +7 -0
  2. package/aeg-root/contracts/archivist-tranche-archivist.md +2 -2
  3. package/aeg-root/contracts/tranche-archivist-planner.md +8 -8
  4. package/aeg-root/enforcement.md +6 -4
  5. package/aeg-root/process.md +5 -5
  6. package/aeg-root/roles/archivist.md +9 -10
  7. package/aeg-root/roles/brief-author.md +1 -1
  8. package/aeg-root/roles/developer.md +1 -1
  9. package/aeg-root/roles/planner.md +1 -1
  10. package/aeg-root/roles/principal.md +1 -1
  11. package/aeg-root/roles/tranche-archivist.md +3 -16
  12. package/aeg-root/skills/aeg/SKILL.md +30 -1
  13. package/aeg-root/skills/aeg-roles/SKILL.md +1 -1
  14. package/aeg-root/skills/brief-authoring/SKILL.md +2 -2
  15. package/aeg-root/state-machine.md +8 -6
  16. package/aeg-root/task-model.md +1 -1
  17. package/aeg-root/templates/pr-report-template.md +4 -0
  18. package/dist/checks/bin/check-body-bare-digits.js +192 -27
  19. package/dist/checks/bin/check-branch-topology.js +518 -11
  20. package/dist/checks/bin/check-brief-shape.js +104 -11
  21. package/dist/checks/bin/check-closes-n.js +518 -11
  22. package/dist/checks/bin/check-coherence.js +526 -12
  23. package/dist/checks/bin/check-dead-branch-push.js +104 -11
  24. package/dist/checks/bin/check-dispatch-readiness.js +621 -14
  25. package/dist/checks/bin/check-doc-coverage-push.js +170 -20
  26. package/dist/checks/bin/check-doc-coverage.js +170 -20
  27. package/dist/checks/bin/check-doctrine-portability.js +112 -12
  28. package/dist/checks/bin/check-evidence-fresh.js +213 -20
  29. package/dist/checks/bin/check-first-push-dispatch.js +526 -12
  30. package/dist/checks/bin/check-issue-assignment.js +518 -11
  31. package/dist/checks/bin/check-main-branch-refusal.js +3724 -0
  32. package/dist/checks/bin/check-no-disk-state.js +104 -11
  33. package/dist/checks/bin/check-reader-resolvable-prose.js +186 -17
  34. package/dist/checks/bin/check-registry-gates.js +185 -16
  35. package/dist/checks/bin/check-retired-vocabulary.js +185 -16
  36. package/dist/checks/bin/check-review-gate.js +112 -12
  37. package/dist/checks/bin/check-single-plan-pr.js +104 -11
  38. package/dist/checks/bin/check-test-plan.js +104 -11
  39. package/dist/checks/bin/check-workspace-escape.js +104 -11
  40. package/dist/index.js +664 -56
  41. package/package.json +1 -1
  42. package/studio-standalone/_node_modules/@attalabs/aeg-core/bin/verify-coherence.ts +1089 -0
  43. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  44. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  45. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  46. package/studio-standalone/apps/vinaya-studio/web/.next/required-server-files.json +5 -0
  47. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  48. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  49. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  50. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  51. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  52. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  53. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  54. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  55. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  56. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  57. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js +1 -1
  58. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +1 -1
  59. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  60. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  61. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  62. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  63. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  64. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  65. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  66. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  67. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  68. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  69. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  70. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  71. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
  72. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  73. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  74. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  75. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  76. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  77. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  78. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  79. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  80. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  81. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  82. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  83. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/{[externals]__0pvgf28._.js → [externals]__1agj1ww._.js} +2 -2
  84. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/[root-of-the-server]__02a-3g8._.js +1 -1
  85. 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
  86. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0053k9k._.js +1 -1
  87. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
  88. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
  89. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
  90. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__03jepya._.js → [root-of-the-server]__16cuydh._.js} +1 -1
  91. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
  92. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
  93. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_03x_w6q._.js +1 -1
  94. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
  95. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
  96. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
  97. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
  98. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  99. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  100. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  101. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
  102. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3noqvds-2bvrd.js → 0ea8-8nopz29h.js} +1 -1
  103. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0la0hhmjprdxm.css +1 -0
  104. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1lk7h-0buf4ab.js +1 -0
  105. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3gehliafvmjo9.js → 2twnwe77d4n-m.js} +1 -1
  106. package/studio-standalone/apps/vinaya-studio/web/server.js +1 -1
  107. package/aeg-root/coordination.md +0 -292
  108. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/2iysedx-n06xc.js +0 -1
  109. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/42wxpzjhw7oy4.css +0 -1
  110. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_buildManifest.js +0 -0
  111. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_clientMiddlewareManifest.js +0 -0
  112. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_ssgManifest.js +0 -0
@@ -4,17 +4,17 @@
4
4
  import { execFileSync as execFileSync3 } from "node:child_process";
5
5
  // ../../packages/aeg-core/src/gate-audience.ts
6
6
  var GATE_AUDIENCE = {
7
- "check-branch-topology": { shippedAs: "branch-topology" },
8
- "check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
9
- "check-no-disk-state": { shippedAs: "no-disk-state" },
10
- "verify-brief": { shippedAs: "brief-shape" },
11
- "verify-coherence": { shippedAs: "coherence" },
12
- "verify-dispatch": { shippedAs: "dispatch-readiness" },
13
- "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
14
- "verify-registry": { shippedAs: "registry-gates" },
15
- "verify-review-gate": { shippedAs: "review-gate" },
16
- "verify-single-plan-pr": { shippedAs: "single-plan-pr" },
17
- "verify-test-plan": { shippedAs: "test-plan" },
7
+ "check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
8
+ "check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
9
+ "check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
10
+ "verify-brief": { shippedAs: "brief-shape", ring: 0 },
11
+ "verify-coherence": { shippedAs: "coherence", ring: 0 },
12
+ "verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
13
+ "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
14
+ "verify-registry": { shippedAs: "registry-gates", ring: 0 },
15
+ "verify-review-gate": { shippedAs: "review-gate", ring: 1 },
16
+ "verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
17
+ "verify-test-plan": { shippedAs: "test-plan", ring: 1 },
18
18
  "check-direct-main-push": {
19
19
  internal: "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."
20
20
  },
@@ -326,6 +326,13 @@ var LABELS = [
326
326
  form: "literal",
327
327
  carries: "Execution is halted pending an external unblock; wins over every other derived status."
328
328
  },
329
+ {
330
+ key: "backlog",
331
+ id: "vinaya/backlog",
332
+ category: "state",
333
+ form: "literal",
334
+ carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
335
+ },
329
336
  {
330
337
  key: "tier-0",
331
338
  id: "vinaya/tier:0",
@@ -1984,7 +1991,59 @@ function overrideActive(opts) {
1984
1991
  return false;
1985
1992
  }
1986
1993
  // ../../packages/aeg-core/src/premise-check.ts
1994
+ import { createHash } from "node:crypto";
1987
1995
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
1996
+ function isPremiseHeader(line) {
1997
+ const stripped = line.replace(/[*#]/g, "").trim();
1998
+ return /^premise\s*:?$/i.test(stripped);
1999
+ }
2000
+ var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
2001
+ function parsePremiseBlock(prBody) {
2002
+ const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
2003
+ const lines = searchIn.split(/\r?\n/);
2004
+ const assertions = [];
2005
+ let inBlock = false;
2006
+ for (const raw of lines) {
2007
+ const line = raw.trim();
2008
+ if (!inBlock) {
2009
+ if (isPremiseHeader(line))
2010
+ inBlock = true;
2011
+ continue;
2012
+ }
2013
+ if (line === "")
2014
+ break;
2015
+ const m = line.match(PREMISE_LINE);
2016
+ if (!m)
2017
+ break;
2018
+ const [, path, kindRaw, value] = m;
2019
+ const kind = kindRaw.toLowerCase();
2020
+ if (!ASSERTION_KINDS.has(kind))
2021
+ continue;
2022
+ assertions.push({ kind, path, value: value.trim() });
2023
+ }
2024
+ return assertions;
2025
+ }
2026
+ function checkPremises(assertions, fileReader) {
2027
+ const failures = [];
2028
+ for (const a of assertions) {
2029
+ const content = fileReader(a.path);
2030
+ if (content === null) {
2031
+ failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
2032
+ continue;
2033
+ }
2034
+ if (a.kind === "contains" && !content.includes(a.value)) {
2035
+ failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
2036
+ } else if (a.kind === "absent" && content.includes(a.value)) {
2037
+ failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2038
+ } else if (a.kind === "sha256") {
2039
+ const actual = createHash("sha256").update(content).digest("hex");
2040
+ if (actual !== a.value.toLowerCase()) {
2041
+ failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2042
+ }
2043
+ }
2044
+ }
2045
+ return { pass: failures.length === 0, failures };
2046
+ }
1988
2047
 
1989
2048
  // ../../packages/aeg-core/src/test-plan-section.ts
1990
2049
  var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
@@ -2788,6 +2847,7 @@ function checkG1(rows, existsFn) {
2788
2847
  }
2789
2848
  return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
2790
2849
  }
2850
+ var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
2791
2851
  function checkG2(rows, candidateFiles) {
2792
2852
  const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
2793
2853
  const findings = [];
@@ -2799,6 +2859,16 @@ function checkG2(rows, candidateFiles) {
2799
2859
  });
2800
2860
  }
2801
2861
  }
2862
+ for (const row of rows) {
2863
+ const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
2864
+ if (carriesPlaceholder) {
2865
+ findings.push({
2866
+ row: row.action,
2867
+ path: row.implementation,
2868
+ reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
2869
+ });
2870
+ }
2871
+ }
2802
2872
  return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
2803
2873
  }
2804
2874
  function checkG3(ring0Rows, crossingFiles) {
@@ -3318,6 +3388,29 @@ function isNewDiskStateFile(path, status) {
3318
3388
  return false;
3319
3389
  return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
3320
3390
  }
3391
+ // ../../packages/aeg-core/src/main-branch-refusal.ts
3392
+ function checkMainBranchRefusal(facts) {
3393
+ const { currentSymbolicBranch, defaultBranch } = facts;
3394
+ if (currentSymbolicBranch === null)
3395
+ return null;
3396
+ if (defaultBranch === null) {
3397
+ return {
3398
+ reason: "default-branch-undetermined",
3399
+ severity: "warning",
3400
+ currentBranch: currentSymbolicBranch,
3401
+ defaultBranch: null
3402
+ };
3403
+ }
3404
+ if (currentSymbolicBranch === defaultBranch) {
3405
+ return {
3406
+ reason: "on-default-branch",
3407
+ severity: "error",
3408
+ currentBranch: currentSymbolicBranch,
3409
+ defaultBranch
3410
+ };
3411
+ }
3412
+ return null;
3413
+ }
3321
3414
  // ../../packages/aeg-core/src/branch-topology-gate.ts
3322
3415
  function taskBranchTopologyFields(branch) {
3323
3416
  if (!/^task\/.*\/.*$/.test(branch))
@@ -3671,8 +3764,15 @@ function isSafeRepoRelPath(p) {
3671
3764
  var SafeRepoRelPath = z.string().refine(isSafeRepoRelPath, {
3672
3765
  message: "must be a repo-root-relative path with no `..` segment or absolute root"
3673
3766
  });
3767
+ var CANONICAL_HOOK_BLOCK_PREFIXES = [".git/", ".husky/", ".vinaya/hooks/", ".claude/hooks/"];
3768
+ function isCanonicalHookBlockPath(p) {
3769
+ return CANONICAL_HOOK_BLOCK_PREFIXES.some((prefix) => p.startsWith(prefix) && p.length > prefix.length);
3770
+ }
3771
+ var ManagedHookBlockPath = SafeRepoRelPath.refine(isCanonicalHookBlockPath, {
3772
+ message: `must start with one of ${CANONICAL_HOOK_BLOCK_PREFIXES.join(", ")} (byte-exact, case-sensitive)`
3773
+ });
3674
3774
  var ManagedBlockRecordSchema = z.object({
3675
- path: SafeRepoRelPath,
3775
+ path: ManagedHookBlockPath,
3676
3776
  marker: z.string(),
3677
3777
  comment: z.enum(["hash", "html"])
3678
3778
  });
@@ -4,17 +4,17 @@
4
4
  import { execFileSync as execFileSync2 } from "node:child_process";
5
5
  // ../../packages/aeg-core/src/gate-audience.ts
6
6
  var GATE_AUDIENCE = {
7
- "check-branch-topology": { shippedAs: "branch-topology" },
8
- "check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
9
- "check-no-disk-state": { shippedAs: "no-disk-state" },
10
- "verify-brief": { shippedAs: "brief-shape" },
11
- "verify-coherence": { shippedAs: "coherence" },
12
- "verify-dispatch": { shippedAs: "dispatch-readiness" },
13
- "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
14
- "verify-registry": { shippedAs: "registry-gates" },
15
- "verify-review-gate": { shippedAs: "review-gate" },
16
- "verify-single-plan-pr": { shippedAs: "single-plan-pr" },
17
- "verify-test-plan": { shippedAs: "test-plan" },
7
+ "check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
8
+ "check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
9
+ "check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
10
+ "verify-brief": { shippedAs: "brief-shape", ring: 0 },
11
+ "verify-coherence": { shippedAs: "coherence", ring: 0 },
12
+ "verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
13
+ "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
14
+ "verify-registry": { shippedAs: "registry-gates", ring: 0 },
15
+ "verify-review-gate": { shippedAs: "review-gate", ring: 1 },
16
+ "verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
17
+ "verify-test-plan": { shippedAs: "test-plan", ring: 1 },
18
18
  "check-direct-main-push": {
19
19
  internal: "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."
20
20
  },
@@ -326,6 +326,13 @@ var LABELS = [
326
326
  form: "literal",
327
327
  carries: "Execution is halted pending an external unblock; wins over every other derived status."
328
328
  },
329
+ {
330
+ key: "backlog",
331
+ id: "vinaya/backlog",
332
+ category: "state",
333
+ form: "literal",
334
+ carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
335
+ },
329
336
  {
330
337
  key: "tier-0",
331
338
  id: "vinaya/tier:0",
@@ -1984,7 +1991,59 @@ function overrideActive(opts) {
1984
1991
  return false;
1985
1992
  }
1986
1993
  // ../../packages/aeg-core/src/premise-check.ts
1994
+ import { createHash } from "node:crypto";
1987
1995
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
1996
+ function isPremiseHeader(line) {
1997
+ const stripped = line.replace(/[*#]/g, "").trim();
1998
+ return /^premise\s*:?$/i.test(stripped);
1999
+ }
2000
+ var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
2001
+ function parsePremiseBlock(prBody) {
2002
+ const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
2003
+ const lines = searchIn.split(/\r?\n/);
2004
+ const assertions = [];
2005
+ let inBlock = false;
2006
+ for (const raw of lines) {
2007
+ const line = raw.trim();
2008
+ if (!inBlock) {
2009
+ if (isPremiseHeader(line))
2010
+ inBlock = true;
2011
+ continue;
2012
+ }
2013
+ if (line === "")
2014
+ break;
2015
+ const m = line.match(PREMISE_LINE);
2016
+ if (!m)
2017
+ break;
2018
+ const [, path, kindRaw, value] = m;
2019
+ const kind = kindRaw.toLowerCase();
2020
+ if (!ASSERTION_KINDS.has(kind))
2021
+ continue;
2022
+ assertions.push({ kind, path, value: value.trim() });
2023
+ }
2024
+ return assertions;
2025
+ }
2026
+ function checkPremises(assertions, fileReader) {
2027
+ const failures = [];
2028
+ for (const a of assertions) {
2029
+ const content = fileReader(a.path);
2030
+ if (content === null) {
2031
+ failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
2032
+ continue;
2033
+ }
2034
+ if (a.kind === "contains" && !content.includes(a.value)) {
2035
+ failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
2036
+ } else if (a.kind === "absent" && content.includes(a.value)) {
2037
+ failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2038
+ } else if (a.kind === "sha256") {
2039
+ const actual = createHash("sha256").update(content).digest("hex");
2040
+ if (actual !== a.value.toLowerCase()) {
2041
+ failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2042
+ }
2043
+ }
2044
+ }
2045
+ return { pass: failures.length === 0, failures };
2046
+ }
1988
2047
 
1989
2048
  // ../../packages/aeg-core/src/test-plan-section.ts
1990
2049
  var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
@@ -2788,6 +2847,7 @@ function checkG1(rows, existsFn) {
2788
2847
  }
2789
2848
  return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
2790
2849
  }
2850
+ var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
2791
2851
  function checkG2(rows, candidateFiles) {
2792
2852
  const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
2793
2853
  const findings = [];
@@ -2799,6 +2859,16 @@ function checkG2(rows, candidateFiles) {
2799
2859
  });
2800
2860
  }
2801
2861
  }
2862
+ for (const row of rows) {
2863
+ const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
2864
+ if (carriesPlaceholder) {
2865
+ findings.push({
2866
+ row: row.action,
2867
+ path: row.implementation,
2868
+ reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
2869
+ });
2870
+ }
2871
+ }
2802
2872
  return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
2803
2873
  }
2804
2874
  function checkG3(ring0Rows, crossingFiles) {
@@ -3318,6 +3388,29 @@ function isNewDiskStateFile(path, status) {
3318
3388
  return false;
3319
3389
  return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
3320
3390
  }
3391
+ // ../../packages/aeg-core/src/main-branch-refusal.ts
3392
+ function checkMainBranchRefusal(facts) {
3393
+ const { currentSymbolicBranch, defaultBranch } = facts;
3394
+ if (currentSymbolicBranch === null)
3395
+ return null;
3396
+ if (defaultBranch === null) {
3397
+ return {
3398
+ reason: "default-branch-undetermined",
3399
+ severity: "warning",
3400
+ currentBranch: currentSymbolicBranch,
3401
+ defaultBranch: null
3402
+ };
3403
+ }
3404
+ if (currentSymbolicBranch === defaultBranch) {
3405
+ return {
3406
+ reason: "on-default-branch",
3407
+ severity: "error",
3408
+ currentBranch: currentSymbolicBranch,
3409
+ defaultBranch
3410
+ };
3411
+ }
3412
+ return null;
3413
+ }
3321
3414
  // ../../packages/aeg-core/src/branch-topology-gate.ts
3322
3415
  function taskBranchTopologyFields(branch) {
3323
3416
  if (!/^task\/.*\/.*$/.test(branch))
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  // ../../packages/aeg-core/src/gate-audience.ts
3
3
  var GATE_AUDIENCE = {
4
- "check-branch-topology": { shippedAs: "branch-topology" },
5
- "check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
6
- "check-no-disk-state": { shippedAs: "no-disk-state" },
7
- "verify-brief": { shippedAs: "brief-shape" },
8
- "verify-coherence": { shippedAs: "coherence" },
9
- "verify-dispatch": { shippedAs: "dispatch-readiness" },
10
- "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
11
- "verify-registry": { shippedAs: "registry-gates" },
12
- "verify-review-gate": { shippedAs: "review-gate" },
13
- "verify-single-plan-pr": { shippedAs: "single-plan-pr" },
14
- "verify-test-plan": { shippedAs: "test-plan" },
4
+ "check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
5
+ "check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
6
+ "check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
7
+ "verify-brief": { shippedAs: "brief-shape", ring: 0 },
8
+ "verify-coherence": { shippedAs: "coherence", ring: 0 },
9
+ "verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
10
+ "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
11
+ "verify-registry": { shippedAs: "registry-gates", ring: 0 },
12
+ "verify-review-gate": { shippedAs: "review-gate", ring: 1 },
13
+ "verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
14
+ "verify-test-plan": { shippedAs: "test-plan", ring: 1 },
15
15
  "check-direct-main-push": {
16
16
  internal: "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."
17
17
  },
@@ -323,6 +323,13 @@ var LABELS = [
323
323
  form: "literal",
324
324
  carries: "Execution is halted pending an external unblock; wins over every other derived status."
325
325
  },
326
+ {
327
+ key: "backlog",
328
+ id: "vinaya/backlog",
329
+ category: "state",
330
+ form: "literal",
331
+ carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
332
+ },
326
333
  {
327
334
  key: "tier-0",
328
335
  id: "vinaya/tier:0",
@@ -1981,7 +1988,59 @@ function overrideActive(opts) {
1981
1988
  return false;
1982
1989
  }
1983
1990
  // ../../packages/aeg-core/src/premise-check.ts
1991
+ import { createHash } from "node:crypto";
1984
1992
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
1993
+ function isPremiseHeader(line) {
1994
+ const stripped = line.replace(/[*#]/g, "").trim();
1995
+ return /^premise\s*:?$/i.test(stripped);
1996
+ }
1997
+ var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
1998
+ function parsePremiseBlock(prBody) {
1999
+ const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
2000
+ const lines = searchIn.split(/\r?\n/);
2001
+ const assertions = [];
2002
+ let inBlock = false;
2003
+ for (const raw of lines) {
2004
+ const line = raw.trim();
2005
+ if (!inBlock) {
2006
+ if (isPremiseHeader(line))
2007
+ inBlock = true;
2008
+ continue;
2009
+ }
2010
+ if (line === "")
2011
+ break;
2012
+ const m = line.match(PREMISE_LINE);
2013
+ if (!m)
2014
+ break;
2015
+ const [, path, kindRaw, value] = m;
2016
+ const kind = kindRaw.toLowerCase();
2017
+ if (!ASSERTION_KINDS.has(kind))
2018
+ continue;
2019
+ assertions.push({ kind, path, value: value.trim() });
2020
+ }
2021
+ return assertions;
2022
+ }
2023
+ function checkPremises(assertions, fileReader) {
2024
+ const failures = [];
2025
+ for (const a of assertions) {
2026
+ const content = fileReader(a.path);
2027
+ if (content === null) {
2028
+ failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
2029
+ continue;
2030
+ }
2031
+ if (a.kind === "contains" && !content.includes(a.value)) {
2032
+ failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
2033
+ } else if (a.kind === "absent" && content.includes(a.value)) {
2034
+ failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2035
+ } else if (a.kind === "sha256") {
2036
+ const actual = createHash("sha256").update(content).digest("hex");
2037
+ if (actual !== a.value.toLowerCase()) {
2038
+ failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2039
+ }
2040
+ }
2041
+ }
2042
+ return { pass: failures.length === 0, failures };
2043
+ }
1985
2044
 
1986
2045
  // ../../packages/aeg-core/src/test-plan-section.ts
1987
2046
  var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
@@ -2785,6 +2844,7 @@ function checkG1(rows, existsFn) {
2785
2844
  }
2786
2845
  return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
2787
2846
  }
2847
+ var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
2788
2848
  function checkG2(rows, candidateFiles) {
2789
2849
  const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
2790
2850
  const findings = [];
@@ -2796,6 +2856,16 @@ function checkG2(rows, candidateFiles) {
2796
2856
  });
2797
2857
  }
2798
2858
  }
2859
+ for (const row of rows) {
2860
+ const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
2861
+ if (carriesPlaceholder) {
2862
+ findings.push({
2863
+ row: row.action,
2864
+ path: row.implementation,
2865
+ reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
2866
+ });
2867
+ }
2868
+ }
2799
2869
  return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
2800
2870
  }
2801
2871
  function checkG3(ring0Rows, crossingFiles) {
@@ -3315,6 +3385,29 @@ function isNewDiskStateFile(path, status) {
3315
3385
  return false;
3316
3386
  return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
3317
3387
  }
3388
+ // ../../packages/aeg-core/src/main-branch-refusal.ts
3389
+ function checkMainBranchRefusal(facts) {
3390
+ const { currentSymbolicBranch, defaultBranch } = facts;
3391
+ if (currentSymbolicBranch === null)
3392
+ return null;
3393
+ if (defaultBranch === null) {
3394
+ return {
3395
+ reason: "default-branch-undetermined",
3396
+ severity: "warning",
3397
+ currentBranch: currentSymbolicBranch,
3398
+ defaultBranch: null
3399
+ };
3400
+ }
3401
+ if (currentSymbolicBranch === defaultBranch) {
3402
+ return {
3403
+ reason: "on-default-branch",
3404
+ severity: "error",
3405
+ currentBranch: currentSymbolicBranch,
3406
+ defaultBranch
3407
+ };
3408
+ }
3409
+ return null;
3410
+ }
3318
3411
  // ../../packages/aeg-core/src/branch-topology-gate.ts
3319
3412
  function taskBranchTopologyFields(branch) {
3320
3413
  if (!/^task\/.*\/.*$/.test(branch))
@@ -5,17 +5,17 @@ import { readdirSync, readFileSync, statSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  // ../../packages/aeg-core/src/gate-audience.ts
7
7
  var GATE_AUDIENCE = {
8
- "check-branch-topology": { shippedAs: "branch-topology" },
9
- "check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
10
- "check-no-disk-state": { shippedAs: "no-disk-state" },
11
- "verify-brief": { shippedAs: "brief-shape" },
12
- "verify-coherence": { shippedAs: "coherence" },
13
- "verify-dispatch": { shippedAs: "dispatch-readiness" },
14
- "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
15
- "verify-registry": { shippedAs: "registry-gates" },
16
- "verify-review-gate": { shippedAs: "review-gate" },
17
- "verify-single-plan-pr": { shippedAs: "single-plan-pr" },
18
- "verify-test-plan": { shippedAs: "test-plan" },
8
+ "check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
9
+ "check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
10
+ "check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
11
+ "verify-brief": { shippedAs: "brief-shape", ring: 0 },
12
+ "verify-coherence": { shippedAs: "coherence", ring: 0 },
13
+ "verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
14
+ "verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
15
+ "verify-registry": { shippedAs: "registry-gates", ring: 0 },
16
+ "verify-review-gate": { shippedAs: "review-gate", ring: 1 },
17
+ "verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
18
+ "verify-test-plan": { shippedAs: "test-plan", ring: 1 },
19
19
  "check-direct-main-push": {
20
20
  internal: "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."
21
21
  },
@@ -327,6 +327,13 @@ var LABELS = [
327
327
  form: "literal",
328
328
  carries: "Execution is halted pending an external unblock; wins over every other derived status."
329
329
  },
330
+ {
331
+ key: "backlog",
332
+ id: "vinaya/backlog",
333
+ category: "state",
334
+ form: "literal",
335
+ carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
336
+ },
330
337
  {
331
338
  key: "tier-0",
332
339
  id: "vinaya/tier:0",
@@ -1985,7 +1992,59 @@ function overrideActive(opts) {
1985
1992
  return false;
1986
1993
  }
1987
1994
  // ../../packages/aeg-core/src/premise-check.ts
1995
+ import { createHash } from "node:crypto";
1988
1996
  var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
1997
+ function isPremiseHeader(line) {
1998
+ const stripped = line.replace(/[*#]/g, "").trim();
1999
+ return /^premise\s*:?$/i.test(stripped);
2000
+ }
2001
+ var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
2002
+ function parsePremiseBlock(prBody) {
2003
+ const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
2004
+ const lines = searchIn.split(/\r?\n/);
2005
+ const assertions = [];
2006
+ let inBlock = false;
2007
+ for (const raw of lines) {
2008
+ const line = raw.trim();
2009
+ if (!inBlock) {
2010
+ if (isPremiseHeader(line))
2011
+ inBlock = true;
2012
+ continue;
2013
+ }
2014
+ if (line === "")
2015
+ break;
2016
+ const m = line.match(PREMISE_LINE);
2017
+ if (!m)
2018
+ break;
2019
+ const [, path, kindRaw, value] = m;
2020
+ const kind = kindRaw.toLowerCase();
2021
+ if (!ASSERTION_KINDS.has(kind))
2022
+ continue;
2023
+ assertions.push({ kind, path, value: value.trim() });
2024
+ }
2025
+ return assertions;
2026
+ }
2027
+ function checkPremises(assertions, fileReader) {
2028
+ const failures = [];
2029
+ for (const a of assertions) {
2030
+ const content = fileReader(a.path);
2031
+ if (content === null) {
2032
+ failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
2033
+ continue;
2034
+ }
2035
+ if (a.kind === "contains" && !content.includes(a.value)) {
2036
+ failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
2037
+ } else if (a.kind === "absent" && content.includes(a.value)) {
2038
+ failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
2039
+ } else if (a.kind === "sha256") {
2040
+ const actual = createHash("sha256").update(content).digest("hex");
2041
+ if (actual !== a.value.toLowerCase()) {
2042
+ failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
2043
+ }
2044
+ }
2045
+ }
2046
+ return { pass: failures.length === 0, failures };
2047
+ }
1989
2048
 
1990
2049
  // ../../packages/aeg-core/src/test-plan-section.ts
1991
2050
  var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
@@ -2789,6 +2848,7 @@ function checkG1(rows, existsFn) {
2789
2848
  }
2790
2849
  return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
2791
2850
  }
2851
+ var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
2792
2852
  function checkG2(rows, candidateFiles) {
2793
2853
  const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
2794
2854
  const findings = [];
@@ -2800,6 +2860,16 @@ function checkG2(rows, candidateFiles) {
2800
2860
  });
2801
2861
  }
2802
2862
  }
2863
+ for (const row of rows) {
2864
+ const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
2865
+ if (carriesPlaceholder) {
2866
+ findings.push({
2867
+ row: row.action,
2868
+ path: row.implementation,
2869
+ reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
2870
+ });
2871
+ }
2872
+ }
2803
2873
  return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
2804
2874
  }
2805
2875
  function checkG3(ring0Rows, crossingFiles) {
@@ -3319,6 +3389,29 @@ function isNewDiskStateFile(path, status) {
3319
3389
  return false;
3320
3390
  return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
3321
3391
  }
3392
+ // ../../packages/aeg-core/src/main-branch-refusal.ts
3393
+ function checkMainBranchRefusal(facts) {
3394
+ const { currentSymbolicBranch, defaultBranch } = facts;
3395
+ if (currentSymbolicBranch === null)
3396
+ return null;
3397
+ if (defaultBranch === null) {
3398
+ return {
3399
+ reason: "default-branch-undetermined",
3400
+ severity: "warning",
3401
+ currentBranch: currentSymbolicBranch,
3402
+ defaultBranch: null
3403
+ };
3404
+ }
3405
+ if (currentSymbolicBranch === defaultBranch) {
3406
+ return {
3407
+ reason: "on-default-branch",
3408
+ severity: "error",
3409
+ currentBranch: currentSymbolicBranch,
3410
+ defaultBranch
3411
+ };
3412
+ }
3413
+ return null;
3414
+ }
3322
3415
  // ../../packages/aeg-core/src/branch-topology-gate.ts
3323
3416
  function taskBranchTopologyFields(branch) {
3324
3417
  if (!/^task\/.*\/.*$/.test(branch))