@attalabs/vinaya 0.16.0 → 0.17.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 (121) hide show
  1. package/README.md +8 -2
  2. package/aeg-root/contracts/planner-brief.md +1 -1
  3. package/aeg-root/enforcement.md +2 -2
  4. package/aeg-root/roles/developer.md +1 -0
  5. package/aeg-root/roles/planner.md +2 -2
  6. package/aeg-root/roles/reviewer.md +1 -1
  7. package/aeg-root/skills/aeg/SKILL.md +1 -1
  8. package/aeg-root/state-machine.md +1 -1
  9. package/aeg-root/templates/pr-report-template.md +2 -0
  10. package/aeg-root/tranche-model.md +1 -1
  11. package/dist/checks/bin/check-body-bare-digits.js +3545 -0
  12. package/dist/checks/bin/check-branch-topology.js +72 -6
  13. package/dist/checks/bin/check-brief-shape.js +72 -6
  14. package/dist/checks/bin/check-closes-n.js +72 -6
  15. package/dist/checks/bin/check-coherence.js +77 -7
  16. package/dist/checks/bin/check-dead-branch-push.js +72 -6
  17. package/dist/checks/bin/check-dispatch-readiness.js +77 -7
  18. package/dist/checks/bin/check-doc-coverage-push.js +77 -7
  19. package/dist/checks/bin/check-doc-coverage.js +80 -11
  20. package/dist/checks/bin/check-evidence-fresh.js +72 -6
  21. package/dist/checks/bin/check-first-push-dispatch.js +77 -7
  22. package/dist/checks/bin/check-issue-assignment.js +72 -6
  23. package/dist/checks/bin/check-no-disk-state.js +72 -6
  24. package/dist/checks/bin/check-reader-resolvable-prose.js +72 -6
  25. package/dist/checks/bin/check-registry-gates.js +72 -6
  26. package/dist/checks/bin/check-review-gate.js +77 -18
  27. package/dist/checks/bin/check-single-plan-pr.js +72 -6
  28. package/dist/checks/bin/check-test-plan.js +72 -6
  29. package/dist/index.js +591 -206
  30. package/package.json +1 -1
  31. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  32. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  33. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  34. package/studio-standalone/apps/vinaya-studio/web/.next/required-server-files.json +1 -1
  35. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  36. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  37. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  38. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  39. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  40. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  41. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  42. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  43. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  44. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  45. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  46. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  47. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js +1 -1
  48. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  49. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  50. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  51. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js +1 -1
  52. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  53. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  54. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  55. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  56. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  57. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
  58. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js +1 -1
  59. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  60. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  61. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  62. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js +1 -1
  63. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  64. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  65. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  66. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js +1 -1
  67. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  68. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  69. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  70. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  71. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  72. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/1q96_modules_@clerk_nextjs_dist_esm_app-router_client_keyless-creator-reader_0lom2js.js +1 -1
  73. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__029-1ch._.js +1 -1
  74. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0gw1_g2._.js +1 -1
  75. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0q56ohl._.js +1 -1
  76. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0rr_lq7._.js +1 -1
  77. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__19jyp3m._.js +1 -1
  78. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1_ojzp1._.js +1 -1
  79. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1qpl4m_._.js → [root-of-the-server]__1ccgndq._.js} +1 -1
  80. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1d_8nm4._.js +1 -1
  81. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1dfzjrd._.js +1 -1
  82. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1zkwtx8._.js +1 -1
  83. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__210ehg9._.js +1 -1
  84. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0-n77dx._.js +1 -1
  85. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_00yjcv1._.js +1 -1
  86. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_01605g7._.js +1 -1
  87. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0o54suy._.js +1 -1
  88. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0rix02i._.js +1 -1
  89. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_1u3abhy._.js → _0x999pb._.js} +2 -2
  90. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0ndy563._.js → _1-6rzip._.js} +2 -2
  91. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_18-d2be._.js +1 -1
  92. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_087xa25._.js → _1_talrs._.js} +2 -2
  93. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_11vnfnm._.js → _1ar5uqe._.js} +2 -2
  94. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_02drwa_._.js → _1c9b9j-._.js} +2 -2
  95. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1gw6vc9._.js +1 -1
  96. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_18kqbvs._.js +1 -1
  97. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_projects_[name]_tranches_[slug]_20yap_f._.js +1 -1
  98. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
  99. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_animate_components_index_ts_186fje1._.js +1 -1
  100. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_libraries_basic_components_index_ts_0xk1vda._.js +1 -1
  101. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  102. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  103. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  104. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
  105. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1mexqnauhtbtp.js → 0_jnwbarv-cqk.js} +1 -1
  106. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0ek6qlqhokys0.js → 0l_vubs1ephe5.js} +1 -1
  107. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0ojfbn3yvy-8_.js +1 -0
  108. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1jx5_q1g9l-cm.js → 0phqfqwbnt_ey.js} +1 -1
  109. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0qcu17x3h94a9.js → 17r0szvqeeyhx.js} +1 -1
  110. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0ve1-nz-mu_lr.js → 18x3rbqzeutpz.js} +1 -1
  111. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{22y4d5yrovcv-.js → 1bqpfvromtwn1.js} +1 -1
  112. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{39w6jbw3rleez.js → 24ojyzmt_fkg3.js} +1 -1
  113. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0tmcnl-z8yt2_.js → 30lyvn0yzwdiz.js} +1 -1
  114. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0fm4p9os2lsom.js → 3m0_gk59s-rbx.js} +1 -1
  115. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0ywkq74falx-x.js → 40x7f5hm7a5tk.js} +1 -1
  116. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0-08g_jjalnd9.js → 453zhecht_m1q.js} +1 -1
  117. package/studio-standalone/apps/vinaya-studio/web/server.js +1 -1
  118. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1s9ixp5nhnevp.js +0 -1
  119. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{R7xvB2iuNFp_jxENpL7xv → p5sWGp4ANwORiaX4Kk6U2}/_buildManifest.js +0 -0
  120. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{R7xvB2iuNFp_jxENpL7xv → p5sWGp4ANwORiaX4Kk6U2}/_clientMiddlewareManifest.js +0 -0
  121. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{R7xvB2iuNFp_jxENpL7xv → p5sWGp4ANwORiaX4Kk6U2}/_ssgManifest.js +0 -0
@@ -5,7 +5,27 @@ import { execFileSync as execFileSync2 } from "node:child_process";
5
5
  // ../../packages/aeg-forge-state/src/strip-code.ts
6
6
  function maskCode(body) {
7
7
  const fill = (line) => " ".repeat(line.length);
8
- return maskIndentedCode(maskFencedCode(body, fill), fill).replace(/(`+)[^\n]*?\1/g, (m) => " ".repeat(m.length));
8
+ const blocksMasked = maskIndentedCode(maskFencedCode(body, fill), fill);
9
+ return blocksMasked.split(`
10
+ `).map((line) => replaceInlineSpans(line, (span) => " ".repeat(span.length))).join(`
11
+ `);
12
+ }
13
+ var DETAILS_OPEN = /<details\b[^>]*>/gi;
14
+ var DETAILS_CLOSE = /<\/details\s*>/gi;
15
+ function maskDetailsBlocks(body) {
16
+ const fill = (line) => " ".repeat(line.length);
17
+ const lines = body.split(`
18
+ `);
19
+ let depth = 0;
20
+ const out = lines.map((line) => {
21
+ const opens = line.match(DETAILS_OPEN)?.length ?? 0;
22
+ const closes = line.match(DETAILS_CLOSE)?.length ?? 0;
23
+ const maskThisLine = depth > 0 || opens > 0;
24
+ depth = Math.max(0, depth + opens - closes);
25
+ return maskThisLine ? fill(line) : line;
26
+ });
27
+ return out.join(`
28
+ `);
9
29
  }
10
30
  function stripCode(body, options = {}) {
11
31
  const normalised = body.replace(/\r\n?/g, `
@@ -14,7 +34,50 @@ function stripCode(body, options = {}) {
14
34
  const blocksStripped = maskIndentedCode(maskFencedCode(normalised, blank), blank);
15
35
  if (options.inlineSpans === "keep")
16
36
  return blocksStripped;
17
- return blocksStripped.replace(/(`+)[^\n]*?\1/g, "");
37
+ return blocksStripped.split(`
38
+ `).map((line) => replaceInlineSpans(line, () => "")).join(`
39
+ `);
40
+ }
41
+ function replaceInlineSpans(line, replace) {
42
+ let result = "";
43
+ let i = 0;
44
+ const runLengthAt = (at) => {
45
+ let j = at;
46
+ while (j < line.length && line[j] === "`")
47
+ j++;
48
+ return j - at;
49
+ };
50
+ while (i < line.length) {
51
+ if (line[i] !== "`") {
52
+ result += line[i];
53
+ i++;
54
+ continue;
55
+ }
56
+ const openLen = runLengthAt(i);
57
+ const openEnd = i + openLen;
58
+ let j = openEnd;
59
+ let closeEnd = -1;
60
+ while (j < line.length) {
61
+ if (line[j] !== "`") {
62
+ j++;
63
+ continue;
64
+ }
65
+ const runLen = runLengthAt(j);
66
+ if (runLen === openLen) {
67
+ closeEnd = j + runLen;
68
+ break;
69
+ }
70
+ j += runLen;
71
+ }
72
+ if (closeEnd === -1) {
73
+ result += line.slice(i, openEnd);
74
+ i = openEnd;
75
+ } else {
76
+ result += replace(line.slice(i, closeEnd));
77
+ i = closeEnd;
78
+ }
79
+ }
80
+ return result;
18
81
  }
19
82
  var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})([^\r\n]*)\r?$/;
20
83
  var FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*\r?$/;
@@ -1753,9 +1816,10 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
1753
1816
  return out;
1754
1817
  }
1755
1818
  // ../../packages/aeg-core/src/pr-tier.ts
1819
+ var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
1756
1820
  function readTierFromPrBody(prBody) {
1757
1821
  const searchIn = anchoredRegion(prBody, "TIER") ?? prBody;
1758
- const m = searchIn.match(/(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i);
1822
+ const m = searchIn.match(TIER_FIELD);
1759
1823
  if (!m)
1760
1824
  return null;
1761
1825
  const t = Number(m[4]);
@@ -2397,9 +2461,6 @@ function extractSecurityReviewVerdict(comments) {
2397
2461
  return extractVerdict(comments, /^[ \t]*(?:\*{1,3}|_{1,3})?VERDICT:\s*(PASS|FAIL)(?![A-Za-z0-9])/im, "security-review");
2398
2462
  }
2399
2463
  // ../../packages/aeg-core/src/review-gate.ts
2400
- function isReviewGateExemptBranch(branch) {
2401
- return branch.startsWith("plan/");
2402
- }
2403
2464
  function isBoundToHead(extraction, headSha) {
2404
2465
  if (!extraction.headSha)
2405
2466
  return false;
@@ -2454,6 +2515,11 @@ function checkReviewGate(input) {
2454
2515
  waived: false
2455
2516
  };
2456
2517
  }
2518
+ var CHANGESET_RELEASE_BRANCH = "changeset-release/main";
2519
+ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
2520
+ function isChangesetsReleasePr(branch, author, expectedAuthor) {
2521
+ return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
2522
+ }
2457
2523
  // ../../packages/aeg-core/src/markdown-table.ts
2458
2524
  function splitRow(line) {
2459
2525
  const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
@@ -2,7 +2,27 @@
2
2
  // ../../packages/aeg-forge-state/src/strip-code.ts
3
3
  function maskCode(body) {
4
4
  const fill = (line) => " ".repeat(line.length);
5
- return maskIndentedCode(maskFencedCode(body, fill), fill).replace(/(`+)[^\n]*?\1/g, (m) => " ".repeat(m.length));
5
+ const blocksMasked = maskIndentedCode(maskFencedCode(body, fill), fill);
6
+ return blocksMasked.split(`
7
+ `).map((line) => replaceInlineSpans(line, (span) => " ".repeat(span.length))).join(`
8
+ `);
9
+ }
10
+ var DETAILS_OPEN = /<details\b[^>]*>/gi;
11
+ var DETAILS_CLOSE = /<\/details\s*>/gi;
12
+ function maskDetailsBlocks(body) {
13
+ const fill = (line) => " ".repeat(line.length);
14
+ const lines = body.split(`
15
+ `);
16
+ let depth = 0;
17
+ const out = lines.map((line) => {
18
+ const opens = line.match(DETAILS_OPEN)?.length ?? 0;
19
+ const closes = line.match(DETAILS_CLOSE)?.length ?? 0;
20
+ const maskThisLine = depth > 0 || opens > 0;
21
+ depth = Math.max(0, depth + opens - closes);
22
+ return maskThisLine ? fill(line) : line;
23
+ });
24
+ return out.join(`
25
+ `);
6
26
  }
7
27
  function stripCode(body, options = {}) {
8
28
  const normalised = body.replace(/\r\n?/g, `
@@ -11,7 +31,50 @@ function stripCode(body, options = {}) {
11
31
  const blocksStripped = maskIndentedCode(maskFencedCode(normalised, blank), blank);
12
32
  if (options.inlineSpans === "keep")
13
33
  return blocksStripped;
14
- return blocksStripped.replace(/(`+)[^\n]*?\1/g, "");
34
+ return blocksStripped.split(`
35
+ `).map((line) => replaceInlineSpans(line, () => "")).join(`
36
+ `);
37
+ }
38
+ function replaceInlineSpans(line, replace) {
39
+ let result = "";
40
+ let i = 0;
41
+ const runLengthAt = (at) => {
42
+ let j = at;
43
+ while (j < line.length && line[j] === "`")
44
+ j++;
45
+ return j - at;
46
+ };
47
+ while (i < line.length) {
48
+ if (line[i] !== "`") {
49
+ result += line[i];
50
+ i++;
51
+ continue;
52
+ }
53
+ const openLen = runLengthAt(i);
54
+ const openEnd = i + openLen;
55
+ let j = openEnd;
56
+ let closeEnd = -1;
57
+ while (j < line.length) {
58
+ if (line[j] !== "`") {
59
+ j++;
60
+ continue;
61
+ }
62
+ const runLen = runLengthAt(j);
63
+ if (runLen === openLen) {
64
+ closeEnd = j + runLen;
65
+ break;
66
+ }
67
+ j += runLen;
68
+ }
69
+ if (closeEnd === -1) {
70
+ result += line.slice(i, openEnd);
71
+ i = openEnd;
72
+ } else {
73
+ result += replace(line.slice(i, closeEnd));
74
+ i = closeEnd;
75
+ }
76
+ }
77
+ return result;
15
78
  }
16
79
  var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})([^\r\n]*)\r?$/;
17
80
  var FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*\r?$/;
@@ -1750,9 +1813,10 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
1750
1813
  return out;
1751
1814
  }
1752
1815
  // ../../packages/aeg-core/src/pr-tier.ts
1816
+ var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
1753
1817
  function readTierFromPrBody(prBody) {
1754
1818
  const searchIn = anchoredRegion(prBody, "TIER") ?? prBody;
1755
- const m = searchIn.match(/(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i);
1819
+ const m = searchIn.match(TIER_FIELD);
1756
1820
  if (!m)
1757
1821
  return null;
1758
1822
  const t = Number(m[4]);
@@ -2394,9 +2458,6 @@ function extractSecurityReviewVerdict(comments) {
2394
2458
  return extractVerdict(comments, /^[ \t]*(?:\*{1,3}|_{1,3})?VERDICT:\s*(PASS|FAIL)(?![A-Za-z0-9])/im, "security-review");
2395
2459
  }
2396
2460
  // ../../packages/aeg-core/src/review-gate.ts
2397
- function isReviewGateExemptBranch(branch) {
2398
- return branch.startsWith("plan/");
2399
- }
2400
2461
  function isBoundToHead(extraction, headSha) {
2401
2462
  if (!extraction.headSha)
2402
2463
  return false;
@@ -2451,6 +2512,11 @@ function checkReviewGate(input) {
2451
2512
  waived: false
2452
2513
  };
2453
2514
  }
2515
+ var CHANGESET_RELEASE_BRANCH = "changeset-release/main";
2516
+ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
2517
+ function isChangesetsReleasePr(branch, author, expectedAuthor) {
2518
+ return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
2519
+ }
2454
2520
  // ../../packages/aeg-core/src/markdown-table.ts
2455
2521
  function splitRow(line) {
2456
2522
  const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
@@ -5,7 +5,27 @@ import { execFileSync as execFileSync2 } from "node:child_process";
5
5
  // ../../packages/aeg-forge-state/src/strip-code.ts
6
6
  function maskCode(body) {
7
7
  const fill = (line) => " ".repeat(line.length);
8
- return maskIndentedCode(maskFencedCode(body, fill), fill).replace(/(`+)[^\n]*?\1/g, (m) => " ".repeat(m.length));
8
+ const blocksMasked = maskIndentedCode(maskFencedCode(body, fill), fill);
9
+ return blocksMasked.split(`
10
+ `).map((line) => replaceInlineSpans(line, (span) => " ".repeat(span.length))).join(`
11
+ `);
12
+ }
13
+ var DETAILS_OPEN = /<details\b[^>]*>/gi;
14
+ var DETAILS_CLOSE = /<\/details\s*>/gi;
15
+ function maskDetailsBlocks(body) {
16
+ const fill = (line) => " ".repeat(line.length);
17
+ const lines = body.split(`
18
+ `);
19
+ let depth = 0;
20
+ const out = lines.map((line) => {
21
+ const opens = line.match(DETAILS_OPEN)?.length ?? 0;
22
+ const closes = line.match(DETAILS_CLOSE)?.length ?? 0;
23
+ const maskThisLine = depth > 0 || opens > 0;
24
+ depth = Math.max(0, depth + opens - closes);
25
+ return maskThisLine ? fill(line) : line;
26
+ });
27
+ return out.join(`
28
+ `);
9
29
  }
10
30
  function stripCode(body, options = {}) {
11
31
  const normalised = body.replace(/\r\n?/g, `
@@ -14,7 +34,50 @@ function stripCode(body, options = {}) {
14
34
  const blocksStripped = maskIndentedCode(maskFencedCode(normalised, blank), blank);
15
35
  if (options.inlineSpans === "keep")
16
36
  return blocksStripped;
17
- return blocksStripped.replace(/(`+)[^\n]*?\1/g, "");
37
+ return blocksStripped.split(`
38
+ `).map((line) => replaceInlineSpans(line, () => "")).join(`
39
+ `);
40
+ }
41
+ function replaceInlineSpans(line, replace) {
42
+ let result = "";
43
+ let i = 0;
44
+ const runLengthAt = (at) => {
45
+ let j = at;
46
+ while (j < line.length && line[j] === "`")
47
+ j++;
48
+ return j - at;
49
+ };
50
+ while (i < line.length) {
51
+ if (line[i] !== "`") {
52
+ result += line[i];
53
+ i++;
54
+ continue;
55
+ }
56
+ const openLen = runLengthAt(i);
57
+ const openEnd = i + openLen;
58
+ let j = openEnd;
59
+ let closeEnd = -1;
60
+ while (j < line.length) {
61
+ if (line[j] !== "`") {
62
+ j++;
63
+ continue;
64
+ }
65
+ const runLen = runLengthAt(j);
66
+ if (runLen === openLen) {
67
+ closeEnd = j + runLen;
68
+ break;
69
+ }
70
+ j += runLen;
71
+ }
72
+ if (closeEnd === -1) {
73
+ result += line.slice(i, openEnd);
74
+ i = openEnd;
75
+ } else {
76
+ result += replace(line.slice(i, closeEnd));
77
+ i = closeEnd;
78
+ }
79
+ }
80
+ return result;
18
81
  }
19
82
  var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})([^\r\n]*)\r?$/;
20
83
  var FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*\r?$/;
@@ -1753,9 +1816,10 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
1753
1816
  return out;
1754
1817
  }
1755
1818
  // ../../packages/aeg-core/src/pr-tier.ts
1819
+ var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
1756
1820
  function readTierFromPrBody(prBody) {
1757
1821
  const searchIn = anchoredRegion(prBody, "TIER") ?? prBody;
1758
- const m = searchIn.match(/(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i);
1822
+ const m = searchIn.match(TIER_FIELD);
1759
1823
  if (!m)
1760
1824
  return null;
1761
1825
  const t = Number(m[4]);
@@ -2397,9 +2461,6 @@ function extractSecurityReviewVerdict(comments) {
2397
2461
  return extractVerdict(comments, /^[ \t]*(?:\*{1,3}|_{1,3})?VERDICT:\s*(PASS|FAIL)(?![A-Za-z0-9])/im, "security-review");
2398
2462
  }
2399
2463
  // ../../packages/aeg-core/src/review-gate.ts
2400
- function isReviewGateExemptBranch(branch) {
2401
- return branch.startsWith("plan/");
2402
- }
2403
2464
  function isBoundToHead(extraction, headSha) {
2404
2465
  if (!extraction.headSha)
2405
2466
  return false;
@@ -2454,6 +2515,11 @@ function checkReviewGate(input) {
2454
2515
  waived: false
2455
2516
  };
2456
2517
  }
2518
+ var CHANGESET_RELEASE_BRANCH = "changeset-release/main";
2519
+ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
2520
+ function isChangesetsReleasePr(branch, author, expectedAuthor) {
2521
+ return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
2522
+ }
2457
2523
  // ../../packages/aeg-core/src/markdown-table.ts
2458
2524
  function splitRow(line) {
2459
2525
  const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
@@ -8,7 +8,27 @@ import { promisify as promisify4 } from "node:util";
8
8
  // ../../packages/aeg-forge-state/src/strip-code.ts
9
9
  function maskCode(body) {
10
10
  const fill = (line) => " ".repeat(line.length);
11
- return maskIndentedCode(maskFencedCode(body, fill), fill).replace(/(`+)[^\n]*?\1/g, (m) => " ".repeat(m.length));
11
+ const blocksMasked = maskIndentedCode(maskFencedCode(body, fill), fill);
12
+ return blocksMasked.split(`
13
+ `).map((line) => replaceInlineSpans(line, (span) => " ".repeat(span.length))).join(`
14
+ `);
15
+ }
16
+ var DETAILS_OPEN = /<details\b[^>]*>/gi;
17
+ var DETAILS_CLOSE = /<\/details\s*>/gi;
18
+ function maskDetailsBlocks(body) {
19
+ const fill = (line) => " ".repeat(line.length);
20
+ const lines = body.split(`
21
+ `);
22
+ let depth = 0;
23
+ const out = lines.map((line) => {
24
+ const opens = line.match(DETAILS_OPEN)?.length ?? 0;
25
+ const closes = line.match(DETAILS_CLOSE)?.length ?? 0;
26
+ const maskThisLine = depth > 0 || opens > 0;
27
+ depth = Math.max(0, depth + opens - closes);
28
+ return maskThisLine ? fill(line) : line;
29
+ });
30
+ return out.join(`
31
+ `);
12
32
  }
13
33
  function stripCode(body, options = {}) {
14
34
  const normalised = body.replace(/\r\n?/g, `
@@ -17,7 +37,50 @@ function stripCode(body, options = {}) {
17
37
  const blocksStripped = maskIndentedCode(maskFencedCode(normalised, blank), blank);
18
38
  if (options.inlineSpans === "keep")
19
39
  return blocksStripped;
20
- return blocksStripped.replace(/(`+)[^\n]*?\1/g, "");
40
+ return blocksStripped.split(`
41
+ `).map((line) => replaceInlineSpans(line, () => "")).join(`
42
+ `);
43
+ }
44
+ function replaceInlineSpans(line, replace) {
45
+ let result = "";
46
+ let i = 0;
47
+ const runLengthAt = (at) => {
48
+ let j = at;
49
+ while (j < line.length && line[j] === "`")
50
+ j++;
51
+ return j - at;
52
+ };
53
+ while (i < line.length) {
54
+ if (line[i] !== "`") {
55
+ result += line[i];
56
+ i++;
57
+ continue;
58
+ }
59
+ const openLen = runLengthAt(i);
60
+ const openEnd = i + openLen;
61
+ let j = openEnd;
62
+ let closeEnd = -1;
63
+ while (j < line.length) {
64
+ if (line[j] !== "`") {
65
+ j++;
66
+ continue;
67
+ }
68
+ const runLen = runLengthAt(j);
69
+ if (runLen === openLen) {
70
+ closeEnd = j + runLen;
71
+ break;
72
+ }
73
+ j += runLen;
74
+ }
75
+ if (closeEnd === -1) {
76
+ result += line.slice(i, openEnd);
77
+ i = openEnd;
78
+ } else {
79
+ result += replace(line.slice(i, closeEnd));
80
+ i = closeEnd;
81
+ }
82
+ }
83
+ return result;
21
84
  }
22
85
  var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})([^\r\n]*)\r?$/;
23
86
  var FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*\r?$/;
@@ -1756,9 +1819,10 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
1756
1819
  return out;
1757
1820
  }
1758
1821
  // ../../packages/aeg-core/src/pr-tier.ts
1822
+ var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
1759
1823
  function readTierFromPrBody(prBody) {
1760
1824
  const searchIn = anchoredRegion(prBody, "TIER") ?? prBody;
1761
- const m = searchIn.match(/(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i);
1825
+ const m = searchIn.match(TIER_FIELD);
1762
1826
  if (!m)
1763
1827
  return null;
1764
1828
  const t = Number(m[4]);
@@ -2400,9 +2464,6 @@ function extractSecurityReviewVerdict(comments) {
2400
2464
  return extractVerdict(comments, /^[ \t]*(?:\*{1,3}|_{1,3})?VERDICT:\s*(PASS|FAIL)(?![A-Za-z0-9])/im, "security-review");
2401
2465
  }
2402
2466
  // ../../packages/aeg-core/src/review-gate.ts
2403
- function isReviewGateExemptBranch(branch) {
2404
- return branch.startsWith("plan/");
2405
- }
2406
2467
  function isBoundToHead(extraction, headSha) {
2407
2468
  if (!extraction.headSha)
2408
2469
  return false;
@@ -2457,6 +2518,11 @@ function checkReviewGate(input) {
2457
2518
  waived: false
2458
2519
  };
2459
2520
  }
2521
+ var CHANGESET_RELEASE_BRANCH = "changeset-release/main";
2522
+ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
2523
+ function isChangesetsReleasePr(branch, author, expectedAuthor) {
2524
+ return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
2525
+ }
2460
2526
  // ../../packages/aeg-core/src/markdown-table.ts
2461
2527
  function splitRow(line) {
2462
2528
  const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
@@ -3173,6 +3239,7 @@ var VinayaConfigSchema = z2.object({
3173
3239
  briefSchema: BriefSchemaSchema.optional(),
3174
3240
  managed: ManagedManifestSchema.optional(),
3175
3241
  principals: z2.array(z2.string()).min(1).optional(),
3242
+ releaseActor: z2.string().min(1).optional(),
3176
3243
  ci: z2.object({ setup: z2.string().min(1) }).optional(),
3177
3244
  blastRadius: z2.object({ extraDomains: z2.array(z2.string()).optional() }).optional()
3178
3245
  });
@@ -3182,6 +3249,9 @@ var LOCAL_CONFIG_FILENAME = "vinaya.config.json";
3182
3249
  function resolvePrincipalAllowlist(config) {
3183
3250
  return config?.principals ?? PRINCIPAL_ALLOWLIST;
3184
3251
  }
3252
+ function resolveReleaseActor(config) {
3253
+ return config?.releaseActor ?? DEFAULT_RELEASE_ACTOR;
3254
+ }
3185
3255
  function trustAnchorRepo() {
3186
3256
  const wellFormed = (slug) => /^[^/\s]+\/[^/\s]+$/.test(slug) ? slug : null;
3187
3257
  const fromRunner = process.env.GITHUB_REPOSITORY?.trim();
@@ -3224,7 +3294,7 @@ function isMissingFileError(err) {
3224
3294
  return /\b404\b|not found/i.test(haystack);
3225
3295
  }
3226
3296
  function loadTrustAnchorConfig(fetcher = ghFetchTrustAnchorConfig) {
3227
- const warn = (why) => process.stdout.write(`⚠ could not read \`principals\` from the default branch (${why}) — falling back to vinaya's built-in principal allowlist.
3297
+ const warn = (why) => process.stdout.write(`⚠ could not read the trust-anchor config (\`principals\`/\`releaseActor\`) from the default branch (${why}) — falling back to vinaya's built-in defaults.
3228
3298
  `);
3229
3299
  let base64;
3230
3300
  try {
@@ -5,7 +5,27 @@ import { execFileSync as execFileSync2 } from "node:child_process";
5
5
  // ../../packages/aeg-forge-state/src/strip-code.ts
6
6
  function maskCode(body) {
7
7
  const fill = (line) => " ".repeat(line.length);
8
- return maskIndentedCode(maskFencedCode(body, fill), fill).replace(/(`+)[^\n]*?\1/g, (m) => " ".repeat(m.length));
8
+ const blocksMasked = maskIndentedCode(maskFencedCode(body, fill), fill);
9
+ return blocksMasked.split(`
10
+ `).map((line) => replaceInlineSpans(line, (span) => " ".repeat(span.length))).join(`
11
+ `);
12
+ }
13
+ var DETAILS_OPEN = /<details\b[^>]*>/gi;
14
+ var DETAILS_CLOSE = /<\/details\s*>/gi;
15
+ function maskDetailsBlocks(body) {
16
+ const fill = (line) => " ".repeat(line.length);
17
+ const lines = body.split(`
18
+ `);
19
+ let depth = 0;
20
+ const out = lines.map((line) => {
21
+ const opens = line.match(DETAILS_OPEN)?.length ?? 0;
22
+ const closes = line.match(DETAILS_CLOSE)?.length ?? 0;
23
+ const maskThisLine = depth > 0 || opens > 0;
24
+ depth = Math.max(0, depth + opens - closes);
25
+ return maskThisLine ? fill(line) : line;
26
+ });
27
+ return out.join(`
28
+ `);
9
29
  }
10
30
  function stripCode(body, options = {}) {
11
31
  const normalised = body.replace(/\r\n?/g, `
@@ -14,7 +34,50 @@ function stripCode(body, options = {}) {
14
34
  const blocksStripped = maskIndentedCode(maskFencedCode(normalised, blank), blank);
15
35
  if (options.inlineSpans === "keep")
16
36
  return blocksStripped;
17
- return blocksStripped.replace(/(`+)[^\n]*?\1/g, "");
37
+ return blocksStripped.split(`
38
+ `).map((line) => replaceInlineSpans(line, () => "")).join(`
39
+ `);
40
+ }
41
+ function replaceInlineSpans(line, replace) {
42
+ let result = "";
43
+ let i = 0;
44
+ const runLengthAt = (at) => {
45
+ let j = at;
46
+ while (j < line.length && line[j] === "`")
47
+ j++;
48
+ return j - at;
49
+ };
50
+ while (i < line.length) {
51
+ if (line[i] !== "`") {
52
+ result += line[i];
53
+ i++;
54
+ continue;
55
+ }
56
+ const openLen = runLengthAt(i);
57
+ const openEnd = i + openLen;
58
+ let j = openEnd;
59
+ let closeEnd = -1;
60
+ while (j < line.length) {
61
+ if (line[j] !== "`") {
62
+ j++;
63
+ continue;
64
+ }
65
+ const runLen = runLengthAt(j);
66
+ if (runLen === openLen) {
67
+ closeEnd = j + runLen;
68
+ break;
69
+ }
70
+ j += runLen;
71
+ }
72
+ if (closeEnd === -1) {
73
+ result += line.slice(i, openEnd);
74
+ i = openEnd;
75
+ } else {
76
+ result += replace(line.slice(i, closeEnd));
77
+ i = closeEnd;
78
+ }
79
+ }
80
+ return result;
18
81
  }
19
82
  var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})([^\r\n]*)\r?$/;
20
83
  var FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*\r?$/;
@@ -1753,9 +1816,10 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
1753
1816
  return out;
1754
1817
  }
1755
1818
  // ../../packages/aeg-core/src/pr-tier.ts
1819
+ var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
1756
1820
  function readTierFromPrBody(prBody) {
1757
1821
  const searchIn = anchoredRegion(prBody, "TIER") ?? prBody;
1758
- const m = searchIn.match(/(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i);
1822
+ const m = searchIn.match(TIER_FIELD);
1759
1823
  if (!m)
1760
1824
  return null;
1761
1825
  const t = Number(m[4]);
@@ -2397,9 +2461,6 @@ function extractSecurityReviewVerdict(comments) {
2397
2461
  return extractVerdict(comments, /^[ \t]*(?:\*{1,3}|_{1,3})?VERDICT:\s*(PASS|FAIL)(?![A-Za-z0-9])/im, "security-review");
2398
2462
  }
2399
2463
  // ../../packages/aeg-core/src/review-gate.ts
2400
- function isReviewGateExemptBranch(branch) {
2401
- return branch.startsWith("plan/");
2402
- }
2403
2464
  function isBoundToHead(extraction, headSha) {
2404
2465
  if (!extraction.headSha)
2405
2466
  return false;
@@ -2454,6 +2515,11 @@ function checkReviewGate(input) {
2454
2515
  waived: false
2455
2516
  };
2456
2517
  }
2518
+ var CHANGESET_RELEASE_BRANCH = "changeset-release/main";
2519
+ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
2520
+ function isChangesetsReleasePr(branch, author, expectedAuthor) {
2521
+ return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
2522
+ }
2457
2523
  // ../../packages/aeg-core/src/markdown-table.ts
2458
2524
  function splitRow(line) {
2459
2525
  const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");