@attalabs/vinaya 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/aeg-root/contracts/planner-developer.md +4 -1
- package/aeg-root/contracts/planner-operator.md +86 -0
- package/aeg-root/contracts/principal-operator.md +88 -0
- package/aeg-root/enforcement.md +4 -4
- package/aeg-root/roles/developer.md +25 -18
- package/aeg-root/roles/operator.md +133 -0
- package/aeg-root/roles/planner.md +6 -0
- package/aeg-root/roles/principal.md +4 -0
- package/aeg-root/roles/reviewer.md +3 -3
- package/aeg-root/roles/security.md +3 -3
- package/aeg-root/skills/aeg-context-packets/SKILL.md +123 -0
- package/aeg-root/skills/aeg-context-packets/examples/operator-start.md +30 -0
- package/aeg-root/templates/brief-template.md +6 -2
- package/dist/checks/bin/check-body-bare-digits.js +1275 -240
- package/dist/checks/bin/check-branch-topology.js +1207 -180
- package/dist/checks/bin/check-brief-shape.js +1279 -243
- package/dist/checks/bin/check-changeset-coverage.js +2176 -264
- package/dist/checks/bin/check-closes-n.js +1211 -184
- package/dist/checks/bin/check-coherence.js +1378 -265
- package/dist/checks/bin/check-dead-branch-push.js +1158 -176
- package/dist/checks/bin/check-dispatch-readiness.js +1440 -276
- package/dist/checks/bin/check-doc-coverage-push.js +2171 -259
- package/dist/checks/bin/check-doc-coverage.js +2173 -261
- package/dist/checks/bin/check-doctrine-no-procedures.js +1275 -240
- package/dist/checks/bin/check-doctrine-portability.js +2171 -259
- package/dist/checks/bin/check-evidence-fresh.js +2613 -347
- package/dist/checks/bin/check-exec-bits.js +2169 -257
- package/dist/checks/bin/check-first-push-dispatch.js +1326 -246
- package/dist/checks/bin/check-issue-assignment.js +1209 -182
- package/dist/checks/bin/check-issue-milestone-attach.js +6087 -0
- package/dist/checks/bin/check-issue-objectives-numbering.js +6089 -0
- package/dist/checks/bin/check-issue-parts-coverage.js +6089 -0
- package/dist/checks/bin/check-issue-surface-globs.js +7304 -0
- package/dist/checks/bin/check-issue-title-grammar.js +6089 -0
- package/dist/checks/bin/check-issue-tranche-label.js +6089 -0
- package/dist/checks/bin/check-main-branch-refusal.js +1158 -176
- package/dist/checks/bin/check-no-disk-state.js +1158 -176
- package/dist/checks/bin/check-pr-premise-reassert.js +1275 -240
- package/dist/checks/bin/check-pr-report-density.js +1158 -176
- package/dist/checks/bin/check-quoted-command.js +2150 -257
- package/dist/checks/bin/check-reader-resolvable-prose.js +2153 -260
- package/dist/checks/bin/check-registry-gates.js +1245 -176
- package/dist/checks/bin/check-retired-vocabulary.js +2148 -255
- package/dist/checks/bin/check-review-gate.js +1375 -245
- package/dist/checks/bin/check-single-plan-pr.js +1158 -176
- package/dist/checks/bin/check-surface-scope.js +1217 -182
- package/dist/checks/bin/check-test-plan.js +1187 -189
- package/dist/checks/bin/check-token-collection-wired.js +1158 -176
- package/dist/checks/bin/check-token-report.js +1171 -179
- package/dist/checks/bin/check-workspace-escape.js +2167 -255
- package/dist/index.js +17322 -8709
- package/dist/lib/pre-push-changed-files.js +57 -0
- package/dist/lib/pre-push-select-tests.js +1616 -0
- package/package.json +4 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error/page.js +2 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js +8 -7
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js +8 -7
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js +9 -8
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js +9 -8
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js +8 -7
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +16 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js +10 -8
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js +8 -7
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js +8 -7
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js +9 -8
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
- 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
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__08f5pba._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1o_0tjy._.js → [root-of-the-server]__0h9yhwx._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0053k9k._.js → [root-of-the-server]__0ls23oh._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0puovz5._.js → [root-of-the-server]__0nye8tb._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__18kqy4q._.js → [root-of-the-server]__0tfykr-._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0o771t1._.js → [root-of-the-server]__0th3gyp._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1-zcufa._.js +51 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0p8q38b._.js → [root-of-the-server]__11svemm._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__02c71kv._.js → [root-of-the-server]__140m1i_._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1bh2awk._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0112h-k._.js → [root-of-the-server]__1gjqmhq._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1qmxez3._.js +4 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1r47dr7._.js +28 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_01fv4fj._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0gvm3og._.js → _096f46i._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0lwxg63._.js → _0af2one._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_1n0cnq-._.js → _0zf4d27._.js} +45 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_03x_w6q._.js → _1-wo68i._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_projects_[name]_tranches_[slug]_05ufo8i._.js +1 -12
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1wdusod._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{node_modules_1vo08dj._.js → node_modules_@clerk_nextjs_dist_esm_app-router_server-actions_1x7vfhn.js} +3 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_1khj-jh._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +17 -5
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3_9xytdmiv1xi.js → 25f3-jtiv8p5n.js} +4 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0bn8c8v5q429o.js → 27-6ym7lp2v8o.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3-6a3tinbdb-7.js → 3daxns3o--9me.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/tsconfig.json +12 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0z6dav-._.js +0 -51
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__13rrmhr._.js +0 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__17h4sy8._.js +0 -45
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +0 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_17sz44y._.js +0 -3
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_ssgManifest.js +0 -0
|
@@ -1645,6 +1645,52 @@ var systemEnv3 = {
|
|
|
1645
1645
|
...process.env,
|
|
1646
1646
|
PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
|
|
1647
1647
|
};
|
|
1648
|
+
var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
|
|
1649
|
+
var cached;
|
|
1650
|
+
var inflight;
|
|
1651
|
+
async function resolveRepo(exec = defaultExec) {
|
|
1652
|
+
if (cached !== undefined)
|
|
1653
|
+
return cached;
|
|
1654
|
+
const fromEnv = process.env.AEG_REPO;
|
|
1655
|
+
if (fromEnv) {
|
|
1656
|
+
const parsed = parseOwnerRepo(fromEnv);
|
|
1657
|
+
if (parsed) {
|
|
1658
|
+
cached = parsed;
|
|
1659
|
+
return cached;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
if (inflight)
|
|
1663
|
+
return inflight;
|
|
1664
|
+
inflight = (async () => {
|
|
1665
|
+
try {
|
|
1666
|
+
const { stdout } = await exec();
|
|
1667
|
+
cached = parseGitRemoteUrl(stdout.trim());
|
|
1668
|
+
return cached;
|
|
1669
|
+
} catch (err) {
|
|
1670
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1671
|
+
console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
|
|
1672
|
+
return null;
|
|
1673
|
+
} finally {
|
|
1674
|
+
inflight = undefined;
|
|
1675
|
+
}
|
|
1676
|
+
})();
|
|
1677
|
+
return inflight;
|
|
1678
|
+
}
|
|
1679
|
+
function parseGitRemoteUrl(url) {
|
|
1680
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1681
|
+
if (ssh?.[1] && ssh[2])
|
|
1682
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
1683
|
+
const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
1684
|
+
if (https?.[1] && https[2])
|
|
1685
|
+
return { owner: https[1], repo: https[2] };
|
|
1686
|
+
return null;
|
|
1687
|
+
}
|
|
1688
|
+
function parseOwnerRepo(value) {
|
|
1689
|
+
const match = value.match(/^([^/]+)\/(.+)$/);
|
|
1690
|
+
if (!match?.[1] || !match[2])
|
|
1691
|
+
return null;
|
|
1692
|
+
return { owner: match[1], repo: match[2] };
|
|
1693
|
+
}
|
|
1648
1694
|
// ../../packages/aeg-core/src/anchored-region.ts
|
|
1649
1695
|
function anchoredRegionBounds(body, field) {
|
|
1650
1696
|
const masked = maskCode(body);
|
|
@@ -1955,6 +2001,9 @@ function parseInlineFieldList(section) {
|
|
|
1955
2001
|
var HEAD_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged head:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1956
2002
|
var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1957
2003
|
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
2004
|
+
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2005
|
+
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2006
|
+
var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1958
2007
|
function firstFiveLines(comment) {
|
|
1959
2008
|
return comment.split(`
|
|
1960
2009
|
`).slice(0, 5).join(`
|
|
@@ -1977,6 +2026,35 @@ function extractRulingOrdinal(comment) {
|
|
|
1977
2026
|
const m = firstSevenLines(comment).match(RULING_ORDINAL_PATTERN);
|
|
1978
2027
|
return m ? Number.parseInt(m[1], 10) : null;
|
|
1979
2028
|
}
|
|
2029
|
+
function firstElevenLines(comment) {
|
|
2030
|
+
return comment.split(`
|
|
2031
|
+
`).slice(0, 11).join(`
|
|
2032
|
+
`);
|
|
2033
|
+
}
|
|
2034
|
+
function extractBriefHash(comment) {
|
|
2035
|
+
const m = firstElevenLines(comment).match(BRIEF_HASH_PATTERN);
|
|
2036
|
+
return m ? m[1].toLowerCase() : null;
|
|
2037
|
+
}
|
|
2038
|
+
function extractPolicyDigest(comment) {
|
|
2039
|
+
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
2040
|
+
return m ? m[1].toLowerCase() : null;
|
|
2041
|
+
}
|
|
2042
|
+
function firstThirteenLines(comment) {
|
|
2043
|
+
return comment.split(`
|
|
2044
|
+
`).slice(0, 13).join(`
|
|
2045
|
+
`);
|
|
2046
|
+
}
|
|
2047
|
+
function extractBaseSha(comment) {
|
|
2048
|
+
const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
|
|
2049
|
+
return m ? m[1].toLowerCase() : null;
|
|
2050
|
+
}
|
|
2051
|
+
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
2052
|
+
function extractFindingSeverities(comment) {
|
|
2053
|
+
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
2054
|
+
severity: m[1],
|
|
2055
|
+
location: m[2]
|
|
2056
|
+
}));
|
|
2057
|
+
}
|
|
1980
2058
|
function extractVerdict(comments, valuePattern, missingLabel) {
|
|
1981
2059
|
const candidates = comments.filter((c) => valuePattern.test(c));
|
|
1982
2060
|
if (candidates.length === 0) {
|
|
@@ -1985,6 +2063,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1985
2063
|
headSha: null,
|
|
1986
2064
|
objectivesVersion: null,
|
|
1987
2065
|
rulingOrdinal: null,
|
|
2066
|
+
briefHash: null,
|
|
2067
|
+
policyDigest: null,
|
|
2068
|
+
baseSha: null,
|
|
2069
|
+
findingSeverities: [],
|
|
1988
2070
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
1989
2071
|
};
|
|
1990
2072
|
}
|
|
@@ -1996,6 +2078,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1996
2078
|
headSha: null,
|
|
1997
2079
|
objectivesVersion: null,
|
|
1998
2080
|
rulingOrdinal: null,
|
|
2081
|
+
briefHash: null,
|
|
2082
|
+
policyDigest: null,
|
|
2083
|
+
baseSha: null,
|
|
2084
|
+
findingSeverities: [],
|
|
1999
2085
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
2000
2086
|
};
|
|
2001
2087
|
}
|
|
@@ -2004,6 +2090,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2004
2090
|
headSha: extractHeadSha(latest),
|
|
2005
2091
|
objectivesVersion: extractObjectivesVersion(latest),
|
|
2006
2092
|
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2093
|
+
briefHash: extractBriefHash(latest),
|
|
2094
|
+
policyDigest: extractPolicyDigest(latest),
|
|
2095
|
+
baseSha: extractBaseSha(latest),
|
|
2096
|
+
findingSeverities: extractFindingSeverities(latest),
|
|
2007
2097
|
danglingNote: null
|
|
2008
2098
|
};
|
|
2009
2099
|
}
|
|
@@ -2339,6 +2429,53 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
|
|
|
2339
2429
|
}
|
|
2340
2430
|
return out;
|
|
2341
2431
|
}
|
|
2432
|
+
// ../../packages/aeg-core/src/review-policy.ts
|
|
2433
|
+
var CODE_REVIEW_SEVERITY_ORDER = ["BLOCKER", "MAJOR", "MINOR"];
|
|
2434
|
+
var SECURITY_SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW"];
|
|
2435
|
+
var DEFAULT_MAX_ROUNDS = 3;
|
|
2436
|
+
var DEFAULT_REVIEW_POLICY = {
|
|
2437
|
+
codeReviewThreshold: "BLOCKER",
|
|
2438
|
+
securityThreshold: "HIGH",
|
|
2439
|
+
maxRounds: DEFAULT_MAX_ROUNDS
|
|
2440
|
+
};
|
|
2441
|
+
var FILE_SHAPED_LOCATION = /\.[a-zA-Z0-9]{1,10}(:\d+)?\s*$/;
|
|
2442
|
+
var PROSE_LOCATION_PATTERNS = [/\bpr\s*body\b/i, /\bcomment\b/i];
|
|
2443
|
+
var ROLE_FILE_LOCATION = /(^|\/)aeg-root\/roles\//i;
|
|
2444
|
+
function isProseLocation(location) {
|
|
2445
|
+
if (ROLE_FILE_LOCATION.test(location))
|
|
2446
|
+
return true;
|
|
2447
|
+
if (FILE_SHAPED_LOCATION.test(location))
|
|
2448
|
+
return false;
|
|
2449
|
+
return PROSE_LOCATION_PATTERNS.some((pattern) => pattern.test(location));
|
|
2450
|
+
}
|
|
2451
|
+
var PROSE_CAP_SEVERITY = "MINOR";
|
|
2452
|
+
function blockingSeverities(scale, threshold) {
|
|
2453
|
+
const idx = scale.indexOf(threshold);
|
|
2454
|
+
if (idx === -1) {
|
|
2455
|
+
throw new Error(`blockingSeverities: threshold "${threshold}" is not one of ${scale.join(" > ")}`);
|
|
2456
|
+
}
|
|
2457
|
+
return scale.slice(0, idx + 1);
|
|
2458
|
+
}
|
|
2459
|
+
function evaluateReviewFindings(findings, scale, threshold) {
|
|
2460
|
+
const blocking = new Set(blockingSeverities(scale, threshold));
|
|
2461
|
+
const blockingFindings = findings.filter((f) => {
|
|
2462
|
+
if (!scale.includes(f.severity)) {
|
|
2463
|
+
throw new Error(`evaluateReviewFindings: severity "${f.severity}" is not one of ${scale.join(" > ")}`);
|
|
2464
|
+
}
|
|
2465
|
+
const effectiveSeverity = f.location !== undefined && isProseLocation(f.location) ? PROSE_CAP_SEVERITY : f.severity;
|
|
2466
|
+
return blocking.has(effectiveSeverity);
|
|
2467
|
+
});
|
|
2468
|
+
return { outcome: blockingFindings.length > 0 ? "blocked" : "clean", blockingFindings };
|
|
2469
|
+
}
|
|
2470
|
+
function evaluateCodeReview(findings, policy) {
|
|
2471
|
+
return evaluateReviewFindings(findings, CODE_REVIEW_SEVERITY_ORDER, policy.codeReviewThreshold);
|
|
2472
|
+
}
|
|
2473
|
+
function evaluateSecurityReview(findings, policy) {
|
|
2474
|
+
return evaluateReviewFindings(findings, SECURITY_SEVERITY_ORDER, policy.securityThreshold);
|
|
2475
|
+
}
|
|
2476
|
+
function isKnownSeverity(scale, value) {
|
|
2477
|
+
return scale.includes(value);
|
|
2478
|
+
}
|
|
2342
2479
|
// ../../packages/aeg-core/src/pr-tier.ts
|
|
2343
2480
|
var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
|
|
2344
2481
|
function readTierFromPrBody(prBody) {
|
|
@@ -2709,7 +2846,7 @@ function checkForField(prBody) {
|
|
|
2709
2846
|
]
|
|
2710
2847
|
};
|
|
2711
2848
|
}
|
|
2712
|
-
function
|
|
2849
|
+
function checkClosesNPresence(prBody) {
|
|
2713
2850
|
const closesPattern = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s{0,8}:?\s{0,8}#\d+/i;
|
|
2714
2851
|
if (closesPattern.test(stripCode(prBody))) {
|
|
2715
2852
|
return { status: "pass", errors: [] };
|
|
@@ -2741,10 +2878,22 @@ var COMMIT_TYPES = [
|
|
|
2741
2878
|
"Test"
|
|
2742
2879
|
];
|
|
2743
2880
|
var COMMIT_TYPE_STYLE = new RegExp(`^(${COMMIT_TYPES.join("|")})(\\([a-z0-9-]+\\))?: \\S`);
|
|
2881
|
+
function checkForgeTitle(title) {
|
|
2882
|
+
const taskStyle = /^\[[a-z0-9._-]+\] \S+ — \S/;
|
|
2883
|
+
if (COMMIT_TYPE_STYLE.test(title) || taskStyle.test(title))
|
|
2884
|
+
return { status: "pass", errors: [] };
|
|
2885
|
+
return {
|
|
2886
|
+
status: "fail",
|
|
2887
|
+
errors: [
|
|
2888
|
+
`brief-validation title: "${title}" matches neither title grammar — expected \`Type: description\` / \`Type(scope): description\` (commitlint types + Plan) or \`[tranche] id — description\` (task form).`
|
|
2889
|
+
]
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2744
2892
|
var BRIEF_SHAPE_MARKERS = [checkSurfaceMap, checkDocUpdateList, checkStopConditions, checkAutonomyClause];
|
|
2745
2893
|
var TASK_BRANCH_PATTERN = /^task\/[^/]+\/[^/]+$/;
|
|
2894
|
+
var TASK_ISSUE_BRANCH_PATTERN = /^task\/issue-\d+$/;
|
|
2746
2895
|
function isTaskBranch(branch) {
|
|
2747
|
-
return TASK_BRANCH_PATTERN.test(branch);
|
|
2896
|
+
return TASK_BRANCH_PATTERN.test(branch) || TASK_ISSUE_BRANCH_PATTERN.test(branch);
|
|
2748
2897
|
}
|
|
2749
2898
|
function isBriefShaped(prBody) {
|
|
2750
2899
|
const stripped = stripCode(prBody);
|
|
@@ -2866,8 +3015,9 @@ function packagesNamedIn(text) {
|
|
|
2866
3015
|
}
|
|
2867
3016
|
function hasTestPathForConsumer(text, consumerDir) {
|
|
2868
3017
|
const escaped = consumerDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2869
|
-
const
|
|
2870
|
-
|
|
3018
|
+
const filePathRe = new RegExp(`${escaped}\\/[\\w./-]*\\.test\\.[A-Za-z0-9]+`);
|
|
3019
|
+
const testDirRe = new RegExp(`${escaped}\\/(?:[\\w-]+\\/)*(?:tests|specs)(?:\\/|\\b)`);
|
|
3020
|
+
return filePathRe.test(text) || testDirRe.test(text);
|
|
2871
3021
|
}
|
|
2872
3022
|
function checkConsumerTests(prBody, consumersOf) {
|
|
2873
3023
|
const section4 = extractNumberedSection(prBody, 4);
|
|
@@ -2971,7 +3121,7 @@ function checkBriefSections(prBody, readTier, options = {}) {
|
|
|
2971
3121
|
checkConsumerTests(prBody, consumersOf),
|
|
2972
3122
|
checkDefeatCases(prBody),
|
|
2973
3123
|
...issueObjectives !== undefined ? [checkObjectivesCopy(prBody, issueObjectives), checkObjectivesCoverage(prBody)] : [],
|
|
2974
|
-
...requireClosesN ? [
|
|
3124
|
+
...requireClosesN ? [checkClosesNPresence(prBody)] : []
|
|
2975
3125
|
];
|
|
2976
3126
|
return { errors: results.flatMap((r) => r.errors) };
|
|
2977
3127
|
}
|
|
@@ -3261,6 +3411,28 @@ function topLevelSectionText(body, headingName) {
|
|
|
3261
3411
|
const next = /^##[ \t]/m.exec(afterHeading);
|
|
3262
3412
|
return next ? afterHeading.slice(0, next.index) : afterHeading;
|
|
3263
3413
|
}
|
|
3414
|
+
function partHasBacktickedPath(text) {
|
|
3415
|
+
let i = 0;
|
|
3416
|
+
while (i < text.length) {
|
|
3417
|
+
const start = text.indexOf("`", i);
|
|
3418
|
+
if (start === -1)
|
|
3419
|
+
return false;
|
|
3420
|
+
const end = text.indexOf("`", start + 1);
|
|
3421
|
+
if (end === -1)
|
|
3422
|
+
return false;
|
|
3423
|
+
if (text.slice(start + 1, end).includes("/"))
|
|
3424
|
+
return true;
|
|
3425
|
+
i = end + 1;
|
|
3426
|
+
}
|
|
3427
|
+
return false;
|
|
3428
|
+
}
|
|
3429
|
+
var PART_MIN_WORDS_OUTSIDE_BACKTICKS = 3;
|
|
3430
|
+
function stripPartBackticks(text) {
|
|
3431
|
+
return text.replace(/`[^`\n]*`/g, " ");
|
|
3432
|
+
}
|
|
3433
|
+
function partWordCount(text) {
|
|
3434
|
+
return text.split(/\s+/).filter((w) => /[a-z]/i.test(w)).length;
|
|
3435
|
+
}
|
|
3264
3436
|
function looksLikeFilePath(entry2) {
|
|
3265
3437
|
const stripped = entry2.replace(/\/\*\*?$/, "");
|
|
3266
3438
|
const lastSegment = stripped.split("/").pop() ?? stripped;
|
|
@@ -3301,6 +3473,18 @@ function globCoversPath(glob, path) {
|
|
|
3301
3473
|
const p = path.replace(/\/+$/, "");
|
|
3302
3474
|
return g === p || g.startsWith(`${p}/`) || p.startsWith(`${g}/`);
|
|
3303
3475
|
}
|
|
3476
|
+
function checkSurfaceGlobsResolve(body, resolvesToFile) {
|
|
3477
|
+
const surface = parseIssueSurface(body);
|
|
3478
|
+
if (!surface.ok)
|
|
3479
|
+
return { status: "pass", errors: [] };
|
|
3480
|
+
const errors = [];
|
|
3481
|
+
for (const glob of surface.value.in) {
|
|
3482
|
+
if (!resolvesToFile(glob)) {
|
|
3483
|
+
errors.push(`issue-validation Surface: \`${glob}\` in \`## Surface\`'s \`in:\` list matches no tracked file — a Surface that cannot resolve cannot render a brief's file list.`);
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3487
|
+
}
|
|
3304
3488
|
function checkSurfaceScope(changedFiles, outGlobs) {
|
|
3305
3489
|
if (outGlobs.length === 0)
|
|
3306
3490
|
return { ok: true };
|
|
@@ -3312,9 +3496,77 @@ function checkSurfaceScope(changedFiles, outGlobs) {
|
|
|
3312
3496
|
}
|
|
3313
3497
|
return violations.length > 0 ? { ok: false, violations } : { ok: true };
|
|
3314
3498
|
}
|
|
3499
|
+
var ISSUE_PART_LINE_RE = /^Part\s+(\d+)\s*\(([^)]*)\)\s*[-—–]\s*(.*)$/i;
|
|
3500
|
+
function parseIssueParts(body) {
|
|
3501
|
+
const section = topLevelSectionText(body, "Parts");
|
|
3502
|
+
if (section === null)
|
|
3503
|
+
return { ok: false, errors: ["no `## Parts` heading found in the body."] };
|
|
3504
|
+
const lines = section.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
|
|
3505
|
+
const parts = [];
|
|
3506
|
+
const errors = [];
|
|
3507
|
+
for (const line of lines) {
|
|
3508
|
+
const m = ISSUE_PART_LINE_RE.exec(line);
|
|
3509
|
+
if (!m) {
|
|
3510
|
+
errors.push(`"${line}" is not a well-formed Parts line — expected \`Part <n> (<refs>) — <outcome>\`.`);
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
const n = Number.parseInt(m[1], 10);
|
|
3514
|
+
const refs = m[2];
|
|
3515
|
+
const text = m[3].trim();
|
|
3516
|
+
if (text.length === 0) {
|
|
3517
|
+
errors.push(`Part ${n} has no outcome text after the dash — every Part states one observable outcome.`);
|
|
3518
|
+
continue;
|
|
3519
|
+
}
|
|
3520
|
+
if (partHasBacktickedPath(text) && partWordCount(stripPartBackticks(text)) < PART_MIN_WORDS_OUTSIDE_BACKTICKS) {
|
|
3521
|
+
errors.push(`Part ${n} is little more than a file path — a Part names an outcome and symbols, never a bare path.`);
|
|
3522
|
+
continue;
|
|
3523
|
+
}
|
|
3524
|
+
const objectiveIds = [...refs.matchAll(/O(\d+)/g)].map((r) => Number.parseInt(r[1], 10));
|
|
3525
|
+
parts.push({ n, objectiveIds, text });
|
|
3526
|
+
}
|
|
3527
|
+
if (parts.length === 0) {
|
|
3528
|
+
errors.push("the `## Parts` section has no well-formed `Part <n> (<refs>) — <outcome>` lines.");
|
|
3529
|
+
}
|
|
3530
|
+
if (errors.length > 0)
|
|
3531
|
+
return { ok: false, errors };
|
|
3532
|
+
return { ok: true, value: parts };
|
|
3533
|
+
}
|
|
3534
|
+
function checkPartsCiteDefinedObjectives(body) {
|
|
3535
|
+
const parts = parseIssueParts(body);
|
|
3536
|
+
const objectives = objectivesOf(body);
|
|
3537
|
+
if (!parts.ok || !objectives.ok)
|
|
3538
|
+
return { status: "pass", errors: [] };
|
|
3539
|
+
const definedIds = new Set(objectives.objectives.map((o) => Number.parseInt(o.id.slice(1), 10)));
|
|
3540
|
+
const errors = [];
|
|
3541
|
+
for (const part of parts.value) {
|
|
3542
|
+
for (const objectiveId of part.objectiveIds) {
|
|
3543
|
+
if (!definedIds.has(objectiveId)) {
|
|
3544
|
+
errors.push(`issue-validation Parts: Part ${part.n} cites O${objectiveId}, which the Issue's own \`## Objectives\` section does not define.`);
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3549
|
+
}
|
|
3315
3550
|
function isTaskIssueLabelSet(labels) {
|
|
3316
3551
|
return hasLabel("tranche", labels);
|
|
3317
3552
|
}
|
|
3553
|
+
function checkTrancheLabelPresence(_body, _labels) {
|
|
3554
|
+
return { status: "pass", errors: [] };
|
|
3555
|
+
}
|
|
3556
|
+
function checkMilestoneAttach(labels, currentMilestoneTitle, resolvedMilestoneTitle) {
|
|
3557
|
+
if (!isTaskIssueLabelSet(labels))
|
|
3558
|
+
return { status: "pass", errors: [] };
|
|
3559
|
+
if (resolvedMilestoneTitle === null)
|
|
3560
|
+
return { status: "pass", errors: [] };
|
|
3561
|
+
if (currentMilestoneTitle === resolvedMilestoneTitle)
|
|
3562
|
+
return { status: "pass", errors: [] };
|
|
3563
|
+
return {
|
|
3564
|
+
status: "fail",
|
|
3565
|
+
errors: [
|
|
3566
|
+
`issue-validation milestone attach: this task Issue's tranche label resolves to Milestone "${resolvedMilestoneTitle}", but its live Milestone is ${currentMilestoneTitle === null ? "unset" : `"${currentMilestoneTitle}"`} — attach it to "${resolvedMilestoneTitle}".`
|
|
3567
|
+
]
|
|
3568
|
+
};
|
|
3569
|
+
}
|
|
3318
3570
|
var TYPE_LABEL_IDS = LABELS.filter((l) => l.category === "type").map((l) => l.id);
|
|
3319
3571
|
function isControlCodePoint(codePoint) {
|
|
3320
3572
|
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
@@ -3379,6 +3631,19 @@ function checkProjectsRegistered(body, _labels, registeredNames) {
|
|
|
3379
3631
|
var DOC_PATH_RE = /(?:(?:aeg-root|apps|packages|specs|docs|tools|\.claude|\.github)\/[\w./@-]*\.(?:md|mdx)|\.claude\/(?:skills|rules)\/[\w./-]+|\b(?:docs-index|decisions|projects|state-machine|enforcement|process|README|CLAUDE)\.md\b|\b[\w-]+-(?:spec|decisions|backlog)\.md\b)/i;
|
|
3380
3632
|
var DOC_PATH_RE_GLOBAL = new RegExp(DOC_PATH_RE.source, "gi");
|
|
3381
3633
|
|
|
3634
|
+
// ../../packages/aeg-core/src/task-branch-identity.ts
|
|
3635
|
+
var ISSUE_BRANCH_PATTERN = /^task\/issue-(\d+)$/;
|
|
3636
|
+
var TRANCHE_BRANCH_PATTERN = /^task\/([^/]+)\/([^/]+)$/;
|
|
3637
|
+
function parseTaskBranchIdentity(branch) {
|
|
3638
|
+
const issueMatch = ISSUE_BRANCH_PATTERN.exec(branch);
|
|
3639
|
+
if (issueMatch)
|
|
3640
|
+
return { kind: "issue", issueNumber: Number(issueMatch[1]) };
|
|
3641
|
+
const trancheMatch = TRANCHE_BRANCH_PATTERN.exec(branch);
|
|
3642
|
+
if (trancheMatch)
|
|
3643
|
+
return { kind: "tranche", tranche: trancheMatch[1], taskId: trancheMatch[2] };
|
|
3644
|
+
return null;
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3382
3647
|
// ../../packages/aeg-core/src/coherence-checks.ts
|
|
3383
3648
|
var COHERENCE_ENFORCED_FROM = "2026-07-01";
|
|
3384
3649
|
function isGrandfathered(isoDate) {
|
|
@@ -3399,6 +3664,7 @@ function checkA1(entries, principalAllowlist = PRINCIPAL_ALLOWLIST) {
|
|
|
3399
3664
|
if (handClosed)
|
|
3400
3665
|
continue;
|
|
3401
3666
|
failures.push({
|
|
3667
|
+
code: "closed-without-merge",
|
|
3402
3668
|
issue: e.task.issue,
|
|
3403
3669
|
tranche: e.trancheSlug,
|
|
3404
3670
|
task: e.task.id,
|
|
@@ -3423,6 +3689,7 @@ function checkA3(entries) {
|
|
|
3423
3689
|
continue;
|
|
3424
3690
|
if (e.facts.prState === "merged" && e.facts.issueState !== "closed") {
|
|
3425
3691
|
failures.push({
|
|
3692
|
+
code: "auto-close-misfire",
|
|
3426
3693
|
issue: e.task.issue,
|
|
3427
3694
|
tranche: e.trancheSlug,
|
|
3428
3695
|
task: e.task.id,
|
|
@@ -3447,6 +3714,7 @@ function checkT1(entries) {
|
|
|
3447
3714
|
continue;
|
|
3448
3715
|
if (e.facts === undefined) {
|
|
3449
3716
|
failures.push({
|
|
3717
|
+
code: "phantom-issue-ref",
|
|
3450
3718
|
issue: e.task.issue,
|
|
3451
3719
|
tranche: e.trancheSlug,
|
|
3452
3720
|
task: e.task.id,
|
|
@@ -3465,6 +3733,7 @@ function checkT2(openIssuesBySlug, topologyIssuesBySlug, ciTrancheSlug) {
|
|
|
3465
3733
|
for (const num of openNums) {
|
|
3466
3734
|
if (!topologySet.has(num)) {
|
|
3467
3735
|
failures.push({
|
|
3736
|
+
code: "orphan-task",
|
|
3468
3737
|
issue: num,
|
|
3469
3738
|
tranche: slug,
|
|
3470
3739
|
reason: `Issue #${num} is open and labeled ${trancheLabel(slug)} but does not appear in the topology file`
|
|
@@ -3499,6 +3768,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3499
3768
|
continue;
|
|
3500
3769
|
if (forgeUnavailableSlugs?.has(e.trancheSlug)) {
|
|
3501
3770
|
failures.push({
|
|
3771
|
+
code: "tbd-in-active-tranche",
|
|
3502
3772
|
issue: null,
|
|
3503
3773
|
tranche: e.trancheSlug,
|
|
3504
3774
|
task: e.task.id,
|
|
@@ -3508,6 +3778,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3508
3778
|
continue;
|
|
3509
3779
|
}
|
|
3510
3780
|
failures.push({
|
|
3781
|
+
code: "tbd-in-active-tranche",
|
|
3511
3782
|
issue: null,
|
|
3512
3783
|
tranche: e.trancheSlug,
|
|
3513
3784
|
task: e.task.id,
|
|
@@ -3540,6 +3811,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3540
3811
|
const sameIssue = depEntry.task.issue !== null && e.task.issue !== null && depEntry.task.issue === e.task.issue;
|
|
3541
3812
|
if (sameTask || sameIssue) {
|
|
3542
3813
|
failures.push({
|
|
3814
|
+
code: "d1-self-dependency",
|
|
3543
3815
|
issue: e.task.issue,
|
|
3544
3816
|
tranche: e.trancheSlug,
|
|
3545
3817
|
task: e.task.id,
|
|
@@ -3551,6 +3823,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3551
3823
|
const depClosed = depFacts?.issueState === "closed";
|
|
3552
3824
|
if (!depClosed) {
|
|
3553
3825
|
failures.push({
|
|
3826
|
+
code: "dispatched-on-unmet-deps",
|
|
3554
3827
|
issue: e.task.issue,
|
|
3555
3828
|
tranche: e.trancheSlug,
|
|
3556
3829
|
task: e.task.id,
|
|
@@ -3576,11 +3849,13 @@ function checkR1(issuesBySlug, grandfatheredIssues, registeredNames = []) {
|
|
|
3576
3849
|
const errors = [
|
|
3577
3850
|
...checkIssueRationale(issue.body).errors,
|
|
3578
3851
|
...checkProjectsRegistered(issue.body, issue.labels, registeredNames).errors,
|
|
3579
|
-
...checkIssueObjectives(issue.body, issue.number).errors
|
|
3852
|
+
...checkIssueObjectives(issue.body, issue.number).errors,
|
|
3853
|
+
...checkPartsCiteDefinedObjectives(issue.body).errors
|
|
3580
3854
|
];
|
|
3581
3855
|
if (errors.length === 0)
|
|
3582
3856
|
continue;
|
|
3583
3857
|
failures.push({
|
|
3858
|
+
code: "missing-rationale-field",
|
|
3584
3859
|
issue: issue.number,
|
|
3585
3860
|
tranche: slug,
|
|
3586
3861
|
reason: `Issue #${issue.number} fails the rationale gate: ${errors.join(" | ")}`,
|
|
@@ -3609,6 +3884,7 @@ function checkL1(files, entriesBySlug) {
|
|
|
3609
3884
|
const allClosed = withFacts.every((e) => e.facts?.issueState === "closed");
|
|
3610
3885
|
if (allClosed) {
|
|
3611
3886
|
failures.push({
|
|
3887
|
+
code: "archive-recommended",
|
|
3612
3888
|
tranche: f.slug,
|
|
3613
3889
|
reason: "Active tranche has no open task-Issues — consider archiving to completed/"
|
|
3614
3890
|
});
|
|
@@ -3640,27 +3916,38 @@ function extractClosesReferences(prBody) {
|
|
|
3640
3916
|
}
|
|
3641
3917
|
return referenced;
|
|
3642
3918
|
}
|
|
3643
|
-
function
|
|
3919
|
+
function checkClosesNTopology(branch, prBody, trancheFiles, taskIssueRefs) {
|
|
3644
3920
|
const referenced = extractClosesReferences(prBody);
|
|
3645
3921
|
if (taskIssueRefs) {
|
|
3646
3922
|
for (const n of referenced) {
|
|
3647
|
-
const
|
|
3648
|
-
if (!
|
|
3923
|
+
const ref2 = taskIssueRefs.get(n);
|
|
3924
|
+
if (!ref2)
|
|
3649
3925
|
continue;
|
|
3650
|
-
const expectedBranch = `task/${
|
|
3926
|
+
const expectedBranch = `task/${ref2.trancheSlug}/${ref2.taskId}`;
|
|
3651
3927
|
if (branch !== expectedBranch) {
|
|
3652
3928
|
return {
|
|
3653
3929
|
ok: false,
|
|
3654
|
-
message: `closes-n-reverse: branch "${branch}" closes #${n} (task ${
|
|
3930
|
+
message: `closes-n-reverse: branch "${branch}" closes #${n} (task ${ref2.taskId} of tranche "${ref2.trancheSlug}") but is not named "${expectedBranch}" — rename the branch and re-push, or if this work is intentionally outside AEG's dispatch flow, remove the Closes reference.`
|
|
3655
3931
|
};
|
|
3656
3932
|
}
|
|
3657
3933
|
}
|
|
3658
3934
|
}
|
|
3659
|
-
const
|
|
3660
|
-
if (!
|
|
3935
|
+
const ref = parseTaskBranchIdentity(branch);
|
|
3936
|
+
if (!ref)
|
|
3661
3937
|
return { ok: true };
|
|
3662
|
-
|
|
3663
|
-
|
|
3938
|
+
if (ref.kind === "issue") {
|
|
3939
|
+
const expectedIssue2 = ref.issueNumber;
|
|
3940
|
+
if (!referenced.has(expectedIssue2)) {
|
|
3941
|
+
return {
|
|
3942
|
+
ok: false,
|
|
3943
|
+
expectedIssue: expectedIssue2,
|
|
3944
|
+
message: `closes-n: PR body does not contain \`Closes #${expectedIssue2}\` (required for branch "${branch}"). Add it to the PR body Summary section.`
|
|
3945
|
+
};
|
|
3946
|
+
}
|
|
3947
|
+
return { ok: true, expectedIssue: expectedIssue2 };
|
|
3948
|
+
}
|
|
3949
|
+
const trancheSlug = ref.tranche;
|
|
3950
|
+
const taskId = ref.taskId;
|
|
3664
3951
|
const trancheFile = trancheFiles.find((f) => f.slug === trancheSlug);
|
|
3665
3952
|
if (!trancheFile) {
|
|
3666
3953
|
return {
|
|
@@ -3712,34 +3999,79 @@ function extractIssue(body) {
|
|
|
3712
3999
|
const issue = headerNums.length > 0 ? headerNums[0] : bodyNums[0];
|
|
3713
4000
|
return { issue, extraIssues: bodyNums.filter((n) => n !== issue), outsideHeader: headerNums.length === 0 };
|
|
3714
4001
|
}
|
|
3715
|
-
// ../../packages/aeg-core/src/review-
|
|
3716
|
-
|
|
3717
|
-
|
|
4002
|
+
// ../../packages/aeg-core/src/review-input-manifest.ts
|
|
4003
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
4004
|
+
function briefHash(brief) {
|
|
4005
|
+
return createHash4("sha256").update(`${brief}
|
|
4006
|
+
`).digest("hex");
|
|
4007
|
+
}
|
|
4008
|
+
function policyDigest(policy) {
|
|
4009
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
4010
|
+
codeReviewThreshold: policy.codeReviewThreshold,
|
|
4011
|
+
securityThreshold: policy.securityThreshold,
|
|
4012
|
+
maxRounds: policy.maxRounds
|
|
4013
|
+
})).digest("hex");
|
|
4014
|
+
}
|
|
4015
|
+
function isBoundToHead(echoed, headSha) {
|
|
4016
|
+
if (!echoed.headSha)
|
|
3718
4017
|
return false;
|
|
3719
|
-
return headSha.toLowerCase().startsWith(
|
|
4018
|
+
return headSha.toLowerCase().startsWith(echoed.headSha.toLowerCase());
|
|
3720
4019
|
}
|
|
3721
|
-
function isBoundByPatchIdentity(
|
|
3722
|
-
if (patchIdOf === undefined || !
|
|
4020
|
+
function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
4021
|
+
if (patchIdOf === undefined || !echoed.headSha)
|
|
3723
4022
|
return false;
|
|
3724
|
-
const judged = patchIdOf(
|
|
4023
|
+
const judged = patchIdOf(echoed.headSha);
|
|
3725
4024
|
const current = patchIdOf(headSha);
|
|
3726
4025
|
if (judged === null || current === null)
|
|
3727
4026
|
return false;
|
|
3728
4027
|
return judged === current;
|
|
3729
4028
|
}
|
|
3730
|
-
function
|
|
3731
|
-
|
|
4029
|
+
function isBoundToBase(echoed, currentBase) {
|
|
4030
|
+
if (currentBase === null)
|
|
4031
|
+
return true;
|
|
4032
|
+
if (!echoed.baseSha)
|
|
4033
|
+
return false;
|
|
4034
|
+
return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
|
|
3732
4035
|
}
|
|
3733
|
-
function isBoundToObjectives(
|
|
4036
|
+
function isBoundToObjectives(echoed, currentVersion) {
|
|
3734
4037
|
if (currentVersion === null)
|
|
3735
4038
|
return true;
|
|
3736
|
-
return
|
|
4039
|
+
return echoed.objectivesVersion === currentVersion;
|
|
3737
4040
|
}
|
|
3738
|
-
function isBoundToRulings(
|
|
3739
|
-
if (
|
|
4041
|
+
function isBoundToRulings(echoed, currentOrdinal) {
|
|
4042
|
+
if (echoed.rulingOrdinal === null)
|
|
3740
4043
|
return currentOrdinal === 0;
|
|
3741
|
-
return
|
|
4044
|
+
return echoed.rulingOrdinal === currentOrdinal;
|
|
4045
|
+
}
|
|
4046
|
+
function isBoundToBriefHash(echoed, currentHash) {
|
|
4047
|
+
if (currentHash === null)
|
|
4048
|
+
return true;
|
|
4049
|
+
return echoed.briefHash === currentHash;
|
|
4050
|
+
}
|
|
4051
|
+
function isBoundToPolicy(echoed, currentDigest) {
|
|
4052
|
+
return echoed.policyDigest === currentDigest;
|
|
4053
|
+
}
|
|
4054
|
+
function compareManifest(echoed, current, patchIdOf) {
|
|
4055
|
+
const exactHead = isBoundToHead(echoed, current.headSha);
|
|
4056
|
+
const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
|
|
4057
|
+
const head = exactHead || patchHead;
|
|
4058
|
+
const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
|
|
4059
|
+
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
4060
|
+
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
4061
|
+
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
4062
|
+
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
4063
|
+
return {
|
|
4064
|
+
bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4065
|
+
head,
|
|
4066
|
+
base,
|
|
4067
|
+
briefHash: briefHashBound,
|
|
4068
|
+
objectivesVersion: objectivesVersion2,
|
|
4069
|
+
rulingOrdinal,
|
|
4070
|
+
policyDigest: policyDigestBound
|
|
4071
|
+
};
|
|
3742
4072
|
}
|
|
4073
|
+
|
|
4074
|
+
// ../../packages/aeg-core/src/review-gate.ts
|
|
3743
4075
|
function checkReviewGate(input) {
|
|
3744
4076
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
3745
4077
|
const waived = isWaiverLabelActorVerified({
|
|
@@ -3762,15 +4094,58 @@ function checkReviewGate(input) {
|
|
|
3762
4094
|
const verifiedBodies = verified.map((c) => c.body);
|
|
3763
4095
|
const codeReview = extractCodeReviewVerdict(verifiedBodies);
|
|
3764
4096
|
const security = extractSecurityReviewVerdict(verifiedBodies);
|
|
3765
|
-
const
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
4097
|
+
const policy = input.policy ?? DEFAULT_REVIEW_POLICY;
|
|
4098
|
+
let codeReviewPolicyEvaluation;
|
|
4099
|
+
let securityPolicyEvaluation;
|
|
4100
|
+
try {
|
|
4101
|
+
codeReviewPolicyEvaluation = evaluateCodeReview(codeReview.findingSeverities, policy);
|
|
4102
|
+
securityPolicyEvaluation = evaluateSecurityReview(security.findingSeverities, policy);
|
|
4103
|
+
} catch (err) {
|
|
4104
|
+
return {
|
|
4105
|
+
verdict: "fail",
|
|
4106
|
+
reason: `a verdict comment carries a finding severity this repository's policy does not recognize: ${err instanceof Error ? err.message : String(err)}`,
|
|
4107
|
+
waived: false
|
|
4108
|
+
};
|
|
4109
|
+
}
|
|
4110
|
+
const codeReviewTextClean = codeReview.value === "APPROVE";
|
|
4111
|
+
const securityTextClean = security.value === "PASS";
|
|
4112
|
+
const codeReviewPolicyClean = codeReviewPolicyEvaluation.outcome === "clean";
|
|
4113
|
+
const securityPolicyClean = securityPolicyEvaluation.outcome === "clean";
|
|
4114
|
+
const codeReviewClean = codeReviewTextClean && codeReviewPolicyClean;
|
|
4115
|
+
const securityClean = securityTextClean && securityPolicyClean;
|
|
4116
|
+
const currentManifest = {
|
|
4117
|
+
headSha: input.headSha,
|
|
4118
|
+
baseSha: input.baseSha ?? null,
|
|
4119
|
+
briefHash: input.briefHash ?? null,
|
|
4120
|
+
objectivesVersion: input.objectivesVersion,
|
|
4121
|
+
rulingOrdinal: input.rulingOrdinal,
|
|
4122
|
+
policyDigest: policyDigest(policy)
|
|
4123
|
+
};
|
|
4124
|
+
const codeReviewEchoed = {
|
|
4125
|
+
headSha: codeReview.headSha,
|
|
4126
|
+
baseSha: codeReview.baseSha,
|
|
4127
|
+
briefHash: codeReview.briefHash,
|
|
4128
|
+
objectivesVersion: codeReview.objectivesVersion,
|
|
4129
|
+
rulingOrdinal: codeReview.rulingOrdinal,
|
|
4130
|
+
policyDigest: codeReview.policyDigest
|
|
4131
|
+
};
|
|
4132
|
+
const securityEchoed = {
|
|
4133
|
+
headSha: security.headSha,
|
|
4134
|
+
baseSha: security.baseSha,
|
|
4135
|
+
briefHash: security.briefHash,
|
|
4136
|
+
objectivesVersion: security.objectivesVersion,
|
|
4137
|
+
rulingOrdinal: security.rulingOrdinal,
|
|
4138
|
+
policyDigest: security.policyDigest
|
|
4139
|
+
};
|
|
4140
|
+
const codeReviewBinding = compareManifest(codeReviewEchoed, currentManifest, input.patchIdOf);
|
|
4141
|
+
const securityBinding = compareManifest(securityEchoed, currentManifest, input.patchIdOf);
|
|
4142
|
+
const codeReviewBound = codeReviewBinding.head;
|
|
4143
|
+
const securityBound = securityBinding.head;
|
|
4144
|
+
const codeReviewObjectivesBound = codeReviewBinding.objectivesVersion;
|
|
4145
|
+
const securityObjectivesBound = securityBinding.objectivesVersion;
|
|
4146
|
+
const codeReviewRulingsBound = codeReviewBinding.rulingOrdinal;
|
|
4147
|
+
const securityRulingsBound = securityBinding.rulingOrdinal;
|
|
4148
|
+
if (codeReviewClean && codeReviewBinding.bound && securityClean && securityBinding.bound && mechanicalChecksClean) {
|
|
3774
4149
|
return {
|
|
3775
4150
|
verdict: "pass",
|
|
3776
4151
|
reason: `code-reviewer verdict is a clean APPROVE and security-review verdict is a clean PASS, both covering head ${input.headSha}, and every reported mechanical check is green.`,
|
|
@@ -3778,23 +4153,39 @@ function checkReviewGate(input) {
|
|
|
3778
4153
|
};
|
|
3779
4154
|
}
|
|
3780
4155
|
const problems = [];
|
|
3781
|
-
if (!
|
|
4156
|
+
if (!codeReviewTextClean) {
|
|
3782
4157
|
problems.push(`code-reviewer verdict is not a clean APPROVE (found: ${codeReview.value})`);
|
|
4158
|
+
} else if (!codeReviewPolicyClean) {
|
|
4159
|
+
problems.push(`code-reviewer verdict says APPROVE but carries a finding (${codeReviewPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's code-review policy threshold (${policy.codeReviewThreshold}) — a reviewer's own APPROVE never overrides policy`);
|
|
3783
4160
|
} else if (!codeReviewBound) {
|
|
3784
4161
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4162
|
+
} else if (!codeReviewBinding.base) {
|
|
4163
|
+
problems.push(`the newest code-review verdict was cast against base ${codeReview.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
|
|
3785
4164
|
} else if (!codeReviewObjectivesBound) {
|
|
3786
4165
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
3787
4166
|
} else if (!codeReviewRulingsBound) {
|
|
3788
4167
|
problems.push(`the newest code-review verdict was cast against ruling ordinal ${codeReview.rulingOrdinal ?? "none"}, a newer ruling (ruling ${input.rulingOrdinal}) is now posted on this PR`);
|
|
4168
|
+
} else if (!codeReviewBinding.briefHash) {
|
|
4169
|
+
problems.push(`the newest code-review verdict was cast against brief hash ${codeReview.briefHash ?? "none"}, the frozen brief's current hash is ${currentManifest.briefHash ?? "none"}`);
|
|
4170
|
+
} else if (!codeReviewBinding.policyDigest) {
|
|
4171
|
+
problems.push(`the newest code-review verdict was cast against review policy digest ${codeReview.policyDigest ?? "none"}, this repository's current policy digest is ${currentManifest.policyDigest}`);
|
|
3789
4172
|
}
|
|
3790
|
-
if (!
|
|
4173
|
+
if (!securityTextClean) {
|
|
3791
4174
|
problems.push(`security-review verdict is not a clean PASS (found: ${security.value})`);
|
|
4175
|
+
} else if (!securityPolicyClean) {
|
|
4176
|
+
problems.push(`security-review verdict says PASS but carries a finding (${securityPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's security policy threshold (${policy.securityThreshold}) — a reviewer's own PASS never overrides policy`);
|
|
3792
4177
|
} else if (!securityBound) {
|
|
3793
4178
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4179
|
+
} else if (!securityBinding.base) {
|
|
4180
|
+
problems.push(`the newest security-review verdict was cast against base ${security.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
|
|
3794
4181
|
} else if (!securityObjectivesBound) {
|
|
3795
4182
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
3796
4183
|
} else if (!securityRulingsBound) {
|
|
3797
4184
|
problems.push(`the newest security-review verdict was cast against ruling ordinal ${security.rulingOrdinal ?? "none"}, a newer ruling (ruling ${input.rulingOrdinal}) is now posted on this PR`);
|
|
4185
|
+
} else if (!securityBinding.briefHash) {
|
|
4186
|
+
problems.push(`the newest security-review verdict was cast against brief hash ${security.briefHash ?? "none"}, the frozen brief's current hash is ${currentManifest.briefHash ?? "none"}`);
|
|
4187
|
+
} else if (!securityBinding.policyDigest) {
|
|
4188
|
+
problems.push(`the newest security-review verdict was cast against review policy digest ${security.policyDigest ?? "none"}, this repository's current policy digest is ${currentManifest.policyDigest}`);
|
|
3798
4189
|
}
|
|
3799
4190
|
if (!mechanicalChecksClean) {
|
|
3800
4191
|
problems.push(reportedMechanicalChecks.length === 0 ? "no mechanical checks have reported for this head yet" : `mechanical check(s) not green: ${reportedMechanicalChecks.filter((c) => c.bucket !== "pass").map((c) => `${c.name} (${c.bucket})`).join(", ")}`);
|
|
@@ -4486,42 +4877,45 @@ function checkDispatchReadiness(input) {
|
|
|
4486
4877
|
const { trancheSlug, task } = input;
|
|
4487
4878
|
const taskLabel = `task ${task.id} (tranche ${trancheSlug})`;
|
|
4488
4879
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
4489
|
-
const
|
|
4880
|
+
const blockerDetails = [];
|
|
4881
|
+
const push = (blockerClass, message) => {
|
|
4882
|
+
blockerDetails.push({ class: blockerClass, message });
|
|
4883
|
+
};
|
|
4490
4884
|
if (task.issue === null) {
|
|
4491
|
-
|
|
4885
|
+
push("issue-existence", `dispatch-gate issue-existence: ${taskLabel} has no Issue (#TBD or blank) in the topology — not dispatchable until the Planner cuts the Issue.`);
|
|
4492
4886
|
} else if (input.issue === null) {
|
|
4493
|
-
|
|
4887
|
+
push("issue-existence", `dispatch-gate issue-existence: ${taskLabel} names Issue #${task.issue}, but it does not resolve to a real GitHub Issue (phantom reference).`);
|
|
4494
4888
|
}
|
|
4495
4889
|
if (input.issue !== null && !input.issueRationalePass) {
|
|
4496
|
-
|
|
4890
|
+
push("rationale", `dispatch-gate rationale: Issue #${input.issue.number} for ${taskLabel} fails the rationale gate (checkIssueRationale) — the Planner must complete the eight-field rationale before this task is dispatchable.`);
|
|
4497
4891
|
}
|
|
4498
4892
|
for (const dep of input.dependsOn) {
|
|
4499
4893
|
if (isSelfDependency(dep, task, input.issue)) {
|
|
4500
4894
|
const issueStr = input.issue !== null ? `#${input.issue.number}` : "?";
|
|
4501
|
-
|
|
4895
|
+
push("internal-self-dependency", `dispatch-gate INTERNAL: parsed a self-dependency for task ${task.id} (${issueStr}) — this is a parser bug in parseRationaleDeps, not a real dependency. Please report it upstream. Re-run once the rationale is corrected or the fix ships.`);
|
|
4502
4896
|
continue;
|
|
4503
4897
|
}
|
|
4504
4898
|
if (dep.resolved === false) {
|
|
4505
|
-
|
|
4899
|
+
push("depends-on-unresolvable", `dispatch-gate depends-on: ${taskLabel} depends on "${dep.id}", which is UNRESOLVABLE — the resolver could not find a matching tranche/task/Issue for this edge (not a claim about merge status). Not dispatchable until the edge is corrected.`);
|
|
4506
4900
|
continue;
|
|
4507
4901
|
}
|
|
4508
4902
|
if (!dep.merged && !isHandClosedByRecognizedPrincipal(dep, principalAllowlist)) {
|
|
4509
4903
|
const issueStr = dep.issue !== null ? ` (#${dep.issue})` : "";
|
|
4510
|
-
|
|
4904
|
+
push("depends-on-not-merged", `dispatch-gate depends-on: ${taskLabel} depends on ${dep.id}${issueStr}, whose PR is not merged yet — not dispatchable, it serializes behind it.`);
|
|
4511
4905
|
}
|
|
4512
4906
|
}
|
|
4513
4907
|
for (const c of input.conflictsWith) {
|
|
4514
4908
|
if (c.openOrInFlight) {
|
|
4515
4909
|
const issueStr = c.issue !== null ? ` (#${c.issue})` : "";
|
|
4516
|
-
|
|
4910
|
+
push("conflicts-with", `dispatch-gate conflicts-with: ${taskLabel} conflicts with ${c.id}${issueStr}, whose PR is open or in-flight — not dispatchable until it merges.`);
|
|
4517
4911
|
}
|
|
4518
4912
|
}
|
|
4519
4913
|
for (const proj of input.priorTrancheArchival) {
|
|
4520
4914
|
if (proj.priorTrancheSlug !== null && !proj.archived) {
|
|
4521
|
-
|
|
4915
|
+
push("prior-tranche-archival", `dispatch-gate prior-tranche-archival: project \`${proj.project}\`'s previous tranche \`${proj.priorTrancheSlug}\` is not archived — the Tranche Archivist must run before new work on this product.`);
|
|
4522
4916
|
}
|
|
4523
4917
|
}
|
|
4524
|
-
return { ready:
|
|
4918
|
+
return { ready: blockerDetails.length === 0, blockers: blockerDetails.map((b) => b.message), blockerDetails };
|
|
4525
4919
|
}
|
|
4526
4920
|
// ../../packages/aeg-core/src/single-plan-pr.ts
|
|
4527
4921
|
function trancheSlugFromTopologyPath(path) {
|
|
@@ -4623,6 +5017,137 @@ function checkBranchTopology(input) {
|
|
|
4623
5017
|
reason: `Branch \`${branch}\` matches topology row \`${taskId}\` in ${topoPath}.`
|
|
4624
5018
|
};
|
|
4625
5019
|
}
|
|
5020
|
+
// ../../packages/aeg-core/src/task-tools.ts
|
|
5021
|
+
import { z } from "zod";
|
|
5022
|
+
var TASK_TOOL_ERROR_KINDS = [
|
|
5023
|
+
"validation",
|
|
5024
|
+
"authority",
|
|
5025
|
+
"precondition",
|
|
5026
|
+
"capability",
|
|
5027
|
+
"infrastructure",
|
|
5028
|
+
"cancellation",
|
|
5029
|
+
"timeout",
|
|
5030
|
+
"uncertain_effect"
|
|
5031
|
+
];
|
|
5032
|
+
var TaskToolErrorSchema = z.object({
|
|
5033
|
+
kind: z.enum(TASK_TOOL_ERROR_KINDS),
|
|
5034
|
+
message: z.string().min(1),
|
|
5035
|
+
detail: z.string().optional()
|
|
5036
|
+
});
|
|
5037
|
+
var TaskToolRefSchema = z.union([
|
|
5038
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
|
|
5039
|
+
z.object({ issue: z.number().int().positive() }).strict()
|
|
5040
|
+
]);
|
|
5041
|
+
var MAX_PAGE_LIMIT = 100;
|
|
5042
|
+
var PageRequestSchema = z.object({
|
|
5043
|
+
cursor: z.string().optional(),
|
|
5044
|
+
limit: z.number().int().positive().max(MAX_PAGE_LIMIT).optional()
|
|
5045
|
+
});
|
|
5046
|
+
var FreshnessSchema = z.enum(["fresh", "stale", "unknown"]);
|
|
5047
|
+
var ObservedSchema = z.object({
|
|
5048
|
+
observedAt: z.string(),
|
|
5049
|
+
freshness: FreshnessSchema
|
|
5050
|
+
});
|
|
5051
|
+
var TaskStatusInputSchema = z.object({
|
|
5052
|
+
task: TaskToolRefSchema.optional()
|
|
5053
|
+
}).merge(PageRequestSchema).strict();
|
|
5054
|
+
var TaskStatusItemSchema = z.object({
|
|
5055
|
+
task: TaskToolRefSchema,
|
|
5056
|
+
issue: z.number().int().positive(),
|
|
5057
|
+
pr: z.number().int().positive().nullable(),
|
|
5058
|
+
state: z.string()
|
|
5059
|
+
}).merge(ObservedSchema);
|
|
5060
|
+
var TaskStatusResultSchema = z.object({
|
|
5061
|
+
items: z.array(TaskStatusItemSchema),
|
|
5062
|
+
nextCursor: z.string().nullable()
|
|
5063
|
+
});
|
|
5064
|
+
var RequestedAuthoritySchema = z.enum(["planner", "principal", "operator", "self"]);
|
|
5065
|
+
var EscalationInputsSchema = z.object({
|
|
5066
|
+
task: z.number().int().positive(),
|
|
5067
|
+
round: z.number().int().nonnegative(),
|
|
5068
|
+
head: z.string(),
|
|
5069
|
+
branch: z.string(),
|
|
5070
|
+
prNumber: z.number().int().positive()
|
|
5071
|
+
});
|
|
5072
|
+
var EscalationEvidenceSchema = z.object({
|
|
5073
|
+
round: z.number().int().nonnegative(),
|
|
5074
|
+
reviewer: z.string().nullable(),
|
|
5075
|
+
security: z.string().nullable()
|
|
5076
|
+
});
|
|
5077
|
+
var EscalationRunIdentitySchema = z.object({
|
|
5078
|
+
runId: z.string(),
|
|
5079
|
+
pid: z.number().int().positive(),
|
|
5080
|
+
host: z.string()
|
|
5081
|
+
});
|
|
5082
|
+
var EscalationInputVersionsSchema = z.object({
|
|
5083
|
+
briefHash: z.string().nullable(),
|
|
5084
|
+
objectivesVersion: z.string().nullable(),
|
|
5085
|
+
rulingOrdinal: z.number().int().nonnegative(),
|
|
5086
|
+
policyDigest: z.string()
|
|
5087
|
+
});
|
|
5088
|
+
var TaskEscalationReadInputSchema = z.object({
|
|
5089
|
+
task: TaskToolRefSchema
|
|
5090
|
+
}).merge(PageRequestSchema).strict();
|
|
5091
|
+
var TaskEscalationPacketSchema = z.object({
|
|
5092
|
+
reason: z.string(),
|
|
5093
|
+
detail: z.string().nullable(),
|
|
5094
|
+
inputs: EscalationInputsSchema.nullable(),
|
|
5095
|
+
evidence: EscalationEvidenceSchema.nullable(),
|
|
5096
|
+
attemptedRecovery: z.string(),
|
|
5097
|
+
requestedAuthority: RequestedAuthoritySchema,
|
|
5098
|
+
permittedNextActions: z.array(z.string()),
|
|
5099
|
+
runIdentity: EscalationRunIdentitySchema.nullable(),
|
|
5100
|
+
inputVersions: EscalationInputVersionsSchema.nullable()
|
|
5101
|
+
}).merge(ObservedSchema);
|
|
5102
|
+
var TaskEscalationReadResultSchema = z.object({
|
|
5103
|
+
items: z.array(TaskEscalationPacketSchema),
|
|
5104
|
+
nextCursor: z.string().nullable()
|
|
5105
|
+
}).merge(ObservedSchema);
|
|
5106
|
+
var TaskStartInputSchema = z.object({
|
|
5107
|
+
tranche: z.string().min(1),
|
|
5108
|
+
id: z.string().min(1)
|
|
5109
|
+
}).strict();
|
|
5110
|
+
var TaskStartResultSchema = z.object({
|
|
5111
|
+
requestId: z.string().min(1),
|
|
5112
|
+
run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
5113
|
+
started: z.boolean(),
|
|
5114
|
+
startedAt: z.string(),
|
|
5115
|
+
mode: z.literal("attended")
|
|
5116
|
+
});
|
|
5117
|
+
var TaskResumeInputSchema = z.object({
|
|
5118
|
+
task: TaskToolRefSchema
|
|
5119
|
+
}).strict();
|
|
5120
|
+
var TaskCancelInputSchema = z.object({
|
|
5121
|
+
task: TaskToolRefSchema,
|
|
5122
|
+
reason: z.string().min(1)
|
|
5123
|
+
}).strict();
|
|
5124
|
+
var TaskResumeResultSchema = z.object({
|
|
5125
|
+
task: z.number().int().positive(),
|
|
5126
|
+
pr: z.number().int().positive(),
|
|
5127
|
+
escalationId: z.string().min(1),
|
|
5128
|
+
outcome: z.enum(["started", "already_resumed"]),
|
|
5129
|
+
authenticatedBy: z.string().min(1),
|
|
5130
|
+
authenticatedFrom: z.string().min(1)
|
|
5131
|
+
});
|
|
5132
|
+
var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
|
|
5133
|
+
var TaskCancelResultSchema = z.object({
|
|
5134
|
+
task: z.number().int().positive(),
|
|
5135
|
+
pr: z.number().int().positive(),
|
|
5136
|
+
escalationId: z.string().min(1),
|
|
5137
|
+
outcome: TaskCancelOutcomeSchema,
|
|
5138
|
+
authenticatedBy: z.string().min(1),
|
|
5139
|
+
authenticatedFrom: z.string().min(1),
|
|
5140
|
+
fencedEffectKeys: z.array(z.string())
|
|
5141
|
+
});
|
|
5142
|
+
var TASK_TOOL_NAMES = [
|
|
5143
|
+
"task_start",
|
|
5144
|
+
"task_status",
|
|
5145
|
+
"task_escalation_read",
|
|
5146
|
+
"task_resume",
|
|
5147
|
+
"task_cancel"
|
|
5148
|
+
];
|
|
5149
|
+
var OPERATOR_STATUS_FOLLOW = "task_status_follow";
|
|
5150
|
+
var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
|
|
4626
5151
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
4627
5152
|
function parseTaskBranch(branch) {
|
|
4628
5153
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -4706,7 +5231,6 @@ function decideIssueAssignment(input) {
|
|
|
4706
5231
|
};
|
|
4707
5232
|
}
|
|
4708
5233
|
// ../../packages/aeg-core/src/test-plan-gate.ts
|
|
4709
|
-
var TASK_BRANCH_PATTERN2 = /^task\/[^/]+\/[^/]+$/;
|
|
4710
5234
|
function evaluateTestPlanGate(body, branch) {
|
|
4711
5235
|
if (!body) {
|
|
4712
5236
|
return {
|
|
@@ -4719,7 +5243,7 @@ function evaluateTestPlanGate(body, branch) {
|
|
|
4719
5243
|
}
|
|
4720
5244
|
const located = locateTestPlanSection(body);
|
|
4721
5245
|
if (!located.found) {
|
|
4722
|
-
if (
|
|
5246
|
+
if (parseTaskBranchIdentity(branch) !== null) {
|
|
4723
5247
|
return {
|
|
4724
5248
|
verdict: "fail",
|
|
4725
5249
|
messages: [
|
|
@@ -4846,8 +5370,11 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
4846
5370
|
}
|
|
4847
5371
|
return findings;
|
|
4848
5372
|
}
|
|
5373
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5374
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5375
|
+
|
|
4849
5376
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
4850
|
-
import { z } from "zod";
|
|
5377
|
+
import { z as z2 } from "zod";
|
|
4851
5378
|
var ROLE_VALUES = [
|
|
4852
5379
|
"planner",
|
|
4853
5380
|
"developer",
|
|
@@ -4857,136 +5384,174 @@ var ROLE_VALUES = [
|
|
|
4857
5384
|
"archivist",
|
|
4858
5385
|
"architect"
|
|
4859
5386
|
];
|
|
4860
|
-
var RoleSchema =
|
|
5387
|
+
var RoleSchema = z2.enum(ROLE_VALUES);
|
|
4861
5388
|
var HOST_VALUES = ["hook", "ci", "cli", "loop"];
|
|
4862
|
-
var HostSchema =
|
|
5389
|
+
var HostSchema = z2.enum(HOST_VALUES);
|
|
4863
5390
|
var RUN_ID_PATTERN = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
4864
|
-
var
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
doctrine: z.string(),
|
|
5391
|
+
var headerMetaCore = {
|
|
5392
|
+
ts: z2.string(),
|
|
5393
|
+
run_id: z2.string().regex(RUN_ID_PATTERN),
|
|
5394
|
+
seq: z2.number().int().nonnegative(),
|
|
5395
|
+
repo: z2.string().nullable(),
|
|
5396
|
+
vinaya: z2.string(),
|
|
5397
|
+
doctrine: z2.string(),
|
|
4872
5398
|
host: HostSchema,
|
|
4873
|
-
machine:
|
|
5399
|
+
machine: z2.string()
|
|
5400
|
+
};
|
|
5401
|
+
var HeaderMetaV1Schema = z2.object({
|
|
5402
|
+
schema: z2.literal(1),
|
|
5403
|
+
...headerMetaCore
|
|
5404
|
+
}).strict();
|
|
5405
|
+
var LineageSchema = z2.object({
|
|
5406
|
+
run: z2.string().nullable(),
|
|
5407
|
+
attempt: z2.number().int().nullable(),
|
|
5408
|
+
parent: z2.string().nullable()
|
|
5409
|
+
}).strict();
|
|
5410
|
+
var InputVersionsSchema = z2.object({
|
|
5411
|
+
objectives_version: z2.string().nullable(),
|
|
5412
|
+
brief_hash: z2.string().nullable(),
|
|
5413
|
+
ruling_ordinal: z2.number().int().nullable(),
|
|
5414
|
+
policy_digest: z2.string().nullable()
|
|
5415
|
+
}).strict();
|
|
5416
|
+
var ProvenanceSchema = z2.enum(["parent_attributed", "env_correlated", "self_reported", "unavailable"]);
|
|
5417
|
+
var HeaderMetaV2Schema = z2.object({
|
|
5418
|
+
schema: z2.literal(2),
|
|
5419
|
+
...headerMetaCore,
|
|
5420
|
+
event_id: z2.string().min(1),
|
|
5421
|
+
process_id: z2.string().min(1),
|
|
5422
|
+
actor_id: z2.string().nullable(),
|
|
5423
|
+
lineage: LineageSchema,
|
|
5424
|
+
input_versions: InputVersionsSchema,
|
|
5425
|
+
provenance: ProvenanceSchema
|
|
4874
5426
|
}).strict();
|
|
4875
|
-
var
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
5427
|
+
var HeaderMetaSchema = z2.discriminatedUnion("schema", [HeaderMetaV1Schema, HeaderMetaV2Schema]);
|
|
5428
|
+
var SubjectSchema = z2.object({
|
|
5429
|
+
issue: z2.number().int().nullable(),
|
|
5430
|
+
pr: z2.number().int().optional(),
|
|
5431
|
+
sha: z2.string().optional(),
|
|
5432
|
+
role: z2.union([RoleSchema, z2.literal("unattributed")]),
|
|
5433
|
+
round: z2.number().int().optional(),
|
|
5434
|
+
objectives_version: z2.string().optional()
|
|
4882
5435
|
}).strict();
|
|
4883
|
-
var HeaderSchema =
|
|
5436
|
+
var HeaderSchema = z2.object({
|
|
4884
5437
|
meta: HeaderMetaSchema,
|
|
4885
5438
|
subject: SubjectSchema
|
|
4886
5439
|
}).strict();
|
|
4887
5440
|
var envelopeTail = {
|
|
4888
|
-
duration_ms:
|
|
4889
|
-
payload:
|
|
5441
|
+
duration_ms: z2.number().nonnegative().optional(),
|
|
5442
|
+
payload: z2.object({}).strict()
|
|
4890
5443
|
};
|
|
4891
|
-
var
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
5444
|
+
var ReviewFindingSchema = z2.object({
|
|
5445
|
+
id: z2.string(),
|
|
5446
|
+
severity: z2.string(),
|
|
5447
|
+
state: z2.string().optional(),
|
|
5448
|
+
severity_scale: z2.string().optional(),
|
|
5449
|
+
policy_treatment: z2.enum(["blocking", "non_blocking", "unavailable"]).optional(),
|
|
5450
|
+
confidence: z2.number().min(0).max(1).optional(),
|
|
5451
|
+
confidence_scale: z2.string().optional(),
|
|
5452
|
+
confidence_source: z2.string().optional()
|
|
5453
|
+
}).strict();
|
|
5454
|
+
var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
5455
|
+
z2.object({ type: z2.literal("pr_opened"), pr: z2.number().int(), head: z2.string() }).strict(),
|
|
5456
|
+
z2.object({
|
|
5457
|
+
type: z2.literal("round_pushed"),
|
|
5458
|
+
pr: z2.number().int(),
|
|
5459
|
+
head: z2.string(),
|
|
5460
|
+
comment_id: z2.number().int()
|
|
4898
5461
|
}).strict(),
|
|
4899
|
-
|
|
4900
|
-
type:
|
|
4901
|
-
verdict:
|
|
4902
|
-
head:
|
|
4903
|
-
comment_id:
|
|
4904
|
-
objectives:
|
|
4905
|
-
findings:
|
|
5462
|
+
z2.object({
|
|
5463
|
+
type: z2.literal("verdict"),
|
|
5464
|
+
verdict: z2.enum(["APPROVE", "REQUEST CHANGES", "PASS", "FAIL"]),
|
|
5465
|
+
head: z2.string(),
|
|
5466
|
+
comment_id: z2.number().int(),
|
|
5467
|
+
objectives: z2.array(z2.object({ id: z2.string(), met: z2.boolean() }).strict()),
|
|
5468
|
+
findings: z2.array(ReviewFindingSchema)
|
|
4906
5469
|
}).strict(),
|
|
4907
|
-
|
|
4908
|
-
type:
|
|
4909
|
-
class:
|
|
4910
|
-
comment_id:
|
|
5470
|
+
z2.object({
|
|
5471
|
+
type: z2.literal("escalation"),
|
|
5472
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5473
|
+
comment_id: z2.number().int()
|
|
4911
5474
|
}).strict(),
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
5475
|
+
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5476
|
+
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5477
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
|
|
5478
|
+
z2.object({ type: z2.literal("completed") }).strict()
|
|
4915
5479
|
]);
|
|
4916
5480
|
var dispatchShared = {
|
|
4917
5481
|
meta: HeaderMetaSchema,
|
|
4918
5482
|
subject: SubjectSchema,
|
|
4919
|
-
kind:
|
|
5483
|
+
kind: z2.literal("dispatch"),
|
|
4920
5484
|
...envelopeTail,
|
|
4921
5485
|
target_role: RoleSchema,
|
|
4922
|
-
model:
|
|
4923
|
-
round:
|
|
4924
|
-
effect_id:
|
|
5486
|
+
model: z2.string(),
|
|
5487
|
+
round: z2.number().int().optional(),
|
|
5488
|
+
effect_id: z2.string()
|
|
4925
5489
|
};
|
|
4926
|
-
var dispatchUsageField =
|
|
4927
|
-
var DispatchEventSchema =
|
|
4928
|
-
|
|
4929
|
-
|
|
5490
|
+
var dispatchUsageField = z2.object({ input: z2.number().nonnegative(), output: z2.number().nonnegative() }).strict().nullable();
|
|
5491
|
+
var DispatchEventSchema = z2.discriminatedUnion("event", [
|
|
5492
|
+
z2.object({ ...dispatchShared, event: z2.literal("dispatched"), prompt_hash: z2.string() }).strict(),
|
|
5493
|
+
z2.object({
|
|
4930
5494
|
...dispatchShared,
|
|
4931
|
-
event:
|
|
5495
|
+
event: z2.literal("outcome_received"),
|
|
4932
5496
|
outcome: DispatchOutcomeSchema,
|
|
4933
5497
|
usage: dispatchUsageField
|
|
4934
5498
|
}).strict(),
|
|
4935
|
-
|
|
5499
|
+
z2.object({
|
|
4936
5500
|
...dispatchShared,
|
|
4937
|
-
event:
|
|
4938
|
-
reason:
|
|
5501
|
+
event: z2.literal("dispatch_failed"),
|
|
5502
|
+
reason: z2.enum(["timeout", "crash", "refused", "unattributed_write"]),
|
|
4939
5503
|
usage: dispatchUsageField
|
|
4940
5504
|
}).strict()
|
|
4941
5505
|
]);
|
|
4942
5506
|
var loopShared = {
|
|
4943
5507
|
meta: HeaderMetaSchema,
|
|
4944
5508
|
subject: SubjectSchema,
|
|
4945
|
-
kind:
|
|
5509
|
+
kind: z2.literal("dev_review_loop"),
|
|
4946
5510
|
...envelopeTail,
|
|
4947
|
-
loop_id:
|
|
5511
|
+
loop_id: z2.string()
|
|
4948
5512
|
};
|
|
4949
|
-
var DevReviewLoopEventSchema =
|
|
4950
|
-
|
|
5513
|
+
var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
5514
|
+
z2.object({
|
|
4951
5515
|
...loopShared,
|
|
4952
|
-
event:
|
|
4953
|
-
task:
|
|
4954
|
-
policy:
|
|
4955
|
-
max_rounds:
|
|
4956
|
-
reviewers:
|
|
4957
|
-
models:
|
|
5516
|
+
event: z2.literal("loop_started"),
|
|
5517
|
+
task: z2.number().int(),
|
|
5518
|
+
policy: z2.object({
|
|
5519
|
+
max_rounds: z2.number().int().nonnegative(),
|
|
5520
|
+
reviewers: z2.array(RoleSchema),
|
|
5521
|
+
models: z2.record(RoleSchema, z2.string())
|
|
4958
5522
|
}).strict()
|
|
4959
5523
|
}).strict(),
|
|
4960
|
-
|
|
4961
|
-
|
|
5524
|
+
z2.object({ ...loopShared, event: z2.literal("round_started"), round: z2.number().int(), base_head: z2.string() }).strict(),
|
|
5525
|
+
z2.object({
|
|
4962
5526
|
...loopShared,
|
|
4963
|
-
event:
|
|
4964
|
-
round:
|
|
4965
|
-
head:
|
|
4966
|
-
green:
|
|
5527
|
+
event: z2.literal("gate_result_read"),
|
|
5528
|
+
round: z2.number().int(),
|
|
5529
|
+
head: z2.string(),
|
|
5530
|
+
green: z2.boolean()
|
|
4967
5531
|
}).strict(),
|
|
4968
|
-
|
|
5532
|
+
z2.object({
|
|
4969
5533
|
...loopShared,
|
|
4970
|
-
event:
|
|
4971
|
-
round:
|
|
4972
|
-
head:
|
|
4973
|
-
all_approve:
|
|
4974
|
-
blockers:
|
|
5534
|
+
event: z2.literal("verdicts_read"),
|
|
5535
|
+
round: z2.number().int(),
|
|
5536
|
+
head: z2.string(),
|
|
5537
|
+
all_approve: z2.boolean(),
|
|
5538
|
+
blockers: z2.number().int().nonnegative(),
|
|
5539
|
+
findings: z2.array(ReviewFindingSchema).optional()
|
|
4975
5540
|
}).strict(),
|
|
4976
|
-
|
|
5541
|
+
z2.object({
|
|
4977
5542
|
...loopShared,
|
|
4978
|
-
event:
|
|
4979
|
-
round:
|
|
4980
|
-
open:
|
|
4981
|
-
resolved:
|
|
4982
|
-
new:
|
|
4983
|
-
recurring:
|
|
5543
|
+
event: z2.literal("findings_compared"),
|
|
5544
|
+
round: z2.number().int(),
|
|
5545
|
+
open: z2.array(z2.string()),
|
|
5546
|
+
resolved: z2.array(z2.string()),
|
|
5547
|
+
new: z2.array(z2.string()),
|
|
5548
|
+
recurring: z2.array(z2.string())
|
|
4984
5549
|
}).strict(),
|
|
4985
|
-
|
|
5550
|
+
z2.object({
|
|
4986
5551
|
...loopShared,
|
|
4987
|
-
event:
|
|
4988
|
-
round:
|
|
4989
|
-
condition:
|
|
5552
|
+
event: z2.literal("stop_condition_met"),
|
|
5553
|
+
round: z2.number().int(),
|
|
5554
|
+
condition: z2.enum([
|
|
4990
5555
|
"green",
|
|
4991
5556
|
"max_rounds",
|
|
4992
5557
|
"no_progress",
|
|
@@ -4996,42 +5561,49 @@ var DevReviewLoopEventSchema = z.discriminatedUnion("event", [
|
|
|
4996
5561
|
"reappearance"
|
|
4997
5562
|
])
|
|
4998
5563
|
}).strict(),
|
|
4999
|
-
|
|
5564
|
+
z2.object({
|
|
5565
|
+
...loopShared,
|
|
5566
|
+
event: z2.literal("paused"),
|
|
5567
|
+
round: z2.number().int(),
|
|
5568
|
+
reason: z2.enum(["escalation", "principal_item", "refreeze_needed"])
|
|
5569
|
+
}).strict(),
|
|
5570
|
+
z2.object({
|
|
5000
5571
|
...loopShared,
|
|
5001
|
-
event:
|
|
5002
|
-
round:
|
|
5003
|
-
|
|
5572
|
+
event: z2.literal("resumed"),
|
|
5573
|
+
round: z2.number().int(),
|
|
5574
|
+
by: z2.literal("principal")
|
|
5004
5575
|
}).strict(),
|
|
5005
|
-
|
|
5576
|
+
z2.object({
|
|
5006
5577
|
...loopShared,
|
|
5007
|
-
event:
|
|
5008
|
-
round:
|
|
5009
|
-
|
|
5578
|
+
event: z2.literal("unpushed_work_resume"),
|
|
5579
|
+
round: z2.number().int(),
|
|
5580
|
+
branch: z2.string(),
|
|
5581
|
+
detail: z2.string()
|
|
5010
5582
|
}).strict(),
|
|
5011
|
-
|
|
5583
|
+
z2.object({
|
|
5012
5584
|
...loopShared,
|
|
5013
|
-
event:
|
|
5014
|
-
round:
|
|
5015
|
-
base_head:
|
|
5016
|
-
head:
|
|
5017
|
-
files_changed:
|
|
5018
|
-
insertions:
|
|
5019
|
-
deletions:
|
|
5020
|
-
wall_ms:
|
|
5021
|
-
outcome:
|
|
5585
|
+
event: z2.literal("round_ended"),
|
|
5586
|
+
round: z2.number().int(),
|
|
5587
|
+
base_head: z2.string(),
|
|
5588
|
+
head: z2.string(),
|
|
5589
|
+
files_changed: z2.number().int().nonnegative(),
|
|
5590
|
+
insertions: z2.number().int().nonnegative(),
|
|
5591
|
+
deletions: z2.number().int().nonnegative(),
|
|
5592
|
+
wall_ms: z2.number().nonnegative(),
|
|
5593
|
+
outcome: z2.enum(["green", "changes_requested", "escalated"])
|
|
5022
5594
|
}).strict(),
|
|
5023
|
-
|
|
5595
|
+
z2.object({
|
|
5024
5596
|
...loopShared,
|
|
5025
|
-
event:
|
|
5026
|
-
rounds:
|
|
5027
|
-
total_wall_ms:
|
|
5028
|
-
time_to_green_ms:
|
|
5029
|
-
files_changed_total:
|
|
5030
|
-
final_head:
|
|
5031
|
-
result:
|
|
5597
|
+
event: z2.literal("journal_finalized"),
|
|
5598
|
+
rounds: z2.number().int().nonnegative(),
|
|
5599
|
+
total_wall_ms: z2.number().nonnegative(),
|
|
5600
|
+
time_to_green_ms: z2.number().nonnegative().nullable(),
|
|
5601
|
+
files_changed_total: z2.number().int().nonnegative(),
|
|
5602
|
+
final_head: z2.string(),
|
|
5603
|
+
result: z2.enum(["merged_ready", "stopped"])
|
|
5032
5604
|
}).strict()
|
|
5033
5605
|
]);
|
|
5034
|
-
var ForgeOpSchema =
|
|
5606
|
+
var ForgeOpSchema = z2.enum([
|
|
5035
5607
|
"pr.create",
|
|
5036
5608
|
"pr.comment",
|
|
5037
5609
|
"pr.body.replace",
|
|
@@ -5045,24 +5617,434 @@ var ForgeOpSchema = z.enum([
|
|
|
5045
5617
|
"label.add",
|
|
5046
5618
|
"label.remove"
|
|
5047
5619
|
]);
|
|
5048
|
-
var ForgeWriteTargetSchema =
|
|
5049
|
-
issue:
|
|
5050
|
-
pr:
|
|
5620
|
+
var ForgeWriteTargetSchema = z2.object({
|
|
5621
|
+
issue: z2.number().int().optional(),
|
|
5622
|
+
pr: z2.number().int().optional()
|
|
5051
5623
|
}).strict();
|
|
5052
5624
|
var forgeWriteShared = {
|
|
5053
5625
|
meta: HeaderMetaSchema,
|
|
5054
5626
|
subject: SubjectSchema,
|
|
5055
|
-
kind:
|
|
5627
|
+
kind: z2.literal("forge_write"),
|
|
5056
5628
|
...envelopeTail,
|
|
5057
5629
|
op: ForgeOpSchema,
|
|
5058
5630
|
target: ForgeWriteTargetSchema
|
|
5059
5631
|
};
|
|
5060
|
-
var ForgeWriteEventSchema =
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5632
|
+
var ForgeWriteEventSchema = z2.discriminatedUnion("event", [
|
|
5633
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("validated") }).strict(),
|
|
5634
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("refused"), reason: z2.string() }).strict(),
|
|
5635
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("written"), comment_ids: z2.array(z2.string()) }).strict()
|
|
5636
|
+
]);
|
|
5637
|
+
var GateOutcomeSchema = z2.enum([
|
|
5638
|
+
"pass",
|
|
5639
|
+
"fail",
|
|
5640
|
+
"wait",
|
|
5641
|
+
"skip",
|
|
5642
|
+
"invalid_input",
|
|
5643
|
+
"unavailable_dependency",
|
|
5644
|
+
"timeout",
|
|
5645
|
+
"cancelled"
|
|
5064
5646
|
]);
|
|
5065
|
-
var
|
|
5647
|
+
var gateShared = {
|
|
5648
|
+
meta: HeaderMetaSchema,
|
|
5649
|
+
subject: SubjectSchema,
|
|
5650
|
+
kind: z2.literal("gate"),
|
|
5651
|
+
...envelopeTail,
|
|
5652
|
+
check: z2.string(),
|
|
5653
|
+
check_version: z2.string().nullable(),
|
|
5654
|
+
policy_version: z2.string().nullable(),
|
|
5655
|
+
input_fingerprint: z2.string().nullable()
|
|
5656
|
+
};
|
|
5657
|
+
var GateEventSchema = z2.discriminatedUnion("event", [
|
|
5658
|
+
z2.object({
|
|
5659
|
+
...gateShared,
|
|
5660
|
+
event: z2.literal("checked"),
|
|
5661
|
+
outcome: GateOutcomeSchema,
|
|
5662
|
+
reason: z2.string().optional()
|
|
5663
|
+
}).strict()
|
|
5664
|
+
]);
|
|
5665
|
+
var OperationResultSchema = z2.enum(["ok", "error", "refused", "timeout", "cancelled", "unavailable"]);
|
|
5666
|
+
var operationShared = {
|
|
5667
|
+
meta: HeaderMetaSchema,
|
|
5668
|
+
subject: SubjectSchema,
|
|
5669
|
+
kind: z2.literal("operation"),
|
|
5670
|
+
...envelopeTail,
|
|
5671
|
+
operation: z2.string(),
|
|
5672
|
+
target: z2.string().nullable()
|
|
5673
|
+
};
|
|
5674
|
+
var OperationEventSchema = z2.discriminatedUnion("event", [
|
|
5675
|
+
z2.object({
|
|
5676
|
+
...operationShared,
|
|
5677
|
+
event: z2.literal("completed"),
|
|
5678
|
+
result: OperationResultSchema,
|
|
5679
|
+
error_class: z2.string().nullable()
|
|
5680
|
+
}).strict()
|
|
5681
|
+
]);
|
|
5682
|
+
var UsageUnitsSchema = z2.object({
|
|
5683
|
+
input: z2.number().nonnegative().nullable(),
|
|
5684
|
+
output: z2.number().nonnegative().nullable(),
|
|
5685
|
+
cache: z2.number().nonnegative().nullable()
|
|
5686
|
+
}).strict();
|
|
5687
|
+
var usageShared = {
|
|
5688
|
+
meta: HeaderMetaSchema,
|
|
5689
|
+
subject: SubjectSchema,
|
|
5690
|
+
kind: z2.literal("usage"),
|
|
5691
|
+
...envelopeTail,
|
|
5692
|
+
model: z2.string().nullable(),
|
|
5693
|
+
source: z2.string(),
|
|
5694
|
+
semantics: z2.enum(["cumulative", "delta"])
|
|
5695
|
+
};
|
|
5696
|
+
var UsageEventSchema = z2.discriminatedUnion("event", [
|
|
5697
|
+
z2.object({
|
|
5698
|
+
...usageShared,
|
|
5699
|
+
event: z2.literal("observed"),
|
|
5700
|
+
units: UsageUnitsSchema,
|
|
5701
|
+
unknown_reason: z2.string().nullable()
|
|
5702
|
+
}).strict()
|
|
5703
|
+
]);
|
|
5704
|
+
var RoleAttemptOutcomeSchema = z2.enum([
|
|
5705
|
+
"completed",
|
|
5706
|
+
"incomplete",
|
|
5707
|
+
"infrastructure_failed",
|
|
5708
|
+
"cancelled",
|
|
5709
|
+
"timed_out",
|
|
5710
|
+
"capability_refused"
|
|
5711
|
+
]);
|
|
5712
|
+
var roleAttemptShared = {
|
|
5713
|
+
meta: HeaderMetaSchema,
|
|
5714
|
+
subject: SubjectSchema,
|
|
5715
|
+
kind: z2.literal("role_attempt"),
|
|
5716
|
+
...envelopeTail,
|
|
5717
|
+
actor: z2.string().nullable(),
|
|
5718
|
+
attempt: z2.number().int().nullable(),
|
|
5719
|
+
effect_id: z2.string(),
|
|
5720
|
+
model: z2.string().nullable()
|
|
5721
|
+
};
|
|
5722
|
+
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5723
|
+
z2.object({
|
|
5724
|
+
...roleAttemptShared,
|
|
5725
|
+
event: z2.literal("attempted"),
|
|
5726
|
+
outcome: RoleAttemptOutcomeSchema,
|
|
5727
|
+
usage: dispatchUsageField
|
|
5728
|
+
}).strict()
|
|
5729
|
+
]);
|
|
5730
|
+
var handoffShared = {
|
|
5731
|
+
meta: HeaderMetaSchema,
|
|
5732
|
+
subject: SubjectSchema,
|
|
5733
|
+
kind: z2.literal("handoff"),
|
|
5734
|
+
...envelopeTail,
|
|
5735
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5736
|
+
reason: z2.string()
|
|
5737
|
+
};
|
|
5738
|
+
var HandoffEventSchema = z2.discriminatedUnion("event", [
|
|
5739
|
+
z2.object({
|
|
5740
|
+
...handoffShared,
|
|
5741
|
+
event: z2.literal("raised"),
|
|
5742
|
+
requested_decision: z2.string().nullable()
|
|
5743
|
+
}).strict(),
|
|
5744
|
+
z2.object({
|
|
5745
|
+
...handoffShared,
|
|
5746
|
+
event: z2.literal("resolved"),
|
|
5747
|
+
resolution: z2.string().nullable(),
|
|
5748
|
+
resolved_by: z2.string().nullable()
|
|
5749
|
+
}).strict()
|
|
5750
|
+
]);
|
|
5751
|
+
var EffectTargetSchema = z2.object({
|
|
5752
|
+
kind: z2.string(),
|
|
5753
|
+
ref: z2.string()
|
|
5754
|
+
}).strict();
|
|
5755
|
+
var effectShared = {
|
|
5756
|
+
meta: HeaderMetaSchema,
|
|
5757
|
+
subject: SubjectSchema,
|
|
5758
|
+
kind: z2.literal("effect"),
|
|
5759
|
+
...envelopeTail,
|
|
5760
|
+
effect_id: z2.string(),
|
|
5761
|
+
target: EffectTargetSchema
|
|
5762
|
+
};
|
|
5763
|
+
var EffectEventSchema = z2.discriminatedUnion("event", [
|
|
5764
|
+
z2.object({ ...effectShared, event: z2.literal("attempted") }).strict(),
|
|
5765
|
+
z2.object({ ...effectShared, event: z2.literal("observed"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict(),
|
|
5766
|
+
z2.object({ ...effectShared, event: z2.literal("verified"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict()
|
|
5767
|
+
]);
|
|
5768
|
+
var LogEventSchema = z2.union([
|
|
5769
|
+
DispatchEventSchema,
|
|
5770
|
+
DevReviewLoopEventSchema,
|
|
5771
|
+
ForgeWriteEventSchema,
|
|
5772
|
+
GateEventSchema,
|
|
5773
|
+
OperationEventSchema,
|
|
5774
|
+
UsageEventSchema,
|
|
5775
|
+
RoleAttemptEventSchema,
|
|
5776
|
+
HandoffEventSchema,
|
|
5777
|
+
EffectEventSchema
|
|
5778
|
+
]);
|
|
5779
|
+
|
|
5780
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5781
|
+
function isRole(value) {
|
|
5782
|
+
return value !== undefined && ROLE_VALUES.includes(value);
|
|
5783
|
+
}
|
|
5784
|
+
function actorIdFromEnv(role) {
|
|
5785
|
+
return role === undefined || role === "" ? null : role;
|
|
5786
|
+
}
|
|
5787
|
+
function lineageFieldFromEnv(value) {
|
|
5788
|
+
return value === undefined || value === "" ? null : value;
|
|
5789
|
+
}
|
|
5790
|
+
function attemptFromEnv(value) {
|
|
5791
|
+
if (value === undefined || value === "")
|
|
5792
|
+
return null;
|
|
5793
|
+
const n = Number(value);
|
|
5794
|
+
return Number.isInteger(n) ? n : null;
|
|
5795
|
+
}
|
|
5796
|
+
function provenanceFor(input) {
|
|
5797
|
+
if (input.provenance)
|
|
5798
|
+
return input.provenance;
|
|
5799
|
+
if (input.env.role || input.env.task)
|
|
5800
|
+
return "env_correlated";
|
|
5801
|
+
return "unavailable";
|
|
5802
|
+
}
|
|
5803
|
+
function issueFromTask(task) {
|
|
5804
|
+
if (task === undefined || task === "")
|
|
5805
|
+
return null;
|
|
5806
|
+
const n = Number(task);
|
|
5807
|
+
return Number.isInteger(n) ? n : null;
|
|
5808
|
+
}
|
|
5809
|
+
function roundFromEnv(round) {
|
|
5810
|
+
if (round === undefined || round === "")
|
|
5811
|
+
return;
|
|
5812
|
+
const n = Number(round);
|
|
5813
|
+
return Number.isInteger(n) ? n : undefined;
|
|
5814
|
+
}
|
|
5815
|
+
function buildHeader(input) {
|
|
5816
|
+
const role = isRole(input.env.role) ? input.env.role : "unattributed";
|
|
5817
|
+
const round = roundFromEnv(input.env.round);
|
|
5818
|
+
const subject = {
|
|
5819
|
+
issue: issueFromTask(input.env.task),
|
|
5820
|
+
role,
|
|
5821
|
+
...round !== undefined ? { round } : {},
|
|
5822
|
+
...input.subject ?? {}
|
|
5823
|
+
};
|
|
5824
|
+
return {
|
|
5825
|
+
meta: {
|
|
5826
|
+
schema: 2,
|
|
5827
|
+
ts: input.now.toISOString(),
|
|
5828
|
+
run_id: input.runId,
|
|
5829
|
+
seq: input.seq,
|
|
5830
|
+
repo: input.repo,
|
|
5831
|
+
vinaya: input.vinaya,
|
|
5832
|
+
doctrine: input.doctrine,
|
|
5833
|
+
host: input.host,
|
|
5834
|
+
machine: createHash5("sha256").update(input.hostname).digest("hex"),
|
|
5835
|
+
event_id: input.eventId,
|
|
5836
|
+
process_id: input.processId,
|
|
5837
|
+
actor_id: actorIdFromEnv(input.env.role),
|
|
5838
|
+
lineage: {
|
|
5839
|
+
run: lineageFieldFromEnv(input.env.run),
|
|
5840
|
+
attempt: attemptFromEnv(input.env.attempt),
|
|
5841
|
+
parent: lineageFieldFromEnv(input.env.parent)
|
|
5842
|
+
},
|
|
5843
|
+
input_versions: {
|
|
5844
|
+
objectives_version: input.inputVersions?.objectivesVersion ?? null,
|
|
5845
|
+
brief_hash: input.inputVersions?.briefHash ?? null,
|
|
5846
|
+
ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
|
|
5847
|
+
policy_digest: input.inputVersions?.policyDigest ?? null
|
|
5848
|
+
},
|
|
5849
|
+
provenance: provenanceFor(input)
|
|
5850
|
+
},
|
|
5851
|
+
subject
|
|
5852
|
+
};
|
|
5853
|
+
}
|
|
5854
|
+
// ../../packages/aeg-core/src/log/redact.ts
|
|
5855
|
+
var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
|
|
5856
|
+
var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
|
|
5857
|
+
var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
|
|
5858
|
+
var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5859
|
+
var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
|
|
5860
|
+
var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
|
|
5861
|
+
var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
|
|
5862
|
+
var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
|
|
5863
|
+
var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
|
|
5864
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
|
|
5865
|
+
var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
|
|
5866
|
+
var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
|
|
5867
|
+
var GENERIC_SECRET_ASSIGNMENT_PATTERN = /\b((?:secret|password|passwd|api[_-]?key|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[:=]\s*)[A-Za-z0-9+/_=-]{16,}\b/gi;
|
|
5868
|
+
function redactString(value, home) {
|
|
5869
|
+
let out = value.replace(GITHUB_TOKEN_PATTERN, "<redacted>").replace(CLASSIC_GITHUB_PAT_PATTERN, "$1<redacted>").replace(BEARER_TOKEN_PATTERN, "<redacted>").replace(AWS_ACCESS_KEY_PATTERN, "<redacted>").replace(SLACK_TOKEN_PATTERN, "<redacted>").replace(STRIPE_KEY_PATTERN, "<redacted>").replace(ANTHROPIC_KEY_PATTERN, "<redacted>").replace(OPENAI_KEY_PATTERN, "<redacted>").replace(NPM_TOKEN_PATTERN, "<redacted>").replace(JWT_PATTERN, "<redacted>").replace(PEM_BLOCK_PATTERN, "<redacted>").replace(BASIC_AUTH_URL_PATTERN, "$1<redacted>@").replace(GENERIC_SECRET_ASSIGNMENT_PATTERN, "$1<redacted>");
|
|
5870
|
+
if (home.length > 0 && out.startsWith(home)) {
|
|
5871
|
+
const rest = out.slice(home.length);
|
|
5872
|
+
if (rest === "" || rest.startsWith("/"))
|
|
5873
|
+
out = `~${rest}`;
|
|
5874
|
+
}
|
|
5875
|
+
return out;
|
|
5876
|
+
}
|
|
5877
|
+
function redact(value, home) {
|
|
5878
|
+
if (typeof value === "string")
|
|
5879
|
+
return redactString(value, home);
|
|
5880
|
+
if (Array.isArray(value))
|
|
5881
|
+
return value.map((v) => redact(v, home));
|
|
5882
|
+
if (value !== null && typeof value === "object") {
|
|
5883
|
+
const out = {};
|
|
5884
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5885
|
+
out[k] = redact(v, home);
|
|
5886
|
+
}
|
|
5887
|
+
return out;
|
|
5888
|
+
}
|
|
5889
|
+
return value;
|
|
5890
|
+
}
|
|
5891
|
+
// ../../packages/aeg-core/src/log/store.ts
|
|
5892
|
+
function metaOf(obj) {
|
|
5893
|
+
if (obj === null || typeof obj !== "object")
|
|
5894
|
+
return null;
|
|
5895
|
+
const meta = obj.meta;
|
|
5896
|
+
if (meta === null || typeof meta !== "object")
|
|
5897
|
+
return null;
|
|
5898
|
+
return meta;
|
|
5899
|
+
}
|
|
5900
|
+
function recordIdentity(obj) {
|
|
5901
|
+
const meta = metaOf(obj);
|
|
5902
|
+
if (meta === null)
|
|
5903
|
+
return null;
|
|
5904
|
+
const eventId = meta.event_id;
|
|
5905
|
+
if (typeof eventId === "string" && eventId.length > 0)
|
|
5906
|
+
return eventId;
|
|
5907
|
+
const runId = meta.run_id;
|
|
5908
|
+
const seq = meta.seq;
|
|
5909
|
+
if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
|
|
5910
|
+
return `${runId}:${seq}`;
|
|
5911
|
+
}
|
|
5912
|
+
return null;
|
|
5913
|
+
}
|
|
5914
|
+
|
|
5915
|
+
// ../../packages/aeg-core/src/log/artifact.ts
|
|
5916
|
+
var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
|
|
5917
|
+
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5918
|
+
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5919
|
+
// ../../packages/aeg-core/src/control-store/records.ts
|
|
5920
|
+
import { z as z3 } from "zod";
|
|
5921
|
+
var isoTimestamp = z3.string().min(1);
|
|
5922
|
+
var taskId = z3.number().int().positive();
|
|
5923
|
+
var epochNumber = z3.number().int().nonnegative();
|
|
5924
|
+
var RunRecordSchema = z3.object({
|
|
5925
|
+
version: z3.literal(1),
|
|
5926
|
+
kind: z3.literal("run"),
|
|
5927
|
+
task: taskId,
|
|
5928
|
+
runId: z3.string().min(1),
|
|
5929
|
+
pid: z3.number().int().positive(),
|
|
5930
|
+
host: z3.string().min(1),
|
|
5931
|
+
startedAt: isoTimestamp,
|
|
5932
|
+
childStartedAt: z3.string().min(1).nullable().optional(),
|
|
5933
|
+
childCommand: z3.string().min(1).nullable().optional()
|
|
5934
|
+
}).strict();
|
|
5935
|
+
var InputRecordSchema = z3.object({
|
|
5936
|
+
version: z3.literal(1),
|
|
5937
|
+
kind: z3.literal("input"),
|
|
5938
|
+
task: taskId,
|
|
5939
|
+
runId: z3.string().min(1),
|
|
5940
|
+
source: z3.union([z3.literal("fresh"), z3.literal("resume")]),
|
|
5941
|
+
pr: z3.number().int().positive().nullable(),
|
|
5942
|
+
round: z3.number().int().nonnegative(),
|
|
5943
|
+
recordedAt: isoTimestamp
|
|
5944
|
+
}).strict();
|
|
5945
|
+
var OwnershipRecordSchema = z3.object({
|
|
5946
|
+
version: z3.literal(1),
|
|
5947
|
+
kind: z3.literal("ownership"),
|
|
5948
|
+
task: taskId,
|
|
5949
|
+
epoch: epochNumber,
|
|
5950
|
+
ownerId: z3.string().min(1),
|
|
5951
|
+
pid: z3.number().int().positive(),
|
|
5952
|
+
host: z3.string().min(1),
|
|
5953
|
+
acquiredAt: isoTimestamp
|
|
5954
|
+
}).strict();
|
|
5955
|
+
var TransitionRecordSchema = z3.object({
|
|
5956
|
+
version: z3.literal(1),
|
|
5957
|
+
kind: z3.literal("transition"),
|
|
5958
|
+
task: taskId,
|
|
5959
|
+
epoch: epochNumber,
|
|
5960
|
+
seq: z3.number().int().nonnegative(),
|
|
5961
|
+
from: z3.string().min(1),
|
|
5962
|
+
to: z3.string().min(1),
|
|
5963
|
+
detail: z3.string().optional(),
|
|
5964
|
+
at: isoTimestamp
|
|
5965
|
+
}).strict();
|
|
5966
|
+
var ManifestRecordSchema = z3.object({
|
|
5967
|
+
version: z3.literal(1),
|
|
5968
|
+
kind: z3.literal("manifest"),
|
|
5969
|
+
task: taskId,
|
|
5970
|
+
round: epochNumber,
|
|
5971
|
+
repository: z3.string().min(1),
|
|
5972
|
+
pr: z3.number().int().positive(),
|
|
5973
|
+
branch: z3.string().min(1),
|
|
5974
|
+
baseSha: z3.string().min(1).nullable(),
|
|
5975
|
+
headSha: z3.string().min(1),
|
|
5976
|
+
briefHash: z3.string().min(1).nullable(),
|
|
5977
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
5978
|
+
rulingOrdinal: epochNumber,
|
|
5979
|
+
policyDigest: z3.string().min(1),
|
|
5980
|
+
recordedAt: isoTimestamp
|
|
5981
|
+
}).strict();
|
|
5982
|
+
var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
|
|
5983
|
+
var LoopBudgetsSchema = z3.object({
|
|
5984
|
+
mechanicalRetries: z3.number().int().nonnegative(),
|
|
5985
|
+
reviewRounds: z3.number().int().nonnegative(),
|
|
5986
|
+
infrastructureRetries: z3.number().int().nonnegative()
|
|
5987
|
+
}).strict();
|
|
5988
|
+
var LoopStateRecordSchema = z3.object({
|
|
5989
|
+
version: z3.literal(1),
|
|
5990
|
+
kind: z3.literal("loop_state"),
|
|
5991
|
+
task: taskId,
|
|
5992
|
+
round: z3.number().int().positive(),
|
|
5993
|
+
phase: z3.string().min(1),
|
|
5994
|
+
pauseReason: z3.string().min(1).nullable(),
|
|
5995
|
+
budgets: LoopBudgetsSchema,
|
|
5996
|
+
heldResult: roundHeadIdentity.nullable(),
|
|
5997
|
+
deliveredFindings: roundHeadIdentity.nullable(),
|
|
5998
|
+
recordedAt: isoTimestamp
|
|
5999
|
+
}).strict();
|
|
6000
|
+
var EffectRecordSchema = z3.object({
|
|
6001
|
+
version: z3.literal(1),
|
|
6002
|
+
kind: z3.literal("effect"),
|
|
6003
|
+
task: taskId,
|
|
6004
|
+
key: z3.string().min(1),
|
|
6005
|
+
operation: z3.string().min(1),
|
|
6006
|
+
target: z3.string().min(1),
|
|
6007
|
+
inputVersion: z3.number().int().nonnegative(),
|
|
6008
|
+
payloadDigest: z3.string().min(1),
|
|
6009
|
+
status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
|
|
6010
|
+
url: z3.string().optional(),
|
|
6011
|
+
recordedAt: isoTimestamp
|
|
6012
|
+
}).strict();
|
|
6013
|
+
var EscalationRecordSchema = z3.object({
|
|
6014
|
+
version: z3.literal(1),
|
|
6015
|
+
kind: z3.literal("escalation"),
|
|
6016
|
+
task: taskId,
|
|
6017
|
+
escalationId: z3.string().min(1),
|
|
6018
|
+
round: epochNumber,
|
|
6019
|
+
head: z3.string().min(1),
|
|
6020
|
+
branch: z3.string().min(1),
|
|
6021
|
+
pr: z3.number().int().positive().nullable(),
|
|
6022
|
+
runId: z3.string().min(1),
|
|
6023
|
+
pid: z3.number().int().positive(),
|
|
6024
|
+
host: z3.string().min(1),
|
|
6025
|
+
agent: z3.string().min(1).optional(),
|
|
6026
|
+
reason: z3.string().min(1),
|
|
6027
|
+
detail: z3.string().optional(),
|
|
6028
|
+
evidence: z3.string().optional(),
|
|
6029
|
+
attemptedRecovery: z3.string().min(1),
|
|
6030
|
+
requestedDecision: z3.string().min(1),
|
|
6031
|
+
recipient: z3.string().min(1),
|
|
6032
|
+
briefHash: z3.string().min(1).nullable(),
|
|
6033
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
6034
|
+
rulingOrdinal: epochNumber,
|
|
6035
|
+
policyDigest: z3.string().min(1),
|
|
6036
|
+
recordedAt: isoTimestamp
|
|
6037
|
+
}).strict();
|
|
6038
|
+
var ResolutionRecordSchema = z3.object({
|
|
6039
|
+
version: z3.literal(1),
|
|
6040
|
+
kind: z3.literal("resolution"),
|
|
6041
|
+
task: taskId,
|
|
6042
|
+
escalationId: z3.string().min(1),
|
|
6043
|
+
decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
|
|
6044
|
+
authenticatedBy: z3.string().min(1),
|
|
6045
|
+
authenticatedFrom: z3.string().min(1),
|
|
6046
|
+
consumedAt: isoTimestamp
|
|
6047
|
+
}).strict();
|
|
5066
6048
|
// src/checks/contract.ts
|
|
5067
6049
|
var CHECK_SCHEMA_VERSION = 1;
|
|
5068
6050
|
function emitCheckError(error) {
|
|
@@ -5075,27 +6057,29 @@ import { execFileSync as execFileSync2 } from "node:child_process";
|
|
|
5075
6057
|
import { existsSync, mkdirSync, readFileSync as readFileSync2, realpathSync, writeFileSync } from "node:fs";
|
|
5076
6058
|
import { homedir } from "node:os";
|
|
5077
6059
|
import { dirname, join, resolve } from "node:path";
|
|
5078
|
-
import { z as
|
|
6060
|
+
import { z as z4 } from "zod";
|
|
5079
6061
|
|
|
5080
6062
|
// src/lib/agent-vendors.ts
|
|
5081
6063
|
var AGENT_VENDORS = ["skills", "claude", "gemini"];
|
|
5082
6064
|
|
|
5083
6065
|
// src/lib/config.ts
|
|
5084
|
-
var EnvEntrySchema =
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
6066
|
+
var EnvEntrySchema = z4.union([
|
|
6067
|
+
z4.literal(true),
|
|
6068
|
+
z4.object({ optional: z4.literal(true) }),
|
|
6069
|
+
z4.object({ anyOf: z4.array(z4.string()).min(2) }),
|
|
6070
|
+
z4.string()
|
|
5089
6071
|
]);
|
|
5090
|
-
var CheckEntrySchema =
|
|
5091
|
-
run:
|
|
5092
|
-
scope:
|
|
5093
|
-
include:
|
|
5094
|
-
args:
|
|
5095
|
-
timeoutMs:
|
|
5096
|
-
env:
|
|
5097
|
-
requiresOpenPr:
|
|
5098
|
-
ownWorkflow:
|
|
6072
|
+
var CheckEntrySchema = z4.object({
|
|
6073
|
+
run: z4.string(),
|
|
6074
|
+
scope: z4.enum(["diff", "full"]),
|
|
6075
|
+
include: z4.array(z4.string()).optional(),
|
|
6076
|
+
args: z4.array(z4.string()).optional(),
|
|
6077
|
+
timeoutMs: z4.number().optional(),
|
|
6078
|
+
env: z4.record(z4.string(), EnvEntrySchema).optional(),
|
|
6079
|
+
requiresOpenPr: z4.boolean().optional(),
|
|
6080
|
+
ownWorkflow: z4.boolean().optional(),
|
|
6081
|
+
principalOwed: z4.literal(true).optional(),
|
|
6082
|
+
validates: z4.enum(["body", "issue"]).optional()
|
|
5099
6083
|
}).superRefine((entry2, ctx) => {
|
|
5100
6084
|
if (!entry2.env)
|
|
5101
6085
|
return;
|
|
@@ -5105,25 +6089,26 @@ var CheckEntrySchema = z2.object({
|
|
|
5105
6089
|
const members = value.anyOf;
|
|
5106
6090
|
if (new Set(members).size !== members.length) {
|
|
5107
6091
|
ctx.addIssue({
|
|
5108
|
-
code:
|
|
6092
|
+
code: z4.ZodIssueCode.custom,
|
|
5109
6093
|
message: `env.${key}.anyOf has duplicate members`,
|
|
5110
6094
|
path: ["env", key, "anyOf"]
|
|
5111
6095
|
});
|
|
5112
6096
|
}
|
|
5113
6097
|
if (!members.includes(key)) {
|
|
5114
6098
|
ctx.addIssue({
|
|
5115
|
-
code:
|
|
6099
|
+
code: z4.ZodIssueCode.custom,
|
|
5116
6100
|
message: `env.${key}.anyOf must include "${key}" itself as a member`,
|
|
5117
6101
|
path: ["env", key, "anyOf"]
|
|
5118
6102
|
});
|
|
5119
6103
|
}
|
|
5120
6104
|
}
|
|
5121
6105
|
});
|
|
5122
|
-
var RoleEntrySchema =
|
|
5123
|
-
contract:
|
|
6106
|
+
var RoleEntrySchema = z4.object({
|
|
6107
|
+
contract: z4.string().refine((p) => p.includes("/"), {
|
|
5124
6108
|
message: 'must be a path (contain at least one "/"), not a bare filename'
|
|
5125
6109
|
})
|
|
5126
6110
|
});
|
|
6111
|
+
var MAX_REPORT_COMMAND_TIMEOUT_MS = 3600000;
|
|
5127
6112
|
var BRIEF_BUILTINS = [
|
|
5128
6113
|
"tier",
|
|
5129
6114
|
"testPlan",
|
|
@@ -5143,17 +6128,17 @@ var BRIEF_BUILTINS = [
|
|
|
5143
6128
|
"briefSections",
|
|
5144
6129
|
"milestoneShape"
|
|
5145
6130
|
];
|
|
5146
|
-
var BriefSectionSchema =
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
6131
|
+
var BriefSectionSchema = z4.union([
|
|
6132
|
+
z4.object({ builtin: z4.enum(BRIEF_BUILTINS) }),
|
|
6133
|
+
z4.object({ heading: z4.string().min(1), name: z4.string().optional() }),
|
|
6134
|
+
z4.object({ field: z4.string().min(1), name: z4.string().optional() }),
|
|
6135
|
+
z4.object({ phrase: z4.string().min(1), name: z4.string().optional() })
|
|
5151
6136
|
]);
|
|
5152
|
-
var BriefSchemaSchema =
|
|
5153
|
-
pr:
|
|
5154
|
-
issue:
|
|
5155
|
-
milestone:
|
|
5156
|
-
ack:
|
|
6137
|
+
var BriefSchemaSchema = z4.object({
|
|
6138
|
+
pr: z4.object({ sections: z4.array(BriefSectionSchema) }).optional(),
|
|
6139
|
+
issue: z4.object({ sections: z4.array(BriefSectionSchema) }).optional(),
|
|
6140
|
+
milestone: z4.object({ sections: z4.array(BriefSectionSchema) }).optional(),
|
|
6141
|
+
ack: z4.array(z4.enum(BRIEF_BUILTINS)).optional()
|
|
5157
6142
|
});
|
|
5158
6143
|
function isSafeRepoRelPath(p) {
|
|
5159
6144
|
if (p.length === 0)
|
|
@@ -5162,7 +6147,7 @@ function isSafeRepoRelPath(p) {
|
|
|
5162
6147
|
return false;
|
|
5163
6148
|
return p.split(/[\\/]/).every((seg) => seg !== ".." && seg !== "");
|
|
5164
6149
|
}
|
|
5165
|
-
var SafeRepoRelPath =
|
|
6150
|
+
var SafeRepoRelPath = z4.string().refine(isSafeRepoRelPath, {
|
|
5166
6151
|
message: "must be a repo-root-relative path with no `..` segment or absolute root"
|
|
5167
6152
|
});
|
|
5168
6153
|
var CANONICAL_HOOK_BLOCK_PREFIXES = [".git/", ".husky/", ".vinaya/hooks/", ".claude/hooks/"];
|
|
@@ -5172,22 +6157,22 @@ function isCanonicalHookBlockPath(p) {
|
|
|
5172
6157
|
var ManagedHookBlockPath = SafeRepoRelPath.refine(isCanonicalHookBlockPath, {
|
|
5173
6158
|
message: `must start with one of ${CANONICAL_HOOK_BLOCK_PREFIXES.join(", ")} (byte-exact, case-sensitive)`
|
|
5174
6159
|
});
|
|
5175
|
-
var ManagedBlockRecordSchema =
|
|
6160
|
+
var ManagedBlockRecordSchema = z4.object({
|
|
5176
6161
|
path: ManagedHookBlockPath,
|
|
5177
|
-
marker:
|
|
5178
|
-
comment:
|
|
6162
|
+
marker: z4.string(),
|
|
6163
|
+
comment: z4.enum(["hash", "html"])
|
|
5179
6164
|
});
|
|
5180
|
-
var ManagedManifestSchema =
|
|
5181
|
-
version:
|
|
5182
|
-
files:
|
|
5183
|
-
blocks:
|
|
5184
|
-
labels:
|
|
5185
|
-
agents:
|
|
6165
|
+
var ManagedManifestSchema = z4.object({
|
|
6166
|
+
version: z4.number().int().positive(),
|
|
6167
|
+
files: z4.array(SafeRepoRelPath),
|
|
6168
|
+
blocks: z4.array(ManagedBlockRecordSchema),
|
|
6169
|
+
labels: z4.array(z4.string()),
|
|
6170
|
+
agents: z4.array(z4.enum(AGENT_VENDORS)).optional()
|
|
5186
6171
|
});
|
|
5187
|
-
var ProjectEntrySchema =
|
|
5188
|
-
name:
|
|
5189
|
-
description:
|
|
5190
|
-
path:
|
|
6172
|
+
var ProjectEntrySchema = z4.object({
|
|
6173
|
+
name: z4.string().min(1),
|
|
6174
|
+
description: z4.string().min(1).optional(),
|
|
6175
|
+
path: z4.string().min(1).optional()
|
|
5191
6176
|
});
|
|
5192
6177
|
function parseTokensCollectDeclaration(value) {
|
|
5193
6178
|
const m = value.trim().match(/^(\S+)\s+(\S+)$/);
|
|
@@ -5198,34 +6183,62 @@ function parseTokensCollectDeclaration(value) {
|
|
|
5198
6183
|
return null;
|
|
5199
6184
|
return { interpreter, script };
|
|
5200
6185
|
}
|
|
5201
|
-
var VinayaConfigSchema =
|
|
5202
|
-
rings:
|
|
5203
|
-
ring1_forgeWriteInterception:
|
|
5204
|
-
ring2_asyncAudits:
|
|
6186
|
+
var VinayaConfigSchema = z4.object({
|
|
6187
|
+
rings: z4.object({
|
|
6188
|
+
ring1_forgeWriteInterception: z4.boolean(),
|
|
6189
|
+
ring2_asyncAudits: z4.boolean()
|
|
5205
6190
|
}).optional(),
|
|
5206
|
-
checks:
|
|
5207
|
-
roles:
|
|
6191
|
+
checks: z4.record(z4.string(), CheckEntrySchema).optional(),
|
|
6192
|
+
roles: z4.record(z4.string(), RoleEntrySchema).optional(),
|
|
5208
6193
|
briefSchema: BriefSchemaSchema.optional(),
|
|
5209
6194
|
managed: ManagedManifestSchema.optional(),
|
|
5210
|
-
principals:
|
|
5211
|
-
releaseActor:
|
|
5212
|
-
ci:
|
|
5213
|
-
tokens:
|
|
5214
|
-
collect:
|
|
6195
|
+
principals: z4.array(z4.string()).min(1).optional(),
|
|
6196
|
+
releaseActor: z4.string().min(1).optional(),
|
|
6197
|
+
ci: z4.object({ setup: z4.string().min(1) }).optional(),
|
|
6198
|
+
tokens: z4.object({
|
|
6199
|
+
collect: z4.string().min(1).refine((v) => parseTokensCollectDeclaration(v) !== null, {
|
|
5215
6200
|
message: 'tokens.collect must be exactly "<interpreter> <repo-relative-script-path>" — two whitespace-separated tokens, no flags, no shell syntax, no quoting'
|
|
5216
6201
|
})
|
|
5217
6202
|
}).optional(),
|
|
5218
|
-
blastRadius:
|
|
5219
|
-
proseGates:
|
|
5220
|
-
doctrineRoot:
|
|
5221
|
-
readerFacingPrefix:
|
|
5222
|
-
readerFacingSuffix:
|
|
5223
|
-
legacySlugDir:
|
|
6203
|
+
blastRadius: z4.object({ extraDomains: z4.array(z4.string()).optional() }).optional(),
|
|
6204
|
+
proseGates: z4.object({
|
|
6205
|
+
doctrineRoot: z4.string().min(1).optional(),
|
|
6206
|
+
readerFacingPrefix: z4.string().min(1).optional(),
|
|
6207
|
+
readerFacingSuffix: z4.string().min(1).optional(),
|
|
6208
|
+
legacySlugDir: z4.string().min(1).optional()
|
|
6209
|
+
}).optional(),
|
|
6210
|
+
projects: z4.array(ProjectEntrySchema).optional(),
|
|
6211
|
+
dispatch: z4.object({
|
|
6212
|
+
timeoutMs: z4.number().int().positive().optional(),
|
|
6213
|
+
killGraceMs: z4.number().int().positive().optional(),
|
|
6214
|
+
agent: z4.enum(["claude", "codex", "gemini"]).optional()
|
|
6215
|
+
}).optional(),
|
|
6216
|
+
reviewPolicy: z4.object({
|
|
6217
|
+
codeReviewThreshold: z4.string().min(1).optional(),
|
|
6218
|
+
securityThreshold: z4.string().min(1).optional(),
|
|
6219
|
+
maxRounds: z4.number().optional()
|
|
6220
|
+
}).optional(),
|
|
6221
|
+
prePush: z4.object({
|
|
6222
|
+
alwaysRun: z4.array(z4.string()).optional()
|
|
6223
|
+
}).optional(),
|
|
6224
|
+
report: z4.object({
|
|
6225
|
+
commandTimeoutMs: z4.number().int().positive().optional()
|
|
6226
|
+
}).superRefine((report, ctx) => {
|
|
6227
|
+
const commandTimeoutMs = report.commandTimeoutMs;
|
|
6228
|
+
if (commandTimeoutMs !== undefined && commandTimeoutMs > MAX_REPORT_COMMAND_TIMEOUT_MS) {
|
|
6229
|
+
ctx.addIssue({
|
|
6230
|
+
code: z4.ZodIssueCode.custom,
|
|
6231
|
+
path: ["commandTimeoutMs"],
|
|
6232
|
+
message: "must be at most 3600000 (1 hour)"
|
|
6233
|
+
});
|
|
6234
|
+
}
|
|
5224
6235
|
}).optional(),
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
6236
|
+
logPublish: z4.object({
|
|
6237
|
+
issue: z4.number().int().positive().optional(),
|
|
6238
|
+
pr: z4.number().int().positive().optional(),
|
|
6239
|
+
maxChunksPerFlush: z4.number().int().positive().optional()
|
|
6240
|
+
}).refine((v) => !(v.issue !== undefined && v.pr !== undefined), {
|
|
6241
|
+
message: "logPublish: set at most one of issue/pr, not both"
|
|
5229
6242
|
}).optional()
|
|
5230
6243
|
});
|
|
5231
6244
|
var GLOBAL_VINAYA_HOME = join(homedir(), ".vinaya");
|
|
@@ -5300,6 +6313,28 @@ function resolvePrincipalAllowlist(config) {
|
|
|
5300
6313
|
function resolveReleaseActor(config) {
|
|
5301
6314
|
return config?.releaseActor ?? DEFAULT_RELEASE_ACTOR;
|
|
5302
6315
|
}
|
|
6316
|
+
function resolveReviewPolicy(config) {
|
|
6317
|
+
const raw = config?.reviewPolicy;
|
|
6318
|
+
if (!raw)
|
|
6319
|
+
return DEFAULT_REVIEW_POLICY;
|
|
6320
|
+
const codeReviewThreshold = raw.codeReviewThreshold ?? DEFAULT_REVIEW_POLICY.codeReviewThreshold;
|
|
6321
|
+
if (!isKnownSeverity(CODE_REVIEW_SEVERITY_ORDER, codeReviewThreshold)) {
|
|
6322
|
+
throw new Error(`vinaya.config.json: reviewPolicy.codeReviewThreshold "${codeReviewThreshold}" is not one of ${CODE_REVIEW_SEVERITY_ORDER.join(" > ")} — fix the config, this never falls back to a default.`);
|
|
6323
|
+
}
|
|
6324
|
+
const securityThreshold = raw.securityThreshold ?? DEFAULT_REVIEW_POLICY.securityThreshold;
|
|
6325
|
+
if (!isKnownSeverity(SECURITY_SEVERITY_ORDER, securityThreshold)) {
|
|
6326
|
+
throw new Error(`vinaya.config.json: reviewPolicy.securityThreshold "${securityThreshold}" is not one of ${SECURITY_SEVERITY_ORDER.join(" > ")} — fix the config, this never falls back to a default.`);
|
|
6327
|
+
}
|
|
6328
|
+
const maxRounds = raw.maxRounds ?? DEFAULT_REVIEW_POLICY.maxRounds;
|
|
6329
|
+
if (!Number.isInteger(maxRounds) || maxRounds < 1) {
|
|
6330
|
+
throw new Error(`vinaya.config.json: reviewPolicy.maxRounds "${maxRounds}" is not a positive integer — fix the config, this never falls back to a default.`);
|
|
6331
|
+
}
|
|
6332
|
+
return {
|
|
6333
|
+
codeReviewThreshold,
|
|
6334
|
+
securityThreshold,
|
|
6335
|
+
maxRounds
|
|
6336
|
+
};
|
|
6337
|
+
}
|
|
5303
6338
|
function trustAnchorRepo() {
|
|
5304
6339
|
const wellFormed = (slug) => /^[^/\s]+\/[^/\s]+$/.test(slug) ? slug : null;
|
|
5305
6340
|
const fromRunner = process.env.GITHUB_REPOSITORY?.trim();
|
|
@@ -5384,7 +6419,8 @@ var CHECK_NAME = "brief-shape";
|
|
|
5384
6419
|
function fetchIssueComments(issueNumber) {
|
|
5385
6420
|
const out = execFileSync3("gh", ["issue", "view", String(issueNumber), "--json", "comments"], {
|
|
5386
6421
|
encoding: "utf8",
|
|
5387
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
6422
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6423
|
+
maxBuffer: 32 * 1024 * 1024
|
|
5388
6424
|
});
|
|
5389
6425
|
return JSON.parse(out);
|
|
5390
6426
|
}
|
|
@@ -5429,14 +6465,14 @@ function readJson(path) {
|
|
|
5429
6465
|
return {};
|
|
5430
6466
|
}
|
|
5431
6467
|
}
|
|
5432
|
-
function
|
|
6468
|
+
function readManifest2(dir) {
|
|
5433
6469
|
const manifest = readJson(`${dir}/package.json`);
|
|
5434
6470
|
return Object.keys(manifest).length === 0 ? null : manifest;
|
|
5435
6471
|
}
|
|
5436
6472
|
function buildConsumersOf2() {
|
|
5437
6473
|
const root = readJson("package.json");
|
|
5438
6474
|
const workspaces = Array.isArray(root.workspaces) ? root.workspaces : [];
|
|
5439
|
-
return buildConsumersOf(workspaces, listDirs,
|
|
6475
|
+
return buildConsumersOf(workspaces, listDirs, readManifest2);
|
|
5440
6476
|
}
|
|
5441
6477
|
function fetchIssueBody(issueNumber) {
|
|
5442
6478
|
return execFileSync3("gh", ["issue", "view", String(issueNumber), "--json", "body", "--jq", ".body"], {
|