@attalabs/vinaya 0.18.0 → 0.19.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 +37 -1
- package/aeg-root/contracts/architect-planner.md +72 -0
- package/aeg-root/enforcement.md +3 -2
- package/aeg-root/roles/architect.md +91 -0
- package/aeg-root/roles/planner.md +14 -15
- package/aeg-root/tranche-model.md +9 -1
- package/dist/checks/bin/check-body-bare-digits.js +262 -26
- package/dist/checks/bin/check-branch-topology.js +171 -23
- package/dist/checks/bin/check-brief-shape.js +171 -23
- package/dist/checks/bin/check-closes-n.js +171 -23
- package/dist/checks/bin/check-coherence.js +265 -29
- package/dist/checks/bin/check-dead-branch-push.js +171 -23
- package/dist/checks/bin/check-dispatch-readiness.js +329 -53
- package/dist/checks/bin/check-doc-coverage-push.js +266 -30
- package/dist/checks/bin/check-doc-coverage.js +266 -30
- package/dist/checks/bin/check-evidence-fresh.js +171 -23
- package/dist/checks/bin/check-first-push-dispatch.js +330 -54
- package/dist/checks/bin/check-issue-assignment.js +171 -23
- package/dist/checks/bin/check-no-disk-state.js +171 -23
- package/dist/checks/bin/check-reader-resolvable-prose.js +465 -46
- package/dist/checks/bin/check-registry-gates.js +171 -23
- package/dist/checks/bin/check-retired-vocabulary.js +3595 -0
- package/dist/checks/bin/check-review-gate.js +262 -26
- package/dist/checks/bin/check-single-plan-pr.js +171 -23
- package/dist/checks/bin/check-test-plan.js +171 -23
- package/dist/index.js +2959 -1581
- package/package.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.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/_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.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/[root-of-the-server]__0e95dv5._.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]__029-1ch._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0q56ohl._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0z47hfl._.js → [root-of-the-server]__0xdkvod._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1_ojzp1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1d_8nm4._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1zkwtx8._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__210ehg9._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_00yjcv1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0rix02i._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_18-d2be._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1fqw88f._.js +5 -5
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1gw6vc9._.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/{2myi4phnshkfw.js → 1zaotsjjq5o6o.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{415k4k1rf3swg.js → 295mri9sjante.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3z3a3gb6he23i.js → 2opd70pfbc5yx.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
- package/templates/noop-check.template.ts +18 -0
- package/templates/role.template.md +20 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → SG6gXRhit12wl-8HLX9d3}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → SG6gXRhit12wl-8HLX9d3}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → SG6gXRhit12wl-8HLX9d3}/_ssgManifest.js +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/checks/bin/check-doc-coverage-push.ts
|
|
4
4
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
6
6
|
// ../../packages/aeg-forge-state/src/strip-code.ts
|
|
7
7
|
function maskCode(body) {
|
|
8
8
|
const fill = (line) => " ".repeat(line.length);
|
|
@@ -274,6 +274,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
274
274
|
"200"
|
|
275
275
|
];
|
|
276
276
|
}
|
|
277
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
278
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
279
|
+
}
|
|
277
280
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
278
281
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
279
282
|
}
|
|
@@ -289,18 +292,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
289
292
|
return dedupeByNumber(perLabel.flat());
|
|
290
293
|
}
|
|
291
294
|
|
|
292
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
293
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
294
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
295
|
-
const match = milestones.find((m) => m.title === slug);
|
|
296
|
-
if (!match)
|
|
297
|
-
return null;
|
|
298
|
-
return {
|
|
299
|
-
goal: match.description ?? "",
|
|
300
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
|
|
304
295
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
305
296
|
var LABELS = [
|
|
306
297
|
{
|
|
@@ -543,6 +534,66 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
543
534
|
return { trancheSlug, taskId };
|
|
544
535
|
}
|
|
545
536
|
|
|
537
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
538
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
539
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
540
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
541
|
+
function intentGoalForSlug(description, slug) {
|
|
542
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
543
|
+
const start = text.match(INTENTS_HEADING);
|
|
544
|
+
if (!start || start.index === undefined)
|
|
545
|
+
return "";
|
|
546
|
+
const rest = text.slice(start.index + start[0].length);
|
|
547
|
+
const next = rest.match(NEXT_HEADING);
|
|
548
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
549
|
+
for (const line of section.split(`
|
|
550
|
+
`)) {
|
|
551
|
+
const trimmed = line.trim();
|
|
552
|
+
if (trimmed.length === 0)
|
|
553
|
+
continue;
|
|
554
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
555
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
556
|
+
return (m[2] ?? "").trim();
|
|
557
|
+
}
|
|
558
|
+
return "";
|
|
559
|
+
}
|
|
560
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
561
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
562
|
+
}
|
|
563
|
+
function factsFromLegacyMilestone(milestone) {
|
|
564
|
+
return {
|
|
565
|
+
goal: milestone.description ?? "",
|
|
566
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
function resolveLegacyFacts(milestone, labelIssues) {
|
|
570
|
+
if (milestone.state === "closed" && labelIssues.length > 0) {
|
|
571
|
+
return { goal: milestone.description ?? "", lifecycle: lifecycleFromIssues(labelIssues) };
|
|
572
|
+
}
|
|
573
|
+
return factsFromLegacyMilestone(milestone);
|
|
574
|
+
}
|
|
575
|
+
function lifecycleFromIssues(issues) {
|
|
576
|
+
if (issues.length === 0)
|
|
577
|
+
return "planned";
|
|
578
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
579
|
+
}
|
|
580
|
+
function goalFromMilestones(milestones, slug) {
|
|
581
|
+
for (const m of milestones) {
|
|
582
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
583
|
+
if (goal)
|
|
584
|
+
return goal;
|
|
585
|
+
}
|
|
586
|
+
return "";
|
|
587
|
+
}
|
|
588
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
589
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
590
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
591
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
592
|
+
if (legacy)
|
|
593
|
+
return resolveLegacyFacts(legacy, issues);
|
|
594
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
595
|
+
}
|
|
596
|
+
|
|
546
597
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
547
598
|
function trancheFromIssues(slug, issues, known) {
|
|
548
599
|
return {
|
|
@@ -2726,16 +2777,18 @@ function checkDeadBranchPush(input) {
|
|
|
2726
2777
|
}
|
|
2727
2778
|
// ../../packages/aeg-core/src/reader-resolvable-prose.ts
|
|
2728
2779
|
var SHIPS_PREFIX = "aeg-root/";
|
|
2729
|
-
|
|
2780
|
+
function shipsArchivePrefix(shipsPrefix) {
|
|
2781
|
+
return `${shipsPrefix}tranches/completed/`;
|
|
2782
|
+
}
|
|
2730
2783
|
function isSpecFile2(path) {
|
|
2731
2784
|
return path.startsWith("apps/") && path.includes("/specs/") && path.endsWith(".md");
|
|
2732
2785
|
}
|
|
2733
2786
|
function isClaudeMdFile(path) {
|
|
2734
2787
|
return path === "CLAUDE.md" || path.endsWith("/CLAUDE.md");
|
|
2735
2788
|
}
|
|
2736
|
-
function classifyProseFile(path, readerFacingPrefix, readerFacingSuffix) {
|
|
2737
|
-
if (path.startsWith(
|
|
2738
|
-
return path.startsWith(
|
|
2789
|
+
function classifyProseFile(path, readerFacingPrefix, readerFacingSuffix, shipsPrefix = SHIPS_PREFIX) {
|
|
2790
|
+
if (path.startsWith(shipsPrefix)) {
|
|
2791
|
+
return path.startsWith(shipsArchivePrefix(shipsPrefix)) ? "internal" : "ships";
|
|
2739
2792
|
}
|
|
2740
2793
|
if (path.startsWith(readerFacingPrefix) && path.endsWith(readerFacingSuffix)) {
|
|
2741
2794
|
return "reader-facing";
|
|
@@ -2770,7 +2823,7 @@ function legacySlugPattern(legacySlugs) {
|
|
|
2770
2823
|
const alternation = legacySlugs.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
2771
2824
|
return new RegExp(`(^|[^a-zA-Z0-9\\n-])(${alternation})([^a-zA-Z0-9\\n-]|$)`, "g");
|
|
2772
2825
|
}
|
|
2773
|
-
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2826
|
+
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2774
2827
|
const findings = [];
|
|
2775
2828
|
const legacyPattern = legacySlugPattern(legacySlugs);
|
|
2776
2829
|
const patterns = [
|
|
@@ -2779,7 +2832,7 @@ function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuff
|
|
|
2779
2832
|
...legacyPattern ? [{ pattern: legacyPattern, what: "an internal tranche slug", group: 2 }] : []
|
|
2780
2833
|
];
|
|
2781
2834
|
for (const file of files) {
|
|
2782
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2835
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2783
2836
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2784
2837
|
continue;
|
|
2785
2838
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2825,10 +2878,10 @@ function definesOrLinksGlossary(content, term) {
|
|
|
2825
2878
|
return true;
|
|
2826
2879
|
return /docs\/glossary|glossary\.md/i.test(content);
|
|
2827
2880
|
}
|
|
2828
|
-
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix) {
|
|
2881
|
+
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix = SHIPS_PREFIX) {
|
|
2829
2882
|
const findings = [];
|
|
2830
2883
|
for (const file of files) {
|
|
2831
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2884
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2832
2885
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2833
2886
|
continue;
|
|
2834
2887
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2847,10 +2900,10 @@ function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, read
|
|
|
2847
2900
|
}
|
|
2848
2901
|
return findings;
|
|
2849
2902
|
}
|
|
2850
|
-
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2903
|
+
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2851
2904
|
return [
|
|
2852
|
-
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs),
|
|
2853
|
-
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix)
|
|
2905
|
+
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs, shipsPrefix),
|
|
2906
|
+
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix)
|
|
2854
2907
|
];
|
|
2855
2908
|
}
|
|
2856
2909
|
function parseGlossaryTerms(glossaryContent) {
|
|
@@ -2864,6 +2917,101 @@ function parseGlossaryTerms(glossaryContent) {
|
|
|
2864
2917
|
}
|
|
2865
2918
|
return terms;
|
|
2866
2919
|
}
|
|
2920
|
+
// ../../packages/aeg-core/src/retired-vocabulary.ts
|
|
2921
|
+
var RETIRED_PATTERNS = [
|
|
2922
|
+
String.raw`\bD-[0-9]{3}\b`,
|
|
2923
|
+
"D-(###|NNN|nnn|xxx)",
|
|
2924
|
+
"decision (entry|logged)",
|
|
2925
|
+
"decision-log entry",
|
|
2926
|
+
"decision log entry",
|
|
2927
|
+
"decision log(s|ged|ging)?([^a-z]|$)",
|
|
2928
|
+
"decision-log",
|
|
2929
|
+
"decision entr",
|
|
2930
|
+
"decisions? (are |is )?logged",
|
|
2931
|
+
"log entries",
|
|
2932
|
+
String.raw`decisions\.md`,
|
|
2933
|
+
"decisions-legacy",
|
|
2934
|
+
"CONTRADICTION",
|
|
2935
|
+
"assumes Tier 3",
|
|
2936
|
+
"Lock: ?YES",
|
|
2937
|
+
"Lock: ?NO",
|
|
2938
|
+
"lock approvals?",
|
|
2939
|
+
"approves locks",
|
|
2940
|
+
"Conforms to lock",
|
|
2941
|
+
"Challenges lock",
|
|
2942
|
+
"checkDecisionNumbersFresh",
|
|
2943
|
+
String.raw`roles/team-leader\.md`,
|
|
2944
|
+
String.raw`\(,`,
|
|
2945
|
+
String.raw`,\)`,
|
|
2946
|
+
String.raw`\(\.\)`
|
|
2947
|
+
];
|
|
2948
|
+
var RETIRED_EXEMPT_SUBSTRINGS = [
|
|
2949
|
+
"docs/decisions-legacy.md",
|
|
2950
|
+
"apps/herald-ai/docs/",
|
|
2951
|
+
"apps/vada-ai/docs/",
|
|
2952
|
+
"aeg-root/tranches/completed/",
|
|
2953
|
+
"packages/aeg-core/src/docs/published-prose",
|
|
2954
|
+
"packages/aeg-core/src/retired-vocabulary.test.ts",
|
|
2955
|
+
"packages/aeg-core/src/retired-vocabulary.ts",
|
|
2956
|
+
"/fixtures/",
|
|
2957
|
+
"/node_modules/",
|
|
2958
|
+
"/.next/",
|
|
2959
|
+
"/.turbo/"
|
|
2960
|
+
];
|
|
2961
|
+
var PATTERN_EXEMPT = {
|
|
2962
|
+
[String.raw`\bD-[0-9]{3}\b`]: ["./CLAUDE.md"],
|
|
2963
|
+
[String.raw`decisions\.md`]: [
|
|
2964
|
+
"docs-index.md",
|
|
2965
|
+
"apps/vada-ai/specs/legacy/README.md",
|
|
2966
|
+
"apps/vada-ai/specs/vada-product-spec.md",
|
|
2967
|
+
"apps/vada-ai/web/CLAUDE.md",
|
|
2968
|
+
"apps/vada-ai/CLAUDE.md"
|
|
2969
|
+
],
|
|
2970
|
+
"decisions-legacy": [
|
|
2971
|
+
"packages/aeg-core/src/file-classify.ts",
|
|
2972
|
+
"packages/aeg-core/src/file-classify.test.ts",
|
|
2973
|
+
"packages/aeg-core/src/pr-tier.test.ts",
|
|
2974
|
+
"docs-index.md",
|
|
2975
|
+
".claude/skills/database/SKILL.md",
|
|
2976
|
+
".claude/skills/vada-architecture/SKILL.md",
|
|
2977
|
+
"apps/vada-ai/specs/vada-byok-principles.md",
|
|
2978
|
+
"apps/vada-ai/web/CLAUDE.md",
|
|
2979
|
+
"apps/vada-ai/CLAUDE.md"
|
|
2980
|
+
],
|
|
2981
|
+
CONTRADICTION: ["apps/vada-ai/specs/vada-reviewers-spec.md"]
|
|
2982
|
+
};
|
|
2983
|
+
function lineNumbers(content, pattern) {
|
|
2984
|
+
const out = [];
|
|
2985
|
+
const lines = content.split(`
|
|
2986
|
+
`);
|
|
2987
|
+
for (let i = 0;i < lines.length; i++) {
|
|
2988
|
+
if (pattern.test(lines[i] ?? ""))
|
|
2989
|
+
out.push(i + 1);
|
|
2990
|
+
}
|
|
2991
|
+
return out;
|
|
2992
|
+
}
|
|
2993
|
+
function scanRetiredVocabulary(files) {
|
|
2994
|
+
const findings = [];
|
|
2995
|
+
for (const file of files) {
|
|
2996
|
+
if (RETIRED_EXEMPT_SUBSTRINGS.some((e) => file.path.includes(e)))
|
|
2997
|
+
continue;
|
|
2998
|
+
for (const pattern of RETIRED_PATTERNS) {
|
|
2999
|
+
const patternExempt = PATTERN_EXEMPT[pattern] ?? [];
|
|
3000
|
+
if (patternExempt.some((e) => file.path.includes(e)))
|
|
3001
|
+
continue;
|
|
3002
|
+
const re = new RegExp(pattern);
|
|
3003
|
+
for (const line of lineNumbers(file.content, re)) {
|
|
3004
|
+
findings.push({
|
|
3005
|
+
file: file.path,
|
|
3006
|
+
line,
|
|
3007
|
+
pattern,
|
|
3008
|
+
message: `claims a retired AEG mechanism is still live (matches /${pattern}/)`
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
return findings;
|
|
3014
|
+
}
|
|
2867
3015
|
// ../../packages/aeg-core/src/dispatch-gate.ts
|
|
2868
3016
|
function isHandClosedByRecognizedPrincipal(dep, principalAllowlist) {
|
|
2869
3017
|
return dep.issueState === "closed" && dep.stateReason === "completed" && isPrincipal(dep.closedByActor ?? null, principalAllowlist);
|
|
@@ -3141,9 +3289,15 @@ function emitCheckError(error) {
|
|
|
3141
3289
|
|
|
3142
3290
|
// src/lib/config.ts
|
|
3143
3291
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3292
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3144
3293
|
import { homedir } from "node:os";
|
|
3145
3294
|
import { dirname, join } from "node:path";
|
|
3146
3295
|
import { z } from "zod";
|
|
3296
|
+
|
|
3297
|
+
// src/lib/agent-vendors.ts
|
|
3298
|
+
var AGENT_VENDORS = ["skills", "claude", "gemini"];
|
|
3299
|
+
|
|
3300
|
+
// src/lib/config.ts
|
|
3147
3301
|
var EnvEntrySchema = z.union([
|
|
3148
3302
|
z.literal(true),
|
|
3149
3303
|
z.object({ optional: z.literal(true) }),
|
|
@@ -3182,6 +3336,11 @@ var CheckEntrySchema = z.object({
|
|
|
3182
3336
|
}
|
|
3183
3337
|
}
|
|
3184
3338
|
});
|
|
3339
|
+
var RoleEntrySchema = z.object({
|
|
3340
|
+
contract: z.string().refine((p) => p.includes("/"), {
|
|
3341
|
+
message: 'must be a path (contain at least one "/"), not a bare filename'
|
|
3342
|
+
})
|
|
3343
|
+
});
|
|
3185
3344
|
var BRIEF_BUILTINS = [
|
|
3186
3345
|
"tier",
|
|
3187
3346
|
"testPlan",
|
|
@@ -3196,7 +3355,8 @@ var BRIEF_BUILTINS = [
|
|
|
3196
3355
|
"for",
|
|
3197
3356
|
"closesN",
|
|
3198
3357
|
"premiseCoverage",
|
|
3199
|
-
"issueRationale"
|
|
3358
|
+
"issueRationale",
|
|
3359
|
+
"milestoneShape"
|
|
3200
3360
|
];
|
|
3201
3361
|
var BriefSectionSchema = z.union([
|
|
3202
3362
|
z.object({ builtin: z.enum(BRIEF_BUILTINS) }),
|
|
@@ -3207,6 +3367,7 @@ var BriefSectionSchema = z.union([
|
|
|
3207
3367
|
var BriefSchemaSchema = z.object({
|
|
3208
3368
|
pr: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3209
3369
|
issue: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3370
|
+
milestone: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3210
3371
|
ack: z.array(z.enum(BRIEF_BUILTINS)).optional()
|
|
3211
3372
|
});
|
|
3212
3373
|
function isSafeRepoRelPath(p) {
|
|
@@ -3228,7 +3389,8 @@ var ManagedManifestSchema = z.object({
|
|
|
3228
3389
|
version: z.number().int().positive(),
|
|
3229
3390
|
files: z.array(SafeRepoRelPath),
|
|
3230
3391
|
blocks: z.array(ManagedBlockRecordSchema),
|
|
3231
|
-
labels: z.array(z.string())
|
|
3392
|
+
labels: z.array(z.string()),
|
|
3393
|
+
agents: z.array(z.enum(AGENT_VENDORS)).optional()
|
|
3232
3394
|
});
|
|
3233
3395
|
var VinayaConfigSchema = z.object({
|
|
3234
3396
|
rings: z.object({
|
|
@@ -3236,16 +3398,79 @@ var VinayaConfigSchema = z.object({
|
|
|
3236
3398
|
ring2_asyncAudits: z.boolean()
|
|
3237
3399
|
}).optional(),
|
|
3238
3400
|
checks: z.record(z.string(), CheckEntrySchema).optional(),
|
|
3401
|
+
roles: z.record(z.string(), RoleEntrySchema).optional(),
|
|
3239
3402
|
briefSchema: BriefSchemaSchema.optional(),
|
|
3240
3403
|
managed: ManagedManifestSchema.optional(),
|
|
3241
3404
|
principals: z.array(z.string()).min(1).optional(),
|
|
3242
3405
|
releaseActor: z.string().min(1).optional(),
|
|
3243
3406
|
ci: z.object({ setup: z.string().min(1) }).optional(),
|
|
3244
|
-
blastRadius: z.object({ extraDomains: z.array(z.string()).optional() }).optional()
|
|
3407
|
+
blastRadius: z.object({ extraDomains: z.array(z.string()).optional() }).optional(),
|
|
3408
|
+
proseGates: z.object({
|
|
3409
|
+
doctrineRoot: z.string().min(1).optional(),
|
|
3410
|
+
readerFacingPrefix: z.string().min(1).optional(),
|
|
3411
|
+
readerFacingSuffix: z.string().min(1).optional(),
|
|
3412
|
+
legacySlugDir: z.string().min(1).optional()
|
|
3413
|
+
}).optional()
|
|
3245
3414
|
});
|
|
3246
3415
|
var GLOBAL_VINAYA_HOME = join(homedir(), ".vinaya");
|
|
3247
3416
|
var GLOBAL_CONFIG_PATH = join(GLOBAL_VINAYA_HOME, "config.json");
|
|
3248
3417
|
var LOCAL_CONFIG_FILENAME = "vinaya.config.json";
|
|
3418
|
+
function findLocalConfig() {
|
|
3419
|
+
let dir = process.cwd();
|
|
3420
|
+
while (true) {
|
|
3421
|
+
const candidate = join(dir, LOCAL_CONFIG_FILENAME);
|
|
3422
|
+
if (existsSync(candidate))
|
|
3423
|
+
return candidate;
|
|
3424
|
+
if (existsSync(join(dir, ".git")))
|
|
3425
|
+
return null;
|
|
3426
|
+
const parent = dirname(dir);
|
|
3427
|
+
if (parent === dir)
|
|
3428
|
+
return null;
|
|
3429
|
+
dir = parent;
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
function configPath() {
|
|
3433
|
+
const local = findLocalConfig();
|
|
3434
|
+
if (local)
|
|
3435
|
+
return local;
|
|
3436
|
+
if (existsSync(GLOBAL_CONFIG_PATH))
|
|
3437
|
+
return GLOBAL_CONFIG_PATH;
|
|
3438
|
+
return null;
|
|
3439
|
+
}
|
|
3440
|
+
function globalChecksIgnoredWarning(path) {
|
|
3441
|
+
return `${path}: "checks" registration in the global config is ignored — checks may only be registered from a repo-local vinaya.config.json.`;
|
|
3442
|
+
}
|
|
3443
|
+
function globalPrincipalsIgnoredWarning(path) {
|
|
3444
|
+
return `${path}: "principals" in the global config is ignored — principals may only be declared from a repo-local vinaya.config.json.`;
|
|
3445
|
+
}
|
|
3446
|
+
function globalRolesIgnoredWarning(path) {
|
|
3447
|
+
return `${path}: "roles" registration in the global config is ignored — roles may only be registered from a repo-local vinaya.config.json.`;
|
|
3448
|
+
}
|
|
3449
|
+
function globalReleaseActorIgnoredWarning(path) {
|
|
3450
|
+
return `${path}: "releaseActor" in the global config is ignored — releaseActor may only be declared from a repo-local vinaya.config.json.`;
|
|
3451
|
+
}
|
|
3452
|
+
function stripGlobalOnlyKeys(config, path) {
|
|
3453
|
+
if (path !== GLOBAL_CONFIG_PATH)
|
|
3454
|
+
return config;
|
|
3455
|
+
let result = config;
|
|
3456
|
+
if (result.checks && Object.keys(result.checks).length > 0) {
|
|
3457
|
+
console.error(`⚠ ${globalChecksIgnoredWarning(path)}`);
|
|
3458
|
+
result = { ...result, checks: undefined };
|
|
3459
|
+
}
|
|
3460
|
+
if (result.roles && Object.keys(result.roles).length > 0) {
|
|
3461
|
+
console.error(`⚠ ${globalRolesIgnoredWarning(path)}`);
|
|
3462
|
+
result = { ...result, roles: undefined };
|
|
3463
|
+
}
|
|
3464
|
+
if (result.principals && result.principals.length > 0) {
|
|
3465
|
+
console.error(`⚠ ${globalPrincipalsIgnoredWarning(path)}`);
|
|
3466
|
+
result = { ...result, principals: undefined };
|
|
3467
|
+
}
|
|
3468
|
+
if (result.releaseActor) {
|
|
3469
|
+
console.error(`⚠ ${globalReleaseActorIgnoredWarning(path)}`);
|
|
3470
|
+
result = { ...result, releaseActor: undefined };
|
|
3471
|
+
}
|
|
3472
|
+
return result;
|
|
3473
|
+
}
|
|
3249
3474
|
function resolvePrincipalAllowlist(config) {
|
|
3250
3475
|
return config?.principals ?? PRINCIPAL_ALLOWLIST;
|
|
3251
3476
|
}
|
|
@@ -3318,6 +3543,17 @@ function loadTrustAnchorConfig(fetcher = ghFetchTrustAnchorConfig) {
|
|
|
3318
3543
|
return null;
|
|
3319
3544
|
}
|
|
3320
3545
|
}
|
|
3546
|
+
function loadConfig() {
|
|
3547
|
+
const path = configPath();
|
|
3548
|
+
if (!path)
|
|
3549
|
+
return null;
|
|
3550
|
+
try {
|
|
3551
|
+
const raw = JSON.parse(readFileSync(path, "utf-8"));
|
|
3552
|
+
return stripGlobalOnlyKeys(VinayaConfigSchema.parse(raw), path);
|
|
3553
|
+
} catch {
|
|
3554
|
+
return null;
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3321
3557
|
|
|
3322
3558
|
// src/checks/bin/check-doc-coverage-push.ts
|
|
3323
3559
|
var CHECK_NAME = "doc-coverage-push";
|
|
@@ -3337,7 +3573,7 @@ function resolvePrBody() {
|
|
|
3337
3573
|
return process.env.PR_BODY;
|
|
3338
3574
|
if (process.env.PR_BODY_FILE) {
|
|
3339
3575
|
try {
|
|
3340
|
-
return
|
|
3576
|
+
return readFileSync2(process.env.PR_BODY_FILE, "utf8");
|
|
3341
3577
|
} catch {
|
|
3342
3578
|
return "";
|
|
3343
3579
|
}
|
|
@@ -3372,8 +3608,8 @@ function main() {
|
|
|
3372
3608
|
}
|
|
3373
3609
|
if (changed.length === 0)
|
|
3374
3610
|
process.exit(0);
|
|
3375
|
-
const content =
|
|
3376
|
-
const result = evaluateC5(changed, content, resolvePrBody(),
|
|
3611
|
+
const content = existsSync2(DOC_OWNERS_PATH) ? readFileSync2(DOC_OWNERS_PATH, "utf8") : null;
|
|
3612
|
+
const result = evaluateC5(changed, content, resolvePrBody(), existsSync2, waiverActiveFromEnv(), (p) => fileDiffAgainst(ref, p));
|
|
3377
3613
|
for (const message of result.errors) {
|
|
3378
3614
|
emitCheckError({
|
|
3379
3615
|
schema: CHECK_SCHEMA_VERSION,
|