@attalabs/vinaya 0.19.0 → 0.19.2
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 +1 -1
- package/aeg-root/enforcement.md +3 -2
- package/aeg-root/milestone-model.md +75 -0
- package/aeg-root/roles/architect.md +4 -4
- package/aeg-root/skills/aeg/SKILL.md +1 -1
- package/aeg-root/task-model.md +45 -0
- package/aeg-root/tranche-model.md +16 -11
- package/dist/checks/bin/check-body-bare-digits.js +204 -15
- package/dist/checks/bin/check-branch-topology.js +116 -13
- package/dist/checks/bin/check-brief-shape.js +116 -13
- package/dist/checks/bin/check-closes-n.js +116 -13
- package/dist/checks/bin/check-coherence.js +207 -18
- package/dist/checks/bin/check-dead-branch-push.js +116 -13
- package/dist/checks/bin/check-dispatch-readiness.js +204 -15
- package/dist/checks/bin/check-doc-coverage-push.js +208 -19
- package/dist/checks/bin/check-doc-coverage.js +208 -19
- package/dist/checks/bin/check-evidence-fresh.js +116 -13
- package/dist/checks/bin/check-first-push-dispatch.js +204 -15
- package/dist/checks/bin/check-issue-assignment.js +116 -13
- package/dist/checks/bin/check-no-disk-state.js +116 -13
- package/dist/checks/bin/check-reader-resolvable-prose.js +410 -36
- package/dist/checks/bin/check-registry-gates.js +116 -13
- package/dist/checks/bin/check-retired-vocabulary.js +3595 -0
- package/dist/checks/bin/check-review-gate.js +204 -15
- package/dist/checks/bin/check-single-plan-pr.js +116 -13
- package/dist/checks/bin/check-test-plan.js +116 -13
- package/dist/index.js +2362 -1602
- 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]__0ulzsom._.js → [root-of-the-server]__0h3web3._.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]__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/{2r36w820aqwb9.js → 1hko4y648-9sa.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3ocvtlhgckh81.js → 20f41k165euzy.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{2xoclb4g7d9n7.js → 3mhcu_-shkfgs.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/{RISz5nirLr1mUfMqzSaFS → Ye7cOzO7rtvyiBouNOFES}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{RISz5nirLr1mUfMqzSaFS → Ye7cOzO7rtvyiBouNOFES}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{RISz5nirLr1mUfMqzSaFS → Ye7cOzO7rtvyiBouNOFES}/_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
|
|
@@ -568,6 +568,12 @@ function factsFromLegacyMilestone(milestone) {
|
|
|
568
568
|
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
569
569
|
};
|
|
570
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
|
+
}
|
|
571
577
|
function lifecycleFromIssues(issues) {
|
|
572
578
|
if (issues.length === 0)
|
|
573
579
|
return "planned";
|
|
@@ -584,9 +590,9 @@ function goalFromMilestones(milestones, slug) {
|
|
|
584
590
|
function findMilestoneForSlug(owner, repo, slug) {
|
|
585
591
|
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
586
592
|
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
587
|
-
if (legacy)
|
|
588
|
-
return factsFromLegacyMilestone(legacy);
|
|
589
593
|
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
594
|
+
if (legacy)
|
|
595
|
+
return resolveLegacyFacts(legacy, issues);
|
|
590
596
|
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
591
597
|
}
|
|
592
598
|
|
|
@@ -2773,16 +2779,18 @@ function checkDeadBranchPush(input) {
|
|
|
2773
2779
|
}
|
|
2774
2780
|
// ../../packages/aeg-core/src/reader-resolvable-prose.ts
|
|
2775
2781
|
var SHIPS_PREFIX = "aeg-root/";
|
|
2776
|
-
|
|
2782
|
+
function shipsArchivePrefix(shipsPrefix) {
|
|
2783
|
+
return `${shipsPrefix}tranches/completed/`;
|
|
2784
|
+
}
|
|
2777
2785
|
function isSpecFile2(path) {
|
|
2778
2786
|
return path.startsWith("apps/") && path.includes("/specs/") && path.endsWith(".md");
|
|
2779
2787
|
}
|
|
2780
2788
|
function isClaudeMdFile(path) {
|
|
2781
2789
|
return path === "CLAUDE.md" || path.endsWith("/CLAUDE.md");
|
|
2782
2790
|
}
|
|
2783
|
-
function classifyProseFile(path, readerFacingPrefix, readerFacingSuffix) {
|
|
2784
|
-
if (path.startsWith(
|
|
2785
|
-
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";
|
|
2786
2794
|
}
|
|
2787
2795
|
if (path.startsWith(readerFacingPrefix) && path.endsWith(readerFacingSuffix)) {
|
|
2788
2796
|
return "reader-facing";
|
|
@@ -2817,7 +2825,7 @@ function legacySlugPattern(legacySlugs) {
|
|
|
2817
2825
|
const alternation = legacySlugs.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
2818
2826
|
return new RegExp(`(^|[^a-zA-Z0-9\\n-])(${alternation})([^a-zA-Z0-9\\n-]|$)`, "g");
|
|
2819
2827
|
}
|
|
2820
|
-
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2828
|
+
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2821
2829
|
const findings = [];
|
|
2822
2830
|
const legacyPattern = legacySlugPattern(legacySlugs);
|
|
2823
2831
|
const patterns = [
|
|
@@ -2826,7 +2834,7 @@ function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuff
|
|
|
2826
2834
|
...legacyPattern ? [{ pattern: legacyPattern, what: "an internal tranche slug", group: 2 }] : []
|
|
2827
2835
|
];
|
|
2828
2836
|
for (const file of files) {
|
|
2829
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2837
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2830
2838
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2831
2839
|
continue;
|
|
2832
2840
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2872,10 +2880,10 @@ function definesOrLinksGlossary(content, term) {
|
|
|
2872
2880
|
return true;
|
|
2873
2881
|
return /docs\/glossary|glossary\.md/i.test(content);
|
|
2874
2882
|
}
|
|
2875
|
-
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix) {
|
|
2883
|
+
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix = SHIPS_PREFIX) {
|
|
2876
2884
|
const findings = [];
|
|
2877
2885
|
for (const file of files) {
|
|
2878
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2886
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2879
2887
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2880
2888
|
continue;
|
|
2881
2889
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2894,10 +2902,10 @@ function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, read
|
|
|
2894
2902
|
}
|
|
2895
2903
|
return findings;
|
|
2896
2904
|
}
|
|
2897
|
-
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2905
|
+
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2898
2906
|
return [
|
|
2899
|
-
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs),
|
|
2900
|
-
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix)
|
|
2907
|
+
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs, shipsPrefix),
|
|
2908
|
+
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix)
|
|
2901
2909
|
];
|
|
2902
2910
|
}
|
|
2903
2911
|
function parseGlossaryTerms(glossaryContent) {
|
|
@@ -2911,6 +2919,101 @@ function parseGlossaryTerms(glossaryContent) {
|
|
|
2911
2919
|
}
|
|
2912
2920
|
return terms;
|
|
2913
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
|
+
}
|
|
2914
3017
|
// ../../packages/aeg-core/src/dispatch-gate.ts
|
|
2915
3018
|
function isHandClosedByRecognizedPrincipal(dep, principalAllowlist) {
|
|
2916
3019
|
return dep.issueState === "closed" && dep.stateReason === "completed" && isPrincipal(dep.closedByActor ?? null, principalAllowlist);
|
|
@@ -3187,9 +3290,15 @@ function emitCheckError(error) {
|
|
|
3187
3290
|
|
|
3188
3291
|
// src/lib/config.ts
|
|
3189
3292
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3293
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3190
3294
|
import { homedir } from "node:os";
|
|
3191
3295
|
import { dirname, join } from "node:path";
|
|
3192
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
|
|
3193
3302
|
var EnvEntrySchema = z2.union([
|
|
3194
3303
|
z2.literal(true),
|
|
3195
3304
|
z2.object({ optional: z2.literal(true) }),
|
|
@@ -3228,6 +3337,11 @@ var CheckEntrySchema = z2.object({
|
|
|
3228
3337
|
}
|
|
3229
3338
|
}
|
|
3230
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
|
+
});
|
|
3231
3345
|
var BRIEF_BUILTINS = [
|
|
3232
3346
|
"tier",
|
|
3233
3347
|
"testPlan",
|
|
@@ -3276,7 +3390,8 @@ var ManagedManifestSchema = z2.object({
|
|
|
3276
3390
|
version: z2.number().int().positive(),
|
|
3277
3391
|
files: z2.array(SafeRepoRelPath),
|
|
3278
3392
|
blocks: z2.array(ManagedBlockRecordSchema),
|
|
3279
|
-
labels: z2.array(z2.string())
|
|
3393
|
+
labels: z2.array(z2.string()),
|
|
3394
|
+
agents: z2.array(z2.enum(AGENT_VENDORS)).optional()
|
|
3280
3395
|
});
|
|
3281
3396
|
var VinayaConfigSchema = z2.object({
|
|
3282
3397
|
rings: z2.object({
|
|
@@ -3284,16 +3399,79 @@ var VinayaConfigSchema = z2.object({
|
|
|
3284
3399
|
ring2_asyncAudits: z2.boolean()
|
|
3285
3400
|
}).optional(),
|
|
3286
3401
|
checks: z2.record(z2.string(), CheckEntrySchema).optional(),
|
|
3402
|
+
roles: z2.record(z2.string(), RoleEntrySchema).optional(),
|
|
3287
3403
|
briefSchema: BriefSchemaSchema.optional(),
|
|
3288
3404
|
managed: ManagedManifestSchema.optional(),
|
|
3289
3405
|
principals: z2.array(z2.string()).min(1).optional(),
|
|
3290
3406
|
releaseActor: z2.string().min(1).optional(),
|
|
3291
3407
|
ci: z2.object({ setup: z2.string().min(1) }).optional(),
|
|
3292
|
-
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()
|
|
3293
3415
|
});
|
|
3294
3416
|
var GLOBAL_VINAYA_HOME = join(homedir(), ".vinaya");
|
|
3295
3417
|
var GLOBAL_CONFIG_PATH = join(GLOBAL_VINAYA_HOME, "config.json");
|
|
3296
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
|
+
}
|
|
3297
3475
|
function resolvePrincipalAllowlist(config) {
|
|
3298
3476
|
return config?.principals ?? PRINCIPAL_ALLOWLIST;
|
|
3299
3477
|
}
|
|
@@ -3366,6 +3544,17 @@ function loadTrustAnchorConfig(fetcher = ghFetchTrustAnchorConfig) {
|
|
|
3366
3544
|
return null;
|
|
3367
3545
|
}
|
|
3368
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
|
+
}
|
|
3369
3558
|
|
|
3370
3559
|
// src/checks/bin/check-coherence.ts
|
|
3371
3560
|
var CHECK_NAME = "coherence";
|
|
@@ -3382,9 +3571,9 @@ function readRegisteredProjectNames() {
|
|
|
3382
3571
|
if (!root)
|
|
3383
3572
|
return [];
|
|
3384
3573
|
const path = join2(root, ".vinaya/projects.md");
|
|
3385
|
-
if (!
|
|
3574
|
+
if (!existsSync2(path))
|
|
3386
3575
|
return [];
|
|
3387
|
-
return parseRegistry(
|
|
3576
|
+
return parseRegistry(readFileSync2(path, "utf8")).map((p) => p.name);
|
|
3388
3577
|
}
|
|
3389
3578
|
function resolveRepo2() {
|
|
3390
3579
|
const fromEnv = process.env.AEG_REPO;
|
|
@@ -565,6 +565,12 @@ function factsFromLegacyMilestone(milestone) {
|
|
|
565
565
|
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
566
566
|
};
|
|
567
567
|
}
|
|
568
|
+
function resolveLegacyFacts(milestone, labelIssues) {
|
|
569
|
+
if (milestone.state === "closed" && labelIssues.length > 0) {
|
|
570
|
+
return { goal: milestone.description ?? "", lifecycle: lifecycleFromIssues(labelIssues) };
|
|
571
|
+
}
|
|
572
|
+
return factsFromLegacyMilestone(milestone);
|
|
573
|
+
}
|
|
568
574
|
function lifecycleFromIssues(issues) {
|
|
569
575
|
if (issues.length === 0)
|
|
570
576
|
return "planned";
|
|
@@ -581,9 +587,9 @@ function goalFromMilestones(milestones, slug) {
|
|
|
581
587
|
function findMilestoneForSlug(owner, repo, slug) {
|
|
582
588
|
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
583
589
|
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
584
|
-
if (legacy)
|
|
585
|
-
return factsFromLegacyMilestone(legacy);
|
|
586
590
|
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
591
|
+
if (legacy)
|
|
592
|
+
return resolveLegacyFacts(legacy, issues);
|
|
587
593
|
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
588
594
|
}
|
|
589
595
|
|
|
@@ -2770,16 +2776,18 @@ function checkDeadBranchPush(input) {
|
|
|
2770
2776
|
}
|
|
2771
2777
|
// ../../packages/aeg-core/src/reader-resolvable-prose.ts
|
|
2772
2778
|
var SHIPS_PREFIX = "aeg-root/";
|
|
2773
|
-
|
|
2779
|
+
function shipsArchivePrefix(shipsPrefix) {
|
|
2780
|
+
return `${shipsPrefix}tranches/completed/`;
|
|
2781
|
+
}
|
|
2774
2782
|
function isSpecFile2(path) {
|
|
2775
2783
|
return path.startsWith("apps/") && path.includes("/specs/") && path.endsWith(".md");
|
|
2776
2784
|
}
|
|
2777
2785
|
function isClaudeMdFile(path) {
|
|
2778
2786
|
return path === "CLAUDE.md" || path.endsWith("/CLAUDE.md");
|
|
2779
2787
|
}
|
|
2780
|
-
function classifyProseFile(path, readerFacingPrefix, readerFacingSuffix) {
|
|
2781
|
-
if (path.startsWith(
|
|
2782
|
-
return path.startsWith(
|
|
2788
|
+
function classifyProseFile(path, readerFacingPrefix, readerFacingSuffix, shipsPrefix = SHIPS_PREFIX) {
|
|
2789
|
+
if (path.startsWith(shipsPrefix)) {
|
|
2790
|
+
return path.startsWith(shipsArchivePrefix(shipsPrefix)) ? "internal" : "ships";
|
|
2783
2791
|
}
|
|
2784
2792
|
if (path.startsWith(readerFacingPrefix) && path.endsWith(readerFacingSuffix)) {
|
|
2785
2793
|
return "reader-facing";
|
|
@@ -2814,7 +2822,7 @@ function legacySlugPattern(legacySlugs) {
|
|
|
2814
2822
|
const alternation = legacySlugs.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
2815
2823
|
return new RegExp(`(^|[^a-zA-Z0-9\\n-])(${alternation})([^a-zA-Z0-9\\n-]|$)`, "g");
|
|
2816
2824
|
}
|
|
2817
|
-
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2825
|
+
function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2818
2826
|
const findings = [];
|
|
2819
2827
|
const legacyPattern = legacySlugPattern(legacySlugs);
|
|
2820
2828
|
const patterns = [
|
|
@@ -2823,7 +2831,7 @@ function checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuff
|
|
|
2823
2831
|
...legacyPattern ? [{ pattern: legacyPattern, what: "an internal tranche slug", group: 2 }] : []
|
|
2824
2832
|
];
|
|
2825
2833
|
for (const file of files) {
|
|
2826
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2834
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2827
2835
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2828
2836
|
continue;
|
|
2829
2837
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2869,10 +2877,10 @@ function definesOrLinksGlossary(content, term) {
|
|
|
2869
2877
|
return true;
|
|
2870
2878
|
return /docs\/glossary|glossary\.md/i.test(content);
|
|
2871
2879
|
}
|
|
2872
|
-
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix) {
|
|
2880
|
+
function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix = SHIPS_PREFIX) {
|
|
2873
2881
|
const findings = [];
|
|
2874
2882
|
for (const file of files) {
|
|
2875
|
-
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix);
|
|
2883
|
+
const cls = classifyProseFile(file.path, readerFacingPrefix, readerFacingSuffix, shipsPrefix);
|
|
2876
2884
|
if (!cls || !SWEPT_CLASSES.has(cls))
|
|
2877
2885
|
continue;
|
|
2878
2886
|
const scrubbed = stripNonProse(file.path, file.content);
|
|
@@ -2891,10 +2899,10 @@ function checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, read
|
|
|
2891
2899
|
}
|
|
2892
2900
|
return findings;
|
|
2893
2901
|
}
|
|
2894
|
-
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = []) {
|
|
2902
|
+
function checkReaderResolvableProse(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, legacySlugs = [], shipsPrefix = SHIPS_PREFIX) {
|
|
2895
2903
|
return [
|
|
2896
|
-
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs),
|
|
2897
|
-
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix)
|
|
2904
|
+
...checkUnresolvableReferences(files, readerFacingPrefix, readerFacingSuffix, legacySlugs, shipsPrefix),
|
|
2905
|
+
...checkUndefinedVocabulary(files, glossaryTerms, readerFacingPrefix, readerFacingSuffix, shipsPrefix)
|
|
2898
2906
|
];
|
|
2899
2907
|
}
|
|
2900
2908
|
function parseGlossaryTerms(glossaryContent) {
|
|
@@ -2908,6 +2916,101 @@ function parseGlossaryTerms(glossaryContent) {
|
|
|
2908
2916
|
}
|
|
2909
2917
|
return terms;
|
|
2910
2918
|
}
|
|
2919
|
+
// ../../packages/aeg-core/src/retired-vocabulary.ts
|
|
2920
|
+
var RETIRED_PATTERNS = [
|
|
2921
|
+
String.raw`\bD-[0-9]{3}\b`,
|
|
2922
|
+
"D-(###|NNN|nnn|xxx)",
|
|
2923
|
+
"decision (entry|logged)",
|
|
2924
|
+
"decision-log entry",
|
|
2925
|
+
"decision log entry",
|
|
2926
|
+
"decision log(s|ged|ging)?([^a-z]|$)",
|
|
2927
|
+
"decision-log",
|
|
2928
|
+
"decision entr",
|
|
2929
|
+
"decisions? (are |is )?logged",
|
|
2930
|
+
"log entries",
|
|
2931
|
+
String.raw`decisions\.md`,
|
|
2932
|
+
"decisions-legacy",
|
|
2933
|
+
"CONTRADICTION",
|
|
2934
|
+
"assumes Tier 3",
|
|
2935
|
+
"Lock: ?YES",
|
|
2936
|
+
"Lock: ?NO",
|
|
2937
|
+
"lock approvals?",
|
|
2938
|
+
"approves locks",
|
|
2939
|
+
"Conforms to lock",
|
|
2940
|
+
"Challenges lock",
|
|
2941
|
+
"checkDecisionNumbersFresh",
|
|
2942
|
+
String.raw`roles/team-leader\.md`,
|
|
2943
|
+
String.raw`\(,`,
|
|
2944
|
+
String.raw`,\)`,
|
|
2945
|
+
String.raw`\(\.\)`
|
|
2946
|
+
];
|
|
2947
|
+
var RETIRED_EXEMPT_SUBSTRINGS = [
|
|
2948
|
+
"docs/decisions-legacy.md",
|
|
2949
|
+
"apps/herald-ai/docs/",
|
|
2950
|
+
"apps/vada-ai/docs/",
|
|
2951
|
+
"aeg-root/tranches/completed/",
|
|
2952
|
+
"packages/aeg-core/src/docs/published-prose",
|
|
2953
|
+
"packages/aeg-core/src/retired-vocabulary.test.ts",
|
|
2954
|
+
"packages/aeg-core/src/retired-vocabulary.ts",
|
|
2955
|
+
"/fixtures/",
|
|
2956
|
+
"/node_modules/",
|
|
2957
|
+
"/.next/",
|
|
2958
|
+
"/.turbo/"
|
|
2959
|
+
];
|
|
2960
|
+
var PATTERN_EXEMPT = {
|
|
2961
|
+
[String.raw`\bD-[0-9]{3}\b`]: ["./CLAUDE.md"],
|
|
2962
|
+
[String.raw`decisions\.md`]: [
|
|
2963
|
+
"docs-index.md",
|
|
2964
|
+
"apps/vada-ai/specs/legacy/README.md",
|
|
2965
|
+
"apps/vada-ai/specs/vada-product-spec.md",
|
|
2966
|
+
"apps/vada-ai/web/CLAUDE.md",
|
|
2967
|
+
"apps/vada-ai/CLAUDE.md"
|
|
2968
|
+
],
|
|
2969
|
+
"decisions-legacy": [
|
|
2970
|
+
"packages/aeg-core/src/file-classify.ts",
|
|
2971
|
+
"packages/aeg-core/src/file-classify.test.ts",
|
|
2972
|
+
"packages/aeg-core/src/pr-tier.test.ts",
|
|
2973
|
+
"docs-index.md",
|
|
2974
|
+
".claude/skills/database/SKILL.md",
|
|
2975
|
+
".claude/skills/vada-architecture/SKILL.md",
|
|
2976
|
+
"apps/vada-ai/specs/vada-byok-principles.md",
|
|
2977
|
+
"apps/vada-ai/web/CLAUDE.md",
|
|
2978
|
+
"apps/vada-ai/CLAUDE.md"
|
|
2979
|
+
],
|
|
2980
|
+
CONTRADICTION: ["apps/vada-ai/specs/vada-reviewers-spec.md"]
|
|
2981
|
+
};
|
|
2982
|
+
function lineNumbers(content, pattern) {
|
|
2983
|
+
const out = [];
|
|
2984
|
+
const lines = content.split(`
|
|
2985
|
+
`);
|
|
2986
|
+
for (let i = 0;i < lines.length; i++) {
|
|
2987
|
+
if (pattern.test(lines[i] ?? ""))
|
|
2988
|
+
out.push(i + 1);
|
|
2989
|
+
}
|
|
2990
|
+
return out;
|
|
2991
|
+
}
|
|
2992
|
+
function scanRetiredVocabulary(files) {
|
|
2993
|
+
const findings = [];
|
|
2994
|
+
for (const file of files) {
|
|
2995
|
+
if (RETIRED_EXEMPT_SUBSTRINGS.some((e) => file.path.includes(e)))
|
|
2996
|
+
continue;
|
|
2997
|
+
for (const pattern of RETIRED_PATTERNS) {
|
|
2998
|
+
const patternExempt = PATTERN_EXEMPT[pattern] ?? [];
|
|
2999
|
+
if (patternExempt.some((e) => file.path.includes(e)))
|
|
3000
|
+
continue;
|
|
3001
|
+
const re = new RegExp(pattern);
|
|
3002
|
+
for (const line of lineNumbers(file.content, re)) {
|
|
3003
|
+
findings.push({
|
|
3004
|
+
file: file.path,
|
|
3005
|
+
line,
|
|
3006
|
+
pattern,
|
|
3007
|
+
message: `claims a retired AEG mechanism is still live (matches /${pattern}/)`
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
return findings;
|
|
3013
|
+
}
|
|
2911
3014
|
// ../../packages/aeg-core/src/dispatch-gate.ts
|
|
2912
3015
|
function isHandClosedByRecognizedPrincipal(dep, principalAllowlist) {
|
|
2913
3016
|
return dep.issueState === "closed" && dep.stateReason === "completed" && isPrincipal(dep.closedByActor ?? null, principalAllowlist);
|