@attalabs/vinaya 0.19.3 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/aeg-root/contracts/archivist-tranche-archivist.md +2 -2
- package/aeg-root/contracts/tranche-archivist-planner.md +8 -8
- package/aeg-root/enforcement.md +6 -4
- package/aeg-root/process.md +5 -5
- package/aeg-root/roles/archivist.md +9 -10
- package/aeg-root/roles/brief-author.md +1 -1
- package/aeg-root/roles/developer.md +1 -1
- package/aeg-root/roles/planner.md +1 -1
- package/aeg-root/roles/principal.md +1 -1
- package/aeg-root/roles/tranche-archivist.md +3 -16
- package/aeg-root/skills/aeg/SKILL.md +30 -1
- package/aeg-root/skills/aeg-roles/SKILL.md +1 -1
- package/aeg-root/skills/brief-authoring/SKILL.md +2 -2
- package/aeg-root/state-machine.md +8 -6
- package/aeg-root/task-model.md +1 -1
- package/aeg-root/templates/pr-report-template.md +4 -0
- package/dist/checks/bin/check-body-bare-digits.js +192 -27
- package/dist/checks/bin/check-branch-topology.js +518 -11
- package/dist/checks/bin/check-brief-shape.js +104 -11
- package/dist/checks/bin/check-closes-n.js +518 -11
- package/dist/checks/bin/check-coherence.js +526 -12
- package/dist/checks/bin/check-dead-branch-push.js +104 -11
- package/dist/checks/bin/check-dispatch-readiness.js +621 -14
- package/dist/checks/bin/check-doc-coverage-push.js +170 -20
- package/dist/checks/bin/check-doc-coverage.js +170 -20
- package/dist/checks/bin/check-doctrine-portability.js +112 -12
- package/dist/checks/bin/check-evidence-fresh.js +213 -20
- package/dist/checks/bin/check-first-push-dispatch.js +526 -12
- package/dist/checks/bin/check-issue-assignment.js +518 -11
- package/dist/checks/bin/check-main-branch-refusal.js +3724 -0
- package/dist/checks/bin/check-no-disk-state.js +104 -11
- package/dist/checks/bin/check-reader-resolvable-prose.js +186 -17
- package/dist/checks/bin/check-registry-gates.js +185 -16
- package/dist/checks/bin/check-retired-vocabulary.js +185 -16
- package/dist/checks/bin/check-review-gate.js +112 -12
- package/dist/checks/bin/check-single-plan-pr.js +104 -11
- package/dist/checks/bin/check-test-plan.js +104 -11
- package/dist/checks/bin/check-workspace-escape.js +104 -11
- package/dist/index.js +664 -56
- package/package.json +1 -1
- package/studio-standalone/_node_modules/@attalabs/aeg-core/bin/verify-coherence.ts +1089 -0
- 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/required-server-files.json +5 -0
- 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.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/api/coherence/route.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +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.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.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.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.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 +2 -2
- 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.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.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.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/{[externals]__0pvgf28._.js → [externals]__1agj1ww._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/[root-of-the-server]__02a-3g8._.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]__0053k9k._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__03jepya._.js → [root-of-the-server]__16cuydh._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
- 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/_03x_w6q._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
- 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 +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3noqvds-2bvrd.js → 0ea8-8nopz29h.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0la0hhmjprdxm.css +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1lk7h-0buf4ab.js +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3gehliafvmjo9.js → 2twnwe77d4n-m.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/server.js +1 -1
- package/aeg-root/coordination.md +0 -292
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/2iysedx-n06xc.js +0 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/42wxpzjhw7oy4.css +0 -1
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → b2VfZK2AItZwlghK_pUN0}/_ssgManifest.js +0 -0
|
@@ -6,17 +6,17 @@ import { existsSync as existsSync3, readdirSync, readFileSync, statSync } from "
|
|
|
6
6
|
import matter2 from "gray-matter";
|
|
7
7
|
// ../../packages/aeg-core/src/gate-audience.ts
|
|
8
8
|
var GATE_AUDIENCE = {
|
|
9
|
-
"check-branch-topology": { shippedAs: "branch-topology" },
|
|
10
|
-
"check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
|
|
11
|
-
"check-no-disk-state": { shippedAs: "no-disk-state" },
|
|
12
|
-
"verify-brief": { shippedAs: "brief-shape" },
|
|
13
|
-
"verify-coherence": { shippedAs: "coherence" },
|
|
14
|
-
"verify-dispatch": { shippedAs: "dispatch-readiness" },
|
|
15
|
-
"verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
|
|
16
|
-
"verify-registry": { shippedAs: "registry-gates" },
|
|
17
|
-
"verify-review-gate": { shippedAs: "review-gate" },
|
|
18
|
-
"verify-single-plan-pr": { shippedAs: "single-plan-pr" },
|
|
19
|
-
"verify-test-plan": { shippedAs: "test-plan" },
|
|
9
|
+
"check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
|
|
10
|
+
"check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
|
|
11
|
+
"check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
|
|
12
|
+
"verify-brief": { shippedAs: "brief-shape", ring: 0 },
|
|
13
|
+
"verify-coherence": { shippedAs: "coherence", ring: 0 },
|
|
14
|
+
"verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
|
|
15
|
+
"verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
|
|
16
|
+
"verify-registry": { shippedAs: "registry-gates", ring: 0 },
|
|
17
|
+
"verify-review-gate": { shippedAs: "review-gate", ring: 1 },
|
|
18
|
+
"verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
|
|
19
|
+
"verify-test-plan": { shippedAs: "test-plan", ring: 1 },
|
|
20
20
|
"check-direct-main-push": {
|
|
21
21
|
internal: "Reaches adopters through `vinaya audit --only=direct-push`, not the check registry: it is a ring-2 sweep over merge history keyed on `GITHUB_SHA`, run by the generated archivist job on push to the default branch. It has no diff to key on, so there is nothing for `vinaya check` to run it against."
|
|
22
22
|
},
|
|
@@ -328,6 +328,13 @@ var LABELS = [
|
|
|
328
328
|
form: "literal",
|
|
329
329
|
carries: "Execution is halted pending an external unblock; wins over every other derived status."
|
|
330
330
|
},
|
|
331
|
+
{
|
|
332
|
+
key: "backlog",
|
|
333
|
+
id: "vinaya/backlog",
|
|
334
|
+
category: "state",
|
|
335
|
+
form: "literal",
|
|
336
|
+
carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
|
|
337
|
+
},
|
|
331
338
|
{
|
|
332
339
|
key: "tier-0",
|
|
333
340
|
id: "vinaya/tier:0",
|
|
@@ -1986,7 +1993,59 @@ function overrideActive(opts) {
|
|
|
1986
1993
|
return false;
|
|
1987
1994
|
}
|
|
1988
1995
|
// ../../packages/aeg-core/src/premise-check.ts
|
|
1996
|
+
import { createHash } from "node:crypto";
|
|
1989
1997
|
var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
|
|
1998
|
+
function isPremiseHeader(line) {
|
|
1999
|
+
const stripped = line.replace(/[*#]/g, "").trim();
|
|
2000
|
+
return /^premise\s*:?$/i.test(stripped);
|
|
2001
|
+
}
|
|
2002
|
+
var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
|
|
2003
|
+
function parsePremiseBlock(prBody) {
|
|
2004
|
+
const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
|
|
2005
|
+
const lines = searchIn.split(/\r?\n/);
|
|
2006
|
+
const assertions = [];
|
|
2007
|
+
let inBlock = false;
|
|
2008
|
+
for (const raw of lines) {
|
|
2009
|
+
const line = raw.trim();
|
|
2010
|
+
if (!inBlock) {
|
|
2011
|
+
if (isPremiseHeader(line))
|
|
2012
|
+
inBlock = true;
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2015
|
+
if (line === "")
|
|
2016
|
+
break;
|
|
2017
|
+
const m = line.match(PREMISE_LINE);
|
|
2018
|
+
if (!m)
|
|
2019
|
+
break;
|
|
2020
|
+
const [, path, kindRaw, value] = m;
|
|
2021
|
+
const kind = kindRaw.toLowerCase();
|
|
2022
|
+
if (!ASSERTION_KINDS.has(kind))
|
|
2023
|
+
continue;
|
|
2024
|
+
assertions.push({ kind, path, value: value.trim() });
|
|
2025
|
+
}
|
|
2026
|
+
return assertions;
|
|
2027
|
+
}
|
|
2028
|
+
function checkPremises(assertions, fileReader) {
|
|
2029
|
+
const failures = [];
|
|
2030
|
+
for (const a of assertions) {
|
|
2031
|
+
const content = fileReader(a.path);
|
|
2032
|
+
if (content === null) {
|
|
2033
|
+
failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
|
|
2034
|
+
continue;
|
|
2035
|
+
}
|
|
2036
|
+
if (a.kind === "contains" && !content.includes(a.value)) {
|
|
2037
|
+
failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
|
|
2038
|
+
} else if (a.kind === "absent" && content.includes(a.value)) {
|
|
2039
|
+
failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
|
|
2040
|
+
} else if (a.kind === "sha256") {
|
|
2041
|
+
const actual = createHash("sha256").update(content).digest("hex");
|
|
2042
|
+
if (actual !== a.value.toLowerCase()) {
|
|
2043
|
+
failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
return { pass: failures.length === 0, failures };
|
|
2048
|
+
}
|
|
1990
2049
|
|
|
1991
2050
|
// ../../packages/aeg-core/src/test-plan-section.ts
|
|
1992
2051
|
var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
|
|
@@ -2790,6 +2849,7 @@ function checkG1(rows, existsFn) {
|
|
|
2790
2849
|
}
|
|
2791
2850
|
return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
|
|
2792
2851
|
}
|
|
2852
|
+
var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
|
|
2793
2853
|
function checkG2(rows, candidateFiles) {
|
|
2794
2854
|
const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
|
|
2795
2855
|
const findings = [];
|
|
@@ -2801,6 +2861,16 @@ function checkG2(rows, candidateFiles) {
|
|
|
2801
2861
|
});
|
|
2802
2862
|
}
|
|
2803
2863
|
}
|
|
2864
|
+
for (const row of rows) {
|
|
2865
|
+
const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
|
|
2866
|
+
if (carriesPlaceholder) {
|
|
2867
|
+
findings.push({
|
|
2868
|
+
row: row.action,
|
|
2869
|
+
path: row.implementation,
|
|
2870
|
+
reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
|
|
2871
|
+
});
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2804
2874
|
return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
|
|
2805
2875
|
}
|
|
2806
2876
|
function checkG3(ring0Rows, crossingFiles) {
|
|
@@ -3320,6 +3390,29 @@ function isNewDiskStateFile(path, status) {
|
|
|
3320
3390
|
return false;
|
|
3321
3391
|
return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
|
|
3322
3392
|
}
|
|
3393
|
+
// ../../packages/aeg-core/src/main-branch-refusal.ts
|
|
3394
|
+
function checkMainBranchRefusal(facts) {
|
|
3395
|
+
const { currentSymbolicBranch, defaultBranch } = facts;
|
|
3396
|
+
if (currentSymbolicBranch === null)
|
|
3397
|
+
return null;
|
|
3398
|
+
if (defaultBranch === null) {
|
|
3399
|
+
return {
|
|
3400
|
+
reason: "default-branch-undetermined",
|
|
3401
|
+
severity: "warning",
|
|
3402
|
+
currentBranch: currentSymbolicBranch,
|
|
3403
|
+
defaultBranch: null
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
if (currentSymbolicBranch === defaultBranch) {
|
|
3407
|
+
return {
|
|
3408
|
+
reason: "on-default-branch",
|
|
3409
|
+
severity: "error",
|
|
3410
|
+
currentBranch: currentSymbolicBranch,
|
|
3411
|
+
defaultBranch
|
|
3412
|
+
};
|
|
3413
|
+
}
|
|
3414
|
+
return null;
|
|
3415
|
+
}
|
|
3323
3416
|
// ../../packages/aeg-core/src/branch-topology-gate.ts
|
|
3324
3417
|
function taskBranchTopologyFields(branch) {
|
|
3325
3418
|
if (!/^task\/.*\/.*$/.test(branch))
|
|
@@ -3609,8 +3702,8 @@ var BIN_EXT = BIN_DIR === DIST_BIN_DIR ? ".js" : ".ts";
|
|
|
3609
3702
|
function bin(name) {
|
|
3610
3703
|
return join2(BIN_DIR, `${name}${BIN_EXT}`);
|
|
3611
3704
|
}
|
|
3612
|
-
|
|
3613
|
-
|
|
3705
|
+
var REGISTRY = [
|
|
3706
|
+
[
|
|
3614
3707
|
{
|
|
3615
3708
|
name: "brief-shape",
|
|
3616
3709
|
run: bin("check-brief-shape"),
|
|
@@ -3621,6 +3714,9 @@ function coreCheckRegistry() {
|
|
|
3621
3714
|
BRANCH: { optional: true }
|
|
3622
3715
|
}
|
|
3623
3716
|
},
|
|
3717
|
+
0
|
|
3718
|
+
],
|
|
3719
|
+
[
|
|
3624
3720
|
{
|
|
3625
3721
|
name: "doc-coverage",
|
|
3626
3722
|
run: bin("check-doc-coverage"),
|
|
@@ -3636,6 +3732,9 @@ function coreCheckRegistry() {
|
|
|
3636
3732
|
GH_TOKEN: { optional: true }
|
|
3637
3733
|
}
|
|
3638
3734
|
},
|
|
3735
|
+
0
|
|
3736
|
+
],
|
|
3737
|
+
[
|
|
3639
3738
|
{
|
|
3640
3739
|
name: "coherence",
|
|
3641
3740
|
run: bin("check-coherence"),
|
|
@@ -3648,6 +3747,9 @@ function coreCheckRegistry() {
|
|
|
3648
3747
|
GH_TOKEN: { optional: true }
|
|
3649
3748
|
}
|
|
3650
3749
|
},
|
|
3750
|
+
0
|
|
3751
|
+
],
|
|
3752
|
+
[
|
|
3651
3753
|
{
|
|
3652
3754
|
name: "dispatch-readiness",
|
|
3653
3755
|
run: bin("check-dispatch-readiness"),
|
|
@@ -3657,9 +3759,13 @@ function coreCheckRegistry() {
|
|
|
3657
3759
|
AEG_REPO: { optional: true },
|
|
3658
3760
|
BRANCH: { optional: true },
|
|
3659
3761
|
GITHUB_TOKEN: { optional: true },
|
|
3660
|
-
GH_TOKEN: { optional: true }
|
|
3762
|
+
GH_TOKEN: { optional: true },
|
|
3763
|
+
PREMISE_FILE: { optional: true }
|
|
3661
3764
|
}
|
|
3662
3765
|
},
|
|
3766
|
+
0
|
|
3767
|
+
],
|
|
3768
|
+
[
|
|
3663
3769
|
{
|
|
3664
3770
|
name: "closes-n",
|
|
3665
3771
|
run: bin("check-closes-n"),
|
|
@@ -3674,6 +3780,9 @@ function coreCheckRegistry() {
|
|
|
3674
3780
|
GH_TOKEN: { optional: true }
|
|
3675
3781
|
}
|
|
3676
3782
|
},
|
|
3783
|
+
1
|
|
3784
|
+
],
|
|
3785
|
+
[
|
|
3677
3786
|
{
|
|
3678
3787
|
name: "single-plan-pr",
|
|
3679
3788
|
run: bin("check-single-plan-pr"),
|
|
@@ -3686,6 +3795,9 @@ function coreCheckRegistry() {
|
|
|
3686
3795
|
GH_TOKEN: { optional: true }
|
|
3687
3796
|
}
|
|
3688
3797
|
},
|
|
3798
|
+
0
|
|
3799
|
+
],
|
|
3800
|
+
[
|
|
3689
3801
|
{
|
|
3690
3802
|
name: "test-plan",
|
|
3691
3803
|
run: bin("check-test-plan"),
|
|
@@ -3697,6 +3809,9 @@ function coreCheckRegistry() {
|
|
|
3697
3809
|
BRANCH: { optional: true }
|
|
3698
3810
|
}
|
|
3699
3811
|
},
|
|
3812
|
+
1
|
|
3813
|
+
],
|
|
3814
|
+
[
|
|
3700
3815
|
{
|
|
3701
3816
|
name: "body-bare-digits",
|
|
3702
3817
|
run: bin("check-body-bare-digits"),
|
|
@@ -3712,6 +3827,9 @@ function coreCheckRegistry() {
|
|
|
3712
3827
|
GH_TOKEN: { optional: true }
|
|
3713
3828
|
}
|
|
3714
3829
|
},
|
|
3830
|
+
1
|
|
3831
|
+
],
|
|
3832
|
+
[
|
|
3715
3833
|
{
|
|
3716
3834
|
name: "no-disk-state",
|
|
3717
3835
|
run: bin("check-no-disk-state"),
|
|
@@ -3719,6 +3837,9 @@ function coreCheckRegistry() {
|
|
|
3719
3837
|
timeoutMs: 15000,
|
|
3720
3838
|
env: { BASE_SHA: { optional: true } }
|
|
3721
3839
|
},
|
|
3840
|
+
0
|
|
3841
|
+
],
|
|
3842
|
+
[
|
|
3722
3843
|
{
|
|
3723
3844
|
name: "registry-gates",
|
|
3724
3845
|
run: bin("check-registry-gates"),
|
|
@@ -3730,6 +3851,9 @@ function coreCheckRegistry() {
|
|
|
3730
3851
|
GH_TOKEN: { optional: true }
|
|
3731
3852
|
}
|
|
3732
3853
|
},
|
|
3854
|
+
0
|
|
3855
|
+
],
|
|
3856
|
+
[
|
|
3733
3857
|
{
|
|
3734
3858
|
name: "review-gate",
|
|
3735
3859
|
run: bin("check-review-gate"),
|
|
@@ -3743,6 +3867,9 @@ function coreCheckRegistry() {
|
|
|
3743
3867
|
GH_TOKEN: { optional: true }
|
|
3744
3868
|
}
|
|
3745
3869
|
},
|
|
3870
|
+
1
|
|
3871
|
+
],
|
|
3872
|
+
[
|
|
3746
3873
|
{
|
|
3747
3874
|
name: "branch-topology",
|
|
3748
3875
|
run: bin("check-branch-topology"),
|
|
@@ -3755,6 +3882,9 @@ function coreCheckRegistry() {
|
|
|
3755
3882
|
GH_TOKEN: { optional: true }
|
|
3756
3883
|
}
|
|
3757
3884
|
},
|
|
3885
|
+
0
|
|
3886
|
+
],
|
|
3887
|
+
[
|
|
3758
3888
|
{
|
|
3759
3889
|
name: "dead-branch-push",
|
|
3760
3890
|
run: bin("check-dead-branch-push"),
|
|
@@ -3766,6 +3896,9 @@ function coreCheckRegistry() {
|
|
|
3766
3896
|
GH_TOKEN: { optional: true }
|
|
3767
3897
|
}
|
|
3768
3898
|
},
|
|
3899
|
+
0
|
|
3900
|
+
],
|
|
3901
|
+
[
|
|
3769
3902
|
{
|
|
3770
3903
|
name: "first-push-dispatch",
|
|
3771
3904
|
run: bin("check-first-push-dispatch"),
|
|
@@ -3778,6 +3911,9 @@ function coreCheckRegistry() {
|
|
|
3778
3911
|
GH_TOKEN: { optional: true }
|
|
3779
3912
|
}
|
|
3780
3913
|
},
|
|
3914
|
+
0
|
|
3915
|
+
],
|
|
3916
|
+
[
|
|
3781
3917
|
{
|
|
3782
3918
|
name: "doc-coverage-push",
|
|
3783
3919
|
run: bin("check-doc-coverage-push"),
|
|
@@ -3795,6 +3931,9 @@ function coreCheckRegistry() {
|
|
|
3795
3931
|
GH_TOKEN: { optional: true }
|
|
3796
3932
|
}
|
|
3797
3933
|
},
|
|
3934
|
+
0
|
|
3935
|
+
],
|
|
3936
|
+
[
|
|
3798
3937
|
{
|
|
3799
3938
|
name: "issue-assignment",
|
|
3800
3939
|
run: bin("check-issue-assignment"),
|
|
@@ -3807,6 +3946,9 @@ function coreCheckRegistry() {
|
|
|
3807
3946
|
GH_TOKEN: { optional: true }
|
|
3808
3947
|
}
|
|
3809
3948
|
},
|
|
3949
|
+
0
|
|
3950
|
+
],
|
|
3951
|
+
[
|
|
3810
3952
|
{
|
|
3811
3953
|
name: "evidence-fresh",
|
|
3812
3954
|
run: bin("check-evidence-fresh"),
|
|
@@ -3821,6 +3963,9 @@ function coreCheckRegistry() {
|
|
|
3821
3963
|
GH_TOKEN: { optional: true }
|
|
3822
3964
|
}
|
|
3823
3965
|
},
|
|
3966
|
+
1
|
|
3967
|
+
],
|
|
3968
|
+
[
|
|
3824
3969
|
{
|
|
3825
3970
|
name: "reader-resolvable-prose",
|
|
3826
3971
|
run: bin("check-reader-resolvable-prose"),
|
|
@@ -3828,6 +3973,9 @@ function coreCheckRegistry() {
|
|
|
3828
3973
|
timeoutMs: 30000,
|
|
3829
3974
|
env: {}
|
|
3830
3975
|
},
|
|
3976
|
+
0
|
|
3977
|
+
],
|
|
3978
|
+
[
|
|
3831
3979
|
{
|
|
3832
3980
|
name: "retired-vocabulary",
|
|
3833
3981
|
run: bin("check-retired-vocabulary"),
|
|
@@ -3835,6 +3983,9 @@ function coreCheckRegistry() {
|
|
|
3835
3983
|
timeoutMs: 30000,
|
|
3836
3984
|
env: {}
|
|
3837
3985
|
},
|
|
3986
|
+
0
|
|
3987
|
+
],
|
|
3988
|
+
[
|
|
3838
3989
|
{
|
|
3839
3990
|
name: "doctrine-portability",
|
|
3840
3991
|
run: bin("check-doctrine-portability"),
|
|
@@ -3842,15 +3993,33 @@ function coreCheckRegistry() {
|
|
|
3842
3993
|
timeoutMs: 30000,
|
|
3843
3994
|
env: { BASE_SHA: { optional: true } }
|
|
3844
3995
|
},
|
|
3996
|
+
0
|
|
3997
|
+
],
|
|
3998
|
+
[
|
|
3845
3999
|
{
|
|
3846
4000
|
name: "workspace-escape",
|
|
3847
4001
|
run: bin("check-workspace-escape"),
|
|
3848
4002
|
scope: "full",
|
|
3849
4003
|
timeoutMs: 30000,
|
|
3850
4004
|
env: {}
|
|
3851
|
-
}
|
|
3852
|
-
|
|
4005
|
+
},
|
|
4006
|
+
0
|
|
4007
|
+
],
|
|
4008
|
+
[
|
|
4009
|
+
{
|
|
4010
|
+
name: "main-branch-refusal",
|
|
4011
|
+
run: bin("check-main-branch-refusal"),
|
|
4012
|
+
scope: "full",
|
|
4013
|
+
timeoutMs: 15000,
|
|
4014
|
+
env: {}
|
|
4015
|
+
},
|
|
4016
|
+
0
|
|
4017
|
+
]
|
|
4018
|
+
];
|
|
4019
|
+
function coreCheckRegistry() {
|
|
4020
|
+
return REGISTRY.map(([spec]) => spec);
|
|
3853
4021
|
}
|
|
4022
|
+
var CORE_CHECK_RING = Object.fromEntries(REGISTRY.map(([spec, ring]) => [spec.name, ring]));
|
|
3854
4023
|
|
|
3855
4024
|
// src/checks/bin/check-registry-gates.ts
|
|
3856
4025
|
var CHECK_NAME = "registry-gates";
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
// src/checks/bin/check-retired-vocabulary.ts
|
|
4
4
|
import { readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
5
|
-
import { join as
|
|
5
|
+
import { join as join5, resolve } from "node:path";
|
|
6
6
|
// ../../packages/aeg-core/src/gate-audience.ts
|
|
7
7
|
var GATE_AUDIENCE = {
|
|
8
|
-
"check-branch-topology": { shippedAs: "branch-topology" },
|
|
9
|
-
"check-first-push-dispatch": { shippedAs: "first-push-dispatch" },
|
|
10
|
-
"check-no-disk-state": { shippedAs: "no-disk-state" },
|
|
11
|
-
"verify-brief": { shippedAs: "brief-shape" },
|
|
12
|
-
"verify-coherence": { shippedAs: "coherence" },
|
|
13
|
-
"verify-dispatch": { shippedAs: "dispatch-readiness" },
|
|
14
|
-
"verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"] },
|
|
15
|
-
"verify-registry": { shippedAs: "registry-gates" },
|
|
16
|
-
"verify-review-gate": { shippedAs: "review-gate" },
|
|
17
|
-
"verify-single-plan-pr": { shippedAs: "single-plan-pr" },
|
|
18
|
-
"verify-test-plan": { shippedAs: "test-plan" },
|
|
8
|
+
"check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
|
|
9
|
+
"check-first-push-dispatch": { shippedAs: "first-push-dispatch", ring: 0 },
|
|
10
|
+
"check-no-disk-state": { shippedAs: "no-disk-state", ring: 0 },
|
|
11
|
+
"verify-brief": { shippedAs: "brief-shape", ring: 0 },
|
|
12
|
+
"verify-coherence": { shippedAs: "coherence", ring: 0 },
|
|
13
|
+
"verify-dispatch": { shippedAs: "dispatch-readiness", ring: 0 },
|
|
14
|
+
"verify-docs": { shippedAs: ["doc-coverage", "doc-coverage-push"], ring: 0 },
|
|
15
|
+
"verify-registry": { shippedAs: "registry-gates", ring: 0 },
|
|
16
|
+
"verify-review-gate": { shippedAs: "review-gate", ring: 1 },
|
|
17
|
+
"verify-single-plan-pr": { shippedAs: "single-plan-pr", ring: 0 },
|
|
18
|
+
"verify-test-plan": { shippedAs: "test-plan", ring: 1 },
|
|
19
19
|
"check-direct-main-push": {
|
|
20
20
|
internal: "Reaches adopters through `vinaya audit --only=direct-push`, not the check registry: it is a ring-2 sweep over merge history keyed on `GITHUB_SHA`, run by the generated archivist job on push to the default branch. It has no diff to key on, so there is nothing for `vinaya check` to run it against."
|
|
21
21
|
},
|
|
@@ -327,6 +327,13 @@ var LABELS = [
|
|
|
327
327
|
form: "literal",
|
|
328
328
|
carries: "Execution is halted pending an external unblock; wins over every other derived status."
|
|
329
329
|
},
|
|
330
|
+
{
|
|
331
|
+
key: "backlog",
|
|
332
|
+
id: "vinaya/backlog",
|
|
333
|
+
category: "state",
|
|
334
|
+
form: "literal",
|
|
335
|
+
carries: "The Issue is deliberately unplanned — belongs to no tranche and is excluded from dispatch, until a Planner promotes it."
|
|
336
|
+
},
|
|
330
337
|
{
|
|
331
338
|
key: "tier-0",
|
|
332
339
|
id: "vinaya/tier:0",
|
|
@@ -1985,7 +1992,59 @@ function overrideActive(opts) {
|
|
|
1985
1992
|
return false;
|
|
1986
1993
|
}
|
|
1987
1994
|
// ../../packages/aeg-core/src/premise-check.ts
|
|
1995
|
+
import { createHash } from "node:crypto";
|
|
1988
1996
|
var ASSERTION_KINDS = new Set(["contains", "absent", "sha256"]);
|
|
1997
|
+
function isPremiseHeader(line) {
|
|
1998
|
+
const stripped = line.replace(/[*#]/g, "").trim();
|
|
1999
|
+
return /^premise\s*:?$/i.test(stripped);
|
|
2000
|
+
}
|
|
2001
|
+
var PREMISE_LINE = /^[-*]\s*(\S+)\s+(contains|absent|sha256)\s*:\s*(.+)$/i;
|
|
2002
|
+
function parsePremiseBlock(prBody) {
|
|
2003
|
+
const searchIn = anchoredRegion(prBody, "PREMISE") ?? prBody;
|
|
2004
|
+
const lines = searchIn.split(/\r?\n/);
|
|
2005
|
+
const assertions = [];
|
|
2006
|
+
let inBlock = false;
|
|
2007
|
+
for (const raw of lines) {
|
|
2008
|
+
const line = raw.trim();
|
|
2009
|
+
if (!inBlock) {
|
|
2010
|
+
if (isPremiseHeader(line))
|
|
2011
|
+
inBlock = true;
|
|
2012
|
+
continue;
|
|
2013
|
+
}
|
|
2014
|
+
if (line === "")
|
|
2015
|
+
break;
|
|
2016
|
+
const m = line.match(PREMISE_LINE);
|
|
2017
|
+
if (!m)
|
|
2018
|
+
break;
|
|
2019
|
+
const [, path, kindRaw, value] = m;
|
|
2020
|
+
const kind = kindRaw.toLowerCase();
|
|
2021
|
+
if (!ASSERTION_KINDS.has(kind))
|
|
2022
|
+
continue;
|
|
2023
|
+
assertions.push({ kind, path, value: value.trim() });
|
|
2024
|
+
}
|
|
2025
|
+
return assertions;
|
|
2026
|
+
}
|
|
2027
|
+
function checkPremises(assertions, fileReader) {
|
|
2028
|
+
const failures = [];
|
|
2029
|
+
for (const a of assertions) {
|
|
2030
|
+
const content = fileReader(a.path);
|
|
2031
|
+
if (content === null) {
|
|
2032
|
+
failures.push(`premise-check: ${a.path} does not exist on disk (premise asserted \`${a.kind}: ${a.value}\`) — the surface moved since this brief was authored; re-dig before proceeding.`);
|
|
2033
|
+
continue;
|
|
2034
|
+
}
|
|
2035
|
+
if (a.kind === "contains" && !content.includes(a.value)) {
|
|
2036
|
+
failures.push(`premise-check: ${a.path} no longer contains "${a.value}" — the premise this brief pinned has moved; re-dig before proceeding.`);
|
|
2037
|
+
} else if (a.kind === "absent" && content.includes(a.value)) {
|
|
2038
|
+
failures.push(`premise-check: ${a.path} now contains "${a.value}", but the brief pinned it absent — the premise has moved; re-dig before proceeding.`);
|
|
2039
|
+
} else if (a.kind === "sha256") {
|
|
2040
|
+
const actual = createHash("sha256").update(content).digest("hex");
|
|
2041
|
+
if (actual !== a.value.toLowerCase()) {
|
|
2042
|
+
failures.push(`premise-check: ${a.path} sha256 mismatch (brief pinned ${a.value}, file is now ${actual}) — the file changed since this brief was authored; re-dig before proceeding.`);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
return { pass: failures.length === 0, failures };
|
|
2047
|
+
}
|
|
1989
2048
|
|
|
1990
2049
|
// ../../packages/aeg-core/src/test-plan-section.ts
|
|
1991
2050
|
var HEADING_FORM_RE = /^#{1,4}[ \t]*(?:\d+[a-z]?\.[ \t]*)?\*{0,2}Test Plan\*{0,2}[ \t]*$/im;
|
|
@@ -2789,6 +2848,7 @@ function checkG1(rows, existsFn) {
|
|
|
2789
2848
|
}
|
|
2790
2849
|
return { check: "G1", status: findings.length > 0 ? "fail" : "pass", findings };
|
|
2791
2850
|
}
|
|
2851
|
+
var SCAFFOLD_PLACEHOLDER = "[undocumented — fill in why]";
|
|
2792
2852
|
function checkG2(rows, candidateFiles) {
|
|
2793
2853
|
const implementations = new Set(rows.map((r) => r.implementation).filter((p) => p !== ""));
|
|
2794
2854
|
const findings = [];
|
|
@@ -2800,6 +2860,16 @@ function checkG2(rows, candidateFiles) {
|
|
|
2800
2860
|
});
|
|
2801
2861
|
}
|
|
2802
2862
|
}
|
|
2863
|
+
for (const row of rows) {
|
|
2864
|
+
const carriesPlaceholder = [row.summary, row.description, row.spec].some((cell) => cell === SCAFFOLD_PLACEHOLDER);
|
|
2865
|
+
if (carriesPlaceholder) {
|
|
2866
|
+
findings.push({
|
|
2867
|
+
row: row.action,
|
|
2868
|
+
path: row.implementation,
|
|
2869
|
+
reason: `${row.ring} row "${row.action}" still carries the scaffold placeholder marker — the why is owed`
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2803
2873
|
return { check: "G2", status: findings.length > 0 ? "info" : "pass", findings };
|
|
2804
2874
|
}
|
|
2805
2875
|
function checkG3(ring0Rows, crossingFiles) {
|
|
@@ -3319,6 +3389,29 @@ function isNewDiskStateFile(path, status) {
|
|
|
3319
3389
|
return false;
|
|
3320
3390
|
return ANY_DEPTH_TRANCHES_MD.test(path) || TOKENS_FILE.test(path);
|
|
3321
3391
|
}
|
|
3392
|
+
// ../../packages/aeg-core/src/main-branch-refusal.ts
|
|
3393
|
+
function checkMainBranchRefusal(facts) {
|
|
3394
|
+
const { currentSymbolicBranch, defaultBranch } = facts;
|
|
3395
|
+
if (currentSymbolicBranch === null)
|
|
3396
|
+
return null;
|
|
3397
|
+
if (defaultBranch === null) {
|
|
3398
|
+
return {
|
|
3399
|
+
reason: "default-branch-undetermined",
|
|
3400
|
+
severity: "warning",
|
|
3401
|
+
currentBranch: currentSymbolicBranch,
|
|
3402
|
+
defaultBranch: null
|
|
3403
|
+
};
|
|
3404
|
+
}
|
|
3405
|
+
if (currentSymbolicBranch === defaultBranch) {
|
|
3406
|
+
return {
|
|
3407
|
+
reason: "on-default-branch",
|
|
3408
|
+
severity: "error",
|
|
3409
|
+
currentBranch: currentSymbolicBranch,
|
|
3410
|
+
defaultBranch
|
|
3411
|
+
};
|
|
3412
|
+
}
|
|
3413
|
+
return null;
|
|
3414
|
+
}
|
|
3322
3415
|
// ../../packages/aeg-core/src/branch-topology-gate.ts
|
|
3323
3416
|
function taskBranchTopologyFields(branch) {
|
|
3324
3417
|
if (!/^task\/.*\/.*$/.test(branch))
|
|
@@ -3700,8 +3793,15 @@ function isSafeRepoRelPath(p) {
|
|
|
3700
3793
|
var SafeRepoRelPath = z.string().refine(isSafeRepoRelPath, {
|
|
3701
3794
|
message: "must be a repo-root-relative path with no `..` segment or absolute root"
|
|
3702
3795
|
});
|
|
3796
|
+
var CANONICAL_HOOK_BLOCK_PREFIXES = [".git/", ".husky/", ".vinaya/hooks/", ".claude/hooks/"];
|
|
3797
|
+
function isCanonicalHookBlockPath(p) {
|
|
3798
|
+
return CANONICAL_HOOK_BLOCK_PREFIXES.some((prefix) => p.startsWith(prefix) && p.length > prefix.length);
|
|
3799
|
+
}
|
|
3800
|
+
var ManagedHookBlockPath = SafeRepoRelPath.refine(isCanonicalHookBlockPath, {
|
|
3801
|
+
message: `must start with one of ${CANONICAL_HOOK_BLOCK_PREFIXES.join(", ")} (byte-exact, case-sensitive)`
|
|
3802
|
+
});
|
|
3703
3803
|
var ManagedBlockRecordSchema = z.object({
|
|
3704
|
-
path:
|
|
3804
|
+
path: ManagedHookBlockPath,
|
|
3705
3805
|
marker: z.string(),
|
|
3706
3806
|
comment: z.enum(["hash", "html"])
|
|
3707
3807
|
});
|
|
@@ -3882,6 +3982,71 @@ function emitCheckError(error) {
|
|
|
3882
3982
|
`);
|
|
3883
3983
|
}
|
|
3884
3984
|
|
|
3985
|
+
// src/lib/diff-evidence.ts
|
|
3986
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3987
|
+
import { join as join4 } from "node:path";
|
|
3988
|
+
function fileDiffAgainst(ref, path) {
|
|
3989
|
+
let out;
|
|
3990
|
+
try {
|
|
3991
|
+
out = execFileSync3("git", ["diff", `${ref}...HEAD`, "--", path], {
|
|
3992
|
+
encoding: "utf8",
|
|
3993
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3994
|
+
}).trim();
|
|
3995
|
+
} catch {
|
|
3996
|
+
return null;
|
|
3997
|
+
}
|
|
3998
|
+
return out === "" ? null : out;
|
|
3999
|
+
}
|
|
4000
|
+
function revParse(ref) {
|
|
4001
|
+
try {
|
|
4002
|
+
return execFileSync3("git", ["rev-parse", "--verify", ref], {
|
|
4003
|
+
encoding: "utf8",
|
|
4004
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4005
|
+
}).trim();
|
|
4006
|
+
} catch {
|
|
4007
|
+
return null;
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
function repoRoot() {
|
|
4011
|
+
try {
|
|
4012
|
+
return execFileSync3("git", ["rev-parse", "--show-toplevel"], {
|
|
4013
|
+
encoding: "utf8",
|
|
4014
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4015
|
+
}).trim();
|
|
4016
|
+
} catch {
|
|
4017
|
+
return null;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
function changedFiles(base) {
|
|
4021
|
+
let out;
|
|
4022
|
+
try {
|
|
4023
|
+
out = execFileSync3("git", ["diff", "--name-only", `${base}...HEAD`], {
|
|
4024
|
+
encoding: "utf8",
|
|
4025
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4026
|
+
}).trim();
|
|
4027
|
+
} catch {
|
|
4028
|
+
return null;
|
|
4029
|
+
}
|
|
4030
|
+
return out === "" ? [] : out.split(`
|
|
4031
|
+
`).map((s) => s.trim()).filter(Boolean);
|
|
4032
|
+
}
|
|
4033
|
+
function resolveChangedFiles(base = process.env.BASE_SHA || "origin/main") {
|
|
4034
|
+
const root = repoRoot();
|
|
4035
|
+
if (root === null)
|
|
4036
|
+
return null;
|
|
4037
|
+
const head = revParse("HEAD");
|
|
4038
|
+
for (const ref of [base, "main"]) {
|
|
4039
|
+
const resolved = revParse(ref);
|
|
4040
|
+
if (resolved === null || resolved === head)
|
|
4041
|
+
continue;
|
|
4042
|
+
const relPaths = changedFiles(ref);
|
|
4043
|
+
if (relPaths === null)
|
|
4044
|
+
continue;
|
|
4045
|
+
return relPaths.map((p) => join4(root, p));
|
|
4046
|
+
}
|
|
4047
|
+
return null;
|
|
4048
|
+
}
|
|
4049
|
+
|
|
3885
4050
|
// src/checks/bin/check-retired-vocabulary.ts
|
|
3886
4051
|
var CHECK_NAME = "retired-vocabulary";
|
|
3887
4052
|
var DOCTRINE_ROOT = loadConfig()?.proseGates?.doctrineRoot ?? resolveDoctrineRoot() ?? "aeg-root";
|
|
@@ -3896,7 +4061,7 @@ function collect(dir, out = []) {
|
|
|
3896
4061
|
return out;
|
|
3897
4062
|
}
|
|
3898
4063
|
for (const name of entries) {
|
|
3899
|
-
const full =
|
|
4064
|
+
const full = join5(dir, name);
|
|
3900
4065
|
let isDir;
|
|
3901
4066
|
try {
|
|
3902
4067
|
isDir = statSync(full).isDirectory();
|
|
@@ -3920,8 +4085,12 @@ function main() {
|
|
|
3920
4085
|
const paths = collect(DOCTRINE_ROOT);
|
|
3921
4086
|
const files = readAll(paths);
|
|
3922
4087
|
const findings = scanRetiredVocabulary(files);
|
|
3923
|
-
|
|
3924
|
-
|
|
4088
|
+
const changedFilesList = resolveChangedFiles();
|
|
4089
|
+
const changed = changedFilesList === null ? null : new Set(changedFilesList);
|
|
4090
|
+
const pathBase = repoRoot() ?? process.cwd();
|
|
4091
|
+
const reportable = changed === null ? findings : findings.filter((f) => changed.has(resolve(pathBase, f.file)));
|
|
4092
|
+
console.log(`${CHECK_NAME}: doctrine root "${DOCTRINE_ROOT}"; ${paths.length} file(s) swept; ${findings.length} finding(s), ${reportable.length} in this diff`);
|
|
4093
|
+
for (const finding of reportable) {
|
|
3925
4094
|
emitCheckError({
|
|
3926
4095
|
schema: CHECK_SCHEMA_VERSION,
|
|
3927
4096
|
check: CHECK_NAME,
|