@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
|
@@ -1646,6 +1646,52 @@ var systemEnv3 = {
|
|
|
1646
1646
|
...process.env,
|
|
1647
1647
|
PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
|
|
1648
1648
|
};
|
|
1649
|
+
var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
|
|
1650
|
+
var cached;
|
|
1651
|
+
var inflight;
|
|
1652
|
+
async function resolveRepo(exec = defaultExec) {
|
|
1653
|
+
if (cached !== undefined)
|
|
1654
|
+
return cached;
|
|
1655
|
+
const fromEnv = process.env.AEG_REPO;
|
|
1656
|
+
if (fromEnv) {
|
|
1657
|
+
const parsed = parseOwnerRepo(fromEnv);
|
|
1658
|
+
if (parsed) {
|
|
1659
|
+
cached = parsed;
|
|
1660
|
+
return cached;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (inflight)
|
|
1664
|
+
return inflight;
|
|
1665
|
+
inflight = (async () => {
|
|
1666
|
+
try {
|
|
1667
|
+
const { stdout } = await exec();
|
|
1668
|
+
cached = parseGitRemoteUrl(stdout.trim());
|
|
1669
|
+
return cached;
|
|
1670
|
+
} catch (err) {
|
|
1671
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1672
|
+
console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
|
|
1673
|
+
return null;
|
|
1674
|
+
} finally {
|
|
1675
|
+
inflight = undefined;
|
|
1676
|
+
}
|
|
1677
|
+
})();
|
|
1678
|
+
return inflight;
|
|
1679
|
+
}
|
|
1680
|
+
function parseGitRemoteUrl(url) {
|
|
1681
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1682
|
+
if (ssh?.[1] && ssh[2])
|
|
1683
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
1684
|
+
const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
1685
|
+
if (https?.[1] && https[2])
|
|
1686
|
+
return { owner: https[1], repo: https[2] };
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
function parseOwnerRepo(value) {
|
|
1690
|
+
const match = value.match(/^([^/]+)\/(.+)$/);
|
|
1691
|
+
if (!match?.[1] || !match[2])
|
|
1692
|
+
return null;
|
|
1693
|
+
return { owner: match[1], repo: match[2] };
|
|
1694
|
+
}
|
|
1649
1695
|
// ../../packages/aeg-core/src/anchored-region.ts
|
|
1650
1696
|
function anchoredRegionBounds(body, field) {
|
|
1651
1697
|
const masked = maskCode(body);
|
|
@@ -1956,6 +2002,9 @@ function parseInlineFieldList(section) {
|
|
|
1956
2002
|
var HEAD_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged head:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1957
2003
|
var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1958
2004
|
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
2005
|
+
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2006
|
+
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2007
|
+
var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1959
2008
|
function firstFiveLines(comment) {
|
|
1960
2009
|
return comment.split(`
|
|
1961
2010
|
`).slice(0, 5).join(`
|
|
@@ -1978,6 +2027,35 @@ function extractRulingOrdinal(comment) {
|
|
|
1978
2027
|
const m = firstSevenLines(comment).match(RULING_ORDINAL_PATTERN);
|
|
1979
2028
|
return m ? Number.parseInt(m[1], 10) : null;
|
|
1980
2029
|
}
|
|
2030
|
+
function firstElevenLines(comment) {
|
|
2031
|
+
return comment.split(`
|
|
2032
|
+
`).slice(0, 11).join(`
|
|
2033
|
+
`);
|
|
2034
|
+
}
|
|
2035
|
+
function extractBriefHash(comment) {
|
|
2036
|
+
const m = firstElevenLines(comment).match(BRIEF_HASH_PATTERN);
|
|
2037
|
+
return m ? m[1].toLowerCase() : null;
|
|
2038
|
+
}
|
|
2039
|
+
function extractPolicyDigest(comment) {
|
|
2040
|
+
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
2041
|
+
return m ? m[1].toLowerCase() : null;
|
|
2042
|
+
}
|
|
2043
|
+
function firstThirteenLines(comment) {
|
|
2044
|
+
return comment.split(`
|
|
2045
|
+
`).slice(0, 13).join(`
|
|
2046
|
+
`);
|
|
2047
|
+
}
|
|
2048
|
+
function extractBaseSha(comment) {
|
|
2049
|
+
const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
|
|
2050
|
+
return m ? m[1].toLowerCase() : null;
|
|
2051
|
+
}
|
|
2052
|
+
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
2053
|
+
function extractFindingSeverities(comment) {
|
|
2054
|
+
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
2055
|
+
severity: m[1],
|
|
2056
|
+
location: m[2]
|
|
2057
|
+
}));
|
|
2058
|
+
}
|
|
1981
2059
|
function extractVerdict(comments, valuePattern, missingLabel) {
|
|
1982
2060
|
const candidates = comments.filter((c) => valuePattern.test(c));
|
|
1983
2061
|
if (candidates.length === 0) {
|
|
@@ -1986,6 +2064,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1986
2064
|
headSha: null,
|
|
1987
2065
|
objectivesVersion: null,
|
|
1988
2066
|
rulingOrdinal: null,
|
|
2067
|
+
briefHash: null,
|
|
2068
|
+
policyDigest: null,
|
|
2069
|
+
baseSha: null,
|
|
2070
|
+
findingSeverities: [],
|
|
1989
2071
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
1990
2072
|
};
|
|
1991
2073
|
}
|
|
@@ -1997,6 +2079,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1997
2079
|
headSha: null,
|
|
1998
2080
|
objectivesVersion: null,
|
|
1999
2081
|
rulingOrdinal: null,
|
|
2082
|
+
briefHash: null,
|
|
2083
|
+
policyDigest: null,
|
|
2084
|
+
baseSha: null,
|
|
2085
|
+
findingSeverities: [],
|
|
2000
2086
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
2001
2087
|
};
|
|
2002
2088
|
}
|
|
@@ -2005,6 +2091,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2005
2091
|
headSha: extractHeadSha(latest),
|
|
2006
2092
|
objectivesVersion: extractObjectivesVersion(latest),
|
|
2007
2093
|
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2094
|
+
briefHash: extractBriefHash(latest),
|
|
2095
|
+
policyDigest: extractPolicyDigest(latest),
|
|
2096
|
+
baseSha: extractBaseSha(latest),
|
|
2097
|
+
findingSeverities: extractFindingSeverities(latest),
|
|
2008
2098
|
danglingNote: null
|
|
2009
2099
|
};
|
|
2010
2100
|
}
|
|
@@ -2340,6 +2430,53 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
|
|
|
2340
2430
|
}
|
|
2341
2431
|
return out;
|
|
2342
2432
|
}
|
|
2433
|
+
// ../../packages/aeg-core/src/review-policy.ts
|
|
2434
|
+
var CODE_REVIEW_SEVERITY_ORDER = ["BLOCKER", "MAJOR", "MINOR"];
|
|
2435
|
+
var SECURITY_SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW"];
|
|
2436
|
+
var DEFAULT_MAX_ROUNDS = 3;
|
|
2437
|
+
var DEFAULT_REVIEW_POLICY = {
|
|
2438
|
+
codeReviewThreshold: "BLOCKER",
|
|
2439
|
+
securityThreshold: "HIGH",
|
|
2440
|
+
maxRounds: DEFAULT_MAX_ROUNDS
|
|
2441
|
+
};
|
|
2442
|
+
var FILE_SHAPED_LOCATION = /\.[a-zA-Z0-9]{1,10}(:\d+)?\s*$/;
|
|
2443
|
+
var PROSE_LOCATION_PATTERNS = [/\bpr\s*body\b/i, /\bcomment\b/i];
|
|
2444
|
+
var ROLE_FILE_LOCATION = /(^|\/)aeg-root\/roles\//i;
|
|
2445
|
+
function isProseLocation(location) {
|
|
2446
|
+
if (ROLE_FILE_LOCATION.test(location))
|
|
2447
|
+
return true;
|
|
2448
|
+
if (FILE_SHAPED_LOCATION.test(location))
|
|
2449
|
+
return false;
|
|
2450
|
+
return PROSE_LOCATION_PATTERNS.some((pattern) => pattern.test(location));
|
|
2451
|
+
}
|
|
2452
|
+
var PROSE_CAP_SEVERITY = "MINOR";
|
|
2453
|
+
function blockingSeverities(scale, threshold) {
|
|
2454
|
+
const idx = scale.indexOf(threshold);
|
|
2455
|
+
if (idx === -1) {
|
|
2456
|
+
throw new Error(`blockingSeverities: threshold "${threshold}" is not one of ${scale.join(" > ")}`);
|
|
2457
|
+
}
|
|
2458
|
+
return scale.slice(0, idx + 1);
|
|
2459
|
+
}
|
|
2460
|
+
function evaluateReviewFindings(findings, scale, threshold) {
|
|
2461
|
+
const blocking = new Set(blockingSeverities(scale, threshold));
|
|
2462
|
+
const blockingFindings = findings.filter((f) => {
|
|
2463
|
+
if (!scale.includes(f.severity)) {
|
|
2464
|
+
throw new Error(`evaluateReviewFindings: severity "${f.severity}" is not one of ${scale.join(" > ")}`);
|
|
2465
|
+
}
|
|
2466
|
+
const effectiveSeverity = f.location !== undefined && isProseLocation(f.location) ? PROSE_CAP_SEVERITY : f.severity;
|
|
2467
|
+
return blocking.has(effectiveSeverity);
|
|
2468
|
+
});
|
|
2469
|
+
return { outcome: blockingFindings.length > 0 ? "blocked" : "clean", blockingFindings };
|
|
2470
|
+
}
|
|
2471
|
+
function evaluateCodeReview(findings, policy) {
|
|
2472
|
+
return evaluateReviewFindings(findings, CODE_REVIEW_SEVERITY_ORDER, policy.codeReviewThreshold);
|
|
2473
|
+
}
|
|
2474
|
+
function evaluateSecurityReview(findings, policy) {
|
|
2475
|
+
return evaluateReviewFindings(findings, SECURITY_SEVERITY_ORDER, policy.securityThreshold);
|
|
2476
|
+
}
|
|
2477
|
+
function isKnownSeverity(scale, value) {
|
|
2478
|
+
return scale.includes(value);
|
|
2479
|
+
}
|
|
2343
2480
|
// ../../packages/aeg-core/src/pr-tier.ts
|
|
2344
2481
|
var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
|
|
2345
2482
|
function readTierFromPrBody(prBody) {
|
|
@@ -2710,7 +2847,7 @@ function checkForField(prBody) {
|
|
|
2710
2847
|
]
|
|
2711
2848
|
};
|
|
2712
2849
|
}
|
|
2713
|
-
function
|
|
2850
|
+
function checkClosesNPresence(prBody) {
|
|
2714
2851
|
const closesPattern = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s{0,8}:?\s{0,8}#\d+/i;
|
|
2715
2852
|
if (closesPattern.test(stripCode(prBody))) {
|
|
2716
2853
|
return { status: "pass", errors: [] };
|
|
@@ -2742,10 +2879,22 @@ var COMMIT_TYPES = [
|
|
|
2742
2879
|
"Test"
|
|
2743
2880
|
];
|
|
2744
2881
|
var COMMIT_TYPE_STYLE = new RegExp(`^(${COMMIT_TYPES.join("|")})(\\([a-z0-9-]+\\))?: \\S`);
|
|
2882
|
+
function checkForgeTitle(title) {
|
|
2883
|
+
const taskStyle = /^\[[a-z0-9._-]+\] \S+ — \S/;
|
|
2884
|
+
if (COMMIT_TYPE_STYLE.test(title) || taskStyle.test(title))
|
|
2885
|
+
return { status: "pass", errors: [] };
|
|
2886
|
+
return {
|
|
2887
|
+
status: "fail",
|
|
2888
|
+
errors: [
|
|
2889
|
+
`brief-validation title: "${title}" matches neither title grammar — expected \`Type: description\` / \`Type(scope): description\` (commitlint types + Plan) or \`[tranche] id — description\` (task form).`
|
|
2890
|
+
]
|
|
2891
|
+
};
|
|
2892
|
+
}
|
|
2745
2893
|
var BRIEF_SHAPE_MARKERS = [checkSurfaceMap, checkDocUpdateList, checkStopConditions, checkAutonomyClause];
|
|
2746
2894
|
var TASK_BRANCH_PATTERN = /^task\/[^/]+\/[^/]+$/;
|
|
2895
|
+
var TASK_ISSUE_BRANCH_PATTERN = /^task\/issue-\d+$/;
|
|
2747
2896
|
function isTaskBranch(branch) {
|
|
2748
|
-
return TASK_BRANCH_PATTERN.test(branch);
|
|
2897
|
+
return TASK_BRANCH_PATTERN.test(branch) || TASK_ISSUE_BRANCH_PATTERN.test(branch);
|
|
2749
2898
|
}
|
|
2750
2899
|
function isBriefShaped(prBody) {
|
|
2751
2900
|
const stripped = stripCode(prBody);
|
|
@@ -2867,8 +3016,9 @@ function packagesNamedIn(text) {
|
|
|
2867
3016
|
}
|
|
2868
3017
|
function hasTestPathForConsumer(text, consumerDir) {
|
|
2869
3018
|
const escaped = consumerDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2870
|
-
const
|
|
2871
|
-
|
|
3019
|
+
const filePathRe = new RegExp(`${escaped}\\/[\\w./-]*\\.test\\.[A-Za-z0-9]+`);
|
|
3020
|
+
const testDirRe = new RegExp(`${escaped}\\/(?:[\\w-]+\\/)*(?:tests|specs)(?:\\/|\\b)`);
|
|
3021
|
+
return filePathRe.test(text) || testDirRe.test(text);
|
|
2872
3022
|
}
|
|
2873
3023
|
function checkConsumerTests(prBody, consumersOf) {
|
|
2874
3024
|
const section4 = extractNumberedSection(prBody, 4);
|
|
@@ -2972,7 +3122,7 @@ function checkBriefSections(prBody, readTier, options = {}) {
|
|
|
2972
3122
|
checkConsumerTests(prBody, consumersOf),
|
|
2973
3123
|
checkDefeatCases(prBody),
|
|
2974
3124
|
...issueObjectives !== undefined ? [checkObjectivesCopy(prBody, issueObjectives), checkObjectivesCoverage(prBody)] : [],
|
|
2975
|
-
...requireClosesN ? [
|
|
3125
|
+
...requireClosesN ? [checkClosesNPresence(prBody)] : []
|
|
2976
3126
|
];
|
|
2977
3127
|
return { errors: results.flatMap((r) => r.errors) };
|
|
2978
3128
|
}
|
|
@@ -3262,6 +3412,28 @@ function topLevelSectionText(body, headingName) {
|
|
|
3262
3412
|
const next = /^##[ \t]/m.exec(afterHeading);
|
|
3263
3413
|
return next ? afterHeading.slice(0, next.index) : afterHeading;
|
|
3264
3414
|
}
|
|
3415
|
+
function partHasBacktickedPath(text) {
|
|
3416
|
+
let i = 0;
|
|
3417
|
+
while (i < text.length) {
|
|
3418
|
+
const start = text.indexOf("`", i);
|
|
3419
|
+
if (start === -1)
|
|
3420
|
+
return false;
|
|
3421
|
+
const end = text.indexOf("`", start + 1);
|
|
3422
|
+
if (end === -1)
|
|
3423
|
+
return false;
|
|
3424
|
+
if (text.slice(start + 1, end).includes("/"))
|
|
3425
|
+
return true;
|
|
3426
|
+
i = end + 1;
|
|
3427
|
+
}
|
|
3428
|
+
return false;
|
|
3429
|
+
}
|
|
3430
|
+
var PART_MIN_WORDS_OUTSIDE_BACKTICKS = 3;
|
|
3431
|
+
function stripPartBackticks(text) {
|
|
3432
|
+
return text.replace(/`[^`\n]*`/g, " ");
|
|
3433
|
+
}
|
|
3434
|
+
function partWordCount(text) {
|
|
3435
|
+
return text.split(/\s+/).filter((w) => /[a-z]/i.test(w)).length;
|
|
3436
|
+
}
|
|
3265
3437
|
function looksLikeFilePath(entry2) {
|
|
3266
3438
|
const stripped = entry2.replace(/\/\*\*?$/, "");
|
|
3267
3439
|
const lastSegment = stripped.split("/").pop() ?? stripped;
|
|
@@ -3302,6 +3474,18 @@ function globCoversPath(glob, path) {
|
|
|
3302
3474
|
const p = path.replace(/\/+$/, "");
|
|
3303
3475
|
return g === p || g.startsWith(`${p}/`) || p.startsWith(`${g}/`);
|
|
3304
3476
|
}
|
|
3477
|
+
function checkSurfaceGlobsResolve(body, resolvesToFile) {
|
|
3478
|
+
const surface = parseIssueSurface(body);
|
|
3479
|
+
if (!surface.ok)
|
|
3480
|
+
return { status: "pass", errors: [] };
|
|
3481
|
+
const errors = [];
|
|
3482
|
+
for (const glob of surface.value.in) {
|
|
3483
|
+
if (!resolvesToFile(glob)) {
|
|
3484
|
+
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.`);
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3488
|
+
}
|
|
3305
3489
|
function checkSurfaceScope(changedFiles, outGlobs) {
|
|
3306
3490
|
if (outGlobs.length === 0)
|
|
3307
3491
|
return { ok: true };
|
|
@@ -3313,9 +3497,77 @@ function checkSurfaceScope(changedFiles, outGlobs) {
|
|
|
3313
3497
|
}
|
|
3314
3498
|
return violations.length > 0 ? { ok: false, violations } : { ok: true };
|
|
3315
3499
|
}
|
|
3500
|
+
var ISSUE_PART_LINE_RE = /^Part\s+(\d+)\s*\(([^)]*)\)\s*[-—–]\s*(.*)$/i;
|
|
3501
|
+
function parseIssueParts(body) {
|
|
3502
|
+
const section = topLevelSectionText(body, "Parts");
|
|
3503
|
+
if (section === null)
|
|
3504
|
+
return { ok: false, errors: ["no `## Parts` heading found in the body."] };
|
|
3505
|
+
const lines = section.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
|
|
3506
|
+
const parts = [];
|
|
3507
|
+
const errors = [];
|
|
3508
|
+
for (const line of lines) {
|
|
3509
|
+
const m = ISSUE_PART_LINE_RE.exec(line);
|
|
3510
|
+
if (!m) {
|
|
3511
|
+
errors.push(`"${line}" is not a well-formed Parts line — expected \`Part <n> (<refs>) — <outcome>\`.`);
|
|
3512
|
+
continue;
|
|
3513
|
+
}
|
|
3514
|
+
const n = Number.parseInt(m[1], 10);
|
|
3515
|
+
const refs = m[2];
|
|
3516
|
+
const text = m[3].trim();
|
|
3517
|
+
if (text.length === 0) {
|
|
3518
|
+
errors.push(`Part ${n} has no outcome text after the dash — every Part states one observable outcome.`);
|
|
3519
|
+
continue;
|
|
3520
|
+
}
|
|
3521
|
+
if (partHasBacktickedPath(text) && partWordCount(stripPartBackticks(text)) < PART_MIN_WORDS_OUTSIDE_BACKTICKS) {
|
|
3522
|
+
errors.push(`Part ${n} is little more than a file path — a Part names an outcome and symbols, never a bare path.`);
|
|
3523
|
+
continue;
|
|
3524
|
+
}
|
|
3525
|
+
const objectiveIds = [...refs.matchAll(/O(\d+)/g)].map((r) => Number.parseInt(r[1], 10));
|
|
3526
|
+
parts.push({ n, objectiveIds, text });
|
|
3527
|
+
}
|
|
3528
|
+
if (parts.length === 0) {
|
|
3529
|
+
errors.push("the `## Parts` section has no well-formed `Part <n> (<refs>) — <outcome>` lines.");
|
|
3530
|
+
}
|
|
3531
|
+
if (errors.length > 0)
|
|
3532
|
+
return { ok: false, errors };
|
|
3533
|
+
return { ok: true, value: parts };
|
|
3534
|
+
}
|
|
3535
|
+
function checkPartsCiteDefinedObjectives(body) {
|
|
3536
|
+
const parts = parseIssueParts(body);
|
|
3537
|
+
const objectives = objectivesOf(body);
|
|
3538
|
+
if (!parts.ok || !objectives.ok)
|
|
3539
|
+
return { status: "pass", errors: [] };
|
|
3540
|
+
const definedIds = new Set(objectives.objectives.map((o) => Number.parseInt(o.id.slice(1), 10)));
|
|
3541
|
+
const errors = [];
|
|
3542
|
+
for (const part of parts.value) {
|
|
3543
|
+
for (const objectiveId of part.objectiveIds) {
|
|
3544
|
+
if (!definedIds.has(objectiveId)) {
|
|
3545
|
+
errors.push(`issue-validation Parts: Part ${part.n} cites O${objectiveId}, which the Issue's own \`## Objectives\` section does not define.`);
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3550
|
+
}
|
|
3316
3551
|
function isTaskIssueLabelSet(labels) {
|
|
3317
3552
|
return hasLabel("tranche", labels);
|
|
3318
3553
|
}
|
|
3554
|
+
function checkTrancheLabelPresence(_body, _labels) {
|
|
3555
|
+
return { status: "pass", errors: [] };
|
|
3556
|
+
}
|
|
3557
|
+
function checkMilestoneAttach(labels, currentMilestoneTitle, resolvedMilestoneTitle) {
|
|
3558
|
+
if (!isTaskIssueLabelSet(labels))
|
|
3559
|
+
return { status: "pass", errors: [] };
|
|
3560
|
+
if (resolvedMilestoneTitle === null)
|
|
3561
|
+
return { status: "pass", errors: [] };
|
|
3562
|
+
if (currentMilestoneTitle === resolvedMilestoneTitle)
|
|
3563
|
+
return { status: "pass", errors: [] };
|
|
3564
|
+
return {
|
|
3565
|
+
status: "fail",
|
|
3566
|
+
errors: [
|
|
3567
|
+
`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}".`
|
|
3568
|
+
]
|
|
3569
|
+
};
|
|
3570
|
+
}
|
|
3319
3571
|
var TYPE_LABEL_IDS = LABELS.filter((l) => l.category === "type").map((l) => l.id);
|
|
3320
3572
|
function isControlCodePoint(codePoint) {
|
|
3321
3573
|
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
@@ -3380,6 +3632,19 @@ function checkProjectsRegistered(body, _labels, registeredNames) {
|
|
|
3380
3632
|
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;
|
|
3381
3633
|
var DOC_PATH_RE_GLOBAL = new RegExp(DOC_PATH_RE.source, "gi");
|
|
3382
3634
|
|
|
3635
|
+
// ../../packages/aeg-core/src/task-branch-identity.ts
|
|
3636
|
+
var ISSUE_BRANCH_PATTERN = /^task\/issue-(\d+)$/;
|
|
3637
|
+
var TRANCHE_BRANCH_PATTERN = /^task\/([^/]+)\/([^/]+)$/;
|
|
3638
|
+
function parseTaskBranchIdentity(branch) {
|
|
3639
|
+
const issueMatch = ISSUE_BRANCH_PATTERN.exec(branch);
|
|
3640
|
+
if (issueMatch)
|
|
3641
|
+
return { kind: "issue", issueNumber: Number(issueMatch[1]) };
|
|
3642
|
+
const trancheMatch = TRANCHE_BRANCH_PATTERN.exec(branch);
|
|
3643
|
+
if (trancheMatch)
|
|
3644
|
+
return { kind: "tranche", tranche: trancheMatch[1], taskId: trancheMatch[2] };
|
|
3645
|
+
return null;
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3383
3648
|
// ../../packages/aeg-core/src/coherence-checks.ts
|
|
3384
3649
|
var COHERENCE_ENFORCED_FROM = "2026-07-01";
|
|
3385
3650
|
function isGrandfathered(isoDate) {
|
|
@@ -3400,6 +3665,7 @@ function checkA1(entries, principalAllowlist = PRINCIPAL_ALLOWLIST) {
|
|
|
3400
3665
|
if (handClosed)
|
|
3401
3666
|
continue;
|
|
3402
3667
|
failures.push({
|
|
3668
|
+
code: "closed-without-merge",
|
|
3403
3669
|
issue: e.task.issue,
|
|
3404
3670
|
tranche: e.trancheSlug,
|
|
3405
3671
|
task: e.task.id,
|
|
@@ -3424,6 +3690,7 @@ function checkA3(entries) {
|
|
|
3424
3690
|
continue;
|
|
3425
3691
|
if (e.facts.prState === "merged" && e.facts.issueState !== "closed") {
|
|
3426
3692
|
failures.push({
|
|
3693
|
+
code: "auto-close-misfire",
|
|
3427
3694
|
issue: e.task.issue,
|
|
3428
3695
|
tranche: e.trancheSlug,
|
|
3429
3696
|
task: e.task.id,
|
|
@@ -3448,6 +3715,7 @@ function checkT1(entries) {
|
|
|
3448
3715
|
continue;
|
|
3449
3716
|
if (e.facts === undefined) {
|
|
3450
3717
|
failures.push({
|
|
3718
|
+
code: "phantom-issue-ref",
|
|
3451
3719
|
issue: e.task.issue,
|
|
3452
3720
|
tranche: e.trancheSlug,
|
|
3453
3721
|
task: e.task.id,
|
|
@@ -3466,6 +3734,7 @@ function checkT2(openIssuesBySlug, topologyIssuesBySlug, ciTrancheSlug) {
|
|
|
3466
3734
|
for (const num of openNums) {
|
|
3467
3735
|
if (!topologySet.has(num)) {
|
|
3468
3736
|
failures.push({
|
|
3737
|
+
code: "orphan-task",
|
|
3469
3738
|
issue: num,
|
|
3470
3739
|
tranche: slug,
|
|
3471
3740
|
reason: `Issue #${num} is open and labeled ${trancheLabel(slug)} but does not appear in the topology file`
|
|
@@ -3500,6 +3769,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3500
3769
|
continue;
|
|
3501
3770
|
if (forgeUnavailableSlugs?.has(e.trancheSlug)) {
|
|
3502
3771
|
failures.push({
|
|
3772
|
+
code: "tbd-in-active-tranche",
|
|
3503
3773
|
issue: null,
|
|
3504
3774
|
tranche: e.trancheSlug,
|
|
3505
3775
|
task: e.task.id,
|
|
@@ -3509,6 +3779,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3509
3779
|
continue;
|
|
3510
3780
|
}
|
|
3511
3781
|
failures.push({
|
|
3782
|
+
code: "tbd-in-active-tranche",
|
|
3512
3783
|
issue: null,
|
|
3513
3784
|
tranche: e.trancheSlug,
|
|
3514
3785
|
task: e.task.id,
|
|
@@ -3541,6 +3812,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3541
3812
|
const sameIssue = depEntry.task.issue !== null && e.task.issue !== null && depEntry.task.issue === e.task.issue;
|
|
3542
3813
|
if (sameTask || sameIssue) {
|
|
3543
3814
|
failures.push({
|
|
3815
|
+
code: "d1-self-dependency",
|
|
3544
3816
|
issue: e.task.issue,
|
|
3545
3817
|
tranche: e.trancheSlug,
|
|
3546
3818
|
task: e.task.id,
|
|
@@ -3552,6 +3824,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3552
3824
|
const depClosed = depFacts?.issueState === "closed";
|
|
3553
3825
|
if (!depClosed) {
|
|
3554
3826
|
failures.push({
|
|
3827
|
+
code: "dispatched-on-unmet-deps",
|
|
3555
3828
|
issue: e.task.issue,
|
|
3556
3829
|
tranche: e.trancheSlug,
|
|
3557
3830
|
task: e.task.id,
|
|
@@ -3577,11 +3850,13 @@ function checkR1(issuesBySlug, grandfatheredIssues, registeredNames = []) {
|
|
|
3577
3850
|
const errors = [
|
|
3578
3851
|
...checkIssueRationale(issue.body).errors,
|
|
3579
3852
|
...checkProjectsRegistered(issue.body, issue.labels, registeredNames).errors,
|
|
3580
|
-
...checkIssueObjectives(issue.body, issue.number).errors
|
|
3853
|
+
...checkIssueObjectives(issue.body, issue.number).errors,
|
|
3854
|
+
...checkPartsCiteDefinedObjectives(issue.body).errors
|
|
3581
3855
|
];
|
|
3582
3856
|
if (errors.length === 0)
|
|
3583
3857
|
continue;
|
|
3584
3858
|
failures.push({
|
|
3859
|
+
code: "missing-rationale-field",
|
|
3585
3860
|
issue: issue.number,
|
|
3586
3861
|
tranche: slug,
|
|
3587
3862
|
reason: `Issue #${issue.number} fails the rationale gate: ${errors.join(" | ")}`,
|
|
@@ -3610,6 +3885,7 @@ function checkL1(files, entriesBySlug) {
|
|
|
3610
3885
|
const allClosed = withFacts.every((e) => e.facts?.issueState === "closed");
|
|
3611
3886
|
if (allClosed) {
|
|
3612
3887
|
failures.push({
|
|
3888
|
+
code: "archive-recommended",
|
|
3613
3889
|
tranche: f.slug,
|
|
3614
3890
|
reason: "Active tranche has no open task-Issues — consider archiving to completed/"
|
|
3615
3891
|
});
|
|
@@ -3641,27 +3917,38 @@ function extractClosesReferences(prBody) {
|
|
|
3641
3917
|
}
|
|
3642
3918
|
return referenced;
|
|
3643
3919
|
}
|
|
3644
|
-
function
|
|
3920
|
+
function checkClosesNTopology(branch, prBody, trancheFiles, taskIssueRefs) {
|
|
3645
3921
|
const referenced = extractClosesReferences(prBody);
|
|
3646
3922
|
if (taskIssueRefs) {
|
|
3647
3923
|
for (const n of referenced) {
|
|
3648
|
-
const
|
|
3649
|
-
if (!
|
|
3924
|
+
const ref2 = taskIssueRefs.get(n);
|
|
3925
|
+
if (!ref2)
|
|
3650
3926
|
continue;
|
|
3651
|
-
const expectedBranch = `task/${
|
|
3927
|
+
const expectedBranch = `task/${ref2.trancheSlug}/${ref2.taskId}`;
|
|
3652
3928
|
if (branch !== expectedBranch) {
|
|
3653
3929
|
return {
|
|
3654
3930
|
ok: false,
|
|
3655
|
-
message: `closes-n-reverse: branch "${branch}" closes #${n} (task ${
|
|
3931
|
+
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.`
|
|
3656
3932
|
};
|
|
3657
3933
|
}
|
|
3658
3934
|
}
|
|
3659
3935
|
}
|
|
3660
|
-
const
|
|
3661
|
-
if (!
|
|
3936
|
+
const ref = parseTaskBranchIdentity(branch);
|
|
3937
|
+
if (!ref)
|
|
3662
3938
|
return { ok: true };
|
|
3663
|
-
|
|
3664
|
-
|
|
3939
|
+
if (ref.kind === "issue") {
|
|
3940
|
+
const expectedIssue2 = ref.issueNumber;
|
|
3941
|
+
if (!referenced.has(expectedIssue2)) {
|
|
3942
|
+
return {
|
|
3943
|
+
ok: false,
|
|
3944
|
+
expectedIssue: expectedIssue2,
|
|
3945
|
+
message: `closes-n: PR body does not contain \`Closes #${expectedIssue2}\` (required for branch "${branch}"). Add it to the PR body Summary section.`
|
|
3946
|
+
};
|
|
3947
|
+
}
|
|
3948
|
+
return { ok: true, expectedIssue: expectedIssue2 };
|
|
3949
|
+
}
|
|
3950
|
+
const trancheSlug = ref.tranche;
|
|
3951
|
+
const taskId = ref.taskId;
|
|
3665
3952
|
const trancheFile = trancheFiles.find((f) => f.slug === trancheSlug);
|
|
3666
3953
|
if (!trancheFile) {
|
|
3667
3954
|
return {
|
|
@@ -3713,34 +4000,79 @@ function extractIssue(body) {
|
|
|
3713
4000
|
const issue = headerNums.length > 0 ? headerNums[0] : bodyNums[0];
|
|
3714
4001
|
return { issue, extraIssues: bodyNums.filter((n) => n !== issue), outsideHeader: headerNums.length === 0 };
|
|
3715
4002
|
}
|
|
3716
|
-
// ../../packages/aeg-core/src/review-
|
|
3717
|
-
|
|
3718
|
-
|
|
4003
|
+
// ../../packages/aeg-core/src/review-input-manifest.ts
|
|
4004
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
4005
|
+
function briefHash(brief) {
|
|
4006
|
+
return createHash4("sha256").update(`${brief}
|
|
4007
|
+
`).digest("hex");
|
|
4008
|
+
}
|
|
4009
|
+
function policyDigest(policy) {
|
|
4010
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
4011
|
+
codeReviewThreshold: policy.codeReviewThreshold,
|
|
4012
|
+
securityThreshold: policy.securityThreshold,
|
|
4013
|
+
maxRounds: policy.maxRounds
|
|
4014
|
+
})).digest("hex");
|
|
4015
|
+
}
|
|
4016
|
+
function isBoundToHead(echoed, headSha) {
|
|
4017
|
+
if (!echoed.headSha)
|
|
3719
4018
|
return false;
|
|
3720
|
-
return headSha.toLowerCase().startsWith(
|
|
4019
|
+
return headSha.toLowerCase().startsWith(echoed.headSha.toLowerCase());
|
|
3721
4020
|
}
|
|
3722
|
-
function isBoundByPatchIdentity(
|
|
3723
|
-
if (patchIdOf === undefined || !
|
|
4021
|
+
function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
4022
|
+
if (patchIdOf === undefined || !echoed.headSha)
|
|
3724
4023
|
return false;
|
|
3725
|
-
const judged = patchIdOf(
|
|
4024
|
+
const judged = patchIdOf(echoed.headSha);
|
|
3726
4025
|
const current = patchIdOf(headSha);
|
|
3727
4026
|
if (judged === null || current === null)
|
|
3728
4027
|
return false;
|
|
3729
4028
|
return judged === current;
|
|
3730
4029
|
}
|
|
3731
|
-
function
|
|
3732
|
-
|
|
4030
|
+
function isBoundToBase(echoed, currentBase) {
|
|
4031
|
+
if (currentBase === null)
|
|
4032
|
+
return true;
|
|
4033
|
+
if (!echoed.baseSha)
|
|
4034
|
+
return false;
|
|
4035
|
+
return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
|
|
3733
4036
|
}
|
|
3734
|
-
function isBoundToObjectives(
|
|
4037
|
+
function isBoundToObjectives(echoed, currentVersion) {
|
|
3735
4038
|
if (currentVersion === null)
|
|
3736
4039
|
return true;
|
|
3737
|
-
return
|
|
4040
|
+
return echoed.objectivesVersion === currentVersion;
|
|
3738
4041
|
}
|
|
3739
|
-
function isBoundToRulings(
|
|
3740
|
-
if (
|
|
4042
|
+
function isBoundToRulings(echoed, currentOrdinal) {
|
|
4043
|
+
if (echoed.rulingOrdinal === null)
|
|
3741
4044
|
return currentOrdinal === 0;
|
|
3742
|
-
return
|
|
4045
|
+
return echoed.rulingOrdinal === currentOrdinal;
|
|
3743
4046
|
}
|
|
4047
|
+
function isBoundToBriefHash(echoed, currentHash) {
|
|
4048
|
+
if (currentHash === null)
|
|
4049
|
+
return true;
|
|
4050
|
+
return echoed.briefHash === currentHash;
|
|
4051
|
+
}
|
|
4052
|
+
function isBoundToPolicy(echoed, currentDigest) {
|
|
4053
|
+
return echoed.policyDigest === currentDigest;
|
|
4054
|
+
}
|
|
4055
|
+
function compareManifest(echoed, current, patchIdOf) {
|
|
4056
|
+
const exactHead = isBoundToHead(echoed, current.headSha);
|
|
4057
|
+
const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
|
|
4058
|
+
const head = exactHead || patchHead;
|
|
4059
|
+
const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
|
|
4060
|
+
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
4061
|
+
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
4062
|
+
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
4063
|
+
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
4064
|
+
return {
|
|
4065
|
+
bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4066
|
+
head,
|
|
4067
|
+
base,
|
|
4068
|
+
briefHash: briefHashBound,
|
|
4069
|
+
objectivesVersion: objectivesVersion2,
|
|
4070
|
+
rulingOrdinal,
|
|
4071
|
+
policyDigest: policyDigestBound
|
|
4072
|
+
};
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
// ../../packages/aeg-core/src/review-gate.ts
|
|
3744
4076
|
function checkReviewGate(input) {
|
|
3745
4077
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
3746
4078
|
const waived = isWaiverLabelActorVerified({
|
|
@@ -3763,15 +4095,58 @@ function checkReviewGate(input) {
|
|
|
3763
4095
|
const verifiedBodies = verified.map((c) => c.body);
|
|
3764
4096
|
const codeReview = extractCodeReviewVerdict(verifiedBodies);
|
|
3765
4097
|
const security = extractSecurityReviewVerdict(verifiedBodies);
|
|
3766
|
-
const
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
4098
|
+
const policy = input.policy ?? DEFAULT_REVIEW_POLICY;
|
|
4099
|
+
let codeReviewPolicyEvaluation;
|
|
4100
|
+
let securityPolicyEvaluation;
|
|
4101
|
+
try {
|
|
4102
|
+
codeReviewPolicyEvaluation = evaluateCodeReview(codeReview.findingSeverities, policy);
|
|
4103
|
+
securityPolicyEvaluation = evaluateSecurityReview(security.findingSeverities, policy);
|
|
4104
|
+
} catch (err) {
|
|
4105
|
+
return {
|
|
4106
|
+
verdict: "fail",
|
|
4107
|
+
reason: `a verdict comment carries a finding severity this repository's policy does not recognize: ${err instanceof Error ? err.message : String(err)}`,
|
|
4108
|
+
waived: false
|
|
4109
|
+
};
|
|
4110
|
+
}
|
|
4111
|
+
const codeReviewTextClean = codeReview.value === "APPROVE";
|
|
4112
|
+
const securityTextClean = security.value === "PASS";
|
|
4113
|
+
const codeReviewPolicyClean = codeReviewPolicyEvaluation.outcome === "clean";
|
|
4114
|
+
const securityPolicyClean = securityPolicyEvaluation.outcome === "clean";
|
|
4115
|
+
const codeReviewClean = codeReviewTextClean && codeReviewPolicyClean;
|
|
4116
|
+
const securityClean = securityTextClean && securityPolicyClean;
|
|
4117
|
+
const currentManifest = {
|
|
4118
|
+
headSha: input.headSha,
|
|
4119
|
+
baseSha: input.baseSha ?? null,
|
|
4120
|
+
briefHash: input.briefHash ?? null,
|
|
4121
|
+
objectivesVersion: input.objectivesVersion,
|
|
4122
|
+
rulingOrdinal: input.rulingOrdinal,
|
|
4123
|
+
policyDigest: policyDigest(policy)
|
|
4124
|
+
};
|
|
4125
|
+
const codeReviewEchoed = {
|
|
4126
|
+
headSha: codeReview.headSha,
|
|
4127
|
+
baseSha: codeReview.baseSha,
|
|
4128
|
+
briefHash: codeReview.briefHash,
|
|
4129
|
+
objectivesVersion: codeReview.objectivesVersion,
|
|
4130
|
+
rulingOrdinal: codeReview.rulingOrdinal,
|
|
4131
|
+
policyDigest: codeReview.policyDigest
|
|
4132
|
+
};
|
|
4133
|
+
const securityEchoed = {
|
|
4134
|
+
headSha: security.headSha,
|
|
4135
|
+
baseSha: security.baseSha,
|
|
4136
|
+
briefHash: security.briefHash,
|
|
4137
|
+
objectivesVersion: security.objectivesVersion,
|
|
4138
|
+
rulingOrdinal: security.rulingOrdinal,
|
|
4139
|
+
policyDigest: security.policyDigest
|
|
4140
|
+
};
|
|
4141
|
+
const codeReviewBinding = compareManifest(codeReviewEchoed, currentManifest, input.patchIdOf);
|
|
4142
|
+
const securityBinding = compareManifest(securityEchoed, currentManifest, input.patchIdOf);
|
|
4143
|
+
const codeReviewBound = codeReviewBinding.head;
|
|
4144
|
+
const securityBound = securityBinding.head;
|
|
4145
|
+
const codeReviewObjectivesBound = codeReviewBinding.objectivesVersion;
|
|
4146
|
+
const securityObjectivesBound = securityBinding.objectivesVersion;
|
|
4147
|
+
const codeReviewRulingsBound = codeReviewBinding.rulingOrdinal;
|
|
4148
|
+
const securityRulingsBound = securityBinding.rulingOrdinal;
|
|
4149
|
+
if (codeReviewClean && codeReviewBinding.bound && securityClean && securityBinding.bound && mechanicalChecksClean) {
|
|
3775
4150
|
return {
|
|
3776
4151
|
verdict: "pass",
|
|
3777
4152
|
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.`,
|
|
@@ -3779,23 +4154,39 @@ function checkReviewGate(input) {
|
|
|
3779
4154
|
};
|
|
3780
4155
|
}
|
|
3781
4156
|
const problems = [];
|
|
3782
|
-
if (!
|
|
4157
|
+
if (!codeReviewTextClean) {
|
|
3783
4158
|
problems.push(`code-reviewer verdict is not a clean APPROVE (found: ${codeReview.value})`);
|
|
4159
|
+
} else if (!codeReviewPolicyClean) {
|
|
4160
|
+
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`);
|
|
3784
4161
|
} else if (!codeReviewBound) {
|
|
3785
4162
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4163
|
+
} else if (!codeReviewBinding.base) {
|
|
4164
|
+
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)`);
|
|
3786
4165
|
} else if (!codeReviewObjectivesBound) {
|
|
3787
4166
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
3788
4167
|
} else if (!codeReviewRulingsBound) {
|
|
3789
4168
|
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`);
|
|
4169
|
+
} else if (!codeReviewBinding.briefHash) {
|
|
4170
|
+
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"}`);
|
|
4171
|
+
} else if (!codeReviewBinding.policyDigest) {
|
|
4172
|
+
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}`);
|
|
3790
4173
|
}
|
|
3791
|
-
if (!
|
|
4174
|
+
if (!securityTextClean) {
|
|
3792
4175
|
problems.push(`security-review verdict is not a clean PASS (found: ${security.value})`);
|
|
4176
|
+
} else if (!securityPolicyClean) {
|
|
4177
|
+
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`);
|
|
3793
4178
|
} else if (!securityBound) {
|
|
3794
4179
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4180
|
+
} else if (!securityBinding.base) {
|
|
4181
|
+
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)`);
|
|
3795
4182
|
} else if (!securityObjectivesBound) {
|
|
3796
4183
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
3797
4184
|
} else if (!securityRulingsBound) {
|
|
3798
4185
|
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`);
|
|
4186
|
+
} else if (!securityBinding.briefHash) {
|
|
4187
|
+
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"}`);
|
|
4188
|
+
} else if (!securityBinding.policyDigest) {
|
|
4189
|
+
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}`);
|
|
3799
4190
|
}
|
|
3800
4191
|
if (!mechanicalChecksClean) {
|
|
3801
4192
|
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(", ")}`);
|
|
@@ -4487,42 +4878,45 @@ function checkDispatchReadiness(input) {
|
|
|
4487
4878
|
const { trancheSlug, task } = input;
|
|
4488
4879
|
const taskLabel = `task ${task.id} (tranche ${trancheSlug})`;
|
|
4489
4880
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
4490
|
-
const
|
|
4881
|
+
const blockerDetails = [];
|
|
4882
|
+
const push = (blockerClass, message) => {
|
|
4883
|
+
blockerDetails.push({ class: blockerClass, message });
|
|
4884
|
+
};
|
|
4491
4885
|
if (task.issue === null) {
|
|
4492
|
-
|
|
4886
|
+
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.`);
|
|
4493
4887
|
} else if (input.issue === null) {
|
|
4494
|
-
|
|
4888
|
+
push("issue-existence", `dispatch-gate issue-existence: ${taskLabel} names Issue #${task.issue}, but it does not resolve to a real GitHub Issue (phantom reference).`);
|
|
4495
4889
|
}
|
|
4496
4890
|
if (input.issue !== null && !input.issueRationalePass) {
|
|
4497
|
-
|
|
4891
|
+
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.`);
|
|
4498
4892
|
}
|
|
4499
4893
|
for (const dep of input.dependsOn) {
|
|
4500
4894
|
if (isSelfDependency(dep, task, input.issue)) {
|
|
4501
4895
|
const issueStr = input.issue !== null ? `#${input.issue.number}` : "?";
|
|
4502
|
-
|
|
4896
|
+
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.`);
|
|
4503
4897
|
continue;
|
|
4504
4898
|
}
|
|
4505
4899
|
if (dep.resolved === false) {
|
|
4506
|
-
|
|
4900
|
+
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.`);
|
|
4507
4901
|
continue;
|
|
4508
4902
|
}
|
|
4509
4903
|
if (!dep.merged && !isHandClosedByRecognizedPrincipal(dep, principalAllowlist)) {
|
|
4510
4904
|
const issueStr = dep.issue !== null ? ` (#${dep.issue})` : "";
|
|
4511
|
-
|
|
4905
|
+
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.`);
|
|
4512
4906
|
}
|
|
4513
4907
|
}
|
|
4514
4908
|
for (const c of input.conflictsWith) {
|
|
4515
4909
|
if (c.openOrInFlight) {
|
|
4516
4910
|
const issueStr = c.issue !== null ? ` (#${c.issue})` : "";
|
|
4517
|
-
|
|
4911
|
+
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.`);
|
|
4518
4912
|
}
|
|
4519
4913
|
}
|
|
4520
4914
|
for (const proj of input.priorTrancheArchival) {
|
|
4521
4915
|
if (proj.priorTrancheSlug !== null && !proj.archived) {
|
|
4522
|
-
|
|
4916
|
+
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.`);
|
|
4523
4917
|
}
|
|
4524
4918
|
}
|
|
4525
|
-
return { ready:
|
|
4919
|
+
return { ready: blockerDetails.length === 0, blockers: blockerDetails.map((b) => b.message), blockerDetails };
|
|
4526
4920
|
}
|
|
4527
4921
|
// ../../packages/aeg-core/src/single-plan-pr.ts
|
|
4528
4922
|
function trancheSlugFromTopologyPath(path) {
|
|
@@ -4624,6 +5018,137 @@ function checkBranchTopology(input) {
|
|
|
4624
5018
|
reason: `Branch \`${branch}\` matches topology row \`${taskId}\` in ${topoPath}.`
|
|
4625
5019
|
};
|
|
4626
5020
|
}
|
|
5021
|
+
// ../../packages/aeg-core/src/task-tools.ts
|
|
5022
|
+
import { z } from "zod";
|
|
5023
|
+
var TASK_TOOL_ERROR_KINDS = [
|
|
5024
|
+
"validation",
|
|
5025
|
+
"authority",
|
|
5026
|
+
"precondition",
|
|
5027
|
+
"capability",
|
|
5028
|
+
"infrastructure",
|
|
5029
|
+
"cancellation",
|
|
5030
|
+
"timeout",
|
|
5031
|
+
"uncertain_effect"
|
|
5032
|
+
];
|
|
5033
|
+
var TaskToolErrorSchema = z.object({
|
|
5034
|
+
kind: z.enum(TASK_TOOL_ERROR_KINDS),
|
|
5035
|
+
message: z.string().min(1),
|
|
5036
|
+
detail: z.string().optional()
|
|
5037
|
+
});
|
|
5038
|
+
var TaskToolRefSchema = z.union([
|
|
5039
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
|
|
5040
|
+
z.object({ issue: z.number().int().positive() }).strict()
|
|
5041
|
+
]);
|
|
5042
|
+
var MAX_PAGE_LIMIT = 100;
|
|
5043
|
+
var PageRequestSchema = z.object({
|
|
5044
|
+
cursor: z.string().optional(),
|
|
5045
|
+
limit: z.number().int().positive().max(MAX_PAGE_LIMIT).optional()
|
|
5046
|
+
});
|
|
5047
|
+
var FreshnessSchema = z.enum(["fresh", "stale", "unknown"]);
|
|
5048
|
+
var ObservedSchema = z.object({
|
|
5049
|
+
observedAt: z.string(),
|
|
5050
|
+
freshness: FreshnessSchema
|
|
5051
|
+
});
|
|
5052
|
+
var TaskStatusInputSchema = z.object({
|
|
5053
|
+
task: TaskToolRefSchema.optional()
|
|
5054
|
+
}).merge(PageRequestSchema).strict();
|
|
5055
|
+
var TaskStatusItemSchema = z.object({
|
|
5056
|
+
task: TaskToolRefSchema,
|
|
5057
|
+
issue: z.number().int().positive(),
|
|
5058
|
+
pr: z.number().int().positive().nullable(),
|
|
5059
|
+
state: z.string()
|
|
5060
|
+
}).merge(ObservedSchema);
|
|
5061
|
+
var TaskStatusResultSchema = z.object({
|
|
5062
|
+
items: z.array(TaskStatusItemSchema),
|
|
5063
|
+
nextCursor: z.string().nullable()
|
|
5064
|
+
});
|
|
5065
|
+
var RequestedAuthoritySchema = z.enum(["planner", "principal", "operator", "self"]);
|
|
5066
|
+
var EscalationInputsSchema = z.object({
|
|
5067
|
+
task: z.number().int().positive(),
|
|
5068
|
+
round: z.number().int().nonnegative(),
|
|
5069
|
+
head: z.string(),
|
|
5070
|
+
branch: z.string(),
|
|
5071
|
+
prNumber: z.number().int().positive()
|
|
5072
|
+
});
|
|
5073
|
+
var EscalationEvidenceSchema = z.object({
|
|
5074
|
+
round: z.number().int().nonnegative(),
|
|
5075
|
+
reviewer: z.string().nullable(),
|
|
5076
|
+
security: z.string().nullable()
|
|
5077
|
+
});
|
|
5078
|
+
var EscalationRunIdentitySchema = z.object({
|
|
5079
|
+
runId: z.string(),
|
|
5080
|
+
pid: z.number().int().positive(),
|
|
5081
|
+
host: z.string()
|
|
5082
|
+
});
|
|
5083
|
+
var EscalationInputVersionsSchema = z.object({
|
|
5084
|
+
briefHash: z.string().nullable(),
|
|
5085
|
+
objectivesVersion: z.string().nullable(),
|
|
5086
|
+
rulingOrdinal: z.number().int().nonnegative(),
|
|
5087
|
+
policyDigest: z.string()
|
|
5088
|
+
});
|
|
5089
|
+
var TaskEscalationReadInputSchema = z.object({
|
|
5090
|
+
task: TaskToolRefSchema
|
|
5091
|
+
}).merge(PageRequestSchema).strict();
|
|
5092
|
+
var TaskEscalationPacketSchema = z.object({
|
|
5093
|
+
reason: z.string(),
|
|
5094
|
+
detail: z.string().nullable(),
|
|
5095
|
+
inputs: EscalationInputsSchema.nullable(),
|
|
5096
|
+
evidence: EscalationEvidenceSchema.nullable(),
|
|
5097
|
+
attemptedRecovery: z.string(),
|
|
5098
|
+
requestedAuthority: RequestedAuthoritySchema,
|
|
5099
|
+
permittedNextActions: z.array(z.string()),
|
|
5100
|
+
runIdentity: EscalationRunIdentitySchema.nullable(),
|
|
5101
|
+
inputVersions: EscalationInputVersionsSchema.nullable()
|
|
5102
|
+
}).merge(ObservedSchema);
|
|
5103
|
+
var TaskEscalationReadResultSchema = z.object({
|
|
5104
|
+
items: z.array(TaskEscalationPacketSchema),
|
|
5105
|
+
nextCursor: z.string().nullable()
|
|
5106
|
+
}).merge(ObservedSchema);
|
|
5107
|
+
var TaskStartInputSchema = z.object({
|
|
5108
|
+
tranche: z.string().min(1),
|
|
5109
|
+
id: z.string().min(1)
|
|
5110
|
+
}).strict();
|
|
5111
|
+
var TaskStartResultSchema = z.object({
|
|
5112
|
+
requestId: z.string().min(1),
|
|
5113
|
+
run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
5114
|
+
started: z.boolean(),
|
|
5115
|
+
startedAt: z.string(),
|
|
5116
|
+
mode: z.literal("attended")
|
|
5117
|
+
});
|
|
5118
|
+
var TaskResumeInputSchema = z.object({
|
|
5119
|
+
task: TaskToolRefSchema
|
|
5120
|
+
}).strict();
|
|
5121
|
+
var TaskCancelInputSchema = z.object({
|
|
5122
|
+
task: TaskToolRefSchema,
|
|
5123
|
+
reason: z.string().min(1)
|
|
5124
|
+
}).strict();
|
|
5125
|
+
var TaskResumeResultSchema = z.object({
|
|
5126
|
+
task: z.number().int().positive(),
|
|
5127
|
+
pr: z.number().int().positive(),
|
|
5128
|
+
escalationId: z.string().min(1),
|
|
5129
|
+
outcome: z.enum(["started", "already_resumed"]),
|
|
5130
|
+
authenticatedBy: z.string().min(1),
|
|
5131
|
+
authenticatedFrom: z.string().min(1)
|
|
5132
|
+
});
|
|
5133
|
+
var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
|
|
5134
|
+
var TaskCancelResultSchema = z.object({
|
|
5135
|
+
task: z.number().int().positive(),
|
|
5136
|
+
pr: z.number().int().positive(),
|
|
5137
|
+
escalationId: z.string().min(1),
|
|
5138
|
+
outcome: TaskCancelOutcomeSchema,
|
|
5139
|
+
authenticatedBy: z.string().min(1),
|
|
5140
|
+
authenticatedFrom: z.string().min(1),
|
|
5141
|
+
fencedEffectKeys: z.array(z.string())
|
|
5142
|
+
});
|
|
5143
|
+
var TASK_TOOL_NAMES = [
|
|
5144
|
+
"task_start",
|
|
5145
|
+
"task_status",
|
|
5146
|
+
"task_escalation_read",
|
|
5147
|
+
"task_resume",
|
|
5148
|
+
"task_cancel"
|
|
5149
|
+
];
|
|
5150
|
+
var OPERATOR_STATUS_FOLLOW = "task_status_follow";
|
|
5151
|
+
var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
|
|
4627
5152
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
4628
5153
|
function parseTaskBranch(branch) {
|
|
4629
5154
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -4707,7 +5232,6 @@ function decideIssueAssignment(input) {
|
|
|
4707
5232
|
};
|
|
4708
5233
|
}
|
|
4709
5234
|
// ../../packages/aeg-core/src/test-plan-gate.ts
|
|
4710
|
-
var TASK_BRANCH_PATTERN2 = /^task\/[^/]+\/[^/]+$/;
|
|
4711
5235
|
function evaluateTestPlanGate(body, branch) {
|
|
4712
5236
|
if (!body) {
|
|
4713
5237
|
return {
|
|
@@ -4720,7 +5244,7 @@ function evaluateTestPlanGate(body, branch) {
|
|
|
4720
5244
|
}
|
|
4721
5245
|
const located = locateTestPlanSection(body);
|
|
4722
5246
|
if (!located.found) {
|
|
4723
|
-
if (
|
|
5247
|
+
if (parseTaskBranchIdentity(branch) !== null) {
|
|
4724
5248
|
return {
|
|
4725
5249
|
verdict: "fail",
|
|
4726
5250
|
messages: [
|
|
@@ -4847,8 +5371,11 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
4847
5371
|
}
|
|
4848
5372
|
return findings;
|
|
4849
5373
|
}
|
|
5374
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5375
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5376
|
+
|
|
4850
5377
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
4851
|
-
import { z } from "zod";
|
|
5378
|
+
import { z as z2 } from "zod";
|
|
4852
5379
|
var ROLE_VALUES = [
|
|
4853
5380
|
"planner",
|
|
4854
5381
|
"developer",
|
|
@@ -4858,136 +5385,174 @@ var ROLE_VALUES = [
|
|
|
4858
5385
|
"archivist",
|
|
4859
5386
|
"architect"
|
|
4860
5387
|
];
|
|
4861
|
-
var RoleSchema =
|
|
5388
|
+
var RoleSchema = z2.enum(ROLE_VALUES);
|
|
4862
5389
|
var HOST_VALUES = ["hook", "ci", "cli", "loop"];
|
|
4863
|
-
var HostSchema =
|
|
5390
|
+
var HostSchema = z2.enum(HOST_VALUES);
|
|
4864
5391
|
var RUN_ID_PATTERN = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
4865
|
-
var
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
doctrine: z.string(),
|
|
5392
|
+
var headerMetaCore = {
|
|
5393
|
+
ts: z2.string(),
|
|
5394
|
+
run_id: z2.string().regex(RUN_ID_PATTERN),
|
|
5395
|
+
seq: z2.number().int().nonnegative(),
|
|
5396
|
+
repo: z2.string().nullable(),
|
|
5397
|
+
vinaya: z2.string(),
|
|
5398
|
+
doctrine: z2.string(),
|
|
4873
5399
|
host: HostSchema,
|
|
4874
|
-
machine:
|
|
5400
|
+
machine: z2.string()
|
|
5401
|
+
};
|
|
5402
|
+
var HeaderMetaV1Schema = z2.object({
|
|
5403
|
+
schema: z2.literal(1),
|
|
5404
|
+
...headerMetaCore
|
|
5405
|
+
}).strict();
|
|
5406
|
+
var LineageSchema = z2.object({
|
|
5407
|
+
run: z2.string().nullable(),
|
|
5408
|
+
attempt: z2.number().int().nullable(),
|
|
5409
|
+
parent: z2.string().nullable()
|
|
5410
|
+
}).strict();
|
|
5411
|
+
var InputVersionsSchema = z2.object({
|
|
5412
|
+
objectives_version: z2.string().nullable(),
|
|
5413
|
+
brief_hash: z2.string().nullable(),
|
|
5414
|
+
ruling_ordinal: z2.number().int().nullable(),
|
|
5415
|
+
policy_digest: z2.string().nullable()
|
|
5416
|
+
}).strict();
|
|
5417
|
+
var ProvenanceSchema = z2.enum(["parent_attributed", "env_correlated", "self_reported", "unavailable"]);
|
|
5418
|
+
var HeaderMetaV2Schema = z2.object({
|
|
5419
|
+
schema: z2.literal(2),
|
|
5420
|
+
...headerMetaCore,
|
|
5421
|
+
event_id: z2.string().min(1),
|
|
5422
|
+
process_id: z2.string().min(1),
|
|
5423
|
+
actor_id: z2.string().nullable(),
|
|
5424
|
+
lineage: LineageSchema,
|
|
5425
|
+
input_versions: InputVersionsSchema,
|
|
5426
|
+
provenance: ProvenanceSchema
|
|
4875
5427
|
}).strict();
|
|
4876
|
-
var
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
5428
|
+
var HeaderMetaSchema = z2.discriminatedUnion("schema", [HeaderMetaV1Schema, HeaderMetaV2Schema]);
|
|
5429
|
+
var SubjectSchema = z2.object({
|
|
5430
|
+
issue: z2.number().int().nullable(),
|
|
5431
|
+
pr: z2.number().int().optional(),
|
|
5432
|
+
sha: z2.string().optional(),
|
|
5433
|
+
role: z2.union([RoleSchema, z2.literal("unattributed")]),
|
|
5434
|
+
round: z2.number().int().optional(),
|
|
5435
|
+
objectives_version: z2.string().optional()
|
|
4883
5436
|
}).strict();
|
|
4884
|
-
var HeaderSchema =
|
|
5437
|
+
var HeaderSchema = z2.object({
|
|
4885
5438
|
meta: HeaderMetaSchema,
|
|
4886
5439
|
subject: SubjectSchema
|
|
4887
5440
|
}).strict();
|
|
4888
5441
|
var envelopeTail = {
|
|
4889
|
-
duration_ms:
|
|
4890
|
-
payload:
|
|
5442
|
+
duration_ms: z2.number().nonnegative().optional(),
|
|
5443
|
+
payload: z2.object({}).strict()
|
|
4891
5444
|
};
|
|
4892
|
-
var
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
5445
|
+
var ReviewFindingSchema = z2.object({
|
|
5446
|
+
id: z2.string(),
|
|
5447
|
+
severity: z2.string(),
|
|
5448
|
+
state: z2.string().optional(),
|
|
5449
|
+
severity_scale: z2.string().optional(),
|
|
5450
|
+
policy_treatment: z2.enum(["blocking", "non_blocking", "unavailable"]).optional(),
|
|
5451
|
+
confidence: z2.number().min(0).max(1).optional(),
|
|
5452
|
+
confidence_scale: z2.string().optional(),
|
|
5453
|
+
confidence_source: z2.string().optional()
|
|
5454
|
+
}).strict();
|
|
5455
|
+
var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
5456
|
+
z2.object({ type: z2.literal("pr_opened"), pr: z2.number().int(), head: z2.string() }).strict(),
|
|
5457
|
+
z2.object({
|
|
5458
|
+
type: z2.literal("round_pushed"),
|
|
5459
|
+
pr: z2.number().int(),
|
|
5460
|
+
head: z2.string(),
|
|
5461
|
+
comment_id: z2.number().int()
|
|
4899
5462
|
}).strict(),
|
|
4900
|
-
|
|
4901
|
-
type:
|
|
4902
|
-
verdict:
|
|
4903
|
-
head:
|
|
4904
|
-
comment_id:
|
|
4905
|
-
objectives:
|
|
4906
|
-
findings:
|
|
5463
|
+
z2.object({
|
|
5464
|
+
type: z2.literal("verdict"),
|
|
5465
|
+
verdict: z2.enum(["APPROVE", "REQUEST CHANGES", "PASS", "FAIL"]),
|
|
5466
|
+
head: z2.string(),
|
|
5467
|
+
comment_id: z2.number().int(),
|
|
5468
|
+
objectives: z2.array(z2.object({ id: z2.string(), met: z2.boolean() }).strict()),
|
|
5469
|
+
findings: z2.array(ReviewFindingSchema)
|
|
4907
5470
|
}).strict(),
|
|
4908
|
-
|
|
4909
|
-
type:
|
|
4910
|
-
class:
|
|
4911
|
-
comment_id:
|
|
5471
|
+
z2.object({
|
|
5472
|
+
type: z2.literal("escalation"),
|
|
5473
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5474
|
+
comment_id: z2.number().int()
|
|
4912
5475
|
}).strict(),
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
5476
|
+
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5477
|
+
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5478
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
|
|
5479
|
+
z2.object({ type: z2.literal("completed") }).strict()
|
|
4916
5480
|
]);
|
|
4917
5481
|
var dispatchShared = {
|
|
4918
5482
|
meta: HeaderMetaSchema,
|
|
4919
5483
|
subject: SubjectSchema,
|
|
4920
|
-
kind:
|
|
5484
|
+
kind: z2.literal("dispatch"),
|
|
4921
5485
|
...envelopeTail,
|
|
4922
5486
|
target_role: RoleSchema,
|
|
4923
|
-
model:
|
|
4924
|
-
round:
|
|
4925
|
-
effect_id:
|
|
5487
|
+
model: z2.string(),
|
|
5488
|
+
round: z2.number().int().optional(),
|
|
5489
|
+
effect_id: z2.string()
|
|
4926
5490
|
};
|
|
4927
|
-
var dispatchUsageField =
|
|
4928
|
-
var DispatchEventSchema =
|
|
4929
|
-
|
|
4930
|
-
|
|
5491
|
+
var dispatchUsageField = z2.object({ input: z2.number().nonnegative(), output: z2.number().nonnegative() }).strict().nullable();
|
|
5492
|
+
var DispatchEventSchema = z2.discriminatedUnion("event", [
|
|
5493
|
+
z2.object({ ...dispatchShared, event: z2.literal("dispatched"), prompt_hash: z2.string() }).strict(),
|
|
5494
|
+
z2.object({
|
|
4931
5495
|
...dispatchShared,
|
|
4932
|
-
event:
|
|
5496
|
+
event: z2.literal("outcome_received"),
|
|
4933
5497
|
outcome: DispatchOutcomeSchema,
|
|
4934
5498
|
usage: dispatchUsageField
|
|
4935
5499
|
}).strict(),
|
|
4936
|
-
|
|
5500
|
+
z2.object({
|
|
4937
5501
|
...dispatchShared,
|
|
4938
|
-
event:
|
|
4939
|
-
reason:
|
|
5502
|
+
event: z2.literal("dispatch_failed"),
|
|
5503
|
+
reason: z2.enum(["timeout", "crash", "refused", "unattributed_write"]),
|
|
4940
5504
|
usage: dispatchUsageField
|
|
4941
5505
|
}).strict()
|
|
4942
5506
|
]);
|
|
4943
5507
|
var loopShared = {
|
|
4944
5508
|
meta: HeaderMetaSchema,
|
|
4945
5509
|
subject: SubjectSchema,
|
|
4946
|
-
kind:
|
|
5510
|
+
kind: z2.literal("dev_review_loop"),
|
|
4947
5511
|
...envelopeTail,
|
|
4948
|
-
loop_id:
|
|
5512
|
+
loop_id: z2.string()
|
|
4949
5513
|
};
|
|
4950
|
-
var DevReviewLoopEventSchema =
|
|
4951
|
-
|
|
5514
|
+
var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
5515
|
+
z2.object({
|
|
4952
5516
|
...loopShared,
|
|
4953
|
-
event:
|
|
4954
|
-
task:
|
|
4955
|
-
policy:
|
|
4956
|
-
max_rounds:
|
|
4957
|
-
reviewers:
|
|
4958
|
-
models:
|
|
5517
|
+
event: z2.literal("loop_started"),
|
|
5518
|
+
task: z2.number().int(),
|
|
5519
|
+
policy: z2.object({
|
|
5520
|
+
max_rounds: z2.number().int().nonnegative(),
|
|
5521
|
+
reviewers: z2.array(RoleSchema),
|
|
5522
|
+
models: z2.record(RoleSchema, z2.string())
|
|
4959
5523
|
}).strict()
|
|
4960
5524
|
}).strict(),
|
|
4961
|
-
|
|
4962
|
-
|
|
5525
|
+
z2.object({ ...loopShared, event: z2.literal("round_started"), round: z2.number().int(), base_head: z2.string() }).strict(),
|
|
5526
|
+
z2.object({
|
|
4963
5527
|
...loopShared,
|
|
4964
|
-
event:
|
|
4965
|
-
round:
|
|
4966
|
-
head:
|
|
4967
|
-
green:
|
|
5528
|
+
event: z2.literal("gate_result_read"),
|
|
5529
|
+
round: z2.number().int(),
|
|
5530
|
+
head: z2.string(),
|
|
5531
|
+
green: z2.boolean()
|
|
4968
5532
|
}).strict(),
|
|
4969
|
-
|
|
5533
|
+
z2.object({
|
|
4970
5534
|
...loopShared,
|
|
4971
|
-
event:
|
|
4972
|
-
round:
|
|
4973
|
-
head:
|
|
4974
|
-
all_approve:
|
|
4975
|
-
blockers:
|
|
5535
|
+
event: z2.literal("verdicts_read"),
|
|
5536
|
+
round: z2.number().int(),
|
|
5537
|
+
head: z2.string(),
|
|
5538
|
+
all_approve: z2.boolean(),
|
|
5539
|
+
blockers: z2.number().int().nonnegative(),
|
|
5540
|
+
findings: z2.array(ReviewFindingSchema).optional()
|
|
4976
5541
|
}).strict(),
|
|
4977
|
-
|
|
5542
|
+
z2.object({
|
|
4978
5543
|
...loopShared,
|
|
4979
|
-
event:
|
|
4980
|
-
round:
|
|
4981
|
-
open:
|
|
4982
|
-
resolved:
|
|
4983
|
-
new:
|
|
4984
|
-
recurring:
|
|
5544
|
+
event: z2.literal("findings_compared"),
|
|
5545
|
+
round: z2.number().int(),
|
|
5546
|
+
open: z2.array(z2.string()),
|
|
5547
|
+
resolved: z2.array(z2.string()),
|
|
5548
|
+
new: z2.array(z2.string()),
|
|
5549
|
+
recurring: z2.array(z2.string())
|
|
4985
5550
|
}).strict(),
|
|
4986
|
-
|
|
5551
|
+
z2.object({
|
|
4987
5552
|
...loopShared,
|
|
4988
|
-
event:
|
|
4989
|
-
round:
|
|
4990
|
-
condition:
|
|
5553
|
+
event: z2.literal("stop_condition_met"),
|
|
5554
|
+
round: z2.number().int(),
|
|
5555
|
+
condition: z2.enum([
|
|
4991
5556
|
"green",
|
|
4992
5557
|
"max_rounds",
|
|
4993
5558
|
"no_progress",
|
|
@@ -4997,42 +5562,49 @@ var DevReviewLoopEventSchema = z.discriminatedUnion("event", [
|
|
|
4997
5562
|
"reappearance"
|
|
4998
5563
|
])
|
|
4999
5564
|
}).strict(),
|
|
5000
|
-
|
|
5565
|
+
z2.object({
|
|
5566
|
+
...loopShared,
|
|
5567
|
+
event: z2.literal("paused"),
|
|
5568
|
+
round: z2.number().int(),
|
|
5569
|
+
reason: z2.enum(["escalation", "principal_item", "refreeze_needed"])
|
|
5570
|
+
}).strict(),
|
|
5571
|
+
z2.object({
|
|
5001
5572
|
...loopShared,
|
|
5002
|
-
event:
|
|
5003
|
-
round:
|
|
5004
|
-
|
|
5573
|
+
event: z2.literal("resumed"),
|
|
5574
|
+
round: z2.number().int(),
|
|
5575
|
+
by: z2.literal("principal")
|
|
5005
5576
|
}).strict(),
|
|
5006
|
-
|
|
5577
|
+
z2.object({
|
|
5007
5578
|
...loopShared,
|
|
5008
|
-
event:
|
|
5009
|
-
round:
|
|
5010
|
-
|
|
5579
|
+
event: z2.literal("unpushed_work_resume"),
|
|
5580
|
+
round: z2.number().int(),
|
|
5581
|
+
branch: z2.string(),
|
|
5582
|
+
detail: z2.string()
|
|
5011
5583
|
}).strict(),
|
|
5012
|
-
|
|
5584
|
+
z2.object({
|
|
5013
5585
|
...loopShared,
|
|
5014
|
-
event:
|
|
5015
|
-
round:
|
|
5016
|
-
base_head:
|
|
5017
|
-
head:
|
|
5018
|
-
files_changed:
|
|
5019
|
-
insertions:
|
|
5020
|
-
deletions:
|
|
5021
|
-
wall_ms:
|
|
5022
|
-
outcome:
|
|
5586
|
+
event: z2.literal("round_ended"),
|
|
5587
|
+
round: z2.number().int(),
|
|
5588
|
+
base_head: z2.string(),
|
|
5589
|
+
head: z2.string(),
|
|
5590
|
+
files_changed: z2.number().int().nonnegative(),
|
|
5591
|
+
insertions: z2.number().int().nonnegative(),
|
|
5592
|
+
deletions: z2.number().int().nonnegative(),
|
|
5593
|
+
wall_ms: z2.number().nonnegative(),
|
|
5594
|
+
outcome: z2.enum(["green", "changes_requested", "escalated"])
|
|
5023
5595
|
}).strict(),
|
|
5024
|
-
|
|
5596
|
+
z2.object({
|
|
5025
5597
|
...loopShared,
|
|
5026
|
-
event:
|
|
5027
|
-
rounds:
|
|
5028
|
-
total_wall_ms:
|
|
5029
|
-
time_to_green_ms:
|
|
5030
|
-
files_changed_total:
|
|
5031
|
-
final_head:
|
|
5032
|
-
result:
|
|
5598
|
+
event: z2.literal("journal_finalized"),
|
|
5599
|
+
rounds: z2.number().int().nonnegative(),
|
|
5600
|
+
total_wall_ms: z2.number().nonnegative(),
|
|
5601
|
+
time_to_green_ms: z2.number().nonnegative().nullable(),
|
|
5602
|
+
files_changed_total: z2.number().int().nonnegative(),
|
|
5603
|
+
final_head: z2.string(),
|
|
5604
|
+
result: z2.enum(["merged_ready", "stopped"])
|
|
5033
5605
|
}).strict()
|
|
5034
5606
|
]);
|
|
5035
|
-
var ForgeOpSchema =
|
|
5607
|
+
var ForgeOpSchema = z2.enum([
|
|
5036
5608
|
"pr.create",
|
|
5037
5609
|
"pr.comment",
|
|
5038
5610
|
"pr.body.replace",
|
|
@@ -5046,24 +5618,434 @@ var ForgeOpSchema = z.enum([
|
|
|
5046
5618
|
"label.add",
|
|
5047
5619
|
"label.remove"
|
|
5048
5620
|
]);
|
|
5049
|
-
var ForgeWriteTargetSchema =
|
|
5050
|
-
issue:
|
|
5051
|
-
pr:
|
|
5621
|
+
var ForgeWriteTargetSchema = z2.object({
|
|
5622
|
+
issue: z2.number().int().optional(),
|
|
5623
|
+
pr: z2.number().int().optional()
|
|
5052
5624
|
}).strict();
|
|
5053
5625
|
var forgeWriteShared = {
|
|
5054
5626
|
meta: HeaderMetaSchema,
|
|
5055
5627
|
subject: SubjectSchema,
|
|
5056
|
-
kind:
|
|
5628
|
+
kind: z2.literal("forge_write"),
|
|
5057
5629
|
...envelopeTail,
|
|
5058
5630
|
op: ForgeOpSchema,
|
|
5059
5631
|
target: ForgeWriteTargetSchema
|
|
5060
5632
|
};
|
|
5061
|
-
var ForgeWriteEventSchema =
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5633
|
+
var ForgeWriteEventSchema = z2.discriminatedUnion("event", [
|
|
5634
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("validated") }).strict(),
|
|
5635
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("refused"), reason: z2.string() }).strict(),
|
|
5636
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("written"), comment_ids: z2.array(z2.string()) }).strict()
|
|
5637
|
+
]);
|
|
5638
|
+
var GateOutcomeSchema = z2.enum([
|
|
5639
|
+
"pass",
|
|
5640
|
+
"fail",
|
|
5641
|
+
"wait",
|
|
5642
|
+
"skip",
|
|
5643
|
+
"invalid_input",
|
|
5644
|
+
"unavailable_dependency",
|
|
5645
|
+
"timeout",
|
|
5646
|
+
"cancelled"
|
|
5065
5647
|
]);
|
|
5066
|
-
var
|
|
5648
|
+
var gateShared = {
|
|
5649
|
+
meta: HeaderMetaSchema,
|
|
5650
|
+
subject: SubjectSchema,
|
|
5651
|
+
kind: z2.literal("gate"),
|
|
5652
|
+
...envelopeTail,
|
|
5653
|
+
check: z2.string(),
|
|
5654
|
+
check_version: z2.string().nullable(),
|
|
5655
|
+
policy_version: z2.string().nullable(),
|
|
5656
|
+
input_fingerprint: z2.string().nullable()
|
|
5657
|
+
};
|
|
5658
|
+
var GateEventSchema = z2.discriminatedUnion("event", [
|
|
5659
|
+
z2.object({
|
|
5660
|
+
...gateShared,
|
|
5661
|
+
event: z2.literal("checked"),
|
|
5662
|
+
outcome: GateOutcomeSchema,
|
|
5663
|
+
reason: z2.string().optional()
|
|
5664
|
+
}).strict()
|
|
5665
|
+
]);
|
|
5666
|
+
var OperationResultSchema = z2.enum(["ok", "error", "refused", "timeout", "cancelled", "unavailable"]);
|
|
5667
|
+
var operationShared = {
|
|
5668
|
+
meta: HeaderMetaSchema,
|
|
5669
|
+
subject: SubjectSchema,
|
|
5670
|
+
kind: z2.literal("operation"),
|
|
5671
|
+
...envelopeTail,
|
|
5672
|
+
operation: z2.string(),
|
|
5673
|
+
target: z2.string().nullable()
|
|
5674
|
+
};
|
|
5675
|
+
var OperationEventSchema = z2.discriminatedUnion("event", [
|
|
5676
|
+
z2.object({
|
|
5677
|
+
...operationShared,
|
|
5678
|
+
event: z2.literal("completed"),
|
|
5679
|
+
result: OperationResultSchema,
|
|
5680
|
+
error_class: z2.string().nullable()
|
|
5681
|
+
}).strict()
|
|
5682
|
+
]);
|
|
5683
|
+
var UsageUnitsSchema = z2.object({
|
|
5684
|
+
input: z2.number().nonnegative().nullable(),
|
|
5685
|
+
output: z2.number().nonnegative().nullable(),
|
|
5686
|
+
cache: z2.number().nonnegative().nullable()
|
|
5687
|
+
}).strict();
|
|
5688
|
+
var usageShared = {
|
|
5689
|
+
meta: HeaderMetaSchema,
|
|
5690
|
+
subject: SubjectSchema,
|
|
5691
|
+
kind: z2.literal("usage"),
|
|
5692
|
+
...envelopeTail,
|
|
5693
|
+
model: z2.string().nullable(),
|
|
5694
|
+
source: z2.string(),
|
|
5695
|
+
semantics: z2.enum(["cumulative", "delta"])
|
|
5696
|
+
};
|
|
5697
|
+
var UsageEventSchema = z2.discriminatedUnion("event", [
|
|
5698
|
+
z2.object({
|
|
5699
|
+
...usageShared,
|
|
5700
|
+
event: z2.literal("observed"),
|
|
5701
|
+
units: UsageUnitsSchema,
|
|
5702
|
+
unknown_reason: z2.string().nullable()
|
|
5703
|
+
}).strict()
|
|
5704
|
+
]);
|
|
5705
|
+
var RoleAttemptOutcomeSchema = z2.enum([
|
|
5706
|
+
"completed",
|
|
5707
|
+
"incomplete",
|
|
5708
|
+
"infrastructure_failed",
|
|
5709
|
+
"cancelled",
|
|
5710
|
+
"timed_out",
|
|
5711
|
+
"capability_refused"
|
|
5712
|
+
]);
|
|
5713
|
+
var roleAttemptShared = {
|
|
5714
|
+
meta: HeaderMetaSchema,
|
|
5715
|
+
subject: SubjectSchema,
|
|
5716
|
+
kind: z2.literal("role_attempt"),
|
|
5717
|
+
...envelopeTail,
|
|
5718
|
+
actor: z2.string().nullable(),
|
|
5719
|
+
attempt: z2.number().int().nullable(),
|
|
5720
|
+
effect_id: z2.string(),
|
|
5721
|
+
model: z2.string().nullable()
|
|
5722
|
+
};
|
|
5723
|
+
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5724
|
+
z2.object({
|
|
5725
|
+
...roleAttemptShared,
|
|
5726
|
+
event: z2.literal("attempted"),
|
|
5727
|
+
outcome: RoleAttemptOutcomeSchema,
|
|
5728
|
+
usage: dispatchUsageField
|
|
5729
|
+
}).strict()
|
|
5730
|
+
]);
|
|
5731
|
+
var handoffShared = {
|
|
5732
|
+
meta: HeaderMetaSchema,
|
|
5733
|
+
subject: SubjectSchema,
|
|
5734
|
+
kind: z2.literal("handoff"),
|
|
5735
|
+
...envelopeTail,
|
|
5736
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5737
|
+
reason: z2.string()
|
|
5738
|
+
};
|
|
5739
|
+
var HandoffEventSchema = z2.discriminatedUnion("event", [
|
|
5740
|
+
z2.object({
|
|
5741
|
+
...handoffShared,
|
|
5742
|
+
event: z2.literal("raised"),
|
|
5743
|
+
requested_decision: z2.string().nullable()
|
|
5744
|
+
}).strict(),
|
|
5745
|
+
z2.object({
|
|
5746
|
+
...handoffShared,
|
|
5747
|
+
event: z2.literal("resolved"),
|
|
5748
|
+
resolution: z2.string().nullable(),
|
|
5749
|
+
resolved_by: z2.string().nullable()
|
|
5750
|
+
}).strict()
|
|
5751
|
+
]);
|
|
5752
|
+
var EffectTargetSchema = z2.object({
|
|
5753
|
+
kind: z2.string(),
|
|
5754
|
+
ref: z2.string()
|
|
5755
|
+
}).strict();
|
|
5756
|
+
var effectShared = {
|
|
5757
|
+
meta: HeaderMetaSchema,
|
|
5758
|
+
subject: SubjectSchema,
|
|
5759
|
+
kind: z2.literal("effect"),
|
|
5760
|
+
...envelopeTail,
|
|
5761
|
+
effect_id: z2.string(),
|
|
5762
|
+
target: EffectTargetSchema
|
|
5763
|
+
};
|
|
5764
|
+
var EffectEventSchema = z2.discriminatedUnion("event", [
|
|
5765
|
+
z2.object({ ...effectShared, event: z2.literal("attempted") }).strict(),
|
|
5766
|
+
z2.object({ ...effectShared, event: z2.literal("observed"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict(),
|
|
5767
|
+
z2.object({ ...effectShared, event: z2.literal("verified"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict()
|
|
5768
|
+
]);
|
|
5769
|
+
var LogEventSchema = z2.union([
|
|
5770
|
+
DispatchEventSchema,
|
|
5771
|
+
DevReviewLoopEventSchema,
|
|
5772
|
+
ForgeWriteEventSchema,
|
|
5773
|
+
GateEventSchema,
|
|
5774
|
+
OperationEventSchema,
|
|
5775
|
+
UsageEventSchema,
|
|
5776
|
+
RoleAttemptEventSchema,
|
|
5777
|
+
HandoffEventSchema,
|
|
5778
|
+
EffectEventSchema
|
|
5779
|
+
]);
|
|
5780
|
+
|
|
5781
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5782
|
+
function isRole(value) {
|
|
5783
|
+
return value !== undefined && ROLE_VALUES.includes(value);
|
|
5784
|
+
}
|
|
5785
|
+
function actorIdFromEnv(role) {
|
|
5786
|
+
return role === undefined || role === "" ? null : role;
|
|
5787
|
+
}
|
|
5788
|
+
function lineageFieldFromEnv(value) {
|
|
5789
|
+
return value === undefined || value === "" ? null : value;
|
|
5790
|
+
}
|
|
5791
|
+
function attemptFromEnv(value) {
|
|
5792
|
+
if (value === undefined || value === "")
|
|
5793
|
+
return null;
|
|
5794
|
+
const n = Number(value);
|
|
5795
|
+
return Number.isInteger(n) ? n : null;
|
|
5796
|
+
}
|
|
5797
|
+
function provenanceFor(input) {
|
|
5798
|
+
if (input.provenance)
|
|
5799
|
+
return input.provenance;
|
|
5800
|
+
if (input.env.role || input.env.task)
|
|
5801
|
+
return "env_correlated";
|
|
5802
|
+
return "unavailable";
|
|
5803
|
+
}
|
|
5804
|
+
function issueFromTask(task) {
|
|
5805
|
+
if (task === undefined || task === "")
|
|
5806
|
+
return null;
|
|
5807
|
+
const n = Number(task);
|
|
5808
|
+
return Number.isInteger(n) ? n : null;
|
|
5809
|
+
}
|
|
5810
|
+
function roundFromEnv(round) {
|
|
5811
|
+
if (round === undefined || round === "")
|
|
5812
|
+
return;
|
|
5813
|
+
const n = Number(round);
|
|
5814
|
+
return Number.isInteger(n) ? n : undefined;
|
|
5815
|
+
}
|
|
5816
|
+
function buildHeader(input) {
|
|
5817
|
+
const role = isRole(input.env.role) ? input.env.role : "unattributed";
|
|
5818
|
+
const round = roundFromEnv(input.env.round);
|
|
5819
|
+
const subject = {
|
|
5820
|
+
issue: issueFromTask(input.env.task),
|
|
5821
|
+
role,
|
|
5822
|
+
...round !== undefined ? { round } : {},
|
|
5823
|
+
...input.subject ?? {}
|
|
5824
|
+
};
|
|
5825
|
+
return {
|
|
5826
|
+
meta: {
|
|
5827
|
+
schema: 2,
|
|
5828
|
+
ts: input.now.toISOString(),
|
|
5829
|
+
run_id: input.runId,
|
|
5830
|
+
seq: input.seq,
|
|
5831
|
+
repo: input.repo,
|
|
5832
|
+
vinaya: input.vinaya,
|
|
5833
|
+
doctrine: input.doctrine,
|
|
5834
|
+
host: input.host,
|
|
5835
|
+
machine: createHash5("sha256").update(input.hostname).digest("hex"),
|
|
5836
|
+
event_id: input.eventId,
|
|
5837
|
+
process_id: input.processId,
|
|
5838
|
+
actor_id: actorIdFromEnv(input.env.role),
|
|
5839
|
+
lineage: {
|
|
5840
|
+
run: lineageFieldFromEnv(input.env.run),
|
|
5841
|
+
attempt: attemptFromEnv(input.env.attempt),
|
|
5842
|
+
parent: lineageFieldFromEnv(input.env.parent)
|
|
5843
|
+
},
|
|
5844
|
+
input_versions: {
|
|
5845
|
+
objectives_version: input.inputVersions?.objectivesVersion ?? null,
|
|
5846
|
+
brief_hash: input.inputVersions?.briefHash ?? null,
|
|
5847
|
+
ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
|
|
5848
|
+
policy_digest: input.inputVersions?.policyDigest ?? null
|
|
5849
|
+
},
|
|
5850
|
+
provenance: provenanceFor(input)
|
|
5851
|
+
},
|
|
5852
|
+
subject
|
|
5853
|
+
};
|
|
5854
|
+
}
|
|
5855
|
+
// ../../packages/aeg-core/src/log/redact.ts
|
|
5856
|
+
var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
|
|
5857
|
+
var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
|
|
5858
|
+
var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
|
|
5859
|
+
var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5860
|
+
var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
|
|
5861
|
+
var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
|
|
5862
|
+
var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
|
|
5863
|
+
var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
|
|
5864
|
+
var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
|
|
5865
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
|
|
5866
|
+
var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
|
|
5867
|
+
var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
|
|
5868
|
+
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;
|
|
5869
|
+
function redactString(value, home) {
|
|
5870
|
+
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>");
|
|
5871
|
+
if (home.length > 0 && out.startsWith(home)) {
|
|
5872
|
+
const rest = out.slice(home.length);
|
|
5873
|
+
if (rest === "" || rest.startsWith("/"))
|
|
5874
|
+
out = `~${rest}`;
|
|
5875
|
+
}
|
|
5876
|
+
return out;
|
|
5877
|
+
}
|
|
5878
|
+
function redact(value, home) {
|
|
5879
|
+
if (typeof value === "string")
|
|
5880
|
+
return redactString(value, home);
|
|
5881
|
+
if (Array.isArray(value))
|
|
5882
|
+
return value.map((v) => redact(v, home));
|
|
5883
|
+
if (value !== null && typeof value === "object") {
|
|
5884
|
+
const out = {};
|
|
5885
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5886
|
+
out[k] = redact(v, home);
|
|
5887
|
+
}
|
|
5888
|
+
return out;
|
|
5889
|
+
}
|
|
5890
|
+
return value;
|
|
5891
|
+
}
|
|
5892
|
+
// ../../packages/aeg-core/src/log/store.ts
|
|
5893
|
+
function metaOf(obj) {
|
|
5894
|
+
if (obj === null || typeof obj !== "object")
|
|
5895
|
+
return null;
|
|
5896
|
+
const meta = obj.meta;
|
|
5897
|
+
if (meta === null || typeof meta !== "object")
|
|
5898
|
+
return null;
|
|
5899
|
+
return meta;
|
|
5900
|
+
}
|
|
5901
|
+
function recordIdentity(obj) {
|
|
5902
|
+
const meta = metaOf(obj);
|
|
5903
|
+
if (meta === null)
|
|
5904
|
+
return null;
|
|
5905
|
+
const eventId = meta.event_id;
|
|
5906
|
+
if (typeof eventId === "string" && eventId.length > 0)
|
|
5907
|
+
return eventId;
|
|
5908
|
+
const runId = meta.run_id;
|
|
5909
|
+
const seq = meta.seq;
|
|
5910
|
+
if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
|
|
5911
|
+
return `${runId}:${seq}`;
|
|
5912
|
+
}
|
|
5913
|
+
return null;
|
|
5914
|
+
}
|
|
5915
|
+
|
|
5916
|
+
// ../../packages/aeg-core/src/log/artifact.ts
|
|
5917
|
+
var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
|
|
5918
|
+
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5919
|
+
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5920
|
+
// ../../packages/aeg-core/src/control-store/records.ts
|
|
5921
|
+
import { z as z3 } from "zod";
|
|
5922
|
+
var isoTimestamp = z3.string().min(1);
|
|
5923
|
+
var taskId = z3.number().int().positive();
|
|
5924
|
+
var epochNumber = z3.number().int().nonnegative();
|
|
5925
|
+
var RunRecordSchema = z3.object({
|
|
5926
|
+
version: z3.literal(1),
|
|
5927
|
+
kind: z3.literal("run"),
|
|
5928
|
+
task: taskId,
|
|
5929
|
+
runId: z3.string().min(1),
|
|
5930
|
+
pid: z3.number().int().positive(),
|
|
5931
|
+
host: z3.string().min(1),
|
|
5932
|
+
startedAt: isoTimestamp,
|
|
5933
|
+
childStartedAt: z3.string().min(1).nullable().optional(),
|
|
5934
|
+
childCommand: z3.string().min(1).nullable().optional()
|
|
5935
|
+
}).strict();
|
|
5936
|
+
var InputRecordSchema = z3.object({
|
|
5937
|
+
version: z3.literal(1),
|
|
5938
|
+
kind: z3.literal("input"),
|
|
5939
|
+
task: taskId,
|
|
5940
|
+
runId: z3.string().min(1),
|
|
5941
|
+
source: z3.union([z3.literal("fresh"), z3.literal("resume")]),
|
|
5942
|
+
pr: z3.number().int().positive().nullable(),
|
|
5943
|
+
round: z3.number().int().nonnegative(),
|
|
5944
|
+
recordedAt: isoTimestamp
|
|
5945
|
+
}).strict();
|
|
5946
|
+
var OwnershipRecordSchema = z3.object({
|
|
5947
|
+
version: z3.literal(1),
|
|
5948
|
+
kind: z3.literal("ownership"),
|
|
5949
|
+
task: taskId,
|
|
5950
|
+
epoch: epochNumber,
|
|
5951
|
+
ownerId: z3.string().min(1),
|
|
5952
|
+
pid: z3.number().int().positive(),
|
|
5953
|
+
host: z3.string().min(1),
|
|
5954
|
+
acquiredAt: isoTimestamp
|
|
5955
|
+
}).strict();
|
|
5956
|
+
var TransitionRecordSchema = z3.object({
|
|
5957
|
+
version: z3.literal(1),
|
|
5958
|
+
kind: z3.literal("transition"),
|
|
5959
|
+
task: taskId,
|
|
5960
|
+
epoch: epochNumber,
|
|
5961
|
+
seq: z3.number().int().nonnegative(),
|
|
5962
|
+
from: z3.string().min(1),
|
|
5963
|
+
to: z3.string().min(1),
|
|
5964
|
+
detail: z3.string().optional(),
|
|
5965
|
+
at: isoTimestamp
|
|
5966
|
+
}).strict();
|
|
5967
|
+
var ManifestRecordSchema = z3.object({
|
|
5968
|
+
version: z3.literal(1),
|
|
5969
|
+
kind: z3.literal("manifest"),
|
|
5970
|
+
task: taskId,
|
|
5971
|
+
round: epochNumber,
|
|
5972
|
+
repository: z3.string().min(1),
|
|
5973
|
+
pr: z3.number().int().positive(),
|
|
5974
|
+
branch: z3.string().min(1),
|
|
5975
|
+
baseSha: z3.string().min(1).nullable(),
|
|
5976
|
+
headSha: z3.string().min(1),
|
|
5977
|
+
briefHash: z3.string().min(1).nullable(),
|
|
5978
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
5979
|
+
rulingOrdinal: epochNumber,
|
|
5980
|
+
policyDigest: z3.string().min(1),
|
|
5981
|
+
recordedAt: isoTimestamp
|
|
5982
|
+
}).strict();
|
|
5983
|
+
var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
|
|
5984
|
+
var LoopBudgetsSchema = z3.object({
|
|
5985
|
+
mechanicalRetries: z3.number().int().nonnegative(),
|
|
5986
|
+
reviewRounds: z3.number().int().nonnegative(),
|
|
5987
|
+
infrastructureRetries: z3.number().int().nonnegative()
|
|
5988
|
+
}).strict();
|
|
5989
|
+
var LoopStateRecordSchema = z3.object({
|
|
5990
|
+
version: z3.literal(1),
|
|
5991
|
+
kind: z3.literal("loop_state"),
|
|
5992
|
+
task: taskId,
|
|
5993
|
+
round: z3.number().int().positive(),
|
|
5994
|
+
phase: z3.string().min(1),
|
|
5995
|
+
pauseReason: z3.string().min(1).nullable(),
|
|
5996
|
+
budgets: LoopBudgetsSchema,
|
|
5997
|
+
heldResult: roundHeadIdentity.nullable(),
|
|
5998
|
+
deliveredFindings: roundHeadIdentity.nullable(),
|
|
5999
|
+
recordedAt: isoTimestamp
|
|
6000
|
+
}).strict();
|
|
6001
|
+
var EffectRecordSchema = z3.object({
|
|
6002
|
+
version: z3.literal(1),
|
|
6003
|
+
kind: z3.literal("effect"),
|
|
6004
|
+
task: taskId,
|
|
6005
|
+
key: z3.string().min(1),
|
|
6006
|
+
operation: z3.string().min(1),
|
|
6007
|
+
target: z3.string().min(1),
|
|
6008
|
+
inputVersion: z3.number().int().nonnegative(),
|
|
6009
|
+
payloadDigest: z3.string().min(1),
|
|
6010
|
+
status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
|
|
6011
|
+
url: z3.string().optional(),
|
|
6012
|
+
recordedAt: isoTimestamp
|
|
6013
|
+
}).strict();
|
|
6014
|
+
var EscalationRecordSchema = z3.object({
|
|
6015
|
+
version: z3.literal(1),
|
|
6016
|
+
kind: z3.literal("escalation"),
|
|
6017
|
+
task: taskId,
|
|
6018
|
+
escalationId: z3.string().min(1),
|
|
6019
|
+
round: epochNumber,
|
|
6020
|
+
head: z3.string().min(1),
|
|
6021
|
+
branch: z3.string().min(1),
|
|
6022
|
+
pr: z3.number().int().positive().nullable(),
|
|
6023
|
+
runId: z3.string().min(1),
|
|
6024
|
+
pid: z3.number().int().positive(),
|
|
6025
|
+
host: z3.string().min(1),
|
|
6026
|
+
agent: z3.string().min(1).optional(),
|
|
6027
|
+
reason: z3.string().min(1),
|
|
6028
|
+
detail: z3.string().optional(),
|
|
6029
|
+
evidence: z3.string().optional(),
|
|
6030
|
+
attemptedRecovery: z3.string().min(1),
|
|
6031
|
+
requestedDecision: z3.string().min(1),
|
|
6032
|
+
recipient: z3.string().min(1),
|
|
6033
|
+
briefHash: z3.string().min(1).nullable(),
|
|
6034
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
6035
|
+
rulingOrdinal: epochNumber,
|
|
6036
|
+
policyDigest: z3.string().min(1),
|
|
6037
|
+
recordedAt: isoTimestamp
|
|
6038
|
+
}).strict();
|
|
6039
|
+
var ResolutionRecordSchema = z3.object({
|
|
6040
|
+
version: z3.literal(1),
|
|
6041
|
+
kind: z3.literal("resolution"),
|
|
6042
|
+
task: taskId,
|
|
6043
|
+
escalationId: z3.string().min(1),
|
|
6044
|
+
decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
|
|
6045
|
+
authenticatedBy: z3.string().min(1),
|
|
6046
|
+
authenticatedFrom: z3.string().min(1),
|
|
6047
|
+
consumedAt: isoTimestamp
|
|
6048
|
+
}).strict();
|
|
5067
6049
|
// src/checks/contract.ts
|
|
5068
6050
|
var CHECK_SCHEMA_VERSION = 1;
|
|
5069
6051
|
function emitCheckError(error) {
|
|
@@ -5104,6 +6086,7 @@ var REGISTRY = [
|
|
|
5104
6086
|
[
|
|
5105
6087
|
{
|
|
5106
6088
|
name: "brief-shape",
|
|
6089
|
+
validates: "body",
|
|
5107
6090
|
run: bin("check-brief-shape"),
|
|
5108
6091
|
scope: "diff",
|
|
5109
6092
|
timeoutMs: 15000,
|
|
@@ -5120,6 +6103,7 @@ var REGISTRY = [
|
|
|
5120
6103
|
[
|
|
5121
6104
|
{
|
|
5122
6105
|
name: "pr-report-density",
|
|
6106
|
+
validates: "body",
|
|
5123
6107
|
run: bin("check-pr-report-density"),
|
|
5124
6108
|
scope: "diff",
|
|
5125
6109
|
timeoutMs: 15000,
|
|
@@ -5132,6 +6116,7 @@ var REGISTRY = [
|
|
|
5132
6116
|
[
|
|
5133
6117
|
{
|
|
5134
6118
|
name: "doc-coverage",
|
|
6119
|
+
validates: "body",
|
|
5135
6120
|
run: bin("check-doc-coverage"),
|
|
5136
6121
|
scope: "diff",
|
|
5137
6122
|
timeoutMs: 15000,
|
|
@@ -5165,6 +6150,7 @@ var REGISTRY = [
|
|
|
5165
6150
|
[
|
|
5166
6151
|
{
|
|
5167
6152
|
name: "pr-premise-reassert",
|
|
6153
|
+
validates: "body",
|
|
5168
6154
|
run: bin("check-pr-premise-reassert"),
|
|
5169
6155
|
scope: "diff",
|
|
5170
6156
|
timeoutMs: 15000,
|
|
@@ -5193,6 +6179,7 @@ var REGISTRY = [
|
|
|
5193
6179
|
[
|
|
5194
6180
|
{
|
|
5195
6181
|
name: "closes-n",
|
|
6182
|
+
validates: "body",
|
|
5196
6183
|
run: bin("check-closes-n"),
|
|
5197
6184
|
scope: "diff",
|
|
5198
6185
|
timeoutMs: 15000,
|
|
@@ -5241,10 +6228,12 @@ var REGISTRY = [
|
|
|
5241
6228
|
[
|
|
5242
6229
|
{
|
|
5243
6230
|
name: "test-plan",
|
|
6231
|
+
validates: "body",
|
|
5244
6232
|
run: bin("check-test-plan"),
|
|
5245
6233
|
scope: "diff",
|
|
5246
6234
|
timeoutMs: 15000,
|
|
5247
6235
|
requiresOpenPr: true,
|
|
6236
|
+
principalOwed: true,
|
|
5248
6237
|
env: {
|
|
5249
6238
|
PR_BODY: { optional: true },
|
|
5250
6239
|
BRANCH: { optional: true }
|
|
@@ -5255,6 +6244,7 @@ var REGISTRY = [
|
|
|
5255
6244
|
[
|
|
5256
6245
|
{
|
|
5257
6246
|
name: "body-bare-digits",
|
|
6247
|
+
validates: "body",
|
|
5258
6248
|
run: bin("check-body-bare-digits"),
|
|
5259
6249
|
scope: "diff",
|
|
5260
6250
|
timeoutMs: 15000,
|
|
@@ -5273,6 +6263,7 @@ var REGISTRY = [
|
|
|
5273
6263
|
[
|
|
5274
6264
|
{
|
|
5275
6265
|
name: "token-report",
|
|
6266
|
+
validates: "body",
|
|
5276
6267
|
run: bin("check-token-report"),
|
|
5277
6268
|
scope: "diff",
|
|
5278
6269
|
timeoutMs: 15000,
|
|
@@ -5373,6 +6364,7 @@ var REGISTRY = [
|
|
|
5373
6364
|
[
|
|
5374
6365
|
{
|
|
5375
6366
|
name: "doc-coverage-push",
|
|
6367
|
+
validates: "body",
|
|
5376
6368
|
run: bin("check-doc-coverage-push"),
|
|
5377
6369
|
scope: "diff",
|
|
5378
6370
|
timeoutMs: 15000,
|
|
@@ -5408,6 +6400,7 @@ var REGISTRY = [
|
|
|
5408
6400
|
[
|
|
5409
6401
|
{
|
|
5410
6402
|
name: "evidence-fresh",
|
|
6403
|
+
validates: "body",
|
|
5411
6404
|
run: bin("check-evidence-fresh"),
|
|
5412
6405
|
scope: "diff",
|
|
5413
6406
|
timeoutMs: 15000,
|
|
@@ -5536,6 +6529,82 @@ var REGISTRY = [
|
|
|
5536
6529
|
}
|
|
5537
6530
|
},
|
|
5538
6531
|
0
|
|
6532
|
+
],
|
|
6533
|
+
[
|
|
6534
|
+
{
|
|
6535
|
+
name: "issue-title-grammar",
|
|
6536
|
+
run: bin("check-issue-title-grammar"),
|
|
6537
|
+
validates: "issue",
|
|
6538
|
+
scope: "full",
|
|
6539
|
+
ownWorkflow: true,
|
|
6540
|
+
timeoutMs: 15000,
|
|
6541
|
+
env: { ISSUE_TITLE: { optional: true } }
|
|
6542
|
+
},
|
|
6543
|
+
1
|
|
6544
|
+
],
|
|
6545
|
+
[
|
|
6546
|
+
{
|
|
6547
|
+
name: "issue-objectives-numbering",
|
|
6548
|
+
run: bin("check-issue-objectives-numbering"),
|
|
6549
|
+
validates: "issue",
|
|
6550
|
+
scope: "full",
|
|
6551
|
+
ownWorkflow: true,
|
|
6552
|
+
timeoutMs: 15000,
|
|
6553
|
+
env: { ISSUE_BODY: { optional: true }, ISSUE_NUMBER: { optional: true } }
|
|
6554
|
+
},
|
|
6555
|
+
1
|
|
6556
|
+
],
|
|
6557
|
+
[
|
|
6558
|
+
{
|
|
6559
|
+
name: "issue-parts-coverage",
|
|
6560
|
+
run: bin("check-issue-parts-coverage"),
|
|
6561
|
+
validates: "issue",
|
|
6562
|
+
scope: "full",
|
|
6563
|
+
ownWorkflow: true,
|
|
6564
|
+
timeoutMs: 15000,
|
|
6565
|
+
env: { ISSUE_BODY: { optional: true } }
|
|
6566
|
+
},
|
|
6567
|
+
1
|
|
6568
|
+
],
|
|
6569
|
+
[
|
|
6570
|
+
{
|
|
6571
|
+
name: "issue-surface-globs",
|
|
6572
|
+
run: bin("check-issue-surface-globs"),
|
|
6573
|
+
validates: "issue",
|
|
6574
|
+
scope: "full",
|
|
6575
|
+
ownWorkflow: true,
|
|
6576
|
+
timeoutMs: 15000,
|
|
6577
|
+
env: { ISSUE_BODY: { optional: true } }
|
|
6578
|
+
},
|
|
6579
|
+
1
|
|
6580
|
+
],
|
|
6581
|
+
[
|
|
6582
|
+
{
|
|
6583
|
+
name: "issue-tranche-label",
|
|
6584
|
+
run: bin("check-issue-tranche-label"),
|
|
6585
|
+
validates: "issue",
|
|
6586
|
+
scope: "full",
|
|
6587
|
+
ownWorkflow: true,
|
|
6588
|
+
timeoutMs: 15000,
|
|
6589
|
+
env: { ISSUE_BODY: { optional: true }, ISSUE_LABELS: { optional: true } }
|
|
6590
|
+
},
|
|
6591
|
+
1
|
|
6592
|
+
],
|
|
6593
|
+
[
|
|
6594
|
+
{
|
|
6595
|
+
name: "issue-milestone-attach",
|
|
6596
|
+
run: bin("check-issue-milestone-attach"),
|
|
6597
|
+
validates: "issue",
|
|
6598
|
+
scope: "full",
|
|
6599
|
+
ownWorkflow: true,
|
|
6600
|
+
timeoutMs: 15000,
|
|
6601
|
+
env: {
|
|
6602
|
+
ISSUE_LABELS: { optional: true },
|
|
6603
|
+
CURRENT_MILESTONE_TITLE: { optional: true },
|
|
6604
|
+
RESOLVED_MILESTONE_TITLE: { optional: true }
|
|
6605
|
+
}
|
|
6606
|
+
},
|
|
6607
|
+
1
|
|
5539
6608
|
]
|
|
5540
6609
|
];
|
|
5541
6610
|
function coreCheckRegistry() {
|