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