@attalabs/vinaya 0.26.0 → 0.28.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 +6 -3
- package/aeg-root/enforcement.md +5 -5
- package/aeg-root/milestone-model.md +2 -0
- package/aeg-root/process.md +1 -1
- package/aeg-root/roles/developer.md +23 -17
- package/aeg-root/roles/planner.md +4 -0
- package/aeg-root/roles/principal.md +8 -2
- package/aeg-root/roles/reviewer.md +9 -5
- package/aeg-root/roles/security.md +9 -5
- package/dist/checks/bin/check-body-bare-digits.js +1038 -257
- package/dist/checks/bin/check-branch-topology.js +963 -199
- package/dist/checks/bin/check-brief-shape.js +1276 -203
- package/dist/checks/bin/check-changeset-coverage.js +1677 -281
- package/dist/checks/bin/check-closes-n.js +967 -203
- package/dist/checks/bin/check-coherence.js +1127 -284
- package/dist/checks/bin/check-dead-branch-push.js +910 -193
- package/dist/checks/bin/check-dispatch-readiness.js +1189 -295
- package/dist/checks/bin/check-doc-coverage-push.js +1673 -277
- package/dist/checks/bin/check-doc-coverage.js +1675 -279
- package/dist/checks/bin/check-doctrine-no-procedures.js +1020 -257
- package/dist/checks/bin/check-doctrine-portability.js +1672 -276
- package/dist/checks/bin/check-evidence-fresh.js +2526 -322
- package/dist/checks/bin/check-exec-bits.js +1670 -274
- package/dist/checks/bin/check-first-push-dispatch.js +1075 -265
- package/dist/checks/bin/check-issue-assignment.js +965 -201
- package/dist/checks/bin/check-issue-milestone-attach.js +5734 -0
- package/dist/checks/bin/check-issue-objectives-numbering.js +5736 -0
- package/dist/checks/bin/check-issue-parts-coverage.js +5736 -0
- package/dist/checks/bin/check-issue-surface-globs.js +6910 -0
- package/dist/checks/bin/check-issue-title-grammar.js +5736 -0
- package/dist/checks/bin/check-issue-tranche-label.js +5736 -0
- package/dist/checks/bin/check-main-branch-refusal.js +910 -193
- package/dist/checks/bin/check-no-disk-state.js +910 -193
- package/dist/checks/bin/check-pr-premise-reassert.js +1020 -257
- package/dist/checks/bin/check-pr-report-density.js +910 -193
- package/dist/checks/bin/check-quoted-command.js +1651 -274
- package/dist/checks/bin/check-reader-resolvable-prose.js +1655 -278
- package/dist/checks/bin/check-registry-gates.js +997 -193
- package/dist/checks/bin/check-retired-vocabulary.js +1649 -272
- package/dist/checks/bin/check-review-gate.js +1163 -316
- package/dist/checks/bin/check-single-plan-pr.js +910 -193
- package/dist/checks/bin/check-surface-scope.js +973 -201
- package/dist/checks/bin/check-test-plan.js +939 -206
- package/dist/checks/bin/check-token-collection-wired.js +910 -193
- package/dist/checks/bin/check-token-report.js +910 -193
- package/dist/checks/bin/check-workspace-escape.js +1668 -272
- package/dist/index.js +10602 -5352
- package/dist/lib/pre-push-changed-files.js +57 -0
- package/dist/lib/pre-push-select-tests.js +1473 -0
- package/package.json +4 -2
|
@@ -305,7 +305,7 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
305
305
|
"--state",
|
|
306
306
|
"all",
|
|
307
307
|
"--json",
|
|
308
|
-
"number,title,body,state,labels,milestone",
|
|
308
|
+
"number,title,body,state,labels,milestone,stateReason",
|
|
309
309
|
"--limit",
|
|
310
310
|
"200"
|
|
311
311
|
];
|
|
@@ -651,14 +651,19 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
651
651
|
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
652
652
|
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
653
653
|
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
654
|
-
function
|
|
655
|
-
const text = stripCode(description, { inlineSpans: "keep" });
|
|
654
|
+
function intentsSection(text) {
|
|
656
655
|
const start = text.match(INTENTS_HEADING);
|
|
657
656
|
if (!start || start.index === undefined)
|
|
658
|
-
return
|
|
657
|
+
return null;
|
|
659
658
|
const rest = text.slice(start.index + start[0].length);
|
|
660
659
|
const next = rest.match(NEXT_HEADING);
|
|
661
|
-
|
|
660
|
+
return rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
661
|
+
}
|
|
662
|
+
function intentGoalForSlug(description, slug) {
|
|
663
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
664
|
+
const section = intentsSection(text);
|
|
665
|
+
if (section === null)
|
|
666
|
+
return "";
|
|
662
667
|
for (const line of section.split(`
|
|
663
668
|
`)) {
|
|
664
669
|
const trimmed = line.trim();
|
|
@@ -1950,6 +1955,9 @@ function parseInlineFieldList(section) {
|
|
|
1950
1955
|
// ../../packages/aeg-core/src/verdict-extraction.ts
|
|
1951
1956
|
var HEAD_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged head:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1952
1957
|
var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1958
|
+
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
1959
|
+
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1960
|
+
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1953
1961
|
function firstFiveLines(comment) {
|
|
1954
1962
|
return comment.split(`
|
|
1955
1963
|
`).slice(0, 5).join(`
|
|
@@ -1963,6 +1971,35 @@ function extractObjectivesVersion(comment) {
|
|
|
1963
1971
|
const m = firstFiveLines(comment).match(OBJECTIVES_VERSION_PATTERN);
|
|
1964
1972
|
return m ? m[1].toLowerCase() : null;
|
|
1965
1973
|
}
|
|
1974
|
+
function firstSevenLines(comment) {
|
|
1975
|
+
return comment.split(`
|
|
1976
|
+
`).slice(0, 7).join(`
|
|
1977
|
+
`);
|
|
1978
|
+
}
|
|
1979
|
+
function extractRulingOrdinal(comment) {
|
|
1980
|
+
const m = firstSevenLines(comment).match(RULING_ORDINAL_PATTERN);
|
|
1981
|
+
return m ? Number.parseInt(m[1], 10) : null;
|
|
1982
|
+
}
|
|
1983
|
+
function firstElevenLines(comment) {
|
|
1984
|
+
return comment.split(`
|
|
1985
|
+
`).slice(0, 11).join(`
|
|
1986
|
+
`);
|
|
1987
|
+
}
|
|
1988
|
+
function extractBriefHash(comment) {
|
|
1989
|
+
const m = firstElevenLines(comment).match(BRIEF_HASH_PATTERN);
|
|
1990
|
+
return m ? m[1].toLowerCase() : null;
|
|
1991
|
+
}
|
|
1992
|
+
function extractPolicyDigest(comment) {
|
|
1993
|
+
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
1994
|
+
return m ? m[1].toLowerCase() : null;
|
|
1995
|
+
}
|
|
1996
|
+
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
1997
|
+
function extractFindingSeverities(comment) {
|
|
1998
|
+
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
1999
|
+
severity: m[1],
|
|
2000
|
+
location: m[2]
|
|
2001
|
+
}));
|
|
2002
|
+
}
|
|
1966
2003
|
function extractVerdict(comments, valuePattern, missingLabel) {
|
|
1967
2004
|
const candidates = comments.filter((c) => valuePattern.test(c));
|
|
1968
2005
|
if (candidates.length === 0) {
|
|
@@ -1970,6 +2007,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1970
2007
|
value: `no ${missingLabel} pass was run before merge — DANGLING, see below`,
|
|
1971
2008
|
headSha: null,
|
|
1972
2009
|
objectivesVersion: null,
|
|
2010
|
+
rulingOrdinal: null,
|
|
2011
|
+
briefHash: null,
|
|
2012
|
+
policyDigest: null,
|
|
2013
|
+
findingSeverities: [],
|
|
1973
2014
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
1974
2015
|
};
|
|
1975
2016
|
}
|
|
@@ -1980,6 +2021,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1980
2021
|
value: `the most recent ${missingLabel} comment's VERDICT line is not within its first five lines — DANGLING, see below`,
|
|
1981
2022
|
headSha: null,
|
|
1982
2023
|
objectivesVersion: null,
|
|
2024
|
+
rulingOrdinal: null,
|
|
2025
|
+
briefHash: null,
|
|
2026
|
+
policyDigest: null,
|
|
2027
|
+
findingSeverities: [],
|
|
1983
2028
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
1984
2029
|
};
|
|
1985
2030
|
}
|
|
@@ -1987,6 +2032,10 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
1987
2032
|
value: m[1].toUpperCase().replace(/[_-]/g, " "),
|
|
1988
2033
|
headSha: extractHeadSha(latest),
|
|
1989
2034
|
objectivesVersion: extractObjectivesVersion(latest),
|
|
2035
|
+
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2036
|
+
briefHash: extractBriefHash(latest),
|
|
2037
|
+
policyDigest: extractPolicyDigest(latest),
|
|
2038
|
+
findingSeverities: extractFindingSeverities(latest),
|
|
1990
2039
|
danglingNote: null
|
|
1991
2040
|
};
|
|
1992
2041
|
}
|
|
@@ -2322,6 +2371,53 @@ function evaluateC5(changed, docOwnersContent, prBody, fileExists, waiverActive,
|
|
|
2322
2371
|
}
|
|
2323
2372
|
return out;
|
|
2324
2373
|
}
|
|
2374
|
+
// ../../packages/aeg-core/src/review-policy.ts
|
|
2375
|
+
var CODE_REVIEW_SEVERITY_ORDER = ["BLOCKER", "MAJOR", "MINOR"];
|
|
2376
|
+
var SECURITY_SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW"];
|
|
2377
|
+
var DEFAULT_MAX_ROUNDS = 3;
|
|
2378
|
+
var DEFAULT_REVIEW_POLICY = {
|
|
2379
|
+
codeReviewThreshold: "BLOCKER",
|
|
2380
|
+
securityThreshold: "HIGH",
|
|
2381
|
+
maxRounds: DEFAULT_MAX_ROUNDS
|
|
2382
|
+
};
|
|
2383
|
+
var FILE_SHAPED_LOCATION = /\.[a-zA-Z0-9]{1,10}(:\d+)?\s*$/;
|
|
2384
|
+
var PROSE_LOCATION_PATTERNS = [/\bpr\s*body\b/i, /\bcomment\b/i];
|
|
2385
|
+
var ROLE_FILE_LOCATION = /(^|\/)aeg-root\/roles\//i;
|
|
2386
|
+
function isProseLocation(location) {
|
|
2387
|
+
if (ROLE_FILE_LOCATION.test(location))
|
|
2388
|
+
return true;
|
|
2389
|
+
if (FILE_SHAPED_LOCATION.test(location))
|
|
2390
|
+
return false;
|
|
2391
|
+
return PROSE_LOCATION_PATTERNS.some((pattern) => pattern.test(location));
|
|
2392
|
+
}
|
|
2393
|
+
var PROSE_CAP_SEVERITY = "MINOR";
|
|
2394
|
+
function blockingSeverities(scale, threshold) {
|
|
2395
|
+
const idx = scale.indexOf(threshold);
|
|
2396
|
+
if (idx === -1) {
|
|
2397
|
+
throw new Error(`blockingSeverities: threshold "${threshold}" is not one of ${scale.join(" > ")}`);
|
|
2398
|
+
}
|
|
2399
|
+
return scale.slice(0, idx + 1);
|
|
2400
|
+
}
|
|
2401
|
+
function evaluateReviewFindings(findings, scale, threshold) {
|
|
2402
|
+
const blocking = new Set(blockingSeverities(scale, threshold));
|
|
2403
|
+
const blockingFindings = findings.filter((f) => {
|
|
2404
|
+
if (!scale.includes(f.severity)) {
|
|
2405
|
+
throw new Error(`evaluateReviewFindings: severity "${f.severity}" is not one of ${scale.join(" > ")}`);
|
|
2406
|
+
}
|
|
2407
|
+
const effectiveSeverity = f.location !== undefined && isProseLocation(f.location) ? PROSE_CAP_SEVERITY : f.severity;
|
|
2408
|
+
return blocking.has(effectiveSeverity);
|
|
2409
|
+
});
|
|
2410
|
+
return { outcome: blockingFindings.length > 0 ? "blocked" : "clean", blockingFindings };
|
|
2411
|
+
}
|
|
2412
|
+
function evaluateCodeReview(findings, policy) {
|
|
2413
|
+
return evaluateReviewFindings(findings, CODE_REVIEW_SEVERITY_ORDER, policy.codeReviewThreshold);
|
|
2414
|
+
}
|
|
2415
|
+
function evaluateSecurityReview(findings, policy) {
|
|
2416
|
+
return evaluateReviewFindings(findings, SECURITY_SEVERITY_ORDER, policy.securityThreshold);
|
|
2417
|
+
}
|
|
2418
|
+
function isKnownSeverity(scale, value) {
|
|
2419
|
+
return scale.includes(value);
|
|
2420
|
+
}
|
|
2325
2421
|
// ../../packages/aeg-core/src/pr-tier.ts
|
|
2326
2422
|
var TIER_FIELD = /(\*\*)?\s*Tier\s*(\*\*)?\s*:\s*(\*\*)?\s*([013])\b/i;
|
|
2327
2423
|
function readTierFromPrBody(prBody) {
|
|
@@ -2348,6 +2444,9 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
2348
2444
|
var HEADING_RE = /^##[ \t]*Objectives[ \t]*$/im;
|
|
2349
2445
|
var NEXT_HEADING_RE = /^##[ \t]/m;
|
|
2350
2446
|
var OBJECTIVE_LINE_RE = /^O(\d+)\.[ \t]*(.*)$/;
|
|
2447
|
+
function maskedForHeadingSearch(body) {
|
|
2448
|
+
return maskDetailsBlocks(maskCode(body));
|
|
2449
|
+
}
|
|
2351
2450
|
function hasBacktickedPath(text) {
|
|
2352
2451
|
let i = 0;
|
|
2353
2452
|
while (i < text.length) {
|
|
@@ -2370,16 +2469,22 @@ function stripObjectiveBackticks(text) {
|
|
|
2370
2469
|
function wordCount(text) {
|
|
2371
2470
|
return text.split(/\s+/).filter((w) => /[a-z]/i.test(w)).length;
|
|
2372
2471
|
}
|
|
2373
|
-
function
|
|
2374
|
-
const
|
|
2472
|
+
function objectivesSectionBounds(body) {
|
|
2473
|
+
const masked = maskedForHeadingSearch(body);
|
|
2474
|
+
const heading = HEADING_RE.exec(masked);
|
|
2375
2475
|
if (!heading)
|
|
2376
2476
|
return null;
|
|
2377
|
-
const
|
|
2477
|
+
const start = heading.index + heading[0].length;
|
|
2478
|
+
const afterHeading = masked.slice(start);
|
|
2378
2479
|
const next = NEXT_HEADING_RE.exec(afterHeading);
|
|
2379
|
-
return next ?
|
|
2480
|
+
return { start, end: next ? start + next.index : body.length };
|
|
2481
|
+
}
|
|
2482
|
+
function objectivesSectionText(body) {
|
|
2483
|
+
const bounds = objectivesSectionBounds(body);
|
|
2484
|
+
return bounds === null ? null : body.slice(bounds.start, bounds.end);
|
|
2380
2485
|
}
|
|
2381
2486
|
function hasObjectivesHeading(body) {
|
|
2382
|
-
return HEADING_RE.test(body);
|
|
2487
|
+
return HEADING_RE.test(maskedForHeadingSearch(body));
|
|
2383
2488
|
}
|
|
2384
2489
|
function objectivesOf(body) {
|
|
2385
2490
|
const section = objectivesSectionText(body);
|
|
@@ -2439,6 +2544,15 @@ function isIssueNotFoundError(err) {
|
|
|
2439
2544
|
`);
|
|
2440
2545
|
return /could not resolve to an (?:issue|pull request)|\b404\b|not found/i.test(haystack);
|
|
2441
2546
|
}
|
|
2547
|
+
function resolveObjectivesSource(prBody, issue, cutoverIssue) {
|
|
2548
|
+
if (issue !== null && issue < cutoverIssue)
|
|
2549
|
+
return { kind: "none" };
|
|
2550
|
+
if (issue !== null)
|
|
2551
|
+
return { kind: "issue", issue };
|
|
2552
|
+
if (hasObjectivesHeading(prBody))
|
|
2553
|
+
return { kind: "body" };
|
|
2554
|
+
return { kind: "none" };
|
|
2555
|
+
}
|
|
2442
2556
|
|
|
2443
2557
|
// ../../packages/aeg-core/src/premise-check.ts
|
|
2444
2558
|
import { createHash as createHash3 } from "node:crypto";
|
|
@@ -2674,7 +2788,7 @@ function checkForField(prBody) {
|
|
|
2674
2788
|
]
|
|
2675
2789
|
};
|
|
2676
2790
|
}
|
|
2677
|
-
function
|
|
2791
|
+
function checkClosesNPresence(prBody) {
|
|
2678
2792
|
const closesPattern = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s{0,8}:?\s{0,8}#\d+/i;
|
|
2679
2793
|
if (closesPattern.test(stripCode(prBody))) {
|
|
2680
2794
|
return { status: "pass", errors: [] };
|
|
@@ -2706,10 +2820,22 @@ var COMMIT_TYPES = [
|
|
|
2706
2820
|
"Test"
|
|
2707
2821
|
];
|
|
2708
2822
|
var COMMIT_TYPE_STYLE = new RegExp(`^(${COMMIT_TYPES.join("|")})(\\([a-z0-9-]+\\))?: \\S`);
|
|
2823
|
+
function checkForgeTitle(title) {
|
|
2824
|
+
const taskStyle = /^\[[a-z0-9._-]+\] \S+ — \S/;
|
|
2825
|
+
if (COMMIT_TYPE_STYLE.test(title) || taskStyle.test(title))
|
|
2826
|
+
return { status: "pass", errors: [] };
|
|
2827
|
+
return {
|
|
2828
|
+
status: "fail",
|
|
2829
|
+
errors: [
|
|
2830
|
+
`brief-validation title: "${title}" matches neither title grammar — expected \`Type: description\` / \`Type(scope): description\` (commitlint types + Plan) or \`[tranche] id — description\` (task form).`
|
|
2831
|
+
]
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2709
2834
|
var BRIEF_SHAPE_MARKERS = [checkSurfaceMap, checkDocUpdateList, checkStopConditions, checkAutonomyClause];
|
|
2710
2835
|
var TASK_BRANCH_PATTERN = /^task\/[^/]+\/[^/]+$/;
|
|
2836
|
+
var TASK_ISSUE_BRANCH_PATTERN = /^task\/issue-\d+$/;
|
|
2711
2837
|
function isTaskBranch(branch) {
|
|
2712
|
-
return TASK_BRANCH_PATTERN.test(branch);
|
|
2838
|
+
return TASK_BRANCH_PATTERN.test(branch) || TASK_ISSUE_BRANCH_PATTERN.test(branch);
|
|
2713
2839
|
}
|
|
2714
2840
|
function isBriefShaped(prBody) {
|
|
2715
2841
|
const stripped = stripCode(prBody);
|
|
@@ -2831,8 +2957,9 @@ function packagesNamedIn(text) {
|
|
|
2831
2957
|
}
|
|
2832
2958
|
function hasTestPathForConsumer(text, consumerDir) {
|
|
2833
2959
|
const escaped = consumerDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2834
|
-
const
|
|
2835
|
-
|
|
2960
|
+
const filePathRe = new RegExp(`${escaped}\\/[\\w./-]*\\.test\\.[A-Za-z0-9]+`);
|
|
2961
|
+
const testDirRe = new RegExp(`${escaped}\\/(?:[\\w-]+\\/)*(?:tests|specs)(?:\\/|\\b)`);
|
|
2962
|
+
return filePathRe.test(text) || testDirRe.test(text);
|
|
2836
2963
|
}
|
|
2837
2964
|
function checkConsumerTests(prBody, consumersOf) {
|
|
2838
2965
|
const section4 = extractNumberedSection(prBody, 4);
|
|
@@ -2936,21 +3063,44 @@ function checkBriefSections(prBody, readTier, options = {}) {
|
|
|
2936
3063
|
checkConsumerTests(prBody, consumersOf),
|
|
2937
3064
|
checkDefeatCases(prBody),
|
|
2938
3065
|
...issueObjectives !== undefined ? [checkObjectivesCopy(prBody, issueObjectives), checkObjectivesCoverage(prBody)] : [],
|
|
2939
|
-
...requireClosesN ? [
|
|
3066
|
+
...requireClosesN ? [checkClosesNPresence(prBody)] : []
|
|
2940
3067
|
];
|
|
2941
3068
|
return { errors: results.flatMap((r) => r.errors) };
|
|
2942
3069
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
`
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
3070
|
+
function contentAfterNLines(body, n) {
|
|
3071
|
+
let idx = -1;
|
|
3072
|
+
for (let i = 0;i < n; i++) {
|
|
3073
|
+
idx = body.indexOf(`
|
|
3074
|
+
`, idx + 1);
|
|
3075
|
+
if (idx === -1)
|
|
3076
|
+
return "";
|
|
3077
|
+
}
|
|
3078
|
+
return body.slice(idx + 1);
|
|
3079
|
+
}
|
|
3080
|
+
var BRIEF_MARKER_LINE_RE = /^<!-- aeg:brief:v(\d+) -->$/;
|
|
3081
|
+
function parseBriefMarkerVersion(firstLine) {
|
|
3082
|
+
const m = BRIEF_MARKER_LINE_RE.exec(firstLine.trim());
|
|
3083
|
+
if (!m)
|
|
3084
|
+
return null;
|
|
3085
|
+
const version = Number.parseInt(m[1], 10);
|
|
3086
|
+
return Number.isInteger(version) && version >= 1 ? version : null;
|
|
3087
|
+
}
|
|
3088
|
+
function frozenBriefContent(body, version) {
|
|
3089
|
+
return contentAfterNLines(body, version === 1 ? 2 : 3);
|
|
3090
|
+
}
|
|
3091
|
+
function resolveNewestFrozenBrief(comments, allowlist) {
|
|
3092
|
+
let best = null;
|
|
3093
|
+
for (const c of comments) {
|
|
3094
|
+
if (!isPrincipal(c.author, allowlist))
|
|
3095
|
+
continue;
|
|
3096
|
+
const version = parseBriefMarkerVersion(c.body.split(`
|
|
3097
|
+
`)[0] ?? "");
|
|
3098
|
+
if (version === null)
|
|
3099
|
+
continue;
|
|
3100
|
+
if (best === null || version > best.version)
|
|
3101
|
+
best = { ...c, version };
|
|
3102
|
+
}
|
|
3103
|
+
return best === null ? null : { ...best, content: frozenBriefContent(best.body, best.version) };
|
|
2954
3104
|
}
|
|
2955
3105
|
// ../../packages/aeg-core/src/doctrine-portability.ts
|
|
2956
3106
|
var DEFAULT_SHIPS_PREFIX = "aeg-root/";
|
|
@@ -3203,6 +3353,28 @@ function topLevelSectionText(body, headingName) {
|
|
|
3203
3353
|
const next = /^##[ \t]/m.exec(afterHeading);
|
|
3204
3354
|
return next ? afterHeading.slice(0, next.index) : afterHeading;
|
|
3205
3355
|
}
|
|
3356
|
+
function partHasBacktickedPath(text) {
|
|
3357
|
+
let i = 0;
|
|
3358
|
+
while (i < text.length) {
|
|
3359
|
+
const start = text.indexOf("`", i);
|
|
3360
|
+
if (start === -1)
|
|
3361
|
+
return false;
|
|
3362
|
+
const end = text.indexOf("`", start + 1);
|
|
3363
|
+
if (end === -1)
|
|
3364
|
+
return false;
|
|
3365
|
+
if (text.slice(start + 1, end).includes("/"))
|
|
3366
|
+
return true;
|
|
3367
|
+
i = end + 1;
|
|
3368
|
+
}
|
|
3369
|
+
return false;
|
|
3370
|
+
}
|
|
3371
|
+
var PART_MIN_WORDS_OUTSIDE_BACKTICKS = 3;
|
|
3372
|
+
function stripPartBackticks(text) {
|
|
3373
|
+
return text.replace(/`[^`\n]*`/g, " ");
|
|
3374
|
+
}
|
|
3375
|
+
function partWordCount(text) {
|
|
3376
|
+
return text.split(/\s+/).filter((w) => /[a-z]/i.test(w)).length;
|
|
3377
|
+
}
|
|
3206
3378
|
function looksLikeFilePath(entry2) {
|
|
3207
3379
|
const stripped = entry2.replace(/\/\*\*?$/, "");
|
|
3208
3380
|
const lastSegment = stripped.split("/").pop() ?? stripped;
|
|
@@ -3243,6 +3415,18 @@ function globCoversPath(glob, path) {
|
|
|
3243
3415
|
const p = path.replace(/\/+$/, "");
|
|
3244
3416
|
return g === p || g.startsWith(`${p}/`) || p.startsWith(`${g}/`);
|
|
3245
3417
|
}
|
|
3418
|
+
function checkSurfaceGlobsResolve(body, resolvesToFile) {
|
|
3419
|
+
const surface = parseIssueSurface(body);
|
|
3420
|
+
if (!surface.ok)
|
|
3421
|
+
return { status: "pass", errors: [] };
|
|
3422
|
+
const errors = [];
|
|
3423
|
+
for (const glob of surface.value.in) {
|
|
3424
|
+
if (!resolvesToFile(glob)) {
|
|
3425
|
+
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.`);
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3428
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3429
|
+
}
|
|
3246
3430
|
function checkSurfaceScope(changedFiles, outGlobs) {
|
|
3247
3431
|
if (outGlobs.length === 0)
|
|
3248
3432
|
return { ok: true };
|
|
@@ -3254,9 +3438,77 @@ function checkSurfaceScope(changedFiles, outGlobs) {
|
|
|
3254
3438
|
}
|
|
3255
3439
|
return violations.length > 0 ? { ok: false, violations } : { ok: true };
|
|
3256
3440
|
}
|
|
3441
|
+
var ISSUE_PART_LINE_RE = /^Part\s+(\d+)\s*\(([^)]*)\)\s*[-—–]\s*(.*)$/i;
|
|
3442
|
+
function parseIssueParts(body) {
|
|
3443
|
+
const section = topLevelSectionText(body, "Parts");
|
|
3444
|
+
if (section === null)
|
|
3445
|
+
return { ok: false, errors: ["no `## Parts` heading found in the body."] };
|
|
3446
|
+
const lines = section.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
|
|
3447
|
+
const parts = [];
|
|
3448
|
+
const errors = [];
|
|
3449
|
+
for (const line of lines) {
|
|
3450
|
+
const m = ISSUE_PART_LINE_RE.exec(line);
|
|
3451
|
+
if (!m) {
|
|
3452
|
+
errors.push(`"${line}" is not a well-formed Parts line — expected \`Part <n> (<refs>) — <outcome>\`.`);
|
|
3453
|
+
continue;
|
|
3454
|
+
}
|
|
3455
|
+
const n = Number.parseInt(m[1], 10);
|
|
3456
|
+
const refs = m[2];
|
|
3457
|
+
const text = m[3].trim();
|
|
3458
|
+
if (text.length === 0) {
|
|
3459
|
+
errors.push(`Part ${n} has no outcome text after the dash — every Part states one observable outcome.`);
|
|
3460
|
+
continue;
|
|
3461
|
+
}
|
|
3462
|
+
if (partHasBacktickedPath(text) && partWordCount(stripPartBackticks(text)) < PART_MIN_WORDS_OUTSIDE_BACKTICKS) {
|
|
3463
|
+
errors.push(`Part ${n} is little more than a file path — a Part names an outcome and symbols, never a bare path.`);
|
|
3464
|
+
continue;
|
|
3465
|
+
}
|
|
3466
|
+
const objectiveIds = [...refs.matchAll(/O(\d+)/g)].map((r) => Number.parseInt(r[1], 10));
|
|
3467
|
+
parts.push({ n, objectiveIds, text });
|
|
3468
|
+
}
|
|
3469
|
+
if (parts.length === 0) {
|
|
3470
|
+
errors.push("the `## Parts` section has no well-formed `Part <n> (<refs>) — <outcome>` lines.");
|
|
3471
|
+
}
|
|
3472
|
+
if (errors.length > 0)
|
|
3473
|
+
return { ok: false, errors };
|
|
3474
|
+
return { ok: true, value: parts };
|
|
3475
|
+
}
|
|
3476
|
+
function checkPartsCiteDefinedObjectives(body) {
|
|
3477
|
+
const parts = parseIssueParts(body);
|
|
3478
|
+
const objectives = objectivesOf(body);
|
|
3479
|
+
if (!parts.ok || !objectives.ok)
|
|
3480
|
+
return { status: "pass", errors: [] };
|
|
3481
|
+
const definedIds = new Set(objectives.objectives.map((o) => Number.parseInt(o.id.slice(1), 10)));
|
|
3482
|
+
const errors = [];
|
|
3483
|
+
for (const part of parts.value) {
|
|
3484
|
+
for (const objectiveId of part.objectiveIds) {
|
|
3485
|
+
if (!definedIds.has(objectiveId)) {
|
|
3486
|
+
errors.push(`issue-validation Parts: Part ${part.n} cites O${objectiveId}, which the Issue's own \`## Objectives\` section does not define.`);
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3490
|
+
return { status: errors.length > 0 ? "fail" : "pass", errors };
|
|
3491
|
+
}
|
|
3257
3492
|
function isTaskIssueLabelSet(labels) {
|
|
3258
3493
|
return hasLabel("tranche", labels);
|
|
3259
3494
|
}
|
|
3495
|
+
function checkTrancheLabelPresence(_body, _labels) {
|
|
3496
|
+
return { status: "pass", errors: [] };
|
|
3497
|
+
}
|
|
3498
|
+
function checkMilestoneAttach(labels, currentMilestoneTitle, resolvedMilestoneTitle) {
|
|
3499
|
+
if (!isTaskIssueLabelSet(labels))
|
|
3500
|
+
return { status: "pass", errors: [] };
|
|
3501
|
+
if (resolvedMilestoneTitle === null)
|
|
3502
|
+
return { status: "pass", errors: [] };
|
|
3503
|
+
if (currentMilestoneTitle === resolvedMilestoneTitle)
|
|
3504
|
+
return { status: "pass", errors: [] };
|
|
3505
|
+
return {
|
|
3506
|
+
status: "fail",
|
|
3507
|
+
errors: [
|
|
3508
|
+
`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}".`
|
|
3509
|
+
]
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3260
3512
|
var TYPE_LABEL_IDS = LABELS.filter((l) => l.category === "type").map((l) => l.id);
|
|
3261
3513
|
function isControlCodePoint(codePoint) {
|
|
3262
3514
|
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
@@ -3321,6 +3573,19 @@ function checkProjectsRegistered(body, _labels, registeredNames) {
|
|
|
3321
3573
|
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;
|
|
3322
3574
|
var DOC_PATH_RE_GLOBAL = new RegExp(DOC_PATH_RE.source, "gi");
|
|
3323
3575
|
|
|
3576
|
+
// ../../packages/aeg-core/src/task-branch-identity.ts
|
|
3577
|
+
var ISSUE_BRANCH_PATTERN = /^task\/issue-(\d+)$/;
|
|
3578
|
+
var TRANCHE_BRANCH_PATTERN = /^task\/([^/]+)\/([^/]+)$/;
|
|
3579
|
+
function parseTaskBranchIdentity(branch) {
|
|
3580
|
+
const issueMatch = ISSUE_BRANCH_PATTERN.exec(branch);
|
|
3581
|
+
if (issueMatch)
|
|
3582
|
+
return { kind: "issue", issueNumber: Number(issueMatch[1]) };
|
|
3583
|
+
const trancheMatch = TRANCHE_BRANCH_PATTERN.exec(branch);
|
|
3584
|
+
if (trancheMatch)
|
|
3585
|
+
return { kind: "tranche", tranche: trancheMatch[1], taskId: trancheMatch[2] };
|
|
3586
|
+
return null;
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3324
3589
|
// ../../packages/aeg-core/src/coherence-checks.ts
|
|
3325
3590
|
var COHERENCE_ENFORCED_FROM = "2026-07-01";
|
|
3326
3591
|
function isGrandfathered(isoDate) {
|
|
@@ -3341,6 +3606,7 @@ function checkA1(entries, principalAllowlist = PRINCIPAL_ALLOWLIST) {
|
|
|
3341
3606
|
if (handClosed)
|
|
3342
3607
|
continue;
|
|
3343
3608
|
failures.push({
|
|
3609
|
+
code: "closed-without-merge",
|
|
3344
3610
|
issue: e.task.issue,
|
|
3345
3611
|
tranche: e.trancheSlug,
|
|
3346
3612
|
task: e.task.id,
|
|
@@ -3365,6 +3631,7 @@ function checkA3(entries) {
|
|
|
3365
3631
|
continue;
|
|
3366
3632
|
if (e.facts.prState === "merged" && e.facts.issueState !== "closed") {
|
|
3367
3633
|
failures.push({
|
|
3634
|
+
code: "auto-close-misfire",
|
|
3368
3635
|
issue: e.task.issue,
|
|
3369
3636
|
tranche: e.trancheSlug,
|
|
3370
3637
|
task: e.task.id,
|
|
@@ -3389,6 +3656,7 @@ function checkT1(entries) {
|
|
|
3389
3656
|
continue;
|
|
3390
3657
|
if (e.facts === undefined) {
|
|
3391
3658
|
failures.push({
|
|
3659
|
+
code: "phantom-issue-ref",
|
|
3392
3660
|
issue: e.task.issue,
|
|
3393
3661
|
tranche: e.trancheSlug,
|
|
3394
3662
|
task: e.task.id,
|
|
@@ -3407,6 +3675,7 @@ function checkT2(openIssuesBySlug, topologyIssuesBySlug, ciTrancheSlug) {
|
|
|
3407
3675
|
for (const num of openNums) {
|
|
3408
3676
|
if (!topologySet.has(num)) {
|
|
3409
3677
|
failures.push({
|
|
3678
|
+
code: "orphan-task",
|
|
3410
3679
|
issue: num,
|
|
3411
3680
|
tranche: slug,
|
|
3412
3681
|
reason: `Issue #${num} is open and labeled ${trancheLabel(slug)} but does not appear in the topology file`
|
|
@@ -3441,6 +3710,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3441
3710
|
continue;
|
|
3442
3711
|
if (forgeUnavailableSlugs?.has(e.trancheSlug)) {
|
|
3443
3712
|
failures.push({
|
|
3713
|
+
code: "tbd-in-active-tranche",
|
|
3444
3714
|
issue: null,
|
|
3445
3715
|
tranche: e.trancheSlug,
|
|
3446
3716
|
task: e.task.id,
|
|
@@ -3450,6 +3720,7 @@ function checkT3(entries, ciTrancheSlug, enrichedEntries, forgeUnavailableSlugs)
|
|
|
3450
3720
|
continue;
|
|
3451
3721
|
}
|
|
3452
3722
|
failures.push({
|
|
3723
|
+
code: "tbd-in-active-tranche",
|
|
3453
3724
|
issue: null,
|
|
3454
3725
|
tranche: e.trancheSlug,
|
|
3455
3726
|
task: e.task.id,
|
|
@@ -3482,6 +3753,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3482
3753
|
const sameIssue = depEntry.task.issue !== null && e.task.issue !== null && depEntry.task.issue === e.task.issue;
|
|
3483
3754
|
if (sameTask || sameIssue) {
|
|
3484
3755
|
failures.push({
|
|
3756
|
+
code: "d1-self-dependency",
|
|
3485
3757
|
issue: e.task.issue,
|
|
3486
3758
|
tranche: e.trancheSlug,
|
|
3487
3759
|
task: e.task.id,
|
|
@@ -3493,6 +3765,7 @@ function checkD1(entries, issueToEntry, taskToEntry) {
|
|
|
3493
3765
|
const depClosed = depFacts?.issueState === "closed";
|
|
3494
3766
|
if (!depClosed) {
|
|
3495
3767
|
failures.push({
|
|
3768
|
+
code: "dispatched-on-unmet-deps",
|
|
3496
3769
|
issue: e.task.issue,
|
|
3497
3770
|
tranche: e.trancheSlug,
|
|
3498
3771
|
task: e.task.id,
|
|
@@ -3518,11 +3791,13 @@ function checkR1(issuesBySlug, grandfatheredIssues, registeredNames = []) {
|
|
|
3518
3791
|
const errors = [
|
|
3519
3792
|
...checkIssueRationale(issue.body).errors,
|
|
3520
3793
|
...checkProjectsRegistered(issue.body, issue.labels, registeredNames).errors,
|
|
3521
|
-
...checkIssueObjectives(issue.body, issue.number).errors
|
|
3794
|
+
...checkIssueObjectives(issue.body, issue.number).errors,
|
|
3795
|
+
...checkPartsCiteDefinedObjectives(issue.body).errors
|
|
3522
3796
|
];
|
|
3523
3797
|
if (errors.length === 0)
|
|
3524
3798
|
continue;
|
|
3525
3799
|
failures.push({
|
|
3800
|
+
code: "missing-rationale-field",
|
|
3526
3801
|
issue: issue.number,
|
|
3527
3802
|
tranche: slug,
|
|
3528
3803
|
reason: `Issue #${issue.number} fails the rationale gate: ${errors.join(" | ")}`,
|
|
@@ -3551,6 +3826,7 @@ function checkL1(files, entriesBySlug) {
|
|
|
3551
3826
|
const allClosed = withFacts.every((e) => e.facts?.issueState === "closed");
|
|
3552
3827
|
if (allClosed) {
|
|
3553
3828
|
failures.push({
|
|
3829
|
+
code: "archive-recommended",
|
|
3554
3830
|
tranche: f.slug,
|
|
3555
3831
|
reason: "Active tranche has no open task-Issues — consider archiving to completed/"
|
|
3556
3832
|
});
|
|
@@ -3582,27 +3858,38 @@ function extractClosesReferences(prBody) {
|
|
|
3582
3858
|
}
|
|
3583
3859
|
return referenced;
|
|
3584
3860
|
}
|
|
3585
|
-
function
|
|
3861
|
+
function checkClosesNTopology(branch, prBody, trancheFiles, taskIssueRefs) {
|
|
3586
3862
|
const referenced = extractClosesReferences(prBody);
|
|
3587
3863
|
if (taskIssueRefs) {
|
|
3588
3864
|
for (const n of referenced) {
|
|
3589
|
-
const
|
|
3590
|
-
if (!
|
|
3865
|
+
const ref2 = taskIssueRefs.get(n);
|
|
3866
|
+
if (!ref2)
|
|
3591
3867
|
continue;
|
|
3592
|
-
const expectedBranch = `task/${
|
|
3868
|
+
const expectedBranch = `task/${ref2.trancheSlug}/${ref2.taskId}`;
|
|
3593
3869
|
if (branch !== expectedBranch) {
|
|
3594
3870
|
return {
|
|
3595
3871
|
ok: false,
|
|
3596
|
-
message: `closes-n-reverse: branch "${branch}" closes #${n} (task ${
|
|
3872
|
+
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.`
|
|
3597
3873
|
};
|
|
3598
3874
|
}
|
|
3599
3875
|
}
|
|
3600
3876
|
}
|
|
3601
|
-
const
|
|
3602
|
-
if (!
|
|
3877
|
+
const ref = parseTaskBranchIdentity(branch);
|
|
3878
|
+
if (!ref)
|
|
3603
3879
|
return { ok: true };
|
|
3604
|
-
|
|
3605
|
-
|
|
3880
|
+
if (ref.kind === "issue") {
|
|
3881
|
+
const expectedIssue2 = ref.issueNumber;
|
|
3882
|
+
if (!referenced.has(expectedIssue2)) {
|
|
3883
|
+
return {
|
|
3884
|
+
ok: false,
|
|
3885
|
+
expectedIssue: expectedIssue2,
|
|
3886
|
+
message: `closes-n: PR body does not contain \`Closes #${expectedIssue2}\` (required for branch "${branch}"). Add it to the PR body Summary section.`
|
|
3887
|
+
};
|
|
3888
|
+
}
|
|
3889
|
+
return { ok: true, expectedIssue: expectedIssue2 };
|
|
3890
|
+
}
|
|
3891
|
+
const trancheSlug = ref.tranche;
|
|
3892
|
+
const taskId = ref.taskId;
|
|
3606
3893
|
const trancheFile = trancheFiles.find((f) => f.slug === trancheSlug);
|
|
3607
3894
|
if (!trancheFile) {
|
|
3608
3895
|
return {
|
|
@@ -3654,29 +3941,67 @@ function extractIssue(body) {
|
|
|
3654
3941
|
const issue = headerNums.length > 0 ? headerNums[0] : bodyNums[0];
|
|
3655
3942
|
return { issue, extraIssues: bodyNums.filter((n) => n !== issue), outsideHeader: headerNums.length === 0 };
|
|
3656
3943
|
}
|
|
3657
|
-
// ../../packages/aeg-core/src/review-
|
|
3658
|
-
|
|
3659
|
-
|
|
3944
|
+
// ../../packages/aeg-core/src/review-input-manifest.ts
|
|
3945
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
3946
|
+
function briefHash(brief) {
|
|
3947
|
+
return createHash4("sha256").update(`${brief}
|
|
3948
|
+
`).digest("hex");
|
|
3949
|
+
}
|
|
3950
|
+
function policyDigest(policy) {
|
|
3951
|
+
return createHash4("sha256").update(JSON.stringify({ codeReviewThreshold: policy.codeReviewThreshold, securityThreshold: policy.securityThreshold })).digest("hex");
|
|
3952
|
+
}
|
|
3953
|
+
function isBoundToHead(echoed, headSha) {
|
|
3954
|
+
if (!echoed.headSha)
|
|
3660
3955
|
return false;
|
|
3661
|
-
return headSha.toLowerCase().startsWith(
|
|
3956
|
+
return headSha.toLowerCase().startsWith(echoed.headSha.toLowerCase());
|
|
3662
3957
|
}
|
|
3663
|
-
function isBoundByPatchIdentity(
|
|
3664
|
-
if (patchIdOf === undefined || !
|
|
3958
|
+
function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
3959
|
+
if (patchIdOf === undefined || !echoed.headSha)
|
|
3665
3960
|
return false;
|
|
3666
|
-
const judged = patchIdOf(
|
|
3961
|
+
const judged = patchIdOf(echoed.headSha);
|
|
3667
3962
|
const current = patchIdOf(headSha);
|
|
3668
3963
|
if (judged === null || current === null)
|
|
3669
3964
|
return false;
|
|
3670
3965
|
return judged === current;
|
|
3671
3966
|
}
|
|
3672
|
-
function isBoundToPatch(
|
|
3673
|
-
return isBoundToHead(
|
|
3967
|
+
function isBoundToPatch(echoed, headSha, patchIdOf) {
|
|
3968
|
+
return isBoundToHead(echoed, headSha) || isBoundByPatchIdentity(echoed, headSha, patchIdOf);
|
|
3674
3969
|
}
|
|
3675
|
-
function isBoundToObjectives(
|
|
3970
|
+
function isBoundToObjectives(echoed, currentVersion) {
|
|
3676
3971
|
if (currentVersion === null)
|
|
3677
3972
|
return true;
|
|
3678
|
-
return
|
|
3973
|
+
return echoed.objectivesVersion === currentVersion;
|
|
3974
|
+
}
|
|
3975
|
+
function isBoundToRulings(echoed, currentOrdinal) {
|
|
3976
|
+
if (echoed.rulingOrdinal === null)
|
|
3977
|
+
return currentOrdinal === 0;
|
|
3978
|
+
return echoed.rulingOrdinal === currentOrdinal;
|
|
3979
|
+
}
|
|
3980
|
+
function isBoundToBriefHash(echoed, currentHash) {
|
|
3981
|
+
if (currentHash === null)
|
|
3982
|
+
return true;
|
|
3983
|
+
return echoed.briefHash === currentHash;
|
|
3984
|
+
}
|
|
3985
|
+
function isBoundToPolicy(echoed, currentDigest) {
|
|
3986
|
+
return echoed.policyDigest === currentDigest;
|
|
3679
3987
|
}
|
|
3988
|
+
function compareManifest(echoed, current, patchIdOf) {
|
|
3989
|
+
const head = isBoundToPatch(echoed, current.headSha, patchIdOf);
|
|
3990
|
+
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
3991
|
+
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
3992
|
+
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
3993
|
+
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
3994
|
+
return {
|
|
3995
|
+
bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
3996
|
+
head,
|
|
3997
|
+
briefHash: briefHashBound,
|
|
3998
|
+
objectivesVersion: objectivesVersion2,
|
|
3999
|
+
rulingOrdinal,
|
|
4000
|
+
policyDigest: policyDigestBound
|
|
4001
|
+
};
|
|
4002
|
+
}
|
|
4003
|
+
|
|
4004
|
+
// ../../packages/aeg-core/src/review-gate.ts
|
|
3680
4005
|
function checkReviewGate(input) {
|
|
3681
4006
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
3682
4007
|
const waived = isWaiverLabelActorVerified({
|
|
@@ -3699,13 +4024,55 @@ function checkReviewGate(input) {
|
|
|
3699
4024
|
const verifiedBodies = verified.map((c) => c.body);
|
|
3700
4025
|
const codeReview = extractCodeReviewVerdict(verifiedBodies);
|
|
3701
4026
|
const security = extractSecurityReviewVerdict(verifiedBodies);
|
|
3702
|
-
const
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
4027
|
+
const policy = input.policy ?? DEFAULT_REVIEW_POLICY;
|
|
4028
|
+
let codeReviewPolicyEvaluation;
|
|
4029
|
+
let securityPolicyEvaluation;
|
|
4030
|
+
try {
|
|
4031
|
+
codeReviewPolicyEvaluation = evaluateCodeReview(codeReview.findingSeverities, policy);
|
|
4032
|
+
securityPolicyEvaluation = evaluateSecurityReview(security.findingSeverities, policy);
|
|
4033
|
+
} catch (err) {
|
|
4034
|
+
return {
|
|
4035
|
+
verdict: "fail",
|
|
4036
|
+
reason: `a verdict comment carries a finding severity this repository's policy does not recognize: ${err instanceof Error ? err.message : String(err)}`,
|
|
4037
|
+
waived: false
|
|
4038
|
+
};
|
|
4039
|
+
}
|
|
4040
|
+
const codeReviewTextClean = codeReview.value === "APPROVE";
|
|
4041
|
+
const securityTextClean = security.value === "PASS";
|
|
4042
|
+
const codeReviewPolicyClean = codeReviewPolicyEvaluation.outcome === "clean";
|
|
4043
|
+
const securityPolicyClean = securityPolicyEvaluation.outcome === "clean";
|
|
4044
|
+
const codeReviewClean = codeReviewTextClean && codeReviewPolicyClean;
|
|
4045
|
+
const securityClean = securityTextClean && securityPolicyClean;
|
|
4046
|
+
const currentManifest = {
|
|
4047
|
+
headSha: input.headSha,
|
|
4048
|
+
briefHash: input.briefHash ?? null,
|
|
4049
|
+
objectivesVersion: input.objectivesVersion,
|
|
4050
|
+
rulingOrdinal: input.rulingOrdinal,
|
|
4051
|
+
policyDigest: policyDigest(policy)
|
|
4052
|
+
};
|
|
4053
|
+
const codeReviewEchoed = {
|
|
4054
|
+
headSha: codeReview.headSha,
|
|
4055
|
+
briefHash: codeReview.briefHash,
|
|
4056
|
+
objectivesVersion: codeReview.objectivesVersion,
|
|
4057
|
+
rulingOrdinal: codeReview.rulingOrdinal,
|
|
4058
|
+
policyDigest: codeReview.policyDigest
|
|
4059
|
+
};
|
|
4060
|
+
const securityEchoed = {
|
|
4061
|
+
headSha: security.headSha,
|
|
4062
|
+
briefHash: security.briefHash,
|
|
4063
|
+
objectivesVersion: security.objectivesVersion,
|
|
4064
|
+
rulingOrdinal: security.rulingOrdinal,
|
|
4065
|
+
policyDigest: security.policyDigest
|
|
4066
|
+
};
|
|
4067
|
+
const codeReviewBinding = compareManifest(codeReviewEchoed, currentManifest, input.patchIdOf);
|
|
4068
|
+
const securityBinding = compareManifest(securityEchoed, currentManifest, input.patchIdOf);
|
|
4069
|
+
const codeReviewBound = codeReviewBinding.head;
|
|
4070
|
+
const securityBound = securityBinding.head;
|
|
4071
|
+
const codeReviewObjectivesBound = codeReviewBinding.objectivesVersion;
|
|
4072
|
+
const securityObjectivesBound = securityBinding.objectivesVersion;
|
|
4073
|
+
const codeReviewRulingsBound = codeReviewBinding.rulingOrdinal;
|
|
4074
|
+
const securityRulingsBound = securityBinding.rulingOrdinal;
|
|
4075
|
+
if (codeReviewClean && codeReviewBinding.bound && securityClean && securityBinding.bound && mechanicalChecksClean) {
|
|
3709
4076
|
return {
|
|
3710
4077
|
verdict: "pass",
|
|
3711
4078
|
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.`,
|
|
@@ -3713,19 +4080,35 @@ function checkReviewGate(input) {
|
|
|
3713
4080
|
};
|
|
3714
4081
|
}
|
|
3715
4082
|
const problems = [];
|
|
3716
|
-
if (!
|
|
4083
|
+
if (!codeReviewTextClean) {
|
|
3717
4084
|
problems.push(`code-reviewer verdict is not a clean APPROVE (found: ${codeReview.value})`);
|
|
4085
|
+
} else if (!codeReviewPolicyClean) {
|
|
4086
|
+
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`);
|
|
3718
4087
|
} else if (!codeReviewBound) {
|
|
3719
4088
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
3720
4089
|
} else if (!codeReviewObjectivesBound) {
|
|
3721
4090
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
3722
|
-
}
|
|
3723
|
-
|
|
4091
|
+
} else if (!codeReviewRulingsBound) {
|
|
4092
|
+
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`);
|
|
4093
|
+
} else if (!codeReviewBinding.briefHash) {
|
|
4094
|
+
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"}`);
|
|
4095
|
+
} else if (!codeReviewBinding.policyDigest) {
|
|
4096
|
+
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}`);
|
|
4097
|
+
}
|
|
4098
|
+
if (!securityTextClean) {
|
|
3724
4099
|
problems.push(`security-review verdict is not a clean PASS (found: ${security.value})`);
|
|
4100
|
+
} else if (!securityPolicyClean) {
|
|
4101
|
+
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`);
|
|
3725
4102
|
} else if (!securityBound) {
|
|
3726
4103
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
3727
4104
|
} else if (!securityObjectivesBound) {
|
|
3728
4105
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4106
|
+
} else if (!securityRulingsBound) {
|
|
4107
|
+
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`);
|
|
4108
|
+
} else if (!securityBinding.briefHash) {
|
|
4109
|
+
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"}`);
|
|
4110
|
+
} else if (!securityBinding.policyDigest) {
|
|
4111
|
+
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}`);
|
|
3729
4112
|
}
|
|
3730
4113
|
if (!mechanicalChecksClean) {
|
|
3731
4114
|
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(", ")}`);
|
|
@@ -3742,6 +4125,24 @@ var DEFAULT_RELEASE_ACTOR = "github-actions[bot]";
|
|
|
3742
4125
|
function isChangesetsReleasePr(branch, author, expectedAuthor) {
|
|
3743
4126
|
return branch === CHANGESET_RELEASE_BRANCH && author === expectedAuthor;
|
|
3744
4127
|
}
|
|
4128
|
+
// ../../packages/aeg-core/src/ruling-ordinal.ts
|
|
4129
|
+
var RULING_MARKER_ORDINAL = /^<!-- aeg:principal:ruling:\d+-(\d+) -->$/;
|
|
4130
|
+
function newestPrincipalRulingOrdinal(comments, allowlist) {
|
|
4131
|
+
let best = 0;
|
|
4132
|
+
for (const c of comments) {
|
|
4133
|
+
if (!isPrincipal(c.author, allowlist))
|
|
4134
|
+
continue;
|
|
4135
|
+
const firstLine = (c.body.split(`
|
|
4136
|
+
`)[0] ?? "").trim();
|
|
4137
|
+
const m = RULING_MARKER_ORDINAL.exec(firstLine);
|
|
4138
|
+
if (!m)
|
|
4139
|
+
continue;
|
|
4140
|
+
const k = Number.parseInt(m[1], 10);
|
|
4141
|
+
if (k > best)
|
|
4142
|
+
best = k;
|
|
4143
|
+
}
|
|
4144
|
+
return best;
|
|
4145
|
+
}
|
|
3745
4146
|
// ../../packages/aeg-core/src/markdown-table.ts
|
|
3746
4147
|
function splitRow(line) {
|
|
3747
4148
|
const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
|
|
@@ -4399,42 +4800,45 @@ function checkDispatchReadiness(input) {
|
|
|
4399
4800
|
const { trancheSlug, task } = input;
|
|
4400
4801
|
const taskLabel = `task ${task.id} (tranche ${trancheSlug})`;
|
|
4401
4802
|
const principalAllowlist = input.principalAllowlist ?? PRINCIPAL_ALLOWLIST;
|
|
4402
|
-
const
|
|
4803
|
+
const blockerDetails = [];
|
|
4804
|
+
const push = (blockerClass, message) => {
|
|
4805
|
+
blockerDetails.push({ class: blockerClass, message });
|
|
4806
|
+
};
|
|
4403
4807
|
if (task.issue === null) {
|
|
4404
|
-
|
|
4808
|
+
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.`);
|
|
4405
4809
|
} else if (input.issue === null) {
|
|
4406
|
-
|
|
4810
|
+
push("issue-existence", `dispatch-gate issue-existence: ${taskLabel} names Issue #${task.issue}, but it does not resolve to a real GitHub Issue (phantom reference).`);
|
|
4407
4811
|
}
|
|
4408
4812
|
if (input.issue !== null && !input.issueRationalePass) {
|
|
4409
|
-
|
|
4813
|
+
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.`);
|
|
4410
4814
|
}
|
|
4411
4815
|
for (const dep of input.dependsOn) {
|
|
4412
4816
|
if (isSelfDependency(dep, task, input.issue)) {
|
|
4413
4817
|
const issueStr = input.issue !== null ? `#${input.issue.number}` : "?";
|
|
4414
|
-
|
|
4818
|
+
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.`);
|
|
4415
4819
|
continue;
|
|
4416
4820
|
}
|
|
4417
4821
|
if (dep.resolved === false) {
|
|
4418
|
-
|
|
4822
|
+
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.`);
|
|
4419
4823
|
continue;
|
|
4420
4824
|
}
|
|
4421
4825
|
if (!dep.merged && !isHandClosedByRecognizedPrincipal(dep, principalAllowlist)) {
|
|
4422
4826
|
const issueStr = dep.issue !== null ? ` (#${dep.issue})` : "";
|
|
4423
|
-
|
|
4827
|
+
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.`);
|
|
4424
4828
|
}
|
|
4425
4829
|
}
|
|
4426
4830
|
for (const c of input.conflictsWith) {
|
|
4427
4831
|
if (c.openOrInFlight) {
|
|
4428
4832
|
const issueStr = c.issue !== null ? ` (#${c.issue})` : "";
|
|
4429
|
-
|
|
4833
|
+
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.`);
|
|
4430
4834
|
}
|
|
4431
4835
|
}
|
|
4432
4836
|
for (const proj of input.priorTrancheArchival) {
|
|
4433
4837
|
if (proj.priorTrancheSlug !== null && !proj.archived) {
|
|
4434
|
-
|
|
4838
|
+
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.`);
|
|
4435
4839
|
}
|
|
4436
4840
|
}
|
|
4437
|
-
return { ready:
|
|
4841
|
+
return { ready: blockerDetails.length === 0, blockers: blockerDetails.map((b) => b.message), blockerDetails };
|
|
4438
4842
|
}
|
|
4439
4843
|
// ../../packages/aeg-core/src/single-plan-pr.ts
|
|
4440
4844
|
function trancheSlugFromTopologyPath(path) {
|
|
@@ -4536,6 +4940,91 @@ function checkBranchTopology(input) {
|
|
|
4536
4940
|
reason: `Branch \`${branch}\` matches topology row \`${taskId}\` in ${topoPath}.`
|
|
4537
4941
|
};
|
|
4538
4942
|
}
|
|
4943
|
+
// ../../packages/aeg-core/src/task-tools.ts
|
|
4944
|
+
import { z } from "zod";
|
|
4945
|
+
var TASK_TOOL_ERROR_KINDS = [
|
|
4946
|
+
"validation",
|
|
4947
|
+
"authority",
|
|
4948
|
+
"precondition",
|
|
4949
|
+
"capability",
|
|
4950
|
+
"infrastructure",
|
|
4951
|
+
"cancellation",
|
|
4952
|
+
"timeout",
|
|
4953
|
+
"uncertain_effect"
|
|
4954
|
+
];
|
|
4955
|
+
var TaskToolErrorSchema = z.object({
|
|
4956
|
+
kind: z.enum(TASK_TOOL_ERROR_KINDS),
|
|
4957
|
+
message: z.string().min(1),
|
|
4958
|
+
detail: z.string().optional()
|
|
4959
|
+
});
|
|
4960
|
+
var TaskToolRefSchema = z.union([
|
|
4961
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
4962
|
+
z.object({ issue: z.number().int().positive() })
|
|
4963
|
+
]);
|
|
4964
|
+
var MAX_PAGE_LIMIT = 100;
|
|
4965
|
+
var PageRequestSchema = z.object({
|
|
4966
|
+
cursor: z.string().optional(),
|
|
4967
|
+
limit: z.number().int().positive().max(MAX_PAGE_LIMIT).optional()
|
|
4968
|
+
});
|
|
4969
|
+
var FreshnessSchema = z.enum(["fresh", "stale", "unknown"]);
|
|
4970
|
+
var ObservedSchema = z.object({
|
|
4971
|
+
observedAt: z.string(),
|
|
4972
|
+
freshness: FreshnessSchema
|
|
4973
|
+
});
|
|
4974
|
+
var TaskStatusInputSchema = z.object({
|
|
4975
|
+
task: TaskToolRefSchema.optional()
|
|
4976
|
+
}).merge(PageRequestSchema);
|
|
4977
|
+
var TaskStatusItemSchema = z.object({
|
|
4978
|
+
task: TaskToolRefSchema,
|
|
4979
|
+
issue: z.number().int().positive(),
|
|
4980
|
+
pr: z.number().int().positive().nullable(),
|
|
4981
|
+
state: z.string()
|
|
4982
|
+
}).merge(ObservedSchema);
|
|
4983
|
+
var TaskStatusResultSchema = z.object({
|
|
4984
|
+
items: z.array(TaskStatusItemSchema),
|
|
4985
|
+
nextCursor: z.string().nullable()
|
|
4986
|
+
});
|
|
4987
|
+
var RequestedAuthoritySchema = z.enum(["planner", "principal", "operator", "self"]);
|
|
4988
|
+
var EscalationInputsSchema = z.object({
|
|
4989
|
+
task: z.number().int().positive(),
|
|
4990
|
+
round: z.number().int().nonnegative(),
|
|
4991
|
+
head: z.string(),
|
|
4992
|
+
branch: z.string(),
|
|
4993
|
+
prNumber: z.number().int().positive()
|
|
4994
|
+
});
|
|
4995
|
+
var EscalationEvidenceSchema = z.object({
|
|
4996
|
+
round: z.number().int().nonnegative(),
|
|
4997
|
+
reviewer: z.string().nullable(),
|
|
4998
|
+
security: z.string().nullable()
|
|
4999
|
+
});
|
|
5000
|
+
var TaskEscalationReadInputSchema = z.object({
|
|
5001
|
+
task: TaskToolRefSchema
|
|
5002
|
+
}).merge(PageRequestSchema);
|
|
5003
|
+
var TaskEscalationPacketSchema = z.object({
|
|
5004
|
+
reason: z.string(),
|
|
5005
|
+
detail: z.string().nullable(),
|
|
5006
|
+
inputs: EscalationInputsSchema.nullable(),
|
|
5007
|
+
evidence: EscalationEvidenceSchema.nullable(),
|
|
5008
|
+
attemptedRecovery: z.string(),
|
|
5009
|
+
requestedAuthority: RequestedAuthoritySchema,
|
|
5010
|
+
permittedNextActions: z.array(z.string())
|
|
5011
|
+
}).merge(ObservedSchema);
|
|
5012
|
+
var TaskEscalationReadResultSchema = z.object({
|
|
5013
|
+
items: z.array(TaskEscalationPacketSchema),
|
|
5014
|
+
nextCursor: z.string().nullable()
|
|
5015
|
+
}).merge(ObservedSchema);
|
|
5016
|
+
var TaskStartInputSchema = z.object({
|
|
5017
|
+
tranche: z.string().min(1),
|
|
5018
|
+
id: z.string().min(1)
|
|
5019
|
+
});
|
|
5020
|
+
var TaskResumeInputSchema = z.object({
|
|
5021
|
+
task: TaskToolRefSchema
|
|
5022
|
+
});
|
|
5023
|
+
var TaskCancelInputSchema = z.object({
|
|
5024
|
+
task: TaskToolRefSchema,
|
|
5025
|
+
reason: z.string().min(1)
|
|
5026
|
+
});
|
|
5027
|
+
var NoResultSchema = z.never();
|
|
4539
5028
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
4540
5029
|
function parseTaskBranch(branch) {
|
|
4541
5030
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -4619,7 +5108,6 @@ function decideIssueAssignment(input) {
|
|
|
4619
5108
|
};
|
|
4620
5109
|
}
|
|
4621
5110
|
// ../../packages/aeg-core/src/test-plan-gate.ts
|
|
4622
|
-
var TASK_BRANCH_PATTERN2 = /^task\/[^/]+\/[^/]+$/;
|
|
4623
5111
|
function evaluateTestPlanGate(body, branch) {
|
|
4624
5112
|
if (!body) {
|
|
4625
5113
|
return {
|
|
@@ -4632,7 +5120,7 @@ function evaluateTestPlanGate(body, branch) {
|
|
|
4632
5120
|
}
|
|
4633
5121
|
const located = locateTestPlanSection(body);
|
|
4634
5122
|
if (!located.found) {
|
|
4635
|
-
if (
|
|
5123
|
+
if (parseTaskBranchIdentity(branch) !== null) {
|
|
4636
5124
|
return {
|
|
4637
5125
|
verdict: "fail",
|
|
4638
5126
|
messages: [
|
|
@@ -4760,7 +5248,7 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
4760
5248
|
return findings;
|
|
4761
5249
|
}
|
|
4762
5250
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
4763
|
-
import { z } from "zod";
|
|
5251
|
+
import { z as z2 } from "zod";
|
|
4764
5252
|
var ROLE_VALUES = [
|
|
4765
5253
|
"planner",
|
|
4766
5254
|
"developer",
|
|
@@ -4770,136 +5258,172 @@ var ROLE_VALUES = [
|
|
|
4770
5258
|
"archivist",
|
|
4771
5259
|
"architect"
|
|
4772
5260
|
];
|
|
4773
|
-
var RoleSchema =
|
|
5261
|
+
var RoleSchema = z2.enum(ROLE_VALUES);
|
|
4774
5262
|
var HOST_VALUES = ["hook", "ci", "cli", "loop"];
|
|
4775
|
-
var HostSchema =
|
|
5263
|
+
var HostSchema = z2.enum(HOST_VALUES);
|
|
4776
5264
|
var RUN_ID_PATTERN = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
4777
|
-
var
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
doctrine: z.string(),
|
|
5265
|
+
var headerMetaCore = {
|
|
5266
|
+
ts: z2.string(),
|
|
5267
|
+
run_id: z2.string().regex(RUN_ID_PATTERN),
|
|
5268
|
+
seq: z2.number().int().nonnegative(),
|
|
5269
|
+
repo: z2.string().nullable(),
|
|
5270
|
+
vinaya: z2.string(),
|
|
5271
|
+
doctrine: z2.string(),
|
|
4785
5272
|
host: HostSchema,
|
|
4786
|
-
machine:
|
|
5273
|
+
machine: z2.string()
|
|
5274
|
+
};
|
|
5275
|
+
var HeaderMetaV1Schema = z2.object({
|
|
5276
|
+
schema: z2.literal(1),
|
|
5277
|
+
...headerMetaCore
|
|
5278
|
+
}).strict();
|
|
5279
|
+
var LineageSchema = z2.object({
|
|
5280
|
+
run: z2.string().nullable(),
|
|
5281
|
+
attempt: z2.number().int().nullable(),
|
|
5282
|
+
parent: z2.string().nullable()
|
|
4787
5283
|
}).strict();
|
|
4788
|
-
var
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
round: z.number().int().optional(),
|
|
4794
|
-
objectives_version: z.string().optional()
|
|
5284
|
+
var InputVersionsSchema = z2.object({
|
|
5285
|
+
objectives_version: z2.string().nullable(),
|
|
5286
|
+
brief_hash: z2.string().nullable(),
|
|
5287
|
+
ruling_ordinal: z2.number().int().nullable(),
|
|
5288
|
+
policy_digest: z2.string().nullable()
|
|
4795
5289
|
}).strict();
|
|
4796
|
-
var
|
|
5290
|
+
var ProvenanceSchema = z2.enum(["parent_attributed", "env_correlated", "self_reported", "unavailable"]);
|
|
5291
|
+
var HeaderMetaV2Schema = z2.object({
|
|
5292
|
+
schema: z2.literal(2),
|
|
5293
|
+
...headerMetaCore,
|
|
5294
|
+
event_id: z2.string().min(1),
|
|
5295
|
+
process_id: z2.string().min(1),
|
|
5296
|
+
actor_id: z2.string().nullable(),
|
|
5297
|
+
lineage: LineageSchema,
|
|
5298
|
+
input_versions: InputVersionsSchema,
|
|
5299
|
+
provenance: ProvenanceSchema
|
|
5300
|
+
}).strict();
|
|
5301
|
+
var HeaderMetaSchema = z2.discriminatedUnion("schema", [HeaderMetaV1Schema, HeaderMetaV2Schema]);
|
|
5302
|
+
var SubjectSchema = z2.object({
|
|
5303
|
+
issue: z2.number().int().nullable(),
|
|
5304
|
+
pr: z2.number().int().optional(),
|
|
5305
|
+
sha: z2.string().optional(),
|
|
5306
|
+
role: z2.union([RoleSchema, z2.literal("unattributed")]),
|
|
5307
|
+
round: z2.number().int().optional(),
|
|
5308
|
+
objectives_version: z2.string().optional()
|
|
5309
|
+
}).strict();
|
|
5310
|
+
var HeaderSchema = z2.object({
|
|
4797
5311
|
meta: HeaderMetaSchema,
|
|
4798
5312
|
subject: SubjectSchema
|
|
4799
5313
|
}).strict();
|
|
4800
5314
|
var envelopeTail = {
|
|
4801
|
-
duration_ms:
|
|
4802
|
-
payload:
|
|
5315
|
+
duration_ms: z2.number().nonnegative().optional(),
|
|
5316
|
+
payload: z2.object({}).strict()
|
|
4803
5317
|
};
|
|
4804
|
-
var
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
5318
|
+
var ReviewFindingSchema = z2.object({
|
|
5319
|
+
id: z2.string(),
|
|
5320
|
+
severity: z2.string(),
|
|
5321
|
+
state: z2.string().optional(),
|
|
5322
|
+
severity_scale: z2.string().optional(),
|
|
5323
|
+
policy_treatment: z2.enum(["blocking", "non_blocking", "unavailable"]).optional(),
|
|
5324
|
+
confidence: z2.number().min(0).max(1).optional(),
|
|
5325
|
+
confidence_scale: z2.string().optional(),
|
|
5326
|
+
confidence_source: z2.string().optional()
|
|
5327
|
+
}).strict();
|
|
5328
|
+
var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
5329
|
+
z2.object({ type: z2.literal("pr_opened"), pr: z2.number().int(), head: z2.string() }).strict(),
|
|
5330
|
+
z2.object({
|
|
5331
|
+
type: z2.literal("round_pushed"),
|
|
5332
|
+
pr: z2.number().int(),
|
|
5333
|
+
head: z2.string(),
|
|
5334
|
+
comment_id: z2.number().int()
|
|
4811
5335
|
}).strict(),
|
|
4812
|
-
|
|
4813
|
-
type:
|
|
4814
|
-
verdict:
|
|
4815
|
-
head:
|
|
4816
|
-
comment_id:
|
|
4817
|
-
objectives:
|
|
4818
|
-
findings:
|
|
5336
|
+
z2.object({
|
|
5337
|
+
type: z2.literal("verdict"),
|
|
5338
|
+
verdict: z2.enum(["APPROVE", "REQUEST CHANGES", "PASS", "FAIL"]),
|
|
5339
|
+
head: z2.string(),
|
|
5340
|
+
comment_id: z2.number().int(),
|
|
5341
|
+
objectives: z2.array(z2.object({ id: z2.string(), met: z2.boolean() }).strict()),
|
|
5342
|
+
findings: z2.array(ReviewFindingSchema)
|
|
4819
5343
|
}).strict(),
|
|
4820
|
-
|
|
4821
|
-
type:
|
|
4822
|
-
class:
|
|
4823
|
-
comment_id:
|
|
5344
|
+
z2.object({
|
|
5345
|
+
type: z2.literal("escalation"),
|
|
5346
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5347
|
+
comment_id: z2.number().int()
|
|
4824
5348
|
}).strict(),
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
5349
|
+
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5350
|
+
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5351
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
|
|
4828
5352
|
]);
|
|
4829
5353
|
var dispatchShared = {
|
|
4830
5354
|
meta: HeaderMetaSchema,
|
|
4831
5355
|
subject: SubjectSchema,
|
|
4832
|
-
kind:
|
|
5356
|
+
kind: z2.literal("dispatch"),
|
|
4833
5357
|
...envelopeTail,
|
|
4834
5358
|
target_role: RoleSchema,
|
|
4835
|
-
model:
|
|
4836
|
-
round:
|
|
4837
|
-
effect_id:
|
|
5359
|
+
model: z2.string(),
|
|
5360
|
+
round: z2.number().int().optional(),
|
|
5361
|
+
effect_id: z2.string()
|
|
4838
5362
|
};
|
|
4839
|
-
var dispatchUsageField =
|
|
4840
|
-
var DispatchEventSchema =
|
|
4841
|
-
|
|
4842
|
-
|
|
5363
|
+
var dispatchUsageField = z2.object({ input: z2.number().nonnegative(), output: z2.number().nonnegative() }).strict().nullable();
|
|
5364
|
+
var DispatchEventSchema = z2.discriminatedUnion("event", [
|
|
5365
|
+
z2.object({ ...dispatchShared, event: z2.literal("dispatched"), prompt_hash: z2.string() }).strict(),
|
|
5366
|
+
z2.object({
|
|
4843
5367
|
...dispatchShared,
|
|
4844
|
-
event:
|
|
5368
|
+
event: z2.literal("outcome_received"),
|
|
4845
5369
|
outcome: DispatchOutcomeSchema,
|
|
4846
5370
|
usage: dispatchUsageField
|
|
4847
5371
|
}).strict(),
|
|
4848
|
-
|
|
5372
|
+
z2.object({
|
|
4849
5373
|
...dispatchShared,
|
|
4850
|
-
event:
|
|
4851
|
-
reason:
|
|
5374
|
+
event: z2.literal("dispatch_failed"),
|
|
5375
|
+
reason: z2.enum(["timeout", "crash", "refused", "unattributed_write"]),
|
|
4852
5376
|
usage: dispatchUsageField
|
|
4853
5377
|
}).strict()
|
|
4854
5378
|
]);
|
|
4855
5379
|
var loopShared = {
|
|
4856
5380
|
meta: HeaderMetaSchema,
|
|
4857
5381
|
subject: SubjectSchema,
|
|
4858
|
-
kind:
|
|
5382
|
+
kind: z2.literal("dev_review_loop"),
|
|
4859
5383
|
...envelopeTail,
|
|
4860
|
-
loop_id:
|
|
5384
|
+
loop_id: z2.string()
|
|
4861
5385
|
};
|
|
4862
|
-
var DevReviewLoopEventSchema =
|
|
4863
|
-
|
|
5386
|
+
var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
5387
|
+
z2.object({
|
|
4864
5388
|
...loopShared,
|
|
4865
|
-
event:
|
|
4866
|
-
task:
|
|
4867
|
-
policy:
|
|
4868
|
-
max_rounds:
|
|
4869
|
-
reviewers:
|
|
4870
|
-
models:
|
|
5389
|
+
event: z2.literal("loop_started"),
|
|
5390
|
+
task: z2.number().int(),
|
|
5391
|
+
policy: z2.object({
|
|
5392
|
+
max_rounds: z2.number().int().nonnegative(),
|
|
5393
|
+
reviewers: z2.array(RoleSchema),
|
|
5394
|
+
models: z2.record(RoleSchema, z2.string())
|
|
4871
5395
|
}).strict()
|
|
4872
5396
|
}).strict(),
|
|
4873
|
-
|
|
4874
|
-
|
|
5397
|
+
z2.object({ ...loopShared, event: z2.literal("round_started"), round: z2.number().int(), base_head: z2.string() }).strict(),
|
|
5398
|
+
z2.object({
|
|
4875
5399
|
...loopShared,
|
|
4876
|
-
event:
|
|
4877
|
-
round:
|
|
4878
|
-
head:
|
|
4879
|
-
green:
|
|
5400
|
+
event: z2.literal("gate_result_read"),
|
|
5401
|
+
round: z2.number().int(),
|
|
5402
|
+
head: z2.string(),
|
|
5403
|
+
green: z2.boolean()
|
|
4880
5404
|
}).strict(),
|
|
4881
|
-
|
|
5405
|
+
z2.object({
|
|
4882
5406
|
...loopShared,
|
|
4883
|
-
event:
|
|
4884
|
-
round:
|
|
4885
|
-
head:
|
|
4886
|
-
all_approve:
|
|
4887
|
-
blockers:
|
|
5407
|
+
event: z2.literal("verdicts_read"),
|
|
5408
|
+
round: z2.number().int(),
|
|
5409
|
+
head: z2.string(),
|
|
5410
|
+
all_approve: z2.boolean(),
|
|
5411
|
+
blockers: z2.number().int().nonnegative()
|
|
4888
5412
|
}).strict(),
|
|
4889
|
-
|
|
5413
|
+
z2.object({
|
|
4890
5414
|
...loopShared,
|
|
4891
|
-
event:
|
|
4892
|
-
round:
|
|
4893
|
-
open:
|
|
4894
|
-
resolved:
|
|
4895
|
-
new:
|
|
4896
|
-
recurring:
|
|
5415
|
+
event: z2.literal("findings_compared"),
|
|
5416
|
+
round: z2.number().int(),
|
|
5417
|
+
open: z2.array(z2.string()),
|
|
5418
|
+
resolved: z2.array(z2.string()),
|
|
5419
|
+
new: z2.array(z2.string()),
|
|
5420
|
+
recurring: z2.array(z2.string())
|
|
4897
5421
|
}).strict(),
|
|
4898
|
-
|
|
5422
|
+
z2.object({
|
|
4899
5423
|
...loopShared,
|
|
4900
|
-
event:
|
|
4901
|
-
round:
|
|
4902
|
-
condition:
|
|
5424
|
+
event: z2.literal("stop_condition_met"),
|
|
5425
|
+
round: z2.number().int(),
|
|
5426
|
+
condition: z2.enum([
|
|
4903
5427
|
"green",
|
|
4904
5428
|
"max_rounds",
|
|
4905
5429
|
"no_progress",
|
|
@@ -4909,42 +5433,49 @@ var DevReviewLoopEventSchema = z.discriminatedUnion("event", [
|
|
|
4909
5433
|
"reappearance"
|
|
4910
5434
|
])
|
|
4911
5435
|
}).strict(),
|
|
4912
|
-
|
|
5436
|
+
z2.object({
|
|
5437
|
+
...loopShared,
|
|
5438
|
+
event: z2.literal("paused"),
|
|
5439
|
+
round: z2.number().int(),
|
|
5440
|
+
reason: z2.enum(["escalation", "principal_item", "refreeze_needed"])
|
|
5441
|
+
}).strict(),
|
|
5442
|
+
z2.object({
|
|
4913
5443
|
...loopShared,
|
|
4914
|
-
event:
|
|
4915
|
-
round:
|
|
4916
|
-
|
|
5444
|
+
event: z2.literal("resumed"),
|
|
5445
|
+
round: z2.number().int(),
|
|
5446
|
+
by: z2.literal("principal")
|
|
4917
5447
|
}).strict(),
|
|
4918
|
-
|
|
5448
|
+
z2.object({
|
|
4919
5449
|
...loopShared,
|
|
4920
|
-
event:
|
|
4921
|
-
round:
|
|
4922
|
-
|
|
5450
|
+
event: z2.literal("unpushed_work_resume"),
|
|
5451
|
+
round: z2.number().int(),
|
|
5452
|
+
branch: z2.string(),
|
|
5453
|
+
detail: z2.string()
|
|
4923
5454
|
}).strict(),
|
|
4924
|
-
|
|
5455
|
+
z2.object({
|
|
4925
5456
|
...loopShared,
|
|
4926
|
-
event:
|
|
4927
|
-
round:
|
|
4928
|
-
base_head:
|
|
4929
|
-
head:
|
|
4930
|
-
files_changed:
|
|
4931
|
-
insertions:
|
|
4932
|
-
deletions:
|
|
4933
|
-
wall_ms:
|
|
4934
|
-
outcome:
|
|
5457
|
+
event: z2.literal("round_ended"),
|
|
5458
|
+
round: z2.number().int(),
|
|
5459
|
+
base_head: z2.string(),
|
|
5460
|
+
head: z2.string(),
|
|
5461
|
+
files_changed: z2.number().int().nonnegative(),
|
|
5462
|
+
insertions: z2.number().int().nonnegative(),
|
|
5463
|
+
deletions: z2.number().int().nonnegative(),
|
|
5464
|
+
wall_ms: z2.number().nonnegative(),
|
|
5465
|
+
outcome: z2.enum(["green", "changes_requested", "escalated"])
|
|
4935
5466
|
}).strict(),
|
|
4936
|
-
|
|
5467
|
+
z2.object({
|
|
4937
5468
|
...loopShared,
|
|
4938
|
-
event:
|
|
4939
|
-
rounds:
|
|
4940
|
-
total_wall_ms:
|
|
4941
|
-
time_to_green_ms:
|
|
4942
|
-
files_changed_total:
|
|
4943
|
-
final_head:
|
|
4944
|
-
result:
|
|
5469
|
+
event: z2.literal("journal_finalized"),
|
|
5470
|
+
rounds: z2.number().int().nonnegative(),
|
|
5471
|
+
total_wall_ms: z2.number().nonnegative(),
|
|
5472
|
+
time_to_green_ms: z2.number().nonnegative().nullable(),
|
|
5473
|
+
files_changed_total: z2.number().int().nonnegative(),
|
|
5474
|
+
final_head: z2.string(),
|
|
5475
|
+
result: z2.enum(["merged_ready", "stopped"])
|
|
4945
5476
|
}).strict()
|
|
4946
5477
|
]);
|
|
4947
|
-
var ForgeOpSchema =
|
|
5478
|
+
var ForgeOpSchema = z2.enum([
|
|
4948
5479
|
"pr.create",
|
|
4949
5480
|
"pr.comment",
|
|
4950
5481
|
"pr.body.replace",
|
|
@@ -4958,24 +5489,210 @@ var ForgeOpSchema = z.enum([
|
|
|
4958
5489
|
"label.add",
|
|
4959
5490
|
"label.remove"
|
|
4960
5491
|
]);
|
|
4961
|
-
var ForgeWriteTargetSchema =
|
|
4962
|
-
issue:
|
|
4963
|
-
pr:
|
|
5492
|
+
var ForgeWriteTargetSchema = z2.object({
|
|
5493
|
+
issue: z2.number().int().optional(),
|
|
5494
|
+
pr: z2.number().int().optional()
|
|
4964
5495
|
}).strict();
|
|
4965
5496
|
var forgeWriteShared = {
|
|
4966
5497
|
meta: HeaderMetaSchema,
|
|
4967
5498
|
subject: SubjectSchema,
|
|
4968
|
-
kind:
|
|
5499
|
+
kind: z2.literal("forge_write"),
|
|
4969
5500
|
...envelopeTail,
|
|
4970
5501
|
op: ForgeOpSchema,
|
|
4971
5502
|
target: ForgeWriteTargetSchema
|
|
4972
5503
|
};
|
|
4973
|
-
var ForgeWriteEventSchema =
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
5504
|
+
var ForgeWriteEventSchema = z2.discriminatedUnion("event", [
|
|
5505
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("validated") }).strict(),
|
|
5506
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("refused"), reason: z2.string() }).strict(),
|
|
5507
|
+
z2.object({ ...forgeWriteShared, event: z2.literal("written"), comment_ids: z2.array(z2.string()) }).strict()
|
|
5508
|
+
]);
|
|
5509
|
+
var GateOutcomeSchema = z2.enum([
|
|
5510
|
+
"pass",
|
|
5511
|
+
"fail",
|
|
5512
|
+
"wait",
|
|
5513
|
+
"skip",
|
|
5514
|
+
"invalid_input",
|
|
5515
|
+
"unavailable_dependency",
|
|
5516
|
+
"timeout",
|
|
5517
|
+
"cancelled"
|
|
5518
|
+
]);
|
|
5519
|
+
var gateShared = {
|
|
5520
|
+
meta: HeaderMetaSchema,
|
|
5521
|
+
subject: SubjectSchema,
|
|
5522
|
+
kind: z2.literal("gate"),
|
|
5523
|
+
...envelopeTail,
|
|
5524
|
+
check: z2.string(),
|
|
5525
|
+
check_version: z2.string().nullable(),
|
|
5526
|
+
policy_version: z2.string().nullable(),
|
|
5527
|
+
input_fingerprint: z2.string().nullable()
|
|
5528
|
+
};
|
|
5529
|
+
var GateEventSchema = z2.discriminatedUnion("event", [
|
|
5530
|
+
z2.object({
|
|
5531
|
+
...gateShared,
|
|
5532
|
+
event: z2.literal("checked"),
|
|
5533
|
+
outcome: GateOutcomeSchema,
|
|
5534
|
+
reason: z2.string().optional()
|
|
5535
|
+
}).strict()
|
|
5536
|
+
]);
|
|
5537
|
+
var OperationResultSchema = z2.enum(["ok", "error", "refused", "timeout", "cancelled", "unavailable"]);
|
|
5538
|
+
var operationShared = {
|
|
5539
|
+
meta: HeaderMetaSchema,
|
|
5540
|
+
subject: SubjectSchema,
|
|
5541
|
+
kind: z2.literal("operation"),
|
|
5542
|
+
...envelopeTail,
|
|
5543
|
+
operation: z2.string(),
|
|
5544
|
+
target: z2.string().nullable()
|
|
5545
|
+
};
|
|
5546
|
+
var OperationEventSchema = z2.discriminatedUnion("event", [
|
|
5547
|
+
z2.object({
|
|
5548
|
+
...operationShared,
|
|
5549
|
+
event: z2.literal("completed"),
|
|
5550
|
+
result: OperationResultSchema,
|
|
5551
|
+
error_class: z2.string().nullable()
|
|
5552
|
+
}).strict()
|
|
5553
|
+
]);
|
|
5554
|
+
var UsageUnitsSchema = z2.object({
|
|
5555
|
+
input: z2.number().nonnegative().nullable(),
|
|
5556
|
+
output: z2.number().nonnegative().nullable(),
|
|
5557
|
+
cache: z2.number().nonnegative().nullable()
|
|
5558
|
+
}).strict();
|
|
5559
|
+
var usageShared = {
|
|
5560
|
+
meta: HeaderMetaSchema,
|
|
5561
|
+
subject: SubjectSchema,
|
|
5562
|
+
kind: z2.literal("usage"),
|
|
5563
|
+
...envelopeTail,
|
|
5564
|
+
model: z2.string().nullable(),
|
|
5565
|
+
source: z2.string(),
|
|
5566
|
+
semantics: z2.enum(["cumulative", "delta"])
|
|
5567
|
+
};
|
|
5568
|
+
var UsageEventSchema = z2.discriminatedUnion("event", [
|
|
5569
|
+
z2.object({
|
|
5570
|
+
...usageShared,
|
|
5571
|
+
event: z2.literal("observed"),
|
|
5572
|
+
units: UsageUnitsSchema,
|
|
5573
|
+
unknown_reason: z2.string().nullable()
|
|
5574
|
+
}).strict()
|
|
5575
|
+
]);
|
|
5576
|
+
var RoleAttemptOutcomeSchema = z2.enum([
|
|
5577
|
+
"completed",
|
|
5578
|
+
"incomplete",
|
|
5579
|
+
"infrastructure_failed",
|
|
5580
|
+
"cancelled",
|
|
5581
|
+
"timed_out",
|
|
5582
|
+
"capability_refused"
|
|
4977
5583
|
]);
|
|
4978
|
-
var
|
|
5584
|
+
var roleAttemptShared = {
|
|
5585
|
+
meta: HeaderMetaSchema,
|
|
5586
|
+
subject: SubjectSchema,
|
|
5587
|
+
kind: z2.literal("role_attempt"),
|
|
5588
|
+
...envelopeTail,
|
|
5589
|
+
actor: z2.string().nullable(),
|
|
5590
|
+
attempt: z2.number().int().nullable()
|
|
5591
|
+
};
|
|
5592
|
+
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5593
|
+
z2.object({
|
|
5594
|
+
...roleAttemptShared,
|
|
5595
|
+
event: z2.literal("attempted"),
|
|
5596
|
+
outcome: RoleAttemptOutcomeSchema,
|
|
5597
|
+
usage: dispatchUsageField
|
|
5598
|
+
}).strict()
|
|
5599
|
+
]);
|
|
5600
|
+
var handoffShared = {
|
|
5601
|
+
meta: HeaderMetaSchema,
|
|
5602
|
+
subject: SubjectSchema,
|
|
5603
|
+
kind: z2.literal("handoff"),
|
|
5604
|
+
...envelopeTail,
|
|
5605
|
+
class: z2.enum(["authority", "strategy", "product"]),
|
|
5606
|
+
reason: z2.string()
|
|
5607
|
+
};
|
|
5608
|
+
var HandoffEventSchema = z2.discriminatedUnion("event", [
|
|
5609
|
+
z2.object({
|
|
5610
|
+
...handoffShared,
|
|
5611
|
+
event: z2.literal("raised"),
|
|
5612
|
+
requested_decision: z2.string().nullable()
|
|
5613
|
+
}).strict(),
|
|
5614
|
+
z2.object({
|
|
5615
|
+
...handoffShared,
|
|
5616
|
+
event: z2.literal("resolved"),
|
|
5617
|
+
resolution: z2.string().nullable(),
|
|
5618
|
+
resolved_by: z2.string().nullable()
|
|
5619
|
+
}).strict()
|
|
5620
|
+
]);
|
|
5621
|
+
var EffectTargetSchema = z2.object({
|
|
5622
|
+
kind: z2.string(),
|
|
5623
|
+
ref: z2.string()
|
|
5624
|
+
}).strict();
|
|
5625
|
+
var effectShared = {
|
|
5626
|
+
meta: HeaderMetaSchema,
|
|
5627
|
+
subject: SubjectSchema,
|
|
5628
|
+
kind: z2.literal("effect"),
|
|
5629
|
+
...envelopeTail,
|
|
5630
|
+
effect_id: z2.string(),
|
|
5631
|
+
target: EffectTargetSchema
|
|
5632
|
+
};
|
|
5633
|
+
var EffectEventSchema = z2.discriminatedUnion("event", [
|
|
5634
|
+
z2.object({ ...effectShared, event: z2.literal("attempted") }).strict(),
|
|
5635
|
+
z2.object({ ...effectShared, event: z2.literal("observed"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict(),
|
|
5636
|
+
z2.object({ ...effectShared, event: z2.literal("verified"), outcome: z2.enum(["success", "failure", "uncertain"]) }).strict()
|
|
5637
|
+
]);
|
|
5638
|
+
var LogEventSchema = z2.union([
|
|
5639
|
+
DispatchEventSchema,
|
|
5640
|
+
DevReviewLoopEventSchema,
|
|
5641
|
+
ForgeWriteEventSchema,
|
|
5642
|
+
GateEventSchema,
|
|
5643
|
+
OperationEventSchema,
|
|
5644
|
+
UsageEventSchema,
|
|
5645
|
+
RoleAttemptEventSchema,
|
|
5646
|
+
HandoffEventSchema,
|
|
5647
|
+
EffectEventSchema
|
|
5648
|
+
]);
|
|
5649
|
+
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5650
|
+
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5651
|
+
// ../../packages/aeg-core/src/control-store/records.ts
|
|
5652
|
+
import { z as z3 } from "zod";
|
|
5653
|
+
var isoTimestamp = z3.string().min(1);
|
|
5654
|
+
var taskId = z3.number().int().positive();
|
|
5655
|
+
var epochNumber = z3.number().int().nonnegative();
|
|
5656
|
+
var RunRecordSchema = z3.object({
|
|
5657
|
+
version: z3.literal(1),
|
|
5658
|
+
kind: z3.literal("run"),
|
|
5659
|
+
task: taskId,
|
|
5660
|
+
runId: z3.string().min(1),
|
|
5661
|
+
pid: z3.number().int().positive(),
|
|
5662
|
+
host: z3.string().min(1),
|
|
5663
|
+
startedAt: isoTimestamp
|
|
5664
|
+
}).strict();
|
|
5665
|
+
var InputRecordSchema = z3.object({
|
|
5666
|
+
version: z3.literal(1),
|
|
5667
|
+
kind: z3.literal("input"),
|
|
5668
|
+
task: taskId,
|
|
5669
|
+
runId: z3.string().min(1),
|
|
5670
|
+
source: z3.union([z3.literal("fresh"), z3.literal("resume")]),
|
|
5671
|
+
pr: z3.number().int().positive().nullable(),
|
|
5672
|
+
round: z3.number().int().nonnegative(),
|
|
5673
|
+
recordedAt: isoTimestamp
|
|
5674
|
+
}).strict();
|
|
5675
|
+
var OwnershipRecordSchema = z3.object({
|
|
5676
|
+
version: z3.literal(1),
|
|
5677
|
+
kind: z3.literal("ownership"),
|
|
5678
|
+
task: taskId,
|
|
5679
|
+
epoch: epochNumber,
|
|
5680
|
+
ownerId: z3.string().min(1),
|
|
5681
|
+
pid: z3.number().int().positive(),
|
|
5682
|
+
host: z3.string().min(1),
|
|
5683
|
+
acquiredAt: isoTimestamp
|
|
5684
|
+
}).strict();
|
|
5685
|
+
var TransitionRecordSchema = z3.object({
|
|
5686
|
+
version: z3.literal(1),
|
|
5687
|
+
kind: z3.literal("transition"),
|
|
5688
|
+
task: taskId,
|
|
5689
|
+
epoch: epochNumber,
|
|
5690
|
+
seq: z3.number().int().nonnegative(),
|
|
5691
|
+
from: z3.string().min(1),
|
|
5692
|
+
to: z3.string().min(1),
|
|
5693
|
+
detail: z3.string().optional(),
|
|
5694
|
+
at: isoTimestamp
|
|
5695
|
+
}).strict();
|
|
4979
5696
|
// src/checks/contract.ts
|
|
4980
5697
|
var CHECK_SCHEMA_VERSION = 1;
|
|
4981
5698
|
function emitCheckError(error) {
|
|
@@ -5016,6 +5733,7 @@ var REGISTRY = [
|
|
|
5016
5733
|
[
|
|
5017
5734
|
{
|
|
5018
5735
|
name: "brief-shape",
|
|
5736
|
+
validates: "body",
|
|
5019
5737
|
run: bin("check-brief-shape"),
|
|
5020
5738
|
scope: "diff",
|
|
5021
5739
|
timeoutMs: 15000,
|
|
@@ -5032,6 +5750,7 @@ var REGISTRY = [
|
|
|
5032
5750
|
[
|
|
5033
5751
|
{
|
|
5034
5752
|
name: "pr-report-density",
|
|
5753
|
+
validates: "body",
|
|
5035
5754
|
run: bin("check-pr-report-density"),
|
|
5036
5755
|
scope: "diff",
|
|
5037
5756
|
timeoutMs: 15000,
|
|
@@ -5044,6 +5763,7 @@ var REGISTRY = [
|
|
|
5044
5763
|
[
|
|
5045
5764
|
{
|
|
5046
5765
|
name: "doc-coverage",
|
|
5766
|
+
validates: "body",
|
|
5047
5767
|
run: bin("check-doc-coverage"),
|
|
5048
5768
|
scope: "diff",
|
|
5049
5769
|
timeoutMs: 15000,
|
|
@@ -5077,6 +5797,7 @@ var REGISTRY = [
|
|
|
5077
5797
|
[
|
|
5078
5798
|
{
|
|
5079
5799
|
name: "pr-premise-reassert",
|
|
5800
|
+
validates: "body",
|
|
5080
5801
|
run: bin("check-pr-premise-reassert"),
|
|
5081
5802
|
scope: "diff",
|
|
5082
5803
|
timeoutMs: 15000,
|
|
@@ -5105,6 +5826,7 @@ var REGISTRY = [
|
|
|
5105
5826
|
[
|
|
5106
5827
|
{
|
|
5107
5828
|
name: "closes-n",
|
|
5829
|
+
validates: "body",
|
|
5108
5830
|
run: bin("check-closes-n"),
|
|
5109
5831
|
scope: "diff",
|
|
5110
5832
|
timeoutMs: 15000,
|
|
@@ -5153,10 +5875,12 @@ var REGISTRY = [
|
|
|
5153
5875
|
[
|
|
5154
5876
|
{
|
|
5155
5877
|
name: "test-plan",
|
|
5878
|
+
validates: "body",
|
|
5156
5879
|
run: bin("check-test-plan"),
|
|
5157
5880
|
scope: "diff",
|
|
5158
5881
|
timeoutMs: 15000,
|
|
5159
5882
|
requiresOpenPr: true,
|
|
5883
|
+
principalOwed: true,
|
|
5160
5884
|
env: {
|
|
5161
5885
|
PR_BODY: { optional: true },
|
|
5162
5886
|
BRANCH: { optional: true }
|
|
@@ -5167,6 +5891,7 @@ var REGISTRY = [
|
|
|
5167
5891
|
[
|
|
5168
5892
|
{
|
|
5169
5893
|
name: "body-bare-digits",
|
|
5894
|
+
validates: "body",
|
|
5170
5895
|
run: bin("check-body-bare-digits"),
|
|
5171
5896
|
scope: "diff",
|
|
5172
5897
|
timeoutMs: 15000,
|
|
@@ -5185,6 +5910,7 @@ var REGISTRY = [
|
|
|
5185
5910
|
[
|
|
5186
5911
|
{
|
|
5187
5912
|
name: "token-report",
|
|
5913
|
+
validates: "body",
|
|
5188
5914
|
run: bin("check-token-report"),
|
|
5189
5915
|
scope: "diff",
|
|
5190
5916
|
timeoutMs: 15000,
|
|
@@ -5285,6 +6011,7 @@ var REGISTRY = [
|
|
|
5285
6011
|
[
|
|
5286
6012
|
{
|
|
5287
6013
|
name: "doc-coverage-push",
|
|
6014
|
+
validates: "body",
|
|
5288
6015
|
run: bin("check-doc-coverage-push"),
|
|
5289
6016
|
scope: "diff",
|
|
5290
6017
|
timeoutMs: 15000,
|
|
@@ -5320,6 +6047,7 @@ var REGISTRY = [
|
|
|
5320
6047
|
[
|
|
5321
6048
|
{
|
|
5322
6049
|
name: "evidence-fresh",
|
|
6050
|
+
validates: "body",
|
|
5323
6051
|
run: bin("check-evidence-fresh"),
|
|
5324
6052
|
scope: "diff",
|
|
5325
6053
|
timeoutMs: 15000,
|
|
@@ -5448,6 +6176,82 @@ var REGISTRY = [
|
|
|
5448
6176
|
}
|
|
5449
6177
|
},
|
|
5450
6178
|
0
|
|
6179
|
+
],
|
|
6180
|
+
[
|
|
6181
|
+
{
|
|
6182
|
+
name: "issue-title-grammar",
|
|
6183
|
+
run: bin("check-issue-title-grammar"),
|
|
6184
|
+
validates: "issue",
|
|
6185
|
+
scope: "full",
|
|
6186
|
+
ownWorkflow: true,
|
|
6187
|
+
timeoutMs: 15000,
|
|
6188
|
+
env: { ISSUE_TITLE: { optional: true } }
|
|
6189
|
+
},
|
|
6190
|
+
1
|
|
6191
|
+
],
|
|
6192
|
+
[
|
|
6193
|
+
{
|
|
6194
|
+
name: "issue-objectives-numbering",
|
|
6195
|
+
run: bin("check-issue-objectives-numbering"),
|
|
6196
|
+
validates: "issue",
|
|
6197
|
+
scope: "full",
|
|
6198
|
+
ownWorkflow: true,
|
|
6199
|
+
timeoutMs: 15000,
|
|
6200
|
+
env: { ISSUE_BODY: { optional: true }, ISSUE_NUMBER: { optional: true } }
|
|
6201
|
+
},
|
|
6202
|
+
1
|
|
6203
|
+
],
|
|
6204
|
+
[
|
|
6205
|
+
{
|
|
6206
|
+
name: "issue-parts-coverage",
|
|
6207
|
+
run: bin("check-issue-parts-coverage"),
|
|
6208
|
+
validates: "issue",
|
|
6209
|
+
scope: "full",
|
|
6210
|
+
ownWorkflow: true,
|
|
6211
|
+
timeoutMs: 15000,
|
|
6212
|
+
env: { ISSUE_BODY: { optional: true } }
|
|
6213
|
+
},
|
|
6214
|
+
1
|
|
6215
|
+
],
|
|
6216
|
+
[
|
|
6217
|
+
{
|
|
6218
|
+
name: "issue-surface-globs",
|
|
6219
|
+
run: bin("check-issue-surface-globs"),
|
|
6220
|
+
validates: "issue",
|
|
6221
|
+
scope: "full",
|
|
6222
|
+
ownWorkflow: true,
|
|
6223
|
+
timeoutMs: 15000,
|
|
6224
|
+
env: { ISSUE_BODY: { optional: true } }
|
|
6225
|
+
},
|
|
6226
|
+
1
|
|
6227
|
+
],
|
|
6228
|
+
[
|
|
6229
|
+
{
|
|
6230
|
+
name: "issue-tranche-label",
|
|
6231
|
+
run: bin("check-issue-tranche-label"),
|
|
6232
|
+
validates: "issue",
|
|
6233
|
+
scope: "full",
|
|
6234
|
+
ownWorkflow: true,
|
|
6235
|
+
timeoutMs: 15000,
|
|
6236
|
+
env: { ISSUE_BODY: { optional: true }, ISSUE_LABELS: { optional: true } }
|
|
6237
|
+
},
|
|
6238
|
+
1
|
|
6239
|
+
],
|
|
6240
|
+
[
|
|
6241
|
+
{
|
|
6242
|
+
name: "issue-milestone-attach",
|
|
6243
|
+
run: bin("check-issue-milestone-attach"),
|
|
6244
|
+
validates: "issue",
|
|
6245
|
+
scope: "full",
|
|
6246
|
+
ownWorkflow: true,
|
|
6247
|
+
timeoutMs: 15000,
|
|
6248
|
+
env: {
|
|
6249
|
+
ISSUE_LABELS: { optional: true },
|
|
6250
|
+
CURRENT_MILESTONE_TITLE: { optional: true },
|
|
6251
|
+
RESOLVED_MILESTONE_TITLE: { optional: true }
|
|
6252
|
+
}
|
|
6253
|
+
},
|
|
6254
|
+
1
|
|
5451
6255
|
]
|
|
5452
6256
|
];
|
|
5453
6257
|
function coreCheckRegistry() {
|