@wairon/cli 5.1.1-dev.72 → 5.1.1-dev.74
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/dist/cli/index.js +5620 -5847
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +707 -486
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2497,7 +2497,7 @@ var require_dist = __commonJS({
|
|
|
2497
2497
|
scaffoldPack: () => scaffoldPack2
|
|
2498
2498
|
});
|
|
2499
2499
|
module2.exports = __toCommonJS2(src_exports2);
|
|
2500
|
-
var
|
|
2500
|
+
var path29 = __toESM2(require("path"));
|
|
2501
2501
|
var import_js_yaml3 = require("js-yaml");
|
|
2502
2502
|
var import_js_yaml = require("js-yaml");
|
|
2503
2503
|
var import_crypto = require("crypto");
|
|
@@ -3061,7 +3061,7 @@ var require_dist = __commonJS({
|
|
|
3061
3061
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3062
3062
|
}
|
|
3063
3063
|
var fs18 = __toESM2(require("fs"));
|
|
3064
|
-
var
|
|
3064
|
+
var path30 = __toESM2(require("path"));
|
|
3065
3065
|
var import_fflate = require_node();
|
|
3066
3066
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".hg", ".svn"]);
|
|
3067
3067
|
function listEntries(archive) {
|
|
@@ -3099,8 +3099,8 @@ var require_dist = __commonJS({
|
|
|
3099
3099
|
}
|
|
3100
3100
|
function writeTree(destDir, files) {
|
|
3101
3101
|
for (const file of files) {
|
|
3102
|
-
const absolute =
|
|
3103
|
-
fs18.mkdirSync(
|
|
3102
|
+
const absolute = path30.join(destDir, file.path);
|
|
3103
|
+
fs18.mkdirSync(path30.dirname(absolute), { recursive: true });
|
|
3104
3104
|
fs18.writeFileSync(absolute, file.contents);
|
|
3105
3105
|
}
|
|
3106
3106
|
}
|
|
@@ -3113,10 +3113,10 @@ var require_dist = __commonJS({
|
|
|
3113
3113
|
for (const entry of fs18.readdirSync(current2, { withFileTypes: true })) {
|
|
3114
3114
|
if (entry.isDirectory()) {
|
|
3115
3115
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
3116
|
-
walkPackDir(root,
|
|
3116
|
+
walkPackDir(root, path30.join(current2, entry.name), out);
|
|
3117
3117
|
} else if (entry.isFile()) {
|
|
3118
|
-
const absolute =
|
|
3119
|
-
const relative22 =
|
|
3118
|
+
const absolute = path30.join(current2, entry.name);
|
|
3119
|
+
const relative22 = path30.relative(root, absolute).split(path30.sep).join("/");
|
|
3120
3120
|
out.push({ path: relative22, contents: fs18.readFileSync(absolute) });
|
|
3121
3121
|
}
|
|
3122
3122
|
}
|
|
@@ -3167,7 +3167,7 @@ var require_dist = __commonJS({
|
|
|
3167
3167
|
function scaffoldPack(request) {
|
|
3168
3168
|
const files = render(request);
|
|
3169
3169
|
writeTree(request.targetDir, files);
|
|
3170
|
-
return files.map((file) =>
|
|
3170
|
+
return files.map((file) => path29.join(request.targetDir, file.path));
|
|
3171
3171
|
}
|
|
3172
3172
|
function buildPack(sourceDir) {
|
|
3173
3173
|
const files = readPackDir(sourceDir);
|
|
@@ -3224,7 +3224,7 @@ var require_dist = __commonJS({
|
|
|
3224
3224
|
}
|
|
3225
3225
|
const manifest = parseManifest(decode(envelope.contents));
|
|
3226
3226
|
verifyIntegrity2(manifest, files);
|
|
3227
|
-
const directory =
|
|
3227
|
+
const directory = path29.resolve(destDir);
|
|
3228
3228
|
writeTree(directory, files);
|
|
3229
3229
|
const result = {
|
|
3230
3230
|
directory,
|
|
@@ -3302,7 +3302,7 @@ var require_dist = __commonJS({
|
|
|
3302
3302
|
}
|
|
3303
3303
|
const manifest = parseTreeManifest(decode(envelope.contents));
|
|
3304
3304
|
verifyTreeIntegrity(manifest, files);
|
|
3305
|
-
const directory =
|
|
3305
|
+
const directory = path29.resolve(destDir);
|
|
3306
3306
|
writeTree(directory, files);
|
|
3307
3307
|
const result = {
|
|
3308
3308
|
destDir: directory,
|
|
@@ -3317,7 +3317,7 @@ var require_dist = __commonJS({
|
|
|
3317
3317
|
return normalized === "." ? ".wai/" : `${normalized}/.wai/`;
|
|
3318
3318
|
}
|
|
3319
3319
|
function normalizeRootPath(relativePath) {
|
|
3320
|
-
const posix2 = relativePath.split(
|
|
3320
|
+
const posix2 = relativePath.split(path29.sep).join("/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
3321
3321
|
return posix2 === "" || posix2 === "." ? "." : posix2;
|
|
3322
3322
|
}
|
|
3323
3323
|
function slugify(projectName) {
|
|
@@ -3511,13 +3511,17 @@ __export(src_exports, {
|
|
|
3511
3511
|
ambiguityMessage: () => ambiguityMessage,
|
|
3512
3512
|
approvalRecord: () => approvalRecord,
|
|
3513
3513
|
approvalVerdict: () => approvalVerdict,
|
|
3514
|
+
assertContainedProjectPath: () => assertContainedProjectPath,
|
|
3514
3515
|
assertProjectInitialized: () => assertProjectInitialized,
|
|
3515
3516
|
backendCommand: () => backendCommand,
|
|
3517
|
+
backfillChainedSubprojectConfigs: () => backfillChainedSubprojectConfigs,
|
|
3516
3518
|
buildCanvasDataModel: () => buildCanvasDataModel,
|
|
3517
3519
|
buildProjectGraph: () => buildProjectGraph,
|
|
3518
3520
|
buildRuleContext: () => buildRuleContext,
|
|
3519
3521
|
callSitesOf: () => callSitesOf,
|
|
3520
3522
|
captureApprovedSpecs: () => captureApprovedSpecs,
|
|
3523
|
+
checkDeclarativePack: () => checkDeclarativePack,
|
|
3524
|
+
clearLoaderIssues: () => clearLoaderIssues,
|
|
3521
3525
|
cognitiveScore: () => cognitiveScore,
|
|
3522
3526
|
complexityLevel: () => complexityLevel,
|
|
3523
3527
|
composeAgentBrief: () => composeAgentBrief,
|
|
@@ -3532,6 +3536,7 @@ __export(src_exports, {
|
|
|
3532
3536
|
createEmptyTopologyConfig: () => createEmptyTopologyConfig,
|
|
3533
3537
|
createProjectConfig: () => createProjectConfig,
|
|
3534
3538
|
currentChildPins: () => currentChildPins,
|
|
3539
|
+
currentRootBinding: () => currentRootBinding,
|
|
3535
3540
|
declaredPackNames: () => declaredPackNames,
|
|
3536
3541
|
declaredProfileIds: () => declaredProfileIds,
|
|
3537
3542
|
declaresGlobalPacks: () => declaresGlobalPacks,
|
|
@@ -3544,6 +3549,7 @@ __export(src_exports, {
|
|
|
3544
3549
|
deriveExecutionProfile: () => deriveExecutionProfile,
|
|
3545
3550
|
derivedDocPaths: () => derivedDocPaths,
|
|
3546
3551
|
detectDomainCandidates: () => detectDomainCandidates,
|
|
3552
|
+
diagnoseProjectPacks: () => diagnoseProjectPacks,
|
|
3547
3553
|
diagramSetIndex: () => diagramSetIndex,
|
|
3548
3554
|
diffAgainstApproval: () => diffAgainstApproval,
|
|
3549
3555
|
diffSize: () => diffSize,
|
|
@@ -3559,6 +3565,9 @@ __export(src_exports, {
|
|
|
3559
3565
|
factsFor: () => factsFor,
|
|
3560
3566
|
fieldTypeRefs: () => fieldTypeRefs,
|
|
3561
3567
|
fieldTypesOf: () => fieldTypesOf,
|
|
3568
|
+
findChainingParent: () => findChainingParent,
|
|
3569
|
+
findChainingSubprojectsMissingConfig: () => findChainingSubprojectsMissingConfig,
|
|
3570
|
+
findLegacySpecFiles: () => findLegacySpecFiles,
|
|
3562
3571
|
findProjectRoot: () => findProjectRoot,
|
|
3563
3572
|
findSystemRoot: () => findSystemRoot,
|
|
3564
3573
|
fromProjectRoot: () => fromProjectRoot,
|
|
@@ -3568,6 +3577,7 @@ __export(src_exports, {
|
|
|
3568
3577
|
generateDiagramSet: () => generateDiagramSet,
|
|
3569
3578
|
generateSequenceDiagram: () => generateSequenceDiagram,
|
|
3570
3579
|
getExporter: () => getExporter,
|
|
3580
|
+
getLoaderIssues: () => getLoaderIssues,
|
|
3571
3581
|
getProjectRoot: () => getProjectRoot,
|
|
3572
3582
|
getProjectRootOverride: () => getProjectRootOverride,
|
|
3573
3583
|
getRequestParentReach: () => getRequestParentReach,
|
|
@@ -3575,6 +3585,7 @@ __export(src_exports, {
|
|
|
3575
3585
|
getStatusReport: () => getStatusReport,
|
|
3576
3586
|
globalGuideFilePath: () => globalGuideFilePath,
|
|
3577
3587
|
globalPacksDir: () => globalPacksDir,
|
|
3588
|
+
globalPacksEnabled: () => globalPacksEnabled,
|
|
3578
3589
|
globalTemplatesDir: () => globalTemplatesDir,
|
|
3579
3590
|
hasContext: () => hasContext,
|
|
3580
3591
|
hasFunctionBody: () => hasFunctionBody,
|
|
@@ -3605,8 +3616,9 @@ __export(src_exports, {
|
|
|
3605
3616
|
loadImplementationSpecs: () => loadImplementationSpecs,
|
|
3606
3617
|
loadInterfaceSpec: () => loadInterfaceSpec,
|
|
3607
3618
|
loadInterfaceSpecs: () => loadInterfaceSpecs,
|
|
3608
|
-
loadProjectConfig: () =>
|
|
3619
|
+
loadProjectConfig: () => loadProjectConfig2,
|
|
3609
3620
|
loadProjectExtensions: () => loadProjectExtensions,
|
|
3621
|
+
loadProjectVariants: () => loadProjectVariants,
|
|
3610
3622
|
loadRegistry: () => loadRegistry,
|
|
3611
3623
|
loadSpec: () => loadSpec,
|
|
3612
3624
|
loadSpecGraph: () => loadSpecGraph,
|
|
@@ -3630,12 +3642,16 @@ __export(src_exports, {
|
|
|
3630
3642
|
moveSubsystemProject: () => moveSubsystemProject,
|
|
3631
3643
|
movedChildren: () => movedChildren,
|
|
3632
3644
|
narrativeStepForeignFields: () => narrativeStepForeignFields,
|
|
3645
|
+
packDirEntry: () => packDirEntry,
|
|
3646
|
+
packEntryLabel: () => packEntryLabel,
|
|
3647
|
+
packEntryRef: () => packEntryRef,
|
|
3633
3648
|
packStoreDir: () => packStoreDir,
|
|
3634
3649
|
parseDeclaredCall: () => parseDeclaredCall,
|
|
3635
3650
|
parseYaml: () => parseYaml,
|
|
3636
3651
|
passesIntentFloor: () => passesIntentFloor,
|
|
3637
3652
|
pathExists: () => pathExists,
|
|
3638
3653
|
pathKey: () => pathKey,
|
|
3654
|
+
pinInstalledPacksAsSelections: () => pinInstalledPacksAsSelections,
|
|
3639
3655
|
projectConfigExists: () => projectConfigExists,
|
|
3640
3656
|
provisionProject: () => provisionProject,
|
|
3641
3657
|
qualifiedTypeId: () => qualifiedTypeId,
|
|
@@ -3663,12 +3679,14 @@ __export(src_exports, {
|
|
|
3663
3679
|
resolveImport: () => resolveImport,
|
|
3664
3680
|
resolveInstalledPack: () => resolveInstalledPack,
|
|
3665
3681
|
resolveSubprojectForNamespace: () => resolveSubprojectForNamespace,
|
|
3682
|
+
resolveVariantGuidance: () => resolveVariantGuidance,
|
|
3666
3683
|
retireSpecialists: () => retireSpecialists,
|
|
3667
3684
|
runWithProjectBinding: () => runWithProjectBinding,
|
|
3668
3685
|
runWithProjectRoot: () => runWithProjectRoot,
|
|
3669
3686
|
sameContract: () => sameContract,
|
|
3670
3687
|
saveSpec: () => saveSpec,
|
|
3671
3688
|
saveTopologyConfig: () => saveTopologyConfig,
|
|
3689
|
+
scanAllSpecs: () => scanAllSpecs,
|
|
3672
3690
|
serializeYaml: () => serializeYaml,
|
|
3673
3691
|
setExecutionTier: () => setExecutionTier,
|
|
3674
3692
|
setLogLevel: () => setLogLevel,
|
|
@@ -3701,7 +3719,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
3701
3719
|
|
|
3702
3720
|
// src/config/project-config.ts
|
|
3703
3721
|
var fs2 = __toESM(require("fs"));
|
|
3704
|
-
var
|
|
3722
|
+
var path3 = __toESM(require("path"));
|
|
3705
3723
|
var import_zod4 = require("zod");
|
|
3706
3724
|
|
|
3707
3725
|
// src/utils/fs.ts
|
|
@@ -3754,6 +3772,9 @@ function listFilesRecursive(dirPath, ext) {
|
|
|
3754
3772
|
}
|
|
3755
3773
|
var projectRootOverride = null;
|
|
3756
3774
|
var requestRootStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
3775
|
+
function currentRootBinding() {
|
|
3776
|
+
return requestRootStore.getStore();
|
|
3777
|
+
}
|
|
3757
3778
|
function runWithProjectRoot(dir, fn) {
|
|
3758
3779
|
return requestRootStore.run({ ...requestRootStore.getStore(), root: path.resolve(dir) }, fn);
|
|
3759
3780
|
}
|
|
@@ -3898,6 +3919,7 @@ var BundleNotFoundError = class extends WaironError {
|
|
|
3898
3919
|
};
|
|
3899
3920
|
|
|
3900
3921
|
// src/models/project.ts
|
|
3922
|
+
var path2 = __toESM(require("path"));
|
|
3901
3923
|
var import_zod3 = require("zod");
|
|
3902
3924
|
|
|
3903
3925
|
// src/models/agent.ts
|
|
@@ -4485,16 +4507,28 @@ function activeTargetTypes(config) {
|
|
|
4485
4507
|
const targets = config.targets;
|
|
4486
4508
|
return targets.filter((t) => typeof t === "string" || t.enabled !== false).map((t) => typeof t === "string" ? t : t.type);
|
|
4487
4509
|
}
|
|
4510
|
+
var PACK_EXT_RE = /\.(ya?ml|cjs|js)$/i;
|
|
4511
|
+
function declaredPackNames(config) {
|
|
4512
|
+
const selection = config.profileSelection;
|
|
4513
|
+
return [.../* @__PURE__ */ new Set([
|
|
4514
|
+
...(config.extensions?.packs ?? []).map((entry) => typeof entry === "string" ? path2.basename(entry).replace(PACK_EXT_RE, "") : entry.name),
|
|
4515
|
+
...selection?.requiredPackNames ?? [],
|
|
4516
|
+
...selection?.defaultPackNames ?? []
|
|
4517
|
+
])];
|
|
4518
|
+
}
|
|
4519
|
+
function declaredProfileIds(config) {
|
|
4520
|
+
return [...new Set(config.profileSelection?.profileIds ?? [])];
|
|
4521
|
+
}
|
|
4488
4522
|
|
|
4489
4523
|
// src/config/project-config.ts
|
|
4490
4524
|
function waiDirAt(root) {
|
|
4491
|
-
const wai =
|
|
4492
|
-
const legacy =
|
|
4525
|
+
const wai = path3.join(root, ".wai");
|
|
4526
|
+
const legacy = path3.join(root, ".wairon");
|
|
4493
4527
|
return !fs2.existsSync(wai) && fs2.existsSync(legacy) ? legacy : wai;
|
|
4494
4528
|
}
|
|
4495
4529
|
function projectConfigFsAdapterAt(rootDir) {
|
|
4496
|
-
const root =
|
|
4497
|
-
const file = () =>
|
|
4530
|
+
const root = path3.resolve(rootDir);
|
|
4531
|
+
const file = () => path3.join(waiDirAt(root), "project.yaml");
|
|
4498
4532
|
return {
|
|
4499
4533
|
readDocument() {
|
|
4500
4534
|
return readYamlFile(file());
|
|
@@ -4703,15 +4737,15 @@ function indexOver(store, root) {
|
|
|
4703
4737
|
specsDir() {
|
|
4704
4738
|
try {
|
|
4705
4739
|
const declared = store.readField("paths.specsDir");
|
|
4706
|
-
if (declared) return
|
|
4740
|
+
if (declared) return path3.resolve(root, declared);
|
|
4707
4741
|
} catch {
|
|
4708
4742
|
}
|
|
4709
|
-
return
|
|
4743
|
+
return path3.join(waiDirAt(root), "specs");
|
|
4710
4744
|
}
|
|
4711
4745
|
};
|
|
4712
4746
|
}
|
|
4713
4747
|
function projectConfigRepositoryOver(adapter, rootDir) {
|
|
4714
|
-
const root =
|
|
4748
|
+
const root = path3.resolve(rootDir);
|
|
4715
4749
|
const store = storeOver(adapter, root);
|
|
4716
4750
|
const index = indexOver(store, root);
|
|
4717
4751
|
const registry = registryOver(store, root);
|
|
@@ -4808,36 +4842,24 @@ var projectConfigRepository = {
|
|
|
4808
4842
|
bound().pinGlobalPacksAsSelections(selections);
|
|
4809
4843
|
}
|
|
4810
4844
|
};
|
|
4811
|
-
var PACK_EXT_RE = /\.(ya?ml|cjs|js)$/i;
|
|
4812
|
-
function declaredPackNames(config) {
|
|
4813
|
-
const selection = config.profileSelection;
|
|
4814
|
-
return [.../* @__PURE__ */ new Set([
|
|
4815
|
-
...(config.extensions?.packs ?? []).map((entry) => typeof entry === "string" ? path2.basename(entry).replace(PACK_EXT_RE, "") : entry.name),
|
|
4816
|
-
...selection?.requiredPackNames ?? [],
|
|
4817
|
-
...selection?.defaultPackNames ?? []
|
|
4818
|
-
])];
|
|
4819
|
-
}
|
|
4820
|
-
function declaredProfileIds(config) {
|
|
4821
|
-
return [...new Set(config.profileSelection?.profileIds ?? [])];
|
|
4822
|
-
}
|
|
4823
4845
|
|
|
4824
4846
|
// src/core/domain_projector.ts
|
|
4825
4847
|
var path16 = __toESM(require("path"));
|
|
4826
4848
|
|
|
4827
4849
|
// src/core/specs.ts
|
|
4828
|
-
var
|
|
4850
|
+
var fs11 = __toESM(require("fs"));
|
|
4829
4851
|
var path15 = __toESM(require("path"));
|
|
4830
4852
|
|
|
4831
4853
|
// src/config/paths.ts
|
|
4832
4854
|
var fs3 = __toESM(require("fs"));
|
|
4833
|
-
var
|
|
4855
|
+
var path4 = __toESM(require("path"));
|
|
4834
4856
|
function aiPathsAt(rootDir) {
|
|
4835
|
-
const resolvedRoot =
|
|
4857
|
+
const resolvedRoot = path4.resolve(rootDir);
|
|
4836
4858
|
const aiDirAt2 = (...segments) => {
|
|
4837
|
-
const waiPath =
|
|
4838
|
-
const waironPath =
|
|
4859
|
+
const waiPath = path4.join(resolvedRoot, ".wai");
|
|
4860
|
+
const waironPath = path4.join(resolvedRoot, ".wairon");
|
|
4839
4861
|
const base = !fs3.existsSync(waiPath) && fs3.existsSync(waironPath) ? waironPath : waiPath;
|
|
4840
|
-
return
|
|
4862
|
+
return path4.join(base, ...segments);
|
|
4841
4863
|
};
|
|
4842
4864
|
const specsDir = () => projectConfigRepositoryAt(resolvedRoot).specsDir();
|
|
4843
4865
|
return {
|
|
@@ -4854,12 +4876,12 @@ function aiPathsAt(rootDir) {
|
|
|
4854
4876
|
contextDomainsMd: () => aiDirAt2("context", "domains.md"),
|
|
4855
4877
|
contextWaironGuideMd: () => aiDirAt2("context", "wairon-guide.md"),
|
|
4856
4878
|
specsDir,
|
|
4857
|
-
specsSystem: () =>
|
|
4858
|
-
specsSubsystemsDir: () =>
|
|
4859
|
-
specsComponentsDir: () =>
|
|
4860
|
-
specsInterfacesDir: () =>
|
|
4861
|
-
specsImplementationsDir: () =>
|
|
4862
|
-
specsTypesDir: () =>
|
|
4879
|
+
specsSystem: () => path4.join(specsDir(), ".index.yaml"),
|
|
4880
|
+
specsSubsystemsDir: () => path4.join(specsDir(), "subsystems"),
|
|
4881
|
+
specsComponentsDir: () => path4.join(specsDir(), "components"),
|
|
4882
|
+
specsInterfacesDir: () => path4.join(specsDir(), "interfaces"),
|
|
4883
|
+
specsImplementationsDir: () => path4.join(specsDir(), "implementations"),
|
|
4884
|
+
specsTypesDir: () => path4.join(specsDir(), "types")
|
|
4863
4885
|
};
|
|
4864
4886
|
}
|
|
4865
4887
|
var AI_PATHS = {
|
|
@@ -4940,7 +4962,7 @@ function stateIdEquals(a, b) {
|
|
|
4940
4962
|
|
|
4941
4963
|
// src/core/lockfile.ts
|
|
4942
4964
|
var fs4 = __toESM(require("fs"));
|
|
4943
|
-
var
|
|
4965
|
+
var path5 = __toESM(require("path"));
|
|
4944
4966
|
function lockPath() {
|
|
4945
4967
|
return aiDir("lock.json");
|
|
4946
4968
|
}
|
|
@@ -4972,7 +4994,7 @@ function normalizeRecord(raw) {
|
|
|
4972
4994
|
}
|
|
4973
4995
|
function writeLockRecord(record) {
|
|
4974
4996
|
const p = lockPath();
|
|
4975
|
-
fs4.mkdirSync(
|
|
4997
|
+
fs4.mkdirSync(path5.dirname(p), { recursive: true });
|
|
4976
4998
|
const tmp = `${p}.tmp`;
|
|
4977
4999
|
fs4.writeFileSync(tmp, JSON.stringify(withSortedMaps(record), null, 2) + "\n");
|
|
4978
5000
|
fs4.renameSync(tmp, p);
|
|
@@ -4995,7 +5017,7 @@ function withSortedMaps(record) {
|
|
|
4995
5017
|
|
|
4996
5018
|
// src/core/spec-files.ts
|
|
4997
5019
|
var fs5 = __toESM(require("fs"));
|
|
4998
|
-
var
|
|
5020
|
+
var path6 = __toESM(require("path"));
|
|
4999
5021
|
var SPEC_FILE_EXTENSION = ".yaml";
|
|
5000
5022
|
function readSpecFile(filePath) {
|
|
5001
5023
|
return readYamlFile(filePath);
|
|
@@ -5009,7 +5031,7 @@ function listSpecFiles(specsDir) {
|
|
|
5009
5031
|
function removeSpecFile(filePath, specsRoot) {
|
|
5010
5032
|
if (!fs5.existsSync(filePath)) return false;
|
|
5011
5033
|
fs5.unlinkSync(filePath);
|
|
5012
|
-
pruneEmptyDirs(
|
|
5034
|
+
pruneEmptyDirs(path6.dirname(filePath), path6.resolve(specsRoot));
|
|
5013
5035
|
return true;
|
|
5014
5036
|
}
|
|
5015
5037
|
function pruneEmptyDirs(dir, specsRoot) {
|
|
@@ -5017,7 +5039,7 @@ function pruneEmptyDirs(dir, specsRoot) {
|
|
|
5017
5039
|
while (at !== specsRoot && at.startsWith(specsRoot)) {
|
|
5018
5040
|
if (!fs5.existsSync(at) || fs5.readdirSync(at).length > 0) return;
|
|
5019
5041
|
fs5.rmdirSync(at);
|
|
5020
|
-
at =
|
|
5042
|
+
at = path6.dirname(at);
|
|
5021
5043
|
}
|
|
5022
5044
|
}
|
|
5023
5045
|
|
|
@@ -6575,7 +6597,7 @@ function jumpFieldsOf(s) {
|
|
|
6575
6597
|
}
|
|
6576
6598
|
|
|
6577
6599
|
// src/models/code-model.ts
|
|
6578
|
-
var
|
|
6600
|
+
var path7 = __toESM(require("path"));
|
|
6579
6601
|
function pathKey(sourcePath) {
|
|
6580
6602
|
return sourcePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
6581
6603
|
}
|
|
@@ -6610,7 +6632,7 @@ function hasFunctionBody(facts, symbol) {
|
|
|
6610
6632
|
}
|
|
6611
6633
|
function resolveImport(fromFile, specifier, knownPaths) {
|
|
6612
6634
|
if (!specifier.startsWith(".")) return void 0;
|
|
6613
|
-
const joined = pathKey(
|
|
6635
|
+
const joined = pathKey(path7.posix.normalize(path7.posix.join(path7.posix.dirname(fromFile), specifier)));
|
|
6614
6636
|
const candidates = [
|
|
6615
6637
|
joined,
|
|
6616
6638
|
joined.replace(/\.js$/, ".ts"),
|
|
@@ -6706,7 +6728,7 @@ function resolveNarrativeLabels(methodName, steps) {
|
|
|
6706
6728
|
|
|
6707
6729
|
// src/core/canvas.ts
|
|
6708
6730
|
var fs6 = __toESM(require("fs"));
|
|
6709
|
-
var
|
|
6731
|
+
var path8 = __toESM(require("path"));
|
|
6710
6732
|
|
|
6711
6733
|
// src/core/canvas-layout.ts
|
|
6712
6734
|
function computeLayout(model, collapsed) {
|
|
@@ -7365,9 +7387,9 @@ function embedJson(value) {
|
|
|
7365
7387
|
}
|
|
7366
7388
|
function loadCytoscapeLib() {
|
|
7367
7389
|
const candidates = [
|
|
7368
|
-
|
|
7390
|
+
path8.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
|
|
7369
7391
|
// src/core & dist/cli
|
|
7370
|
-
|
|
7392
|
+
path8.resolve(__dirname, "templates", "canvas", "cytoscape.min.js")
|
|
7371
7393
|
// dist (library entry)
|
|
7372
7394
|
];
|
|
7373
7395
|
for (const p of candidates) {
|
|
@@ -11539,10 +11561,47 @@ var MODEL = __MODEL_JSON__;
|
|
|
11539
11561
|
</html>
|
|
11540
11562
|
`;
|
|
11541
11563
|
|
|
11564
|
+
// src/core/surfaces.ts
|
|
11565
|
+
var fs7 = __toESM(require("fs"));
|
|
11566
|
+
var path9 = __toESM(require("path"));
|
|
11567
|
+
|
|
11568
|
+
// src/core/openapi.ts
|
|
11569
|
+
var yaml2 = __toESM(require("js-yaml"));
|
|
11570
|
+
|
|
11571
|
+
// src/core/surfaces.ts
|
|
11572
|
+
var SURFACES_DIRNAME = "surfaces";
|
|
11573
|
+
function surfacesDir(rootDir) {
|
|
11574
|
+
return path9.join(rootDir, ".wai", SURFACES_DIRNAME);
|
|
11575
|
+
}
|
|
11576
|
+
function listSnapshots(rootDir = getProjectRoot()) {
|
|
11577
|
+
const dir = surfacesDir(rootDir);
|
|
11578
|
+
if (!fs7.existsSync(dir)) return [];
|
|
11579
|
+
const out = [];
|
|
11580
|
+
for (const file of fs7.readdirSync(dir)) {
|
|
11581
|
+
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
11582
|
+
try {
|
|
11583
|
+
out.push(SurfaceSnapshotSchema.parse(readYamlFile(path9.join(dir, file))));
|
|
11584
|
+
} catch {
|
|
11585
|
+
}
|
|
11586
|
+
}
|
|
11587
|
+
return out;
|
|
11588
|
+
}
|
|
11589
|
+
function listMountSnapshots(mounts) {
|
|
11590
|
+
const bound2 = path9.resolve(getProjectRoot());
|
|
11591
|
+
const out = [];
|
|
11592
|
+
for (const namespace of mounts) {
|
|
11593
|
+
const dir = resolveSubprojectForNamespace(namespace);
|
|
11594
|
+
if (!dir || path9.resolve(dir) === bound2) continue;
|
|
11595
|
+
const snapshots = listSnapshots(dir);
|
|
11596
|
+
if (snapshots.length > 0) out.push({ namespace, snapshots });
|
|
11597
|
+
}
|
|
11598
|
+
return out;
|
|
11599
|
+
}
|
|
11600
|
+
|
|
11542
11601
|
// src/core/extensions.ts
|
|
11543
|
-
var
|
|
11602
|
+
var fs9 = __toESM(require("fs"));
|
|
11544
11603
|
var os2 = __toESM(require("os"));
|
|
11545
|
-
var
|
|
11604
|
+
var path12 = __toESM(require("path"));
|
|
11546
11605
|
var import_module = require("module");
|
|
11547
11606
|
var import_zod9 = require("zod");
|
|
11548
11607
|
|
|
@@ -11570,12 +11629,12 @@ function isNewerVersion(current2, candidate) {
|
|
|
11570
11629
|
|
|
11571
11630
|
// src/core/packstore.ts
|
|
11572
11631
|
var crypto2 = __toESM(require("crypto"));
|
|
11573
|
-
var
|
|
11574
|
-
var
|
|
11632
|
+
var fs8 = __toESM(require("fs"));
|
|
11633
|
+
var path11 = __toESM(require("path"));
|
|
11575
11634
|
|
|
11576
11635
|
// src/config/defaults.ts
|
|
11577
11636
|
var os = __toESM(require("os"));
|
|
11578
|
-
var
|
|
11637
|
+
var path10 = __toESM(require("path"));
|
|
11579
11638
|
var DEFAULT_TARGET_DIRS = {
|
|
11580
11639
|
claude: ".claude/agents",
|
|
11581
11640
|
gemini: ".gemini/agents",
|
|
@@ -11591,7 +11650,7 @@ function defaultTargetConfig(type) {
|
|
|
11591
11650
|
enabled: true
|
|
11592
11651
|
};
|
|
11593
11652
|
}
|
|
11594
|
-
var WAIRON_VERSION = "5.1.1-dev.
|
|
11653
|
+
var WAIRON_VERSION = "5.1.1-dev.74";
|
|
11595
11654
|
var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
11596
11655
|
var ARCHITECT_AGENT_ID = "agent-architect";
|
|
11597
11656
|
var ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -11602,7 +11661,7 @@ function globalTemplatesDir(projectOverride) {
|
|
|
11602
11661
|
if (projectOverride) {
|
|
11603
11662
|
return projectOverride;
|
|
11604
11663
|
}
|
|
11605
|
-
return
|
|
11664
|
+
return path10.join(os.homedir(), ".wairon", "templates");
|
|
11606
11665
|
}
|
|
11607
11666
|
var BACKEND_COMMANDS = {
|
|
11608
11667
|
claude: "claude",
|
|
@@ -11638,7 +11697,7 @@ function packStoreDir() {
|
|
|
11638
11697
|
function packFiles(dir, prefix = "") {
|
|
11639
11698
|
let entries;
|
|
11640
11699
|
try {
|
|
11641
|
-
entries =
|
|
11700
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
11642
11701
|
} catch {
|
|
11643
11702
|
return [];
|
|
11644
11703
|
}
|
|
@@ -11646,25 +11705,25 @@ function packFiles(dir, prefix = "") {
|
|
|
11646
11705
|
for (const e of entries) {
|
|
11647
11706
|
if (DIGEST_EXCLUDED.has(e.name)) continue;
|
|
11648
11707
|
const rel2 = prefix ? `${prefix}/${e.name}` : e.name;
|
|
11649
|
-
if (e.isDirectory()) out.push(...packFiles(
|
|
11708
|
+
if (e.isDirectory()) out.push(...packFiles(path11.join(dir, e.name), rel2));
|
|
11650
11709
|
else if (e.isFile()) out.push(rel2);
|
|
11651
11710
|
}
|
|
11652
11711
|
return out.sort();
|
|
11653
11712
|
}
|
|
11654
11713
|
function computePackDigest(packDir) {
|
|
11655
11714
|
const hash = crypto2.createHash("sha256");
|
|
11656
|
-
const abs =
|
|
11715
|
+
const abs = path11.resolve(packDir);
|
|
11657
11716
|
let isFile = false;
|
|
11658
11717
|
try {
|
|
11659
|
-
isFile =
|
|
11718
|
+
isFile = fs8.statSync(abs).isFile();
|
|
11660
11719
|
} catch {
|
|
11661
11720
|
}
|
|
11662
|
-
const entries = isFile ? [[
|
|
11721
|
+
const entries = isFile ? [[path11.basename(abs), abs]] : packFiles(abs).map((rel2) => [rel2, path11.join(abs, rel2)]);
|
|
11663
11722
|
for (const [rel2, full] of entries) {
|
|
11664
11723
|
hash.update(rel2);
|
|
11665
11724
|
hash.update("\0");
|
|
11666
11725
|
try {
|
|
11667
|
-
hash.update(
|
|
11726
|
+
hash.update(fs8.readFileSync(full));
|
|
11668
11727
|
} catch {
|
|
11669
11728
|
}
|
|
11670
11729
|
hash.update("\0");
|
|
@@ -11673,7 +11732,7 @@ function computePackDigest(packDir) {
|
|
|
11673
11732
|
}
|
|
11674
11733
|
function readInstallRecord(packPath) {
|
|
11675
11734
|
try {
|
|
11676
|
-
const raw = readYamlFile(
|
|
11735
|
+
const raw = readYamlFile(path11.join(packPath, INSTALL_RECORD));
|
|
11677
11736
|
return raw && typeof raw === "object" ? raw : {};
|
|
11678
11737
|
} catch {
|
|
11679
11738
|
return {};
|
|
@@ -11704,14 +11763,14 @@ function installedFrom(location, name, version) {
|
|
|
11704
11763
|
function versionedEntries(nameDir, fallbackName) {
|
|
11705
11764
|
let versions;
|
|
11706
11765
|
try {
|
|
11707
|
-
versions =
|
|
11766
|
+
versions = fs8.readdirSync(nameDir, { withFileTypes: true });
|
|
11708
11767
|
} catch {
|
|
11709
11768
|
return [];
|
|
11710
11769
|
}
|
|
11711
11770
|
const out = [];
|
|
11712
11771
|
for (const v of versions) {
|
|
11713
11772
|
if (!v.isDirectory()) continue;
|
|
11714
|
-
const versionDir =
|
|
11773
|
+
const versionDir = path11.join(nameDir, v.name);
|
|
11715
11774
|
const entryFile = packDirEntry(versionDir);
|
|
11716
11775
|
if (!entryFile) continue;
|
|
11717
11776
|
out.push(installedFrom(versionDir, declaredName(entryFile) ?? fallbackName, v.name));
|
|
@@ -11719,7 +11778,7 @@ function versionedEntries(nameDir, fallbackName) {
|
|
|
11719
11778
|
return out;
|
|
11720
11779
|
}
|
|
11721
11780
|
function storeEntryPacks(store, entry) {
|
|
11722
|
-
const full =
|
|
11781
|
+
const full = path11.join(store, entry.name);
|
|
11723
11782
|
if (entry.isFile()) {
|
|
11724
11783
|
if (!PACK_FILE_RE.test(entry.name)) return [];
|
|
11725
11784
|
const name = declaredName(full) ?? entry.name.replace(PACK_FILE_RE, "");
|
|
@@ -11734,7 +11793,7 @@ function listInstalledPacks() {
|
|
|
11734
11793
|
const store = packStoreDir();
|
|
11735
11794
|
let entries;
|
|
11736
11795
|
try {
|
|
11737
|
-
entries =
|
|
11796
|
+
entries = fs8.readdirSync(store, { withFileTypes: true });
|
|
11738
11797
|
} catch {
|
|
11739
11798
|
return [];
|
|
11740
11799
|
}
|
|
@@ -11751,17 +11810,17 @@ function resolveInstalledPack(name, version) {
|
|
|
11751
11810
|
return candidates[0];
|
|
11752
11811
|
}
|
|
11753
11812
|
function installPackFromDirectory(sourceDir, origin) {
|
|
11754
|
-
const abs =
|
|
11813
|
+
const abs = path11.resolve(sourceDir);
|
|
11755
11814
|
const entryFile = packDirEntry(abs);
|
|
11756
11815
|
if (!entryFile) {
|
|
11757
11816
|
throw new Error(`"${sourceDir}" is not a pack directory (no pack.yaml | pack.cjs | index.cjs | \u2026).`);
|
|
11758
11817
|
}
|
|
11759
|
-
const manifest = readManifest(entryFile,
|
|
11818
|
+
const manifest = readManifest(entryFile, path11.dirname(entryFile));
|
|
11760
11819
|
const version = manifest.version && manifest.version.length > 0 ? manifest.version : UNVERSIONED;
|
|
11761
|
-
const dest =
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11820
|
+
const dest = path11.join(packStoreDir(), manifest.name, version);
|
|
11821
|
+
fs8.rmSync(dest, { recursive: true, force: true });
|
|
11822
|
+
fs8.mkdirSync(path11.dirname(dest), { recursive: true });
|
|
11823
|
+
fs8.cpSync(abs, dest, { recursive: true });
|
|
11765
11824
|
const digest2 = computePackDigest(dest);
|
|
11766
11825
|
const record = {
|
|
11767
11826
|
origin,
|
|
@@ -11769,7 +11828,7 @@ function installPackFromDirectory(sourceDir, origin) {
|
|
|
11769
11828
|
waironVersion: WAIRON_VERSION,
|
|
11770
11829
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11771
11830
|
};
|
|
11772
|
-
writeYamlFile(
|
|
11831
|
+
writeYamlFile(path11.join(dest, INSTALL_RECORD), record);
|
|
11773
11832
|
return {
|
|
11774
11833
|
name: manifest.name,
|
|
11775
11834
|
version,
|
|
@@ -11784,11 +11843,11 @@ function uninstallPack(name, version) {
|
|
|
11784
11843
|
const targets = listInstalledPacks().filter((p) => p.name === name && (!version || p.version === version));
|
|
11785
11844
|
if (targets.length === 0) return false;
|
|
11786
11845
|
for (const target of targets) {
|
|
11787
|
-
|
|
11788
|
-
const parent =
|
|
11789
|
-
if (
|
|
11846
|
+
fs8.rmSync(target.path, { recursive: true, force: true });
|
|
11847
|
+
const parent = path11.dirname(target.path);
|
|
11848
|
+
if (path11.resolve(parent) === path11.resolve(packStoreDir())) continue;
|
|
11790
11849
|
try {
|
|
11791
|
-
if (
|
|
11850
|
+
if (fs8.readdirSync(parent).length === 0) fs8.rmdirSync(parent);
|
|
11792
11851
|
} catch {
|
|
11793
11852
|
}
|
|
11794
11853
|
}
|
|
@@ -11939,6 +11998,10 @@ function skillExtendErrors(skills) {
|
|
|
11939
11998
|
return skills.filter((s) => s.extends !== void 0 && !EXTENDABLE_BUILTIN_SKILLS.includes(s.extends)).map((s) => `Extension pack "${s.pack}" declares a skill extending "${s.extends}", which is not a builtin skill (extendable: ${EXTENDABLE_BUILTIN_SKILLS.join(", ")}).`);
|
|
11940
11999
|
}
|
|
11941
12000
|
var GLOBAL_PACKS_DEFAULT = false;
|
|
12001
|
+
function checkDeclarativePack(manifest) {
|
|
12002
|
+
const result = DeclarativePackSchema.safeParse(manifest);
|
|
12003
|
+
return result.success ? null : result.error.issues[0]?.message ?? "shape mismatch";
|
|
12004
|
+
}
|
|
11942
12005
|
function globalPacksEnabled(config) {
|
|
11943
12006
|
return config.extensions?.useGlobalPacks ?? GLOBAL_PACKS_DEFAULT;
|
|
11944
12007
|
}
|
|
@@ -11946,27 +12009,27 @@ function emptyExtensions() {
|
|
|
11946
12009
|
return { packNames: [], packs: [], rules: [], profiles: {}, languages: {}, skills: [], patterns: [], guarantees: [], assertions: [], instructions: [], errors: [], selectionFailures: [] };
|
|
11947
12010
|
}
|
|
11948
12011
|
function globalPacksDir() {
|
|
11949
|
-
return process.env.WAIRON_PACKS_DIR ??
|
|
12012
|
+
return process.env.WAIRON_PACKS_DIR ?? path12.join(os2.homedir(), ".wairon", "packs");
|
|
11950
12013
|
}
|
|
11951
12014
|
var PACK_DIR_ENTRIES = ["pack.yaml", "pack.yml", "pack.cjs", "pack.js", "index.cjs", "index.js"];
|
|
11952
12015
|
function packDirEntry(dir) {
|
|
11953
12016
|
for (const name of PACK_DIR_ENTRIES) {
|
|
11954
|
-
const p =
|
|
11955
|
-
if (
|
|
12017
|
+
const p = path12.join(dir, name);
|
|
12018
|
+
if (fs9.existsSync(p)) return p;
|
|
11956
12019
|
}
|
|
11957
12020
|
return null;
|
|
11958
12021
|
}
|
|
11959
12022
|
function latestVersionDir(nameDir) {
|
|
11960
12023
|
let versions;
|
|
11961
12024
|
try {
|
|
11962
|
-
versions =
|
|
12025
|
+
versions = fs9.readdirSync(nameDir, { withFileTypes: true });
|
|
11963
12026
|
} catch {
|
|
11964
12027
|
return null;
|
|
11965
12028
|
}
|
|
11966
12029
|
let best = null;
|
|
11967
12030
|
for (const v of versions) {
|
|
11968
12031
|
if (!v.isDirectory()) continue;
|
|
11969
|
-
const dir =
|
|
12032
|
+
const dir = path12.join(nameDir, v.name);
|
|
11970
12033
|
if (!packDirEntry(dir)) continue;
|
|
11971
12034
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
11972
12035
|
}
|
|
@@ -11975,13 +12038,13 @@ function latestVersionDir(nameDir) {
|
|
|
11975
12038
|
function discoverPacks(dir) {
|
|
11976
12039
|
let entries;
|
|
11977
12040
|
try {
|
|
11978
|
-
entries =
|
|
12041
|
+
entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
11979
12042
|
} catch {
|
|
11980
12043
|
return [];
|
|
11981
12044
|
}
|
|
11982
12045
|
const refs = [];
|
|
11983
12046
|
for (const e of entries.sort((a, b) => compareOrdinal(a.name, b.name))) {
|
|
11984
|
-
const full =
|
|
12047
|
+
const full = path12.join(dir, e.name);
|
|
11985
12048
|
if (e.isDirectory()) {
|
|
11986
12049
|
if (packDirEntry(full)) refs.push(full);
|
|
11987
12050
|
else {
|
|
@@ -12011,7 +12074,7 @@ function mergePack(out, pack, ref, scope, packDir) {
|
|
|
12011
12074
|
foreignBuiltins: [.../* @__PURE__ */ new Set([...existing.foreignBuiltins, ...def.foreignBuiltins])]
|
|
12012
12075
|
} : def;
|
|
12013
12076
|
}
|
|
12014
|
-
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath:
|
|
12077
|
+
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath: path12.resolve(packDir, s.source) });
|
|
12015
12078
|
for (const p of pack.patterns) out.patterns.push({ ...p, pack: pack.name });
|
|
12016
12079
|
out.guarantees = [.../* @__PURE__ */ new Set([...out.guarantees, ...pack.guarantees])];
|
|
12017
12080
|
for (const a of pack.assertions) out.assertions.push({ ...a, pack: pack.name, fullCode: assertionFullCode(pack.name, a.code) });
|
|
@@ -12019,10 +12082,10 @@ function mergePack(out, pack, ref, scope, packDir) {
|
|
|
12019
12082
|
}
|
|
12020
12083
|
var isYamlPath = (p) => /\.ya?ml$/i.test(p);
|
|
12021
12084
|
function resolvePackRef(ref, projectRoot) {
|
|
12022
|
-
const pathLike = ref.startsWith(".") ||
|
|
12085
|
+
const pathLike = ref.startsWith(".") || path12.isAbsolute(ref) || isYamlPath(ref);
|
|
12023
12086
|
if (!pathLike) return ref;
|
|
12024
|
-
const resolved =
|
|
12025
|
-
if (
|
|
12087
|
+
const resolved = path12.resolve(projectRoot, ref);
|
|
12088
|
+
if (fs9.existsSync(resolved) && fs9.statSync(resolved).isDirectory()) {
|
|
12026
12089
|
const entry = packDirEntry(resolved);
|
|
12027
12090
|
if (!entry) throw new Error(`directory pack has no entry file (${PACK_DIR_ENTRIES.join(" | ")})`);
|
|
12028
12091
|
return entry;
|
|
@@ -12035,7 +12098,7 @@ function readManifest(target, projectRoot) {
|
|
|
12035
12098
|
if (raw == null) throw new Error("file not found or empty");
|
|
12036
12099
|
return { ...DeclarativePackSchema.parse(raw), rules: [] };
|
|
12037
12100
|
}
|
|
12038
|
-
const req = (0, import_module.createRequire)(
|
|
12101
|
+
const req = (0, import_module.createRequire)(path12.join(projectRoot, "package.json"));
|
|
12039
12102
|
const modRaw = req(target);
|
|
12040
12103
|
const mod = modRaw?.default ?? modRaw;
|
|
12041
12104
|
const parsed = DeclarativePackSchema.parse({
|
|
@@ -12063,7 +12126,7 @@ function loadExtensionPacks(refs, projectRoot) {
|
|
|
12063
12126
|
try {
|
|
12064
12127
|
const target = resolvePackRef(ref, projectRoot);
|
|
12065
12128
|
const manifest = readManifest(target, projectRoot);
|
|
12066
|
-
mergePack(out, manifest, ref, scope,
|
|
12129
|
+
mergePack(out, manifest, ref, scope, path12.dirname(target));
|
|
12067
12130
|
for (const r of manifest.rules) out.rules.push(r);
|
|
12068
12131
|
} catch (e) {
|
|
12069
12132
|
out.errors.push(`Extension pack "${ref}" failed to load: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -12109,7 +12172,7 @@ function defaultPackSelections() {
|
|
|
12109
12172
|
const entry = packDirEntry(pack.path) ?? pack.path;
|
|
12110
12173
|
let manifest;
|
|
12111
12174
|
try {
|
|
12112
|
-
manifest = readManifest(entry,
|
|
12175
|
+
manifest = readManifest(entry, path12.dirname(entry));
|
|
12113
12176
|
} catch {
|
|
12114
12177
|
continue;
|
|
12115
12178
|
}
|
|
@@ -12125,6 +12188,66 @@ function defaultPackSelections() {
|
|
|
12125
12188
|
return [];
|
|
12126
12189
|
}
|
|
12127
12190
|
}
|
|
12191
|
+
function diagnoseProjectPacks() {
|
|
12192
|
+
const empty = { globalsUndeclared: false, notApplied: [], unresolved: [], globalsApplied: [] };
|
|
12193
|
+
try {
|
|
12194
|
+
const config = projectConfigRepository.load();
|
|
12195
|
+
if (!config) return empty;
|
|
12196
|
+
const globalsUndeclared = !projectConfigRepository.declaresGlobalPacks();
|
|
12197
|
+
const projectRoot = getProjectRoot();
|
|
12198
|
+
const entries = config.extensions?.packs ?? [];
|
|
12199
|
+
const unresolved = [];
|
|
12200
|
+
const selectedNames = /* @__PURE__ */ new Set();
|
|
12201
|
+
for (const entry of entries) {
|
|
12202
|
+
if (typeof entry === "string") continue;
|
|
12203
|
+
selectedNames.add(entry.name);
|
|
12204
|
+
const resolution = resolveSelection(entry, projectRoot);
|
|
12205
|
+
if (resolution.failure) {
|
|
12206
|
+
unresolved.push({ label: packEntryLabel(entry), message: `[${resolution.failure.code}] ${resolution.failure.message}` });
|
|
12207
|
+
}
|
|
12208
|
+
}
|
|
12209
|
+
const installed = listInstalledPacks();
|
|
12210
|
+
const globalsOn = globalPacksEnabled(config);
|
|
12211
|
+
const globalsApplied = [];
|
|
12212
|
+
if (globalsOn) {
|
|
12213
|
+
for (const ref of discoverPacks(globalPacksDir())) {
|
|
12214
|
+
const match = installed.find((p) => path12.resolve(p.path) === path12.resolve(ref));
|
|
12215
|
+
if (match) globalsApplied.push({ name: match.name, version: match.version });
|
|
12216
|
+
}
|
|
12217
|
+
}
|
|
12218
|
+
const applying = /* @__PURE__ */ new Set([...selectedNames, ...globalsApplied.map((p) => p.name)]);
|
|
12219
|
+
const notApplied = installed.filter((p) => !applying.has(p.name)).map((p) => ({ name: p.name, version: p.version, origin: p.origin }));
|
|
12220
|
+
return { globalsUndeclared, notApplied, unresolved, globalsApplied };
|
|
12221
|
+
} catch {
|
|
12222
|
+
return empty;
|
|
12223
|
+
}
|
|
12224
|
+
}
|
|
12225
|
+
function pinInstalledPacksAsSelections() {
|
|
12226
|
+
const diagnosis = diagnoseProjectPacks();
|
|
12227
|
+
if (!diagnosis.globalsUndeclared || diagnosis.notApplied.length === 0) return [];
|
|
12228
|
+
const added = [];
|
|
12229
|
+
const selections = [];
|
|
12230
|
+
for (const pack of diagnosis.notApplied) {
|
|
12231
|
+
selections.push({
|
|
12232
|
+
name: pack.name,
|
|
12233
|
+
version: pack.version,
|
|
12234
|
+
// Carry the origin so the selection can be obtained elsewhere; a local
|
|
12235
|
+
// path is not fetchable, so it is deliberately not recorded as a source.
|
|
12236
|
+
...pack.origin && /^[a-z][a-z0-9+.-]*:\/\//i.test(pack.origin) ? { source: pack.origin } : {}
|
|
12237
|
+
});
|
|
12238
|
+
added.push(`${pack.name}@${pack.version}`);
|
|
12239
|
+
}
|
|
12240
|
+
projectConfigRepository.pinGlobalPacksAsSelections(selections);
|
|
12241
|
+
return added;
|
|
12242
|
+
}
|
|
12243
|
+
function packEntryLabel(entry) {
|
|
12244
|
+
if (typeof entry === "string") return entry;
|
|
12245
|
+
return entry.version ? `${entry.name}@${entry.version}` : entry.name;
|
|
12246
|
+
}
|
|
12247
|
+
function packEntryRef(entry, projectRoot) {
|
|
12248
|
+
if (typeof entry === "string") return entry;
|
|
12249
|
+
return resolveSelection(entry, projectRoot).ref ?? null;
|
|
12250
|
+
}
|
|
12128
12251
|
function resolveSelection(selection, projectRoot) {
|
|
12129
12252
|
const wanted = selection.version ? `${selection.name}@${selection.version}` : selection.name;
|
|
12130
12253
|
const fail = (code, message) => ({ failure: { code, severity: "error", name: selection.name, message } });
|
|
@@ -12166,7 +12289,7 @@ function verifyIntegrity(selection, packDir, where) {
|
|
|
12166
12289
|
};
|
|
12167
12290
|
}
|
|
12168
12291
|
function detectBundleStoreDrift(selection, bundleDir) {
|
|
12169
|
-
const bundledVersion =
|
|
12292
|
+
const bundledVersion = path12.basename(bundleDir);
|
|
12170
12293
|
const installed = resolveInstalledPack(selection.name, bundledVersion);
|
|
12171
12294
|
if (!installed) return void 0;
|
|
12172
12295
|
const bundleDigest = computePackDigest(bundleDir);
|
|
@@ -12180,22 +12303,22 @@ function detectBundleStoreDrift(selection, bundleDir) {
|
|
|
12180
12303
|
};
|
|
12181
12304
|
}
|
|
12182
12305
|
function findBundledPack(projectRoot, selection) {
|
|
12183
|
-
const base =
|
|
12306
|
+
const base = path12.join(projectRoot, ".wai", "packs", selection.name);
|
|
12184
12307
|
if (selection.version) {
|
|
12185
|
-
const pinned =
|
|
12308
|
+
const pinned = path12.join(base, selection.version);
|
|
12186
12309
|
return packDirEntry(pinned) ? pinned : null;
|
|
12187
12310
|
}
|
|
12188
12311
|
if (packDirEntry(base)) return base;
|
|
12189
12312
|
let versions;
|
|
12190
12313
|
try {
|
|
12191
|
-
versions =
|
|
12314
|
+
versions = fs9.readdirSync(base, { withFileTypes: true });
|
|
12192
12315
|
} catch {
|
|
12193
12316
|
return null;
|
|
12194
12317
|
}
|
|
12195
12318
|
let best = null;
|
|
12196
12319
|
for (const v of versions) {
|
|
12197
12320
|
if (!v.isDirectory()) continue;
|
|
12198
|
-
const dir =
|
|
12321
|
+
const dir = path12.join(base, v.name);
|
|
12199
12322
|
if (!packDirEntry(dir)) continue;
|
|
12200
12323
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
12201
12324
|
}
|
|
@@ -12238,21 +12361,21 @@ function buildCodeIndex(model) {
|
|
|
12238
12361
|
const declarations = /* @__PURE__ */ new Map();
|
|
12239
12362
|
const anchors = /* @__PURE__ */ new Map();
|
|
12240
12363
|
const findingAnchors = /* @__PURE__ */ new Map();
|
|
12241
|
-
const namesAt = (cache,
|
|
12242
|
-
const cached = cache.get(
|
|
12364
|
+
const namesAt = (cache, path29, make) => {
|
|
12365
|
+
const cached = cache.get(path29);
|
|
12243
12366
|
if (cached) return cached;
|
|
12244
|
-
const f = facts.get(
|
|
12367
|
+
const f = facts.get(path29);
|
|
12245
12368
|
if (!f) return NO_NAMES;
|
|
12246
12369
|
const built = make(f);
|
|
12247
|
-
cache.set(
|
|
12370
|
+
cache.set(path29, built);
|
|
12248
12371
|
return built;
|
|
12249
12372
|
};
|
|
12250
12373
|
const republished = /* @__PURE__ */ new Map();
|
|
12251
|
-
const republishedFrom = (
|
|
12252
|
-
const cached = republished.get(
|
|
12374
|
+
const republishedFrom = (path29) => {
|
|
12375
|
+
const cached = republished.get(path29);
|
|
12253
12376
|
if (cached) return cached;
|
|
12254
|
-
const out = /* @__PURE__ */ new Set([
|
|
12255
|
-
const queue = [
|
|
12377
|
+
const out = /* @__PURE__ */ new Set([path29]);
|
|
12378
|
+
const queue = [path29];
|
|
12256
12379
|
while (queue.length) {
|
|
12257
12380
|
const from = queue.pop();
|
|
12258
12381
|
const f = facts.get(from);
|
|
@@ -12265,7 +12388,7 @@ function buildCodeIndex(model) {
|
|
|
12265
12388
|
}
|
|
12266
12389
|
}
|
|
12267
12390
|
}
|
|
12268
|
-
republished.set(
|
|
12391
|
+
republished.set(path29, out);
|
|
12269
12392
|
return out;
|
|
12270
12393
|
};
|
|
12271
12394
|
const NO_ORIGIN = /* @__PURE__ */ new Set();
|
|
@@ -12274,9 +12397,9 @@ function buildCodeIndex(model) {
|
|
|
12274
12397
|
return to ? republishedFrom(to) : NO_ORIGIN;
|
|
12275
12398
|
};
|
|
12276
12399
|
const scopeOf = (site, from) => {
|
|
12277
|
-
const
|
|
12278
|
-
const f = facts.get(
|
|
12279
|
-
return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path:
|
|
12400
|
+
const path29 = pathKey(site.from ?? from);
|
|
12401
|
+
const f = facts.get(path29);
|
|
12402
|
+
return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path: path29, facts: f } : void 0;
|
|
12280
12403
|
};
|
|
12281
12404
|
const originOf2 = (site, from) => {
|
|
12282
12405
|
const resolved = scopeOf(site, from);
|
|
@@ -12315,14 +12438,14 @@ function buildCodeIndex(model) {
|
|
|
12315
12438
|
if (site.via) for (const typeName of localTypesOf(f, site.via)) widenThroughType(typeName);
|
|
12316
12439
|
return out;
|
|
12317
12440
|
};
|
|
12318
|
-
const declarationsAt = (
|
|
12441
|
+
const declarationsAt = (path29) => namesAt(declarations, pathKey(path29), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
|
|
12319
12442
|
return {
|
|
12320
12443
|
paths,
|
|
12321
12444
|
exactPaths,
|
|
12322
|
-
factsAt: (
|
|
12445
|
+
factsAt: (path29) => facts.get(pathKey(path29)),
|
|
12323
12446
|
declarationsAt,
|
|
12324
|
-
anchorsAt: (
|
|
12325
|
-
findingAnchorsAt: (
|
|
12447
|
+
anchorsAt: (path29) => namesAt(anchors, pathKey(path29), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames, ...f.anchoredNames])),
|
|
12448
|
+
findingAnchorsAt: (path29) => namesAt(findingAnchors, pathKey(path29), (f) => new Set(f.anchoredNames)),
|
|
12326
12449
|
originOf: originOf2,
|
|
12327
12450
|
possibleOriginsOf
|
|
12328
12451
|
};
|
|
@@ -12360,10 +12483,10 @@ function buildRealizationIndex(ctx) {
|
|
|
12360
12483
|
return {
|
|
12361
12484
|
paths,
|
|
12362
12485
|
implementationsOf: (compId) => implsByComponent.get(compId) ?? NONE_IMPL,
|
|
12363
|
-
implementationsAt: (
|
|
12486
|
+
implementationsAt: (path29) => implsByPath.get(pathKey(path29)) ?? NONE_IMPL,
|
|
12364
12487
|
filesOf: (compId) => filesByComponent.get(compId) ?? NONE_PATH,
|
|
12365
12488
|
filesIn: (subsystemId) => filesBySubsystem.get(subsystemId) ?? NONE_PATH,
|
|
12366
|
-
componentsAt: (
|
|
12489
|
+
componentsAt: (path29) => componentsByPath.get(pathKey(path29)) ?? NONE_COMP
|
|
12367
12490
|
};
|
|
12368
12491
|
}
|
|
12369
12492
|
function buildImportGraph(index, universe) {
|
|
@@ -12375,22 +12498,22 @@ function buildImportGraph(index, universe) {
|
|
|
12375
12498
|
if (to && to !== from) into.add(to);
|
|
12376
12499
|
}
|
|
12377
12500
|
};
|
|
12378
|
-
const importsOf = (
|
|
12379
|
-
const cached = imports.get(
|
|
12501
|
+
const importsOf = (path29) => {
|
|
12502
|
+
const cached = imports.get(path29);
|
|
12380
12503
|
if (cached) return cached;
|
|
12381
|
-
const facts = index.factsAt(
|
|
12504
|
+
const facts = index.factsAt(path29);
|
|
12382
12505
|
const out = /* @__PURE__ */ new Set();
|
|
12383
|
-
if (facts?.status === "analyzed") resolveAll(
|
|
12384
|
-
imports.set(
|
|
12506
|
+
if (facts?.status === "analyzed") resolveAll(path29, facts.imports, out);
|
|
12507
|
+
imports.set(path29, out);
|
|
12385
12508
|
return out;
|
|
12386
12509
|
};
|
|
12387
|
-
const tracesOf = (
|
|
12388
|
-
const cached = traces.get(
|
|
12510
|
+
const tracesOf = (path29) => {
|
|
12511
|
+
const cached = traces.get(path29);
|
|
12389
12512
|
if (cached) return cached;
|
|
12390
|
-
const facts = index.factsAt(
|
|
12391
|
-
const out = new Set(importsOf(
|
|
12392
|
-
if (facts?.status === "analyzed") resolveAll(
|
|
12393
|
-
traces.set(
|
|
12513
|
+
const facts = index.factsAt(path29);
|
|
12514
|
+
const out = new Set(importsOf(path29));
|
|
12515
|
+
if (facts?.status === "analyzed") resolveAll(path29, facts.reexports, out);
|
|
12516
|
+
traces.set(path29, out);
|
|
12394
12517
|
return out;
|
|
12395
12518
|
};
|
|
12396
12519
|
return {
|
|
@@ -13727,11 +13850,11 @@ var unconditionalCallCyclesRule = {
|
|
|
13727
13850
|
const memberEdges = keys.flatMap((k) => (adjacency.get(k) ?? []).filter((e) => inScc.has(e.toKey)));
|
|
13728
13851
|
if (memberEdges.length === 0) continue;
|
|
13729
13852
|
const anchor = [...memberEdges].sort((a, b) => byCodeUnit(a.fromKey, b.fromKey) || byCodeUnit(a.impl.id, b.impl.id) || a.stepNumber - b.stepNumber)[0];
|
|
13730
|
-
const
|
|
13853
|
+
const path29 = [...keys].sort(byCodeUnit).join(" \u2192 ");
|
|
13731
13854
|
ctx.addIssue(
|
|
13732
13855
|
"warning",
|
|
13733
13856
|
"UNCONDITIONAL_CALL_CYCLE",
|
|
13734
|
-
`Call cycle with no guard: ${
|
|
13857
|
+
`Call cycle with no guard: ${path29} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
|
|
13735
13858
|
anchor.impl.id,
|
|
13736
13859
|
memberEdges.some((e) => ctx.isImplementationDraft(e.impl))
|
|
13737
13860
|
);
|
|
@@ -15398,8 +15521,8 @@ var lifecycleRule = {
|
|
|
15398
15521
|
};
|
|
15399
15522
|
|
|
15400
15523
|
// src/core/rules/wiring/portal-mounts.ts
|
|
15401
|
-
function liesUnder(
|
|
15402
|
-
return
|
|
15524
|
+
function liesUnder(path29, prefix) {
|
|
15525
|
+
return path29 === prefix || path29.startsWith(prefix + "/");
|
|
15403
15526
|
}
|
|
15404
15527
|
var portalMountsRule = {
|
|
15405
15528
|
name: "portal-mounts",
|
|
@@ -16567,11 +16690,11 @@ var hiddenStateRule = {
|
|
|
16567
16690
|
byPath.set(key, list);
|
|
16568
16691
|
}
|
|
16569
16692
|
}
|
|
16570
|
-
for (const
|
|
16571
|
-
const facts = code.factsAt(
|
|
16693
|
+
for (const path29 of code.exactPaths) {
|
|
16694
|
+
const facts = code.factsAt(path29);
|
|
16572
16695
|
const bindings = facts.topLevelMutableBindings ?? [];
|
|
16573
16696
|
if (bindings.length === 0) continue;
|
|
16574
|
-
const mapped = byPath.get(
|
|
16697
|
+
const mapped = byPath.get(path29) ?? [];
|
|
16575
16698
|
if (mapped.length === 0) continue;
|
|
16576
16699
|
if (!mapped.every((m) => isStatelessLogic(m.component))) continue;
|
|
16577
16700
|
const anchor = [...mapped].sort((a, b) => a.impl.id.localeCompare(b.impl.id))[0];
|
|
@@ -16637,7 +16760,7 @@ var dependencyConformanceRule = {
|
|
|
16637
16760
|
}
|
|
16638
16761
|
return false;
|
|
16639
16762
|
};
|
|
16640
|
-
const draftAt = (
|
|
16763
|
+
const draftAt = (path29) => realization.implementationsAt(path29).some((impl) => ctx.isImplementationDraft(impl));
|
|
16641
16764
|
for (const fromPath of mappedPaths) {
|
|
16642
16765
|
const fromComponents = realization.componentsAt(fromPath);
|
|
16643
16766
|
for (const toPath of graph.importsOf(fromPath)) {
|
|
@@ -16693,6 +16816,60 @@ var dependencyConformanceRule = {
|
|
|
16693
16816
|
}
|
|
16694
16817
|
};
|
|
16695
16818
|
|
|
16819
|
+
// src/core/rules/conformance/portal-imports.ts
|
|
16820
|
+
var portalImportsRule = {
|
|
16821
|
+
name: "portal-imports",
|
|
16822
|
+
description: "A runtime import that crosses a subsystem boundary must land on a file that realizes one of the target subsystem's PUBLISHED components \u2014 its portal file. dependency-conformance asks whether the hop is declared; this asks where it lands. An import that reaches past the portal into a concrete module can use anything that module exports, published or not, so the portal stops being the boundary and names no contract ever promised leak across it \u2014 which is how a surface grows that nobody designed. In-process it is cosmetic at runtime; it is not cosmetic for the contract. Only exact-grade component-mapped files participate; type-only imports are exempt; chained subprojects validate standalone.",
|
|
16823
|
+
codes: [
|
|
16824
|
+
{
|
|
16825
|
+
code: "IMPORT_BYPASSES_PORTAL",
|
|
16826
|
+
defaultSeverity: "warning",
|
|
16827
|
+
summary: "A runtime import crosses into another subsystem through a file that realizes none of its published components",
|
|
16828
|
+
carryable: true
|
|
16829
|
+
}
|
|
16830
|
+
],
|
|
16831
|
+
check(ctx) {
|
|
16832
|
+
const code = ctx.codeIndex();
|
|
16833
|
+
const realization = ctx.realizationIndex();
|
|
16834
|
+
const mappedPaths = new Set(realization.paths.filter((p) => code.exactPaths.has(p)));
|
|
16835
|
+
const graph = ctx.importGraph(mappedPaths);
|
|
16836
|
+
const portalFiles = /* @__PURE__ */ new Map();
|
|
16837
|
+
const portalFilesOf = (subsystemId) => {
|
|
16838
|
+
let files = portalFiles.get(subsystemId);
|
|
16839
|
+
if (!files) {
|
|
16840
|
+
files = /* @__PURE__ */ new Set();
|
|
16841
|
+
for (const compId of ctx.publicSet.get(subsystemId) ?? []) {
|
|
16842
|
+
for (const f of realization.filesOf(compId)) if (mappedPaths.has(f)) files.add(f);
|
|
16843
|
+
}
|
|
16844
|
+
portalFiles.set(subsystemId, files);
|
|
16845
|
+
}
|
|
16846
|
+
return files;
|
|
16847
|
+
};
|
|
16848
|
+
const draftAt = (path29) => realization.implementationsAt(path29).some((impl) => ctx.isImplementationDraft(impl));
|
|
16849
|
+
for (const fromPath of mappedPaths) {
|
|
16850
|
+
const fromSubsystems = new Set(realization.componentsAt(fromPath).map((c) => c.subsystem));
|
|
16851
|
+
for (const toPath of graph.importsOf(fromPath)) {
|
|
16852
|
+
const crossed = [...new Set(realization.componentsAt(toPath).map((c) => c.subsystem))].filter((s) => !fromSubsystems.has(s));
|
|
16853
|
+
const bypassed = crossed.filter((s) => !portalFilesOf(s).has(toPath));
|
|
16854
|
+
if (bypassed.length === 0) continue;
|
|
16855
|
+
for (const subsystemId of bypassed) {
|
|
16856
|
+
const portals = [...portalFilesOf(subsystemId)];
|
|
16857
|
+
ctx.addIssue(
|
|
16858
|
+
"warning",
|
|
16859
|
+
"IMPORT_BYPASSES_PORTAL",
|
|
16860
|
+
`"${fromPath}" imports "${toPath}", crossing into subsystem "${subsystemId}" somewhere other than its portal file (${portals.length > 0 ? portals.join(", ") : "none realized at exact grade"}). Import the name from the portal file instead; when no portal of "${subsystemId}" publishes it, it is a surface the provider never promised \u2014 publish it on the contract of the portal whose capability it is, or stop depending on it.`,
|
|
16861
|
+
realization.implementationsAt(fromPath)[0]?.id,
|
|
16862
|
+
draftAt(fromPath) || draftAt(toPath),
|
|
16863
|
+
void 0,
|
|
16864
|
+
// One import edge, one indivisible fact: the EDGE is the site.
|
|
16865
|
+
{ at: `${fromPath} -> ${toPath}` }
|
|
16866
|
+
);
|
|
16867
|
+
}
|
|
16868
|
+
}
|
|
16869
|
+
}
|
|
16870
|
+
}
|
|
16871
|
+
};
|
|
16872
|
+
|
|
16696
16873
|
// src/core/rules/conformance/integration-sim-declaration.ts
|
|
16697
16874
|
var integrationSimDeclarationRule = {
|
|
16698
16875
|
name: "integration-sim-declaration",
|
|
@@ -17204,8 +17381,8 @@ var paramConformanceRule = {
|
|
|
17204
17381
|
};
|
|
17205
17382
|
|
|
17206
17383
|
// src/core/rules/conformance/route-coverage.ts
|
|
17207
|
-
function liesUnder2(
|
|
17208
|
-
return
|
|
17384
|
+
function liesUnder2(path29, prefix) {
|
|
17385
|
+
return path29 === prefix || path29.startsWith(prefix + "/");
|
|
17209
17386
|
}
|
|
17210
17387
|
function normalizeSegment(segment) {
|
|
17211
17388
|
return /^\{.+\}$/.test(segment) || segment.startsWith(":") ? "*" : segment;
|
|
@@ -18827,6 +19004,8 @@ var SDD_RULES = [
|
|
|
18827
19004
|
// The fields-vs-Store criterion: mutable module state in logic-only files.
|
|
18828
19005
|
hiddenStateRule,
|
|
18829
19006
|
dependencyConformanceRule,
|
|
19007
|
+
// Where a declared crossing LANDS: on the target subsystem's portal file.
|
|
19008
|
+
portalImportsRule,
|
|
18830
19009
|
// Integration wiring proof rides after the code↔spec family: it consumes
|
|
18831
19010
|
// the same code model and speaks about the same sourcePath modules. Four
|
|
18832
19011
|
// questions about one harness, in the order a reader meets them: is one
|
|
@@ -18903,8 +19082,8 @@ function knownIssueCodes() {
|
|
|
18903
19082
|
}
|
|
18904
19083
|
|
|
18905
19084
|
// src/core/source-analysis.ts
|
|
18906
|
-
var
|
|
18907
|
-
var
|
|
19085
|
+
var fs10 = __toESM(require("fs"));
|
|
19086
|
+
var path13 = __toESM(require("path"));
|
|
18908
19087
|
var import_module2 = require("module");
|
|
18909
19088
|
function emptyCodeModel() {
|
|
18910
19089
|
return { files: [], projectRoot: "", rootFiles: [] };
|
|
@@ -19129,7 +19308,7 @@ function resolveTypeScript(projectRoot) {
|
|
|
19129
19308
|
return cached.ts;
|
|
19130
19309
|
}
|
|
19131
19310
|
let ts = null;
|
|
19132
|
-
const bases = [
|
|
19311
|
+
const bases = [path13.join(projectRoot, "package.json"), __filename];
|
|
19133
19312
|
for (const base of bases) {
|
|
19134
19313
|
try {
|
|
19135
19314
|
const req = (0, import_module2.createRequire)(base);
|
|
@@ -19525,7 +19704,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
19525
19704
|
}
|
|
19526
19705
|
function resolveRelativeModule(fromFile, specifier) {
|
|
19527
19706
|
if (!specifier.startsWith(".")) return null;
|
|
19528
|
-
const base =
|
|
19707
|
+
const base = path13.resolve(path13.dirname(fromFile), specifier);
|
|
19529
19708
|
const candidates = [
|
|
19530
19709
|
base,
|
|
19531
19710
|
base.replace(/\.js$/, ".ts"),
|
|
@@ -19533,12 +19712,12 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
19533
19712
|
`${base}.ts`,
|
|
19534
19713
|
`${base}.tsx`,
|
|
19535
19714
|
`${base}.js`,
|
|
19536
|
-
|
|
19537
|
-
|
|
19715
|
+
path13.join(base, "index.ts"),
|
|
19716
|
+
path13.join(base, "index.js")
|
|
19538
19717
|
];
|
|
19539
19718
|
for (const c of candidates) {
|
|
19540
19719
|
try {
|
|
19541
|
-
if (
|
|
19720
|
+
if (fs10.statSync(c).isFile()) return c;
|
|
19542
19721
|
} catch {
|
|
19543
19722
|
}
|
|
19544
19723
|
}
|
|
@@ -19546,11 +19725,11 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
19546
19725
|
}
|
|
19547
19726
|
function reexportTarget(ts, filePath, specifier, projectRoot, visited, exactCache) {
|
|
19548
19727
|
const target = resolveRelativeModule(filePath, specifier);
|
|
19549
|
-
if (!target ||
|
|
19728
|
+
if (!target || path13.relative(projectRoot, target).startsWith("..")) return null;
|
|
19550
19729
|
let targetFacts = exactCache.get(target);
|
|
19551
19730
|
if (targetFacts === void 0) {
|
|
19552
19731
|
try {
|
|
19553
|
-
targetFacts = walkExact(ts,
|
|
19732
|
+
targetFacts = walkExact(ts, fs10.readFileSync(target, "utf8"), target);
|
|
19554
19733
|
} catch {
|
|
19555
19734
|
targetFacts = null;
|
|
19556
19735
|
}
|
|
@@ -19568,7 +19747,7 @@ function carryBody(facts, target, targetPath, local, exported, projectRoot) {
|
|
|
19568
19747
|
if (score !== void 0) facts.complexity.set(exported, Math.max(facts.complexity.get(exported) ?? 0, score));
|
|
19569
19748
|
const targetCalls = target.calls.get(local);
|
|
19570
19749
|
if (!targetCalls) return;
|
|
19571
|
-
const carriedFrom = pathKey(
|
|
19750
|
+
const carriedFrom = pathKey(path13.relative(projectRoot, targetPath));
|
|
19572
19751
|
const sites = facts.calls.get(exported) ?? /* @__PURE__ */ new Map();
|
|
19573
19752
|
for (const [key, site] of targetCalls) sites.set(carriedFrom + "|" + key, { ...site, from: site.from ?? carriedFrom });
|
|
19574
19753
|
facts.calls.set(exported, sites);
|
|
@@ -19598,24 +19777,24 @@ function walkDeclaredRoots(roots, exclude, projectRoot) {
|
|
|
19598
19777
|
const excluded = exclude.map(pathKey);
|
|
19599
19778
|
const isExcluded = (key) => excluded.some((e) => key === e || key.startsWith(`${e}/`));
|
|
19600
19779
|
const record = (absolute) => {
|
|
19601
|
-
const key = pathKey(
|
|
19780
|
+
const key = pathKey(path13.relative(projectRoot, absolute));
|
|
19602
19781
|
if (seen.has(key) || isExcluded(key)) return;
|
|
19603
|
-
if (!EXTENSION_LANGUAGE[
|
|
19782
|
+
if (!EXTENSION_LANGUAGE[path13.extname(key).toLowerCase()]) return;
|
|
19604
19783
|
seen.add(key);
|
|
19605
19784
|
found.push(key);
|
|
19606
19785
|
};
|
|
19607
19786
|
const descend = (dir) => {
|
|
19608
19787
|
let entries;
|
|
19609
19788
|
try {
|
|
19610
|
-
entries =
|
|
19789
|
+
entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
19611
19790
|
} catch {
|
|
19612
19791
|
return;
|
|
19613
19792
|
}
|
|
19614
19793
|
for (const entry of entries.slice().sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
19615
|
-
const child =
|
|
19794
|
+
const child = path13.join(dir, entry.name);
|
|
19616
19795
|
if (entry.isDirectory()) {
|
|
19617
19796
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
19618
|
-
if (isExcluded(pathKey(
|
|
19797
|
+
if (isExcluded(pathKey(path13.relative(projectRoot, child)))) continue;
|
|
19619
19798
|
descend(child);
|
|
19620
19799
|
} else if (entry.isFile()) {
|
|
19621
19800
|
record(child);
|
|
@@ -19624,13 +19803,13 @@ function walkDeclaredRoots(roots, exclude, projectRoot) {
|
|
|
19624
19803
|
};
|
|
19625
19804
|
for (const root of roots) {
|
|
19626
19805
|
const key = pathKey(root);
|
|
19627
|
-
if (
|
|
19628
|
-
const absolute =
|
|
19629
|
-
if (
|
|
19806
|
+
if (path13.isAbsolute(key) || path13.normalize(key).split(path13.sep)[0] === "..") continue;
|
|
19807
|
+
const absolute = path13.resolve(projectRoot, key);
|
|
19808
|
+
if (path13.relative(projectRoot, absolute).startsWith("..")) continue;
|
|
19630
19809
|
if (isExcluded(key)) continue;
|
|
19631
19810
|
let stat;
|
|
19632
19811
|
try {
|
|
19633
|
-
stat =
|
|
19812
|
+
stat = fs10.statSync(absolute);
|
|
19634
19813
|
} catch {
|
|
19635
19814
|
continue;
|
|
19636
19815
|
}
|
|
@@ -19656,23 +19835,23 @@ function buildCodeModel(implementations, types, projectRoot, sourceRoots = [], e
|
|
|
19656
19835
|
if (seen.has(sourcePath)) continue;
|
|
19657
19836
|
seen.add(sourcePath);
|
|
19658
19837
|
const empty = { declaredNames: [], anchoredNames: [], exportedNames: [], imports: [], reexports: [] };
|
|
19659
|
-
if (
|
|
19838
|
+
if (path13.isAbsolute(sourcePath) || path13.normalize(sourcePath).split(path13.sep)[0] === "..") {
|
|
19660
19839
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
19661
19840
|
continue;
|
|
19662
19841
|
}
|
|
19663
|
-
const absolute =
|
|
19664
|
-
if (
|
|
19842
|
+
const absolute = path13.resolve(projectRoot, sourcePath);
|
|
19843
|
+
if (path13.relative(projectRoot, absolute).startsWith("..")) {
|
|
19665
19844
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
19666
19845
|
continue;
|
|
19667
19846
|
}
|
|
19668
19847
|
let buffer;
|
|
19669
19848
|
try {
|
|
19670
|
-
const stat =
|
|
19849
|
+
const stat = fs10.statSync(absolute);
|
|
19671
19850
|
if (!stat.isFile()) {
|
|
19672
19851
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
19673
19852
|
continue;
|
|
19674
19853
|
}
|
|
19675
|
-
buffer =
|
|
19854
|
+
buffer = fs10.readFileSync(absolute);
|
|
19676
19855
|
} catch {
|
|
19677
19856
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
19678
19857
|
continue;
|
|
@@ -19682,7 +19861,7 @@ function buildCodeModel(implementations, types, projectRoot, sourceRoots = [], e
|
|
|
19682
19861
|
continue;
|
|
19683
19862
|
}
|
|
19684
19863
|
const text = buffer.toString("utf8");
|
|
19685
|
-
const language = EXTENSION_LANGUAGE[
|
|
19864
|
+
const language = EXTENSION_LANGUAGE[path13.extname(sourcePath).toLowerCase()];
|
|
19686
19865
|
let analyzed;
|
|
19687
19866
|
if (language === "typescript" || language === "javascript") {
|
|
19688
19867
|
const ts = resolveTypeScript(projectRoot);
|
|
@@ -19753,6 +19932,7 @@ var DEPTH_GATED_CODES = {
|
|
|
19753
19932
|
CONFORMANCE_DEGRADED: "implementations",
|
|
19754
19933
|
UNDECLARED_DEPENDENCY: "implementations",
|
|
19755
19934
|
UNREALIZED_DEPENDENCY: "implementations",
|
|
19935
|
+
IMPORT_BYPASSES_PORTAL: "implementations",
|
|
19756
19936
|
MISSING_INTEGRATION_SIM: "implementations",
|
|
19757
19937
|
// L5 expectations: narratives and everything whose fuel is narrative edges
|
|
19758
19938
|
// (the reachability walk and the hydration round-trip would drown a
|
|
@@ -19787,6 +19967,7 @@ var COMPLETENESS_RULES = /* @__PURE__ */ new Set([
|
|
|
19787
19967
|
"CONFORMANCE_ANALYSIS_SKIPPED",
|
|
19788
19968
|
"UNDECLARED_DEPENDENCY",
|
|
19789
19969
|
"UNREALIZED_DEPENDENCY",
|
|
19970
|
+
"IMPORT_BYPASSES_PORTAL",
|
|
19790
19971
|
// Detail sufficiency reads the realized code like the conformance family
|
|
19791
19972
|
// does — a draft tree is allowed to disagree with its code.
|
|
19792
19973
|
"UNNARRATED_COMPLEXITY",
|
|
@@ -20218,206 +20399,11 @@ function buildRuleContext(opts) {
|
|
|
20218
20399
|
return ctx;
|
|
20219
20400
|
}
|
|
20220
20401
|
|
|
20221
|
-
// src/core/variants.ts
|
|
20222
|
-
var fs10 = __toESM(require("fs"));
|
|
20223
|
-
var os3 = __toESM(require("os"));
|
|
20224
|
-
var path12 = __toESM(require("path"));
|
|
20225
|
-
var import_zod10 = require("zod");
|
|
20226
|
-
var VariantDefSchema = import_zod10.z.object({
|
|
20227
|
-
/** Variant id referenced by a component's `variant` (e.g. "publisher", "org/external-config-adapter"). */
|
|
20228
|
-
id: import_zod10.z.string().min(1),
|
|
20229
|
-
/** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Orchestrator, …). */
|
|
20230
|
-
base: import_zod10.z.string().min(1),
|
|
20231
|
-
/** How to implement a component of this variant — the recipe the implementer follows and reuses across same-variant components. */
|
|
20232
|
-
guidance: import_zod10.z.string().min(1),
|
|
20233
|
-
/** Optional: this variant only applies for the given target language (else it applies everywhere). */
|
|
20234
|
-
target: import_zod10.z.string().optional(),
|
|
20235
|
-
/** Optional: this variant only applies under the given architectural profile. */
|
|
20236
|
-
profile: import_zod10.z.string().optional()
|
|
20237
|
-
});
|
|
20238
|
-
function globalVariantsDir() {
|
|
20239
|
-
return process.env.WAIRON_VARIANTS_DIR ?? path12.join(os3.homedir(), ".wairon", "variants");
|
|
20240
|
-
}
|
|
20241
|
-
function builtinVariantsDir() {
|
|
20242
|
-
const candidates = [
|
|
20243
|
-
path12.resolve(__dirname, "..", "templates", "variants"),
|
|
20244
|
-
// src/core & dist/cli
|
|
20245
|
-
path12.resolve(__dirname, "templates", "variants")
|
|
20246
|
-
// dist (library entry)
|
|
20247
|
-
];
|
|
20248
|
-
return candidates.find((dir) => fs10.existsSync(dir)) ?? candidates[0];
|
|
20249
|
-
}
|
|
20250
|
-
function projectVariantsDir() {
|
|
20251
|
-
return path12.join(getProjectRoot(), ".wai", "variants");
|
|
20252
|
-
}
|
|
20253
|
-
function variantFiles(dir) {
|
|
20254
|
-
let entries;
|
|
20255
|
-
try {
|
|
20256
|
-
entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
20257
|
-
} catch {
|
|
20258
|
-
return [];
|
|
20259
|
-
}
|
|
20260
|
-
return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path12.join(dir, e.name));
|
|
20261
|
-
}
|
|
20262
|
-
function parseVariants(raw) {
|
|
20263
|
-
if (raw == null) return [];
|
|
20264
|
-
return (Array.isArray(raw) ? raw : [raw]).map((item) => VariantDefSchema.parse(item));
|
|
20265
|
-
}
|
|
20266
|
-
function reportSkippedFile(file, err) {
|
|
20267
|
-
console.error(`[variants] skipped "${file}": ${err instanceof Error ? err.message : String(err)}`);
|
|
20268
|
-
}
|
|
20269
|
-
function readVariantsDir(dir) {
|
|
20270
|
-
const out = [];
|
|
20271
|
-
for (const file of variantFiles(dir)) {
|
|
20272
|
-
try {
|
|
20273
|
-
out.push(...parseVariants(readYamlFile(file)));
|
|
20274
|
-
} catch (err) {
|
|
20275
|
-
reportSkippedFile(file, err);
|
|
20276
|
-
}
|
|
20277
|
-
}
|
|
20278
|
-
return out;
|
|
20279
|
-
}
|
|
20280
|
-
function mergeById(...layers) {
|
|
20281
|
-
const byId = /* @__PURE__ */ new Map();
|
|
20282
|
-
for (const layer of layers) {
|
|
20283
|
-
for (const v of layer) byId.set(v.id, v);
|
|
20284
|
-
}
|
|
20285
|
-
return [...byId.values()];
|
|
20286
|
-
}
|
|
20287
|
-
function resolveVariantGuidance(component, allComponents, variantsById) {
|
|
20288
|
-
if (!component.variant) return null;
|
|
20289
|
-
const def = variantsById.get(component.variant);
|
|
20290
|
-
if (!def) return null;
|
|
20291
|
-
return {
|
|
20292
|
-
variant: component.variant,
|
|
20293
|
-
base: def.base,
|
|
20294
|
-
guidance: def.guidance,
|
|
20295
|
-
siblings: allComponents.filter((o) => o.variant === component.variant && o.id !== component.id).map((o) => o.id),
|
|
20296
|
-
...def.target ? { target: def.target } : {},
|
|
20297
|
-
...def.profile ? { profile: def.profile } : {}
|
|
20298
|
-
};
|
|
20299
|
-
}
|
|
20300
|
-
function composeVariantGuidance(comps, allComponents, variantsById) {
|
|
20301
|
-
const resolved = comps.map((c) => ({ id: c.id, guidance: resolveVariantGuidance(c, allComponents, variantsById) })).filter((r) => r.guidance !== null);
|
|
20302
|
-
if (resolved.length === 0) return "";
|
|
20303
|
-
const lines = [
|
|
20304
|
-
"## Component variants \u2014 reuse the shared approach",
|
|
20305
|
-
"",
|
|
20306
|
-
"One or more of your components declare a variant \u2014 a base-anchored kind with implementation guidance. Implement every component of the same variant alike, reusing one shared approach instead of reinventing it per instance:",
|
|
20307
|
-
""
|
|
20308
|
-
];
|
|
20309
|
-
for (const { id, guidance } of resolved) {
|
|
20310
|
-
let line = `- **${id}** \u2014 variant \`${guidance.variant}\` (a kind of ${guidance.base}): ${guidance.guidance}`;
|
|
20311
|
-
if (guidance.siblings.length > 0) {
|
|
20312
|
-
line += ` Same-variant components elsewhere: ${guidance.siblings.join(", ")} \u2014 implement them consistently, reusing the same logic/concept.`;
|
|
20313
|
-
}
|
|
20314
|
-
lines.push(line);
|
|
20315
|
-
}
|
|
20316
|
-
return lines.join("\n");
|
|
20317
|
-
}
|
|
20318
|
-
function loadProjectVariants() {
|
|
20319
|
-
try {
|
|
20320
|
-
return mergeById(
|
|
20321
|
-
readVariantsDir(builtinVariantsDir()),
|
|
20322
|
-
readVariantsDir(globalVariantsDir()),
|
|
20323
|
-
readVariantsDir(projectVariantsDir())
|
|
20324
|
-
);
|
|
20325
|
-
} catch {
|
|
20326
|
-
return [];
|
|
20327
|
-
}
|
|
20328
|
-
}
|
|
20329
|
-
function listProjectVariants() {
|
|
20330
|
-
return mergeById(readVariantsDir(projectVariantsDir()));
|
|
20331
|
-
}
|
|
20332
|
-
function rebaseProjectVariants(fromBase, toBase) {
|
|
20333
|
-
const rebased = [];
|
|
20334
|
-
for (const file of variantFiles(projectVariantsDir())) {
|
|
20335
|
-
const content = readFileOrNull(file);
|
|
20336
|
-
if (content === null) continue;
|
|
20337
|
-
let raw;
|
|
20338
|
-
let variants;
|
|
20339
|
-
try {
|
|
20340
|
-
raw = parseYaml(content, file);
|
|
20341
|
-
variants = parseVariants(raw);
|
|
20342
|
-
} catch (err) {
|
|
20343
|
-
reportSkippedFile(file, err);
|
|
20344
|
-
continue;
|
|
20345
|
-
}
|
|
20346
|
-
const matching = variants.filter((v) => v.base === fromBase);
|
|
20347
|
-
if (matching.length === 0) continue;
|
|
20348
|
-
writeFile(file, rebasedText(content, fromBase, toBase, withRebasedEntries(raw, fromBase, toBase)));
|
|
20349
|
-
for (const v of matching) {
|
|
20350
|
-
if (!rebased.includes(v.id)) rebased.push(v.id);
|
|
20351
|
-
}
|
|
20352
|
-
}
|
|
20353
|
-
return rebased;
|
|
20354
|
-
}
|
|
20355
|
-
function withRebasedEntries(raw, fromBase, toBase) {
|
|
20356
|
-
const rebase = (entry) => entry.base === fromBase ? { ...entry, base: toBase } : entry;
|
|
20357
|
-
return Array.isArray(raw) ? raw.map(rebase) : rebase(raw);
|
|
20358
|
-
}
|
|
20359
|
-
function rebasedText(content, fromBase, toBase, rebasedContent) {
|
|
20360
|
-
const escaped = fromBase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20361
|
-
const baseLine = new RegExp(`^([ \\t]*(?:-[ \\t]+)?base:[ \\t]*)(["']?)${escaped}\\2(?=[ \\t]*(?:#.*)?$)`, "gm");
|
|
20362
|
-
const edited = content.replace(baseLine, (_line, key, quote) => `${key}${quote}${toBase}${quote}`);
|
|
20363
|
-
try {
|
|
20364
|
-
if (JSON.stringify(parseYaml(edited)) === JSON.stringify(rebasedContent)) return edited;
|
|
20365
|
-
} catch {
|
|
20366
|
-
}
|
|
20367
|
-
return serializeYaml(rebasedContent);
|
|
20368
|
-
}
|
|
20369
|
-
|
|
20370
|
-
// src/core/surfaces.ts
|
|
20371
|
-
var fs11 = __toESM(require("fs"));
|
|
20372
|
-
var path13 = __toESM(require("path"));
|
|
20373
|
-
|
|
20374
|
-
// src/core/openapi.ts
|
|
20375
|
-
var yaml2 = __toESM(require("js-yaml"));
|
|
20376
|
-
|
|
20377
|
-
// src/core/surfaces.ts
|
|
20378
|
-
var SURFACES_DIRNAME = "surfaces";
|
|
20379
|
-
function surfacesDir(rootDir) {
|
|
20380
|
-
return path13.join(rootDir, ".wai", SURFACES_DIRNAME);
|
|
20381
|
-
}
|
|
20382
|
-
function listSnapshots(rootDir = getProjectRoot()) {
|
|
20383
|
-
const dir = surfacesDir(rootDir);
|
|
20384
|
-
if (!fs11.existsSync(dir)) return [];
|
|
20385
|
-
const out = [];
|
|
20386
|
-
for (const file of fs11.readdirSync(dir)) {
|
|
20387
|
-
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
20388
|
-
try {
|
|
20389
|
-
out.push(SurfaceSnapshotSchema.parse(readYamlFile(path13.join(dir, file))));
|
|
20390
|
-
} catch {
|
|
20391
|
-
}
|
|
20392
|
-
}
|
|
20393
|
-
return out;
|
|
20394
|
-
}
|
|
20395
|
-
function loadSurfaceSnapshots() {
|
|
20396
|
-
return listSnapshots();
|
|
20397
|
-
}
|
|
20398
|
-
function listMountSnapshots(mounts) {
|
|
20399
|
-
const bound2 = path13.resolve(getProjectRoot());
|
|
20400
|
-
const out = [];
|
|
20401
|
-
for (const namespace of mounts) {
|
|
20402
|
-
const dir = resolveSubprojectForNamespace(namespace);
|
|
20403
|
-
if (!dir || path13.resolve(dir) === bound2) continue;
|
|
20404
|
-
const snapshots = listSnapshots(dir);
|
|
20405
|
-
if (snapshots.length > 0) out.push({ namespace, snapshots });
|
|
20406
|
-
}
|
|
20407
|
-
return out;
|
|
20408
|
-
}
|
|
20409
|
-
function loadMountSurfaceSnapshots(mounts) {
|
|
20410
|
-
return listMountSnapshots(mounts);
|
|
20411
|
-
}
|
|
20412
|
-
|
|
20413
20402
|
// src/core/validation.ts
|
|
20414
20403
|
var path14 = __toESM(require("path"));
|
|
20415
|
-
function loadProjectConfig2() {
|
|
20416
|
-
return loadProjectConfig();
|
|
20417
|
-
}
|
|
20418
20404
|
function projectPackSelections() {
|
|
20419
20405
|
try {
|
|
20420
|
-
return (
|
|
20406
|
+
return (loadProjectConfig()?.extensions?.packs ?? []).filter((e) => typeof e !== "string");
|
|
20421
20407
|
} catch {
|
|
20422
20408
|
return [];
|
|
20423
20409
|
}
|
|
@@ -20487,7 +20473,7 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
|
|
|
20487
20473
|
const interfaces = loadInterfaceSpecs();
|
|
20488
20474
|
const implementations = loadImplementationSpecs();
|
|
20489
20475
|
const types = loadTypeSpecs();
|
|
20490
|
-
const surfaceSnapshots =
|
|
20476
|
+
const surfaceSnapshots = listSnapshots();
|
|
20491
20477
|
const conformance = rules?.conformance;
|
|
20492
20478
|
const codeModel = buildCodeModel(
|
|
20493
20479
|
implementations,
|
|
@@ -20534,7 +20520,7 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
|
|
|
20534
20520
|
for (const err of extensions.errors) {
|
|
20535
20521
|
issues.push(issue("error", "EXTENSION_LOAD_ERROR", err));
|
|
20536
20522
|
}
|
|
20537
|
-
const mountSurfaceSnapshots =
|
|
20523
|
+
const mountSurfaceSnapshots = listMountSnapshots(
|
|
20538
20524
|
subsystems.filter((s) => s.projectPath).map((s) => s.id)
|
|
20539
20525
|
);
|
|
20540
20526
|
const roundTripIssues = dryRunSerializeSpecs(isSpecInScope);
|
|
@@ -20622,10 +20608,9 @@ function resolveThroughParent(boundRoot, treatAllAsComplete, childRules) {
|
|
|
20622
20608
|
if (chain.length === 0) return null;
|
|
20623
20609
|
const scope = chain.join("::");
|
|
20624
20610
|
const inner = runWithProjectRoot(top, () => {
|
|
20625
|
-
invalidateSpecCache();
|
|
20626
20611
|
let governing = { rules: stricterSeverities(void 0, childRules) };
|
|
20627
20612
|
try {
|
|
20628
|
-
const config =
|
|
20613
|
+
const config = loadProjectConfig();
|
|
20629
20614
|
if (config) governing = { rules: stricterSeverities(config.rules, childRules), projectType: config.projectType };
|
|
20630
20615
|
} catch {
|
|
20631
20616
|
}
|
|
@@ -21325,7 +21310,7 @@ function canonicalPath(target) {
|
|
|
21325
21310
|
const rest = [];
|
|
21326
21311
|
for (; ; ) {
|
|
21327
21312
|
try {
|
|
21328
|
-
|
|
21313
|
+
fs11.lstatSync(existing);
|
|
21329
21314
|
break;
|
|
21330
21315
|
} catch {
|
|
21331
21316
|
const up = path15.dirname(existing);
|
|
@@ -21335,7 +21320,7 @@ function canonicalPath(target) {
|
|
|
21335
21320
|
}
|
|
21336
21321
|
}
|
|
21337
21322
|
try {
|
|
21338
|
-
return path15.join(
|
|
21323
|
+
return path15.join(fs11.realpathSync.native(existing), ...rest);
|
|
21339
21324
|
} catch {
|
|
21340
21325
|
return null;
|
|
21341
21326
|
}
|
|
@@ -21427,7 +21412,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
21427
21412
|
let reason;
|
|
21428
21413
|
if (projectPathEscapesRoot(projectDir, projectPath, childDir)) reason = "escapes";
|
|
21429
21414
|
else if (ancestors.has(chainDirKey(childDir))) reason = "cyclic";
|
|
21430
|
-
else if (!
|
|
21415
|
+
else if (!fs11.existsSync(childDir)) reason = "missing";
|
|
21431
21416
|
else if (depth >= 32) reason = "too-deep";
|
|
21432
21417
|
if (reason) {
|
|
21433
21418
|
const mount = prefix ? qualifyDeclaredId(localId, prefix, true) : localId;
|
|
@@ -21568,9 +21553,9 @@ function findOwner(id, components) {
|
|
|
21568
21553
|
}
|
|
21569
21554
|
function moveComponentFolder(fromDir, toDir) {
|
|
21570
21555
|
if (path15.normalize(fromDir) === path15.normalize(toDir)) return false;
|
|
21571
|
-
if (!
|
|
21556
|
+
if (!fs11.existsSync(fromDir) || fs11.existsSync(toDir)) return false;
|
|
21572
21557
|
ensureDir(path15.dirname(toDir));
|
|
21573
|
-
|
|
21558
|
+
fs11.renameSync(fromDir, toDir);
|
|
21574
21559
|
return true;
|
|
21575
21560
|
}
|
|
21576
21561
|
function formatZodIssues(error) {
|
|
@@ -21587,13 +21572,13 @@ var SIGNATURE_TTL_MS = 2e3;
|
|
|
21587
21572
|
function computeSpecTreeSignature(dirs) {
|
|
21588
21573
|
const parts = [];
|
|
21589
21574
|
for (const dir of dirs) {
|
|
21590
|
-
if (!
|
|
21575
|
+
if (!fs11.existsSync(dir)) {
|
|
21591
21576
|
parts.push(`${dir}:missing`);
|
|
21592
21577
|
continue;
|
|
21593
21578
|
}
|
|
21594
21579
|
for (const f of listSpecFiles(dir)) {
|
|
21595
21580
|
try {
|
|
21596
|
-
const st =
|
|
21581
|
+
const st = fs11.statSync(f);
|
|
21597
21582
|
parts.push(`${f}:${st.mtimeMs}:${st.size}`);
|
|
21598
21583
|
} catch {
|
|
21599
21584
|
parts.push(`${f}:gone`);
|
|
@@ -21865,13 +21850,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
21865
21850
|
const isPlain = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
21866
21851
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
21867
21852
|
const at = (prefix, key) => prefix ? `${prefix}.${key}` : key;
|
|
21868
|
-
const say = (
|
|
21869
|
-
out.push(`${
|
|
21853
|
+
const say = (path29, why) => {
|
|
21854
|
+
out.push(`${path29} \u2014 ${why}`);
|
|
21870
21855
|
};
|
|
21871
|
-
const walkValue = (d, m, s,
|
|
21856
|
+
const walkValue = (d, m, s, path29, field) => {
|
|
21872
21857
|
if (Array.isArray(d)) {
|
|
21873
21858
|
if (!Array.isArray(m)) {
|
|
21874
|
-
say(
|
|
21859
|
+
say(path29, "the level does not have this field, so the write dropped it");
|
|
21875
21860
|
return;
|
|
21876
21861
|
}
|
|
21877
21862
|
if (field === "narrative" && d.some(carriesEditMarker)) return;
|
|
@@ -21879,32 +21864,32 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
21879
21864
|
if (carriesEditMarker(element)) continue;
|
|
21880
21865
|
const key = reportIdentityOf(field, element);
|
|
21881
21866
|
if (key === null) {
|
|
21882
|
-
if (!same(m, d)) say(
|
|
21883
|
-
else if (same(s, d)) say(
|
|
21867
|
+
if (!same(m, d)) say(path29, "the level does not keep this value, so the write dropped it");
|
|
21868
|
+
else if (same(s, d)) say(path29, "the stored spec already held this value");
|
|
21884
21869
|
return;
|
|
21885
21870
|
}
|
|
21886
21871
|
const mMatch = m.find((i) => reportIdentityOf(field, i) === key);
|
|
21887
21872
|
const sMatch = Array.isArray(s) ? s.find((i) => reportIdentityOf(field, i) === key) : void 0;
|
|
21888
21873
|
if (mMatch === void 0) {
|
|
21889
|
-
say(at(
|
|
21874
|
+
say(at(path29, key), "the write did not store this element");
|
|
21890
21875
|
continue;
|
|
21891
21876
|
}
|
|
21892
|
-
walk2(element, mMatch, sMatch, at(
|
|
21877
|
+
walk2(element, mMatch, sMatch, at(path29, key), field);
|
|
21893
21878
|
}
|
|
21894
21879
|
return;
|
|
21895
21880
|
}
|
|
21896
21881
|
if (isPlain(d)) {
|
|
21897
21882
|
if (!isPlain(m)) {
|
|
21898
|
-
say(
|
|
21883
|
+
say(path29, "the level does not have this field, so the write dropped it");
|
|
21899
21884
|
return;
|
|
21900
21885
|
}
|
|
21901
|
-
walk2(d, m, s,
|
|
21886
|
+
walk2(d, m, s, path29, field);
|
|
21902
21887
|
return;
|
|
21903
21888
|
}
|
|
21904
|
-
if (!same(m, d)) say(
|
|
21905
|
-
else if (same(s, d)) say(
|
|
21889
|
+
if (!same(m, d)) say(path29, "the write did not store it \u2014 the level's schema does not keep this value");
|
|
21890
|
+
else if (same(s, d)) say(path29, "the stored spec already held this value");
|
|
21906
21891
|
};
|
|
21907
|
-
function walk2(d, m, s,
|
|
21892
|
+
function walk2(d, m, s, path29, container) {
|
|
21908
21893
|
for (const [key, value] of Object.entries(d)) {
|
|
21909
21894
|
if (DELTA_VERBS.has(key) || JUMP_LABEL_TWINS.has(key)) continue;
|
|
21910
21895
|
if (key === "label" && LABEL_TWIN_CONTAINERS.has(container)) continue;
|
|
@@ -21914,13 +21899,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
21914
21899
|
if (typeof name !== "string") continue;
|
|
21915
21900
|
const had = isPlain(s) && s[name] !== void 0;
|
|
21916
21901
|
const still = isPlain(m) && m[name] !== void 0;
|
|
21917
|
-
if (!had) say(at(
|
|
21918
|
-
else if (still) say(at(
|
|
21902
|
+
if (!had) say(at(path29, name), "unset named a field the stored spec did not have");
|
|
21903
|
+
else if (still) say(at(path29, name), "unset did not remove it");
|
|
21919
21904
|
}
|
|
21920
21905
|
continue;
|
|
21921
21906
|
}
|
|
21922
21907
|
if (value === void 0 || value === null) continue;
|
|
21923
|
-
const here = at(
|
|
21908
|
+
const here = at(path29, key);
|
|
21924
21909
|
const mValue = isPlain(m) ? m[key] : void 0;
|
|
21925
21910
|
const sValue = isPlain(s) ? s[key] : void 0;
|
|
21926
21911
|
if (mValue === void 0) {
|
|
@@ -21946,6 +21931,15 @@ var SpecWorkspace = class {
|
|
|
21946
21931
|
this.rootDir = path15.resolve(rootDir);
|
|
21947
21932
|
this.paths = aiPathsAt(this.rootDir);
|
|
21948
21933
|
}
|
|
21934
|
+
/**
|
|
21935
|
+
* The next scan re-verifies the tree's file signature whatever the TTL says.
|
|
21936
|
+
* Called when the bound project root switches to this workspace: a caller that
|
|
21937
|
+
* just bound a root reads it as it is NOW, even if another process changed it
|
|
21938
|
+
* a moment after this workspace last looked.
|
|
21939
|
+
*/
|
|
21940
|
+
expireFreshness() {
|
|
21941
|
+
this.lastSignatureCheckMs = 0;
|
|
21942
|
+
}
|
|
21949
21943
|
invalidate() {
|
|
21950
21944
|
this.cachedIndex = null;
|
|
21951
21945
|
this.cachedRecursive = null;
|
|
@@ -22199,7 +22193,7 @@ var SpecWorkspace = class {
|
|
|
22199
22193
|
});
|
|
22200
22194
|
continue;
|
|
22201
22195
|
}
|
|
22202
|
-
if (!
|
|
22196
|
+
if (!fs11.existsSync(childDir)) {
|
|
22203
22197
|
this.loaderIssues.push({
|
|
22204
22198
|
severity: "error",
|
|
22205
22199
|
code: "SUBPROJECT_NOT_FOUND",
|
|
@@ -23203,8 +23197,8 @@ var SpecWorkspace = class {
|
|
|
23203
23197
|
}
|
|
23204
23198
|
}
|
|
23205
23199
|
for (const file of files) {
|
|
23206
|
-
if (
|
|
23207
|
-
snapshot.set(file,
|
|
23200
|
+
if (fs11.existsSync(file)) {
|
|
23201
|
+
snapshot.set(file, fs11.readFileSync(file, "utf8"));
|
|
23208
23202
|
}
|
|
23209
23203
|
}
|
|
23210
23204
|
return snapshot;
|
|
@@ -24273,8 +24267,15 @@ function workspaceFor(rootDir) {
|
|
|
24273
24267
|
}
|
|
24274
24268
|
return ws;
|
|
24275
24269
|
}
|
|
24270
|
+
var lastServedBinding = null;
|
|
24276
24271
|
function current() {
|
|
24277
|
-
|
|
24272
|
+
const ws = workspaceFor(getProjectRoot());
|
|
24273
|
+
const binding = currentRootBinding() ?? ws.rootDir;
|
|
24274
|
+
if (binding !== lastServedBinding) {
|
|
24275
|
+
lastServedBinding = binding;
|
|
24276
|
+
ws.expireFreshness();
|
|
24277
|
+
}
|
|
24278
|
+
return ws;
|
|
24278
24279
|
}
|
|
24279
24280
|
function invalidateSpecCache() {
|
|
24280
24281
|
for (const ws of workspaces.values()) ws.invalidate();
|
|
@@ -24371,7 +24372,7 @@ function consumedSurfaceInputsAt(rootDir) {
|
|
|
24371
24372
|
const dir = path15.join(rootDir, ".wai", "surfaces");
|
|
24372
24373
|
if (!pathExists(dir)) return [];
|
|
24373
24374
|
const keys = [];
|
|
24374
|
-
for (const file of
|
|
24375
|
+
for (const file of fs11.readdirSync(dir)) {
|
|
24375
24376
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
24376
24377
|
try {
|
|
24377
24378
|
keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path15.join(dir, file)))));
|
|
@@ -24433,6 +24434,9 @@ function specPathsInScope(scopeSubsystem) {
|
|
|
24433
24434
|
function snapshotSpecFiles() {
|
|
24434
24435
|
return current().snapshotSpecFiles();
|
|
24435
24436
|
}
|
|
24437
|
+
function findLegacySpecFiles() {
|
|
24438
|
+
return current().findLegacySpecFiles();
|
|
24439
|
+
}
|
|
24436
24440
|
function loadSpec(kind, id) {
|
|
24437
24441
|
const workspace = current();
|
|
24438
24442
|
return workspace.load(kind, id);
|
|
@@ -24539,7 +24543,7 @@ function unregisterDomain(id) {
|
|
|
24539
24543
|
}
|
|
24540
24544
|
|
|
24541
24545
|
// src/core/provision.ts
|
|
24542
|
-
var
|
|
24546
|
+
var fs12 = __toESM(require("fs"));
|
|
24543
24547
|
var path17 = __toESM(require("path"));
|
|
24544
24548
|
function defaultProjectConfig(name, now) {
|
|
24545
24549
|
return {
|
|
@@ -24588,7 +24592,7 @@ function provisionProject(name) {
|
|
|
24588
24592
|
function ensureProjectInitialized(fallbackName) {
|
|
24589
24593
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24590
24594
|
const paths = aiPathsAt(getProjectRoot());
|
|
24591
|
-
const hasSystem =
|
|
24595
|
+
const hasSystem = fs12.existsSync(paths.specsSystem());
|
|
24592
24596
|
let name = fallbackName;
|
|
24593
24597
|
if (hasSystem) {
|
|
24594
24598
|
const existing = loadSystemSpec();
|
|
@@ -24607,10 +24611,41 @@ function ensureProjectInitialized(fallbackName) {
|
|
|
24607
24611
|
if (wroteConfig || wroteSystem) invalidateSpecCache();
|
|
24608
24612
|
return { wroteConfig, wroteSystem };
|
|
24609
24613
|
}
|
|
24614
|
+
function walkChainedSubprojects(projectRoot, onChild) {
|
|
24615
|
+
const visited = /* @__PURE__ */ new Set();
|
|
24616
|
+
const walk2 = (dir) => {
|
|
24617
|
+
const resolved = path17.resolve(dir);
|
|
24618
|
+
if (visited.has(resolved)) return;
|
|
24619
|
+
visited.add(resolved);
|
|
24620
|
+
const specsDir = aiPathsAt(dir).specsDir();
|
|
24621
|
+
if (!fs12.existsSync(specsDir)) return;
|
|
24622
|
+
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
24623
|
+
let raw;
|
|
24624
|
+
try {
|
|
24625
|
+
raw = readYamlFile(file);
|
|
24626
|
+
} catch {
|
|
24627
|
+
continue;
|
|
24628
|
+
}
|
|
24629
|
+
if (!(raw && typeof raw === "object" && "parentSystem" in raw)) continue;
|
|
24630
|
+
const pp = raw.projectPath;
|
|
24631
|
+
if (typeof pp !== "string" || pp.trim() === "") continue;
|
|
24632
|
+
let childDir;
|
|
24633
|
+
try {
|
|
24634
|
+
childDir = assertContainedProjectPath(dir, pp);
|
|
24635
|
+
} catch {
|
|
24636
|
+
continue;
|
|
24637
|
+
}
|
|
24638
|
+
const id = raw.id;
|
|
24639
|
+
onChild(childDir, typeof id === "string" ? id : path17.basename(childDir));
|
|
24640
|
+
walk2(childDir);
|
|
24641
|
+
}
|
|
24642
|
+
};
|
|
24643
|
+
walk2(projectRoot);
|
|
24644
|
+
}
|
|
24610
24645
|
function listDirectChainedSubprojects(projectRoot) {
|
|
24611
24646
|
const out = [];
|
|
24612
24647
|
const specsDir = aiPathsAt(projectRoot).specsDir();
|
|
24613
|
-
if (!
|
|
24648
|
+
if (!fs12.existsSync(specsDir)) return out;
|
|
24614
24649
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
24615
24650
|
let raw;
|
|
24616
24651
|
try {
|
|
@@ -24632,6 +24667,28 @@ function listDirectChainedSubprojects(projectRoot) {
|
|
|
24632
24667
|
}
|
|
24633
24668
|
return out;
|
|
24634
24669
|
}
|
|
24670
|
+
function childHasSpecsButNoConfig(childDir) {
|
|
24671
|
+
return fs12.existsSync(aiPathsAt(childDir).specsDir()) && !projectConfigRepositoryAt(childDir).exists();
|
|
24672
|
+
}
|
|
24673
|
+
function findChainingSubprojectsMissingConfig(projectRoot) {
|
|
24674
|
+
const missing = [];
|
|
24675
|
+
walkChainedSubprojects(projectRoot, (childDir) => {
|
|
24676
|
+
if (childHasSpecsButNoConfig(childDir)) missing.push(childDir);
|
|
24677
|
+
});
|
|
24678
|
+
return missing;
|
|
24679
|
+
}
|
|
24680
|
+
function backfillChainedSubprojectConfigs(projectRoot) {
|
|
24681
|
+
const backfilled = [];
|
|
24682
|
+
walkChainedSubprojects(projectRoot, (childDir, subsystemId) => {
|
|
24683
|
+
if (childHasSpecsButNoConfig(childDir)) {
|
|
24684
|
+
runWithProjectRoot(childDir, () => {
|
|
24685
|
+
ensureProjectInitialized(subsystemId);
|
|
24686
|
+
});
|
|
24687
|
+
backfilled.push(childDir);
|
|
24688
|
+
}
|
|
24689
|
+
});
|
|
24690
|
+
return backfilled;
|
|
24691
|
+
}
|
|
24635
24692
|
function createChainedSubsystem(subsystem, projectName) {
|
|
24636
24693
|
if (!subsystem.projectPath || subsystem.projectPath.trim() === "") {
|
|
24637
24694
|
throw new WaironError("projectPath is required to create a chained subsystem.");
|
|
@@ -24660,14 +24717,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
|
|
|
24660
24717
|
const oldDir = assertContainedProjectPath(root, sub.projectPath);
|
|
24661
24718
|
const newDir = assertContainedProjectPath(root, nextPath);
|
|
24662
24719
|
if (oldDir !== newDir) {
|
|
24663
|
-
if (!
|
|
24720
|
+
if (!fs12.existsSync(oldDir)) {
|
|
24664
24721
|
throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
|
|
24665
24722
|
}
|
|
24666
|
-
if (
|
|
24723
|
+
if (fs12.existsSync(newDir)) {
|
|
24667
24724
|
throw new WaironError(`Target directory already exists: ${newDir}`);
|
|
24668
24725
|
}
|
|
24669
24726
|
ensureDir(path17.dirname(newDir));
|
|
24670
|
-
|
|
24727
|
+
fs12.renameSync(oldDir, newDir);
|
|
24671
24728
|
}
|
|
24672
24729
|
saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
24673
24730
|
invalidateSpecCache();
|
|
@@ -24691,13 +24748,13 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
24691
24748
|
const parentRoot = getProjectRoot();
|
|
24692
24749
|
const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
|
|
24693
24750
|
const fooDir = path17.join(parentSpecsDir, subsystemId);
|
|
24694
|
-
if (!
|
|
24751
|
+
if (!fs12.existsSync(fooDir)) {
|
|
24695
24752
|
throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
|
|
24696
24753
|
}
|
|
24697
24754
|
const relPath = toPosixPath(projectPath);
|
|
24698
24755
|
const childDir = assertContainedProjectPath(parentRoot, relPath);
|
|
24699
24756
|
const childFooDir = path17.join(childDir, ".wai", "specs", subsystemId);
|
|
24700
|
-
if (
|
|
24757
|
+
if (fs12.existsSync(childFooDir)) {
|
|
24701
24758
|
throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
|
|
24702
24759
|
}
|
|
24703
24760
|
const renameMap = buildRenameMap(
|
|
@@ -24713,7 +24770,7 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
24713
24770
|
saveSystemSpec(bootstrapSystemSpec(childSystemName, now));
|
|
24714
24771
|
});
|
|
24715
24772
|
ensureDir(path17.dirname(childFooDir));
|
|
24716
|
-
|
|
24773
|
+
fs12.renameSync(fooDir, childFooDir);
|
|
24717
24774
|
rebaseImplementationPaths(childFooDir, parentRoot, childDir);
|
|
24718
24775
|
patchSubsystemIndex(path17.join(childFooDir, ".index.yaml"), (s) => {
|
|
24719
24776
|
s.parentSystem = childSystemName;
|
|
@@ -24749,7 +24806,7 @@ function internalizeSubsystem(subsystemId) {
|
|
|
24749
24806
|
const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
|
|
24750
24807
|
const childWai = path17.join(childDir, ".wai");
|
|
24751
24808
|
const childFooDir = path17.join(childDir, ".wai", "specs", subsystemId);
|
|
24752
|
-
if (!
|
|
24809
|
+
if (!fs12.existsSync(childFooDir)) {
|
|
24753
24810
|
throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
|
|
24754
24811
|
}
|
|
24755
24812
|
const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
|
|
@@ -24763,15 +24820,15 @@ function internalizeSubsystem(subsystemId) {
|
|
|
24763
24820
|
);
|
|
24764
24821
|
const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
|
|
24765
24822
|
const fooDir = path17.join(parentSpecsDir, subsystemId);
|
|
24766
|
-
|
|
24823
|
+
fs12.rmSync(fooDir, { recursive: true, force: true });
|
|
24767
24824
|
ensureDir(path17.dirname(fooDir));
|
|
24768
|
-
|
|
24825
|
+
fs12.renameSync(childFooDir, fooDir);
|
|
24769
24826
|
rebaseImplementationPaths(fooDir, childDir, parentRoot);
|
|
24770
24827
|
patchSubsystemIndex(path17.join(fooDir, ".index.yaml"), (s) => {
|
|
24771
24828
|
s.parentSystem = parentSystemName;
|
|
24772
24829
|
delete s.projectPath;
|
|
24773
24830
|
});
|
|
24774
|
-
|
|
24831
|
+
fs12.rmSync(childWai, { recursive: true, force: true });
|
|
24775
24832
|
rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
|
|
24776
24833
|
rebaseMovedRefs(fooDir, subsystemId, "outOf");
|
|
24777
24834
|
invalidateSpecCache();
|
|
@@ -24866,7 +24923,7 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
|
|
|
24866
24923
|
}
|
|
24867
24924
|
}
|
|
24868
24925
|
function patchSubsystemIndex(indexPath, mutate) {
|
|
24869
|
-
if (!
|
|
24926
|
+
if (!fs12.existsSync(indexPath)) return;
|
|
24870
24927
|
const raw = readYamlFile(indexPath);
|
|
24871
24928
|
mutate(raw);
|
|
24872
24929
|
raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -24928,7 +24985,7 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
24928
24985
|
if (movedImplementation) {
|
|
24929
24986
|
const oldFile = getImplementationPath(movedImplementation.id);
|
|
24930
24987
|
if (path17.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path17.resolve(oldFile)) {
|
|
24931
|
-
|
|
24988
|
+
fs12.unlinkSync(oldFile);
|
|
24932
24989
|
}
|
|
24933
24990
|
saveImplementationSpec({ ...movedImplementation, id: implementationId });
|
|
24934
24991
|
}
|
|
@@ -24938,17 +24995,17 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
24938
24995
|
invalidateSpecCache();
|
|
24939
24996
|
}
|
|
24940
24997
|
function removeSpecFile2(file, id) {
|
|
24941
|
-
if (!
|
|
24998
|
+
if (!fs12.existsSync(file)) return;
|
|
24942
24999
|
try {
|
|
24943
25000
|
if (readYamlFile(file)?.id !== id) return;
|
|
24944
25001
|
} catch {
|
|
24945
25002
|
return;
|
|
24946
25003
|
}
|
|
24947
|
-
|
|
25004
|
+
fs12.unlinkSync(file);
|
|
24948
25005
|
const specsRoot = path17.resolve(aiPathsAt(getProjectRoot()).specsDir());
|
|
24949
25006
|
for (let dir = path17.dirname(path17.resolve(file)); dir !== specsRoot && isWithinDir(specsRoot, dir); dir = path17.dirname(dir)) {
|
|
24950
|
-
if (
|
|
24951
|
-
|
|
25007
|
+
if (fs12.readdirSync(dir).length > 0) break;
|
|
25008
|
+
fs12.rmdirSync(dir);
|
|
24952
25009
|
}
|
|
24953
25010
|
}
|
|
24954
25011
|
var METHOD_NAME = /^[a-z][a-zA-Z0-9]*$/;
|
|
@@ -25059,7 +25116,7 @@ function identifierPattern(methodName) {
|
|
|
25059
25116
|
}
|
|
25060
25117
|
|
|
25061
25118
|
// src/core/detection.ts
|
|
25062
|
-
var
|
|
25119
|
+
var fs13 = __toESM(require("fs"));
|
|
25063
25120
|
var path18 = __toESM(require("path"));
|
|
25064
25121
|
var PACKAGE_MARKERS = [
|
|
25065
25122
|
"package.json",
|
|
@@ -25111,7 +25168,7 @@ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
|
|
|
25111
25168
|
});
|
|
25112
25169
|
}
|
|
25113
25170
|
function parseGitmodules(filePath) {
|
|
25114
|
-
const content =
|
|
25171
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
25115
25172
|
const entries = [];
|
|
25116
25173
|
let current2 = {};
|
|
25117
25174
|
for (const line of content.split("\n")) {
|
|
@@ -25134,7 +25191,7 @@ function parseGitmodules(filePath) {
|
|
|
25134
25191
|
}
|
|
25135
25192
|
function detectGitSubmodules(projectRoot) {
|
|
25136
25193
|
const gitmodulesPath = path18.join(projectRoot, ".gitmodules");
|
|
25137
|
-
if (!
|
|
25194
|
+
if (!fs13.existsSync(gitmodulesPath)) return [];
|
|
25138
25195
|
return parseGitmodules(gitmodulesPath).map((entry) => ({
|
|
25139
25196
|
suggestedId: pathToId(entry.path),
|
|
25140
25197
|
suggestedName: pathToName(entry.path),
|
|
@@ -25152,7 +25209,7 @@ function walkForGit(projectRoot, currentDir, depth, results) {
|
|
|
25152
25209
|
if (depth > MAX_SCAN_DEPTH) return;
|
|
25153
25210
|
let entries;
|
|
25154
25211
|
try {
|
|
25155
|
-
entries =
|
|
25212
|
+
entries = fs13.readdirSync(currentDir, { withFileTypes: true });
|
|
25156
25213
|
} catch {
|
|
25157
25214
|
return;
|
|
25158
25215
|
}
|
|
@@ -25163,7 +25220,7 @@ function walkForGit(projectRoot, currentDir, depth, results) {
|
|
|
25163
25220
|
const relPath = normalizePath(path18.relative(projectRoot, fullPath));
|
|
25164
25221
|
if (relPath === "" || relPath === ".") continue;
|
|
25165
25222
|
const gitPath = path18.join(fullPath, ".git");
|
|
25166
|
-
if (
|
|
25223
|
+
if (fs13.existsSync(gitPath)) {
|
|
25167
25224
|
results.push({
|
|
25168
25225
|
suggestedId: pathToId(relPath),
|
|
25169
25226
|
suggestedName: pathToName(relPath),
|
|
@@ -25185,7 +25242,7 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
|
|
|
25185
25242
|
if (depth > MAX_SCAN_DEPTH) return;
|
|
25186
25243
|
let entries;
|
|
25187
25244
|
try {
|
|
25188
|
-
entries =
|
|
25245
|
+
entries = fs13.readdirSync(currentDir, { withFileTypes: true });
|
|
25189
25246
|
} catch {
|
|
25190
25247
|
return;
|
|
25191
25248
|
}
|
|
@@ -25195,7 +25252,7 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
|
|
|
25195
25252
|
const fullPath = path18.join(currentDir, entry.name);
|
|
25196
25253
|
const relPath = normalizePath(path18.relative(projectRoot, fullPath));
|
|
25197
25254
|
if (relPath === "" || relPath === ".") continue;
|
|
25198
|
-
const hasMarker = PACKAGE_MARKERS.some((m) =>
|
|
25255
|
+
const hasMarker = PACKAGE_MARKERS.some((m) => fs13.existsSync(path18.join(fullPath, m)));
|
|
25199
25256
|
if (hasMarker) {
|
|
25200
25257
|
results.push({
|
|
25201
25258
|
suggestedId: pathToId(relPath),
|
|
@@ -25220,19 +25277,168 @@ function normalizePath(p) {
|
|
|
25220
25277
|
return p.replace(/\\/g, "/");
|
|
25221
25278
|
}
|
|
25222
25279
|
|
|
25280
|
+
// src/core/variants.ts
|
|
25281
|
+
var fs14 = __toESM(require("fs"));
|
|
25282
|
+
var os3 = __toESM(require("os"));
|
|
25283
|
+
var path19 = __toESM(require("path"));
|
|
25284
|
+
var import_zod10 = require("zod");
|
|
25285
|
+
var VariantDefSchema = import_zod10.z.object({
|
|
25286
|
+
/** Variant id referenced by a component's `variant` (e.g. "publisher", "org/external-config-adapter"). */
|
|
25287
|
+
id: import_zod10.z.string().min(1),
|
|
25288
|
+
/** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Orchestrator, …). */
|
|
25289
|
+
base: import_zod10.z.string().min(1),
|
|
25290
|
+
/** How to implement a component of this variant — the recipe the implementer follows and reuses across same-variant components. */
|
|
25291
|
+
guidance: import_zod10.z.string().min(1),
|
|
25292
|
+
/** Optional: this variant only applies for the given target language (else it applies everywhere). */
|
|
25293
|
+
target: import_zod10.z.string().optional(),
|
|
25294
|
+
/** Optional: this variant only applies under the given architectural profile. */
|
|
25295
|
+
profile: import_zod10.z.string().optional()
|
|
25296
|
+
});
|
|
25297
|
+
function globalVariantsDir() {
|
|
25298
|
+
return process.env.WAIRON_VARIANTS_DIR ?? path19.join(os3.homedir(), ".wairon", "variants");
|
|
25299
|
+
}
|
|
25300
|
+
function builtinVariantsDir() {
|
|
25301
|
+
const candidates = [
|
|
25302
|
+
path19.resolve(__dirname, "..", "templates", "variants"),
|
|
25303
|
+
// src/core & dist/cli
|
|
25304
|
+
path19.resolve(__dirname, "templates", "variants")
|
|
25305
|
+
// dist (library entry)
|
|
25306
|
+
];
|
|
25307
|
+
return candidates.find((dir) => fs14.existsSync(dir)) ?? candidates[0];
|
|
25308
|
+
}
|
|
25309
|
+
function projectVariantsDir() {
|
|
25310
|
+
return path19.join(getProjectRoot(), ".wai", "variants");
|
|
25311
|
+
}
|
|
25312
|
+
function variantFiles(dir) {
|
|
25313
|
+
let entries;
|
|
25314
|
+
try {
|
|
25315
|
+
entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
25316
|
+
} catch {
|
|
25317
|
+
return [];
|
|
25318
|
+
}
|
|
25319
|
+
return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path19.join(dir, e.name));
|
|
25320
|
+
}
|
|
25321
|
+
function parseVariants(raw) {
|
|
25322
|
+
if (raw == null) return [];
|
|
25323
|
+
return (Array.isArray(raw) ? raw : [raw]).map((item) => VariantDefSchema.parse(item));
|
|
25324
|
+
}
|
|
25325
|
+
function reportSkippedFile(file, err) {
|
|
25326
|
+
console.error(`[variants] skipped "${file}": ${err instanceof Error ? err.message : String(err)}`);
|
|
25327
|
+
}
|
|
25328
|
+
function readVariantsDir(dir) {
|
|
25329
|
+
const out = [];
|
|
25330
|
+
for (const file of variantFiles(dir)) {
|
|
25331
|
+
try {
|
|
25332
|
+
out.push(...parseVariants(readYamlFile(file)));
|
|
25333
|
+
} catch (err) {
|
|
25334
|
+
reportSkippedFile(file, err);
|
|
25335
|
+
}
|
|
25336
|
+
}
|
|
25337
|
+
return out;
|
|
25338
|
+
}
|
|
25339
|
+
function mergeById(...layers) {
|
|
25340
|
+
const byId = /* @__PURE__ */ new Map();
|
|
25341
|
+
for (const layer of layers) {
|
|
25342
|
+
for (const v of layer) byId.set(v.id, v);
|
|
25343
|
+
}
|
|
25344
|
+
return [...byId.values()];
|
|
25345
|
+
}
|
|
25346
|
+
function resolveVariantGuidance(component, allComponents, variantsById) {
|
|
25347
|
+
if (!component.variant) return null;
|
|
25348
|
+
const def = variantsById.get(component.variant);
|
|
25349
|
+
if (!def) return null;
|
|
25350
|
+
return {
|
|
25351
|
+
variant: component.variant,
|
|
25352
|
+
base: def.base,
|
|
25353
|
+
guidance: def.guidance,
|
|
25354
|
+
siblings: allComponents.filter((o) => o.variant === component.variant && o.id !== component.id).map((o) => o.id),
|
|
25355
|
+
...def.target ? { target: def.target } : {},
|
|
25356
|
+
...def.profile ? { profile: def.profile } : {}
|
|
25357
|
+
};
|
|
25358
|
+
}
|
|
25359
|
+
function composeVariantGuidance(comps, allComponents, variantsById) {
|
|
25360
|
+
const resolved = comps.map((c) => ({ id: c.id, guidance: resolveVariantGuidance(c, allComponents, variantsById) })).filter((r) => r.guidance !== null);
|
|
25361
|
+
if (resolved.length === 0) return "";
|
|
25362
|
+
const lines = [
|
|
25363
|
+
"## Component variants \u2014 reuse the shared approach",
|
|
25364
|
+
"",
|
|
25365
|
+
"One or more of your components declare a variant \u2014 a base-anchored kind with implementation guidance. Implement every component of the same variant alike, reusing one shared approach instead of reinventing it per instance:",
|
|
25366
|
+
""
|
|
25367
|
+
];
|
|
25368
|
+
for (const { id, guidance } of resolved) {
|
|
25369
|
+
let line = `- **${id}** \u2014 variant \`${guidance.variant}\` (a kind of ${guidance.base}): ${guidance.guidance}`;
|
|
25370
|
+
if (guidance.siblings.length > 0) {
|
|
25371
|
+
line += ` Same-variant components elsewhere: ${guidance.siblings.join(", ")} \u2014 implement them consistently, reusing the same logic/concept.`;
|
|
25372
|
+
}
|
|
25373
|
+
lines.push(line);
|
|
25374
|
+
}
|
|
25375
|
+
return lines.join("\n");
|
|
25376
|
+
}
|
|
25377
|
+
function loadProjectVariants() {
|
|
25378
|
+
try {
|
|
25379
|
+
return mergeById(
|
|
25380
|
+
readVariantsDir(builtinVariantsDir()),
|
|
25381
|
+
readVariantsDir(globalVariantsDir()),
|
|
25382
|
+
readVariantsDir(projectVariantsDir())
|
|
25383
|
+
);
|
|
25384
|
+
} catch {
|
|
25385
|
+
return [];
|
|
25386
|
+
}
|
|
25387
|
+
}
|
|
25388
|
+
function listProjectVariants() {
|
|
25389
|
+
return mergeById(readVariantsDir(projectVariantsDir()));
|
|
25390
|
+
}
|
|
25391
|
+
function rebaseProjectVariants(fromBase, toBase) {
|
|
25392
|
+
const rebased = [];
|
|
25393
|
+
for (const file of variantFiles(projectVariantsDir())) {
|
|
25394
|
+
const content = readFileOrNull(file);
|
|
25395
|
+
if (content === null) continue;
|
|
25396
|
+
let raw;
|
|
25397
|
+
let variants;
|
|
25398
|
+
try {
|
|
25399
|
+
raw = parseYaml(content, file);
|
|
25400
|
+
variants = parseVariants(raw);
|
|
25401
|
+
} catch (err) {
|
|
25402
|
+
reportSkippedFile(file, err);
|
|
25403
|
+
continue;
|
|
25404
|
+
}
|
|
25405
|
+
const matching = variants.filter((v) => v.base === fromBase);
|
|
25406
|
+
if (matching.length === 0) continue;
|
|
25407
|
+
writeFile(file, rebasedText(content, fromBase, toBase, withRebasedEntries(raw, fromBase, toBase)));
|
|
25408
|
+
for (const v of matching) {
|
|
25409
|
+
if (!rebased.includes(v.id)) rebased.push(v.id);
|
|
25410
|
+
}
|
|
25411
|
+
}
|
|
25412
|
+
return rebased;
|
|
25413
|
+
}
|
|
25414
|
+
function withRebasedEntries(raw, fromBase, toBase) {
|
|
25415
|
+
const rebase = (entry) => entry.base === fromBase ? { ...entry, base: toBase } : entry;
|
|
25416
|
+
return Array.isArray(raw) ? raw.map(rebase) : rebase(raw);
|
|
25417
|
+
}
|
|
25418
|
+
function rebasedText(content, fromBase, toBase, rebasedContent) {
|
|
25419
|
+
const escaped = fromBase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25420
|
+
const baseLine = new RegExp(`^([ \\t]*(?:-[ \\t]+)?base:[ \\t]*)(["']?)${escaped}\\2(?=[ \\t]*(?:#.*)?$)`, "gm");
|
|
25421
|
+
const edited = content.replace(baseLine, (_line, key, quote) => `${key}${quote}${toBase}${quote}`);
|
|
25422
|
+
try {
|
|
25423
|
+
if (JSON.stringify(parseYaml(edited)) === JSON.stringify(rebasedContent)) return edited;
|
|
25424
|
+
} catch {
|
|
25425
|
+
}
|
|
25426
|
+
return serializeYaml(rebasedContent);
|
|
25427
|
+
}
|
|
25428
|
+
|
|
25223
25429
|
// src/core/agent_resolver.ts
|
|
25224
|
-
var
|
|
25430
|
+
var path21 = __toESM(require("path"));
|
|
25225
25431
|
var fs15 = __toESM(require("fs"));
|
|
25226
25432
|
|
|
25227
25433
|
// src/core/templates.ts
|
|
25228
|
-
var
|
|
25434
|
+
var path20 = __toESM(require("path"));
|
|
25229
25435
|
function builtinTemplatesDir() {
|
|
25230
|
-
return
|
|
25436
|
+
return path20.resolve(__dirname, "..", "templates");
|
|
25231
25437
|
}
|
|
25232
25438
|
function loadTemplate(id, globalOverride) {
|
|
25233
25439
|
const dirs = templateSearchDirs(globalOverride);
|
|
25234
25440
|
for (const dir of dirs) {
|
|
25235
|
-
const filePath =
|
|
25441
|
+
const filePath = path20.join(dir, `${id}.yaml`);
|
|
25236
25442
|
if (pathExists(filePath)) {
|
|
25237
25443
|
const raw = readYamlFile(filePath);
|
|
25238
25444
|
return { ...TemplateSchema.parse(raw), templateName: id };
|
|
@@ -25241,7 +25447,7 @@ function loadTemplate(id, globalOverride) {
|
|
|
25241
25447
|
throw new TemplateNotFoundError(id);
|
|
25242
25448
|
}
|
|
25243
25449
|
function loadAgentOverride(agentId) {
|
|
25244
|
-
const filePath =
|
|
25450
|
+
const filePath = path20.join(AI_PATHS.root(), "agents", `${agentId}.md`);
|
|
25245
25451
|
return readFileOrNull(filePath);
|
|
25246
25452
|
}
|
|
25247
25453
|
function templateSearchDirs(globalOverride) {
|
|
@@ -25393,7 +25599,7 @@ function resolveBudget(profile, config, agentId) {
|
|
|
25393
25599
|
var projectFilesCache = /* @__PURE__ */ new Map();
|
|
25394
25600
|
function listFilesRecursiveSafe(dirPath, ext) {
|
|
25395
25601
|
if (!fs15.existsSync(dirPath)) return [];
|
|
25396
|
-
const nameLower =
|
|
25602
|
+
const nameLower = path21.basename(dirPath).toLowerCase();
|
|
25397
25603
|
const IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
25398
25604
|
"node_modules",
|
|
25399
25605
|
"target",
|
|
@@ -25411,7 +25617,7 @@ function listFilesRecursiveSafe(dirPath, ext) {
|
|
|
25411
25617
|
const entries = fs15.readdirSync(dirPath, { withFileTypes: true });
|
|
25412
25618
|
const files = [];
|
|
25413
25619
|
for (const entry of entries) {
|
|
25414
|
-
const fullPath =
|
|
25620
|
+
const fullPath = path21.join(dirPath, entry.name);
|
|
25415
25621
|
if (entry.isDirectory()) {
|
|
25416
25622
|
files.push(...listFilesRecursiveSafe(fullPath, ext));
|
|
25417
25623
|
} else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
@@ -25424,8 +25630,8 @@ function getProjectFiles(projectDir) {
|
|
|
25424
25630
|
let files = projectFilesCache.get(projectDir);
|
|
25425
25631
|
if (!files) {
|
|
25426
25632
|
files = [];
|
|
25427
|
-
const srcDir =
|
|
25428
|
-
const legacySrcDir =
|
|
25633
|
+
const srcDir = path21.join(projectDir, "src");
|
|
25634
|
+
const legacySrcDir = path21.join(projectDir, "legacy-src");
|
|
25429
25635
|
let searchDir = projectDir;
|
|
25430
25636
|
if (pathExists(srcDir)) {
|
|
25431
25637
|
searchDir = srcDir;
|
|
@@ -25440,7 +25646,7 @@ function getProjectFiles(projectDir) {
|
|
|
25440
25646
|
files.push(...listFilesRecursiveSafe(searchDir, ext));
|
|
25441
25647
|
}
|
|
25442
25648
|
const rootDir = getProjectRoot();
|
|
25443
|
-
files = files.map((f) =>
|
|
25649
|
+
files = files.map((f) => path21.relative(rootDir, f).replace(/\\/g, "/"));
|
|
25444
25650
|
projectFilesCache.set(projectDir, files);
|
|
25445
25651
|
}
|
|
25446
25652
|
return files;
|
|
@@ -25465,8 +25671,8 @@ function inferSourcePathForComponent(comp, subsystems) {
|
|
|
25465
25671
|
let bestFile = null;
|
|
25466
25672
|
let bestScore = -1;
|
|
25467
25673
|
for (const f of files) {
|
|
25468
|
-
const ext =
|
|
25469
|
-
const base =
|
|
25674
|
+
const ext = path21.extname(f);
|
|
25675
|
+
const base = path21.basename(f, ext).toLowerCase();
|
|
25470
25676
|
if (candidates.has(base)) {
|
|
25471
25677
|
let score = 0;
|
|
25472
25678
|
const normalizedPath = f.toLowerCase();
|
|
@@ -25563,7 +25769,7 @@ function resolveAgentTopology() {
|
|
|
25563
25769
|
});
|
|
25564
25770
|
for (const sub of subsystems) {
|
|
25565
25771
|
if (sub.projectPath) {
|
|
25566
|
-
const mountSpecPath =
|
|
25772
|
+
const mountSpecPath = path21.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
|
|
25567
25773
|
agents.push({
|
|
25568
25774
|
id: `${sub.id}-owner`,
|
|
25569
25775
|
name: `${sub.name} (chained subproject)`,
|
|
@@ -25585,9 +25791,9 @@ function resolveAgentTopology() {
|
|
|
25585
25791
|
}
|
|
25586
25792
|
const subComponents = components.filter((c) => c.subsystem === sub.id);
|
|
25587
25793
|
const ownedPaths = [];
|
|
25588
|
-
ownedPaths.push(
|
|
25794
|
+
ownedPaths.push(path21.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
|
|
25589
25795
|
for (const c of subComponents) {
|
|
25590
|
-
ownedPaths.push(
|
|
25796
|
+
ownedPaths.push(path21.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
|
|
25591
25797
|
}
|
|
25592
25798
|
if (!config.rules.generateComponentImplementers) {
|
|
25593
25799
|
for (const comp of subComponents) {
|
|
@@ -25663,10 +25869,10 @@ function resolveAgentTopology() {
|
|
|
25663
25869
|
}
|
|
25664
25870
|
const dependencies = comp.dependsOn.map((depId) => `${depId}-implementer`);
|
|
25665
25871
|
const readPaths = [
|
|
25666
|
-
|
|
25667
|
-
|
|
25668
|
-
...compInterfaces.map((i) =>
|
|
25669
|
-
...compImpls.map((impl) =>
|
|
25872
|
+
path21.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
|
|
25873
|
+
path21.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
|
|
25874
|
+
...compInterfaces.map((i) => path21.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
|
|
25875
|
+
...compImpls.map((impl) => path21.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
|
|
25670
25876
|
];
|
|
25671
25877
|
agents.push({
|
|
25672
25878
|
id: `${comp.id}-implementer`,
|
|
@@ -25772,10 +25978,10 @@ function loadRegistry() {
|
|
|
25772
25978
|
}
|
|
25773
25979
|
|
|
25774
25980
|
// src/exporters/generate.ts
|
|
25775
|
-
var
|
|
25981
|
+
var path25 = __toESM(require("path"));
|
|
25776
25982
|
|
|
25777
25983
|
// src/exporters/claude.ts
|
|
25778
|
-
var
|
|
25984
|
+
var path22 = __toESM(require("path"));
|
|
25779
25985
|
var MODEL_BY_TIER = {
|
|
25780
25986
|
small: "haiku",
|
|
25781
25987
|
standard: "sonnet",
|
|
@@ -25814,7 +26020,7 @@ var ClaudeExporter = class {
|
|
|
25814
26020
|
outputPath(ctx) {
|
|
25815
26021
|
const { agent, target, projectRoot } = ctx;
|
|
25816
26022
|
const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
|
|
25817
|
-
return
|
|
26023
|
+
return path22.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
25818
26024
|
}
|
|
25819
26025
|
export(ctx) {
|
|
25820
26026
|
const { agent, renderedInstructions, budget } = ctx;
|
|
@@ -25839,7 +26045,7 @@ var ClaudeExporter = class {
|
|
|
25839
26045
|
};
|
|
25840
26046
|
|
|
25841
26047
|
// src/exporters/custom.ts
|
|
25842
|
-
var
|
|
26048
|
+
var path23 = __toESM(require("path"));
|
|
25843
26049
|
var CustomExporter = class {
|
|
25844
26050
|
constructor() {
|
|
25845
26051
|
this.targetType = "custom";
|
|
@@ -25849,7 +26055,7 @@ var CustomExporter = class {
|
|
|
25849
26055
|
if (!("outputDir" in target)) {
|
|
25850
26056
|
throw new Error("CustomExporter requires target.outputDir");
|
|
25851
26057
|
}
|
|
25852
|
-
return
|
|
26058
|
+
return path23.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
25853
26059
|
}
|
|
25854
26060
|
export(ctx) {
|
|
25855
26061
|
const { agent, target, renderedInstructions } = ctx;
|
|
@@ -25872,7 +26078,7 @@ var CustomExporter = class {
|
|
|
25872
26078
|
};
|
|
25873
26079
|
|
|
25874
26080
|
// src/exporters/gemini.ts
|
|
25875
|
-
var
|
|
26081
|
+
var path24 = __toESM(require("path"));
|
|
25876
26082
|
var GeminiExporter = class {
|
|
25877
26083
|
constructor() {
|
|
25878
26084
|
this.targetType = "gemini";
|
|
@@ -25880,7 +26086,7 @@ var GeminiExporter = class {
|
|
|
25880
26086
|
outputPath(ctx) {
|
|
25881
26087
|
const { agent, target, projectRoot } = ctx;
|
|
25882
26088
|
const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
|
|
25883
|
-
return
|
|
26089
|
+
return path24.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
|
|
25884
26090
|
}
|
|
25885
26091
|
export(ctx) {
|
|
25886
26092
|
const { agent, renderedInstructions } = ctx;
|
|
@@ -25977,7 +26183,7 @@ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProj
|
|
|
25977
26183
|
const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
|
|
25978
26184
|
if (!targetConfig) continue;
|
|
25979
26185
|
const ctx = { agent, projectRoot, target: targetConfig };
|
|
25980
|
-
expected.add(
|
|
26186
|
+
expected.add(path25.resolve(getExporter(targetConfig).outputPath(ctx)));
|
|
25981
26187
|
}
|
|
25982
26188
|
}
|
|
25983
26189
|
return expected;
|
|
@@ -25992,7 +26198,7 @@ function resolveTargetConfig(agentTarget, projectConfig) {
|
|
|
25992
26198
|
|
|
25993
26199
|
// src/core/treetransfer.ts
|
|
25994
26200
|
var fs16 = __toESM(require("fs"));
|
|
25995
|
-
var
|
|
26201
|
+
var path26 = __toESM(require("path"));
|
|
25996
26202
|
var sdkPortal = __toESM(require_dist());
|
|
25997
26203
|
var STAGING_PREFIX = ".wai-staging-";
|
|
25998
26204
|
var BACKUP_DIR = ".wai-backups";
|
|
@@ -26018,39 +26224,39 @@ function hasAuthoredSpecs(root) {
|
|
|
26018
26224
|
if (!pathExists(specsDir)) {
|
|
26019
26225
|
return false;
|
|
26020
26226
|
}
|
|
26021
|
-
const systemIndex =
|
|
26227
|
+
const systemIndex = path26.resolve(paths.specsSystem());
|
|
26022
26228
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
26023
|
-
if (
|
|
26229
|
+
if (path26.resolve(file) !== systemIndex) {
|
|
26024
26230
|
return true;
|
|
26025
26231
|
}
|
|
26026
26232
|
}
|
|
26027
26233
|
return false;
|
|
26028
26234
|
}
|
|
26029
26235
|
function createStagingDir(destDir) {
|
|
26030
|
-
const root =
|
|
26236
|
+
const root = path26.resolve(destDir);
|
|
26031
26237
|
fs16.mkdirSync(root, { recursive: true });
|
|
26032
|
-
const stagingDir = fs16.mkdtempSync(
|
|
26238
|
+
const stagingDir = fs16.mkdtempSync(path26.join(root, STAGING_PREFIX));
|
|
26033
26239
|
return stagingDir;
|
|
26034
26240
|
}
|
|
26035
26241
|
function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
|
|
26036
|
-
const root =
|
|
26037
|
-
const backupDir =
|
|
26242
|
+
const root = path26.resolve(destDir);
|
|
26243
|
+
const backupDir = path26.join(root, BACKUP_DIR, timestampSlug());
|
|
26038
26244
|
let backedUp = false;
|
|
26039
26245
|
for (const rootRel of roots) {
|
|
26040
26246
|
const relative9 = rootRel === "." ? "" : rootRel;
|
|
26041
|
-
const stagedSpecDir =
|
|
26247
|
+
const stagedSpecDir = path26.join(stagingDir, relative9, ".wai");
|
|
26042
26248
|
if (!fs16.existsSync(stagedSpecDir)) continue;
|
|
26043
|
-
const liveSpecDir = liveSpecDirFor(
|
|
26249
|
+
const liveSpecDir = liveSpecDirFor(path26.join(root, relative9));
|
|
26044
26250
|
if (backupExisting && liveSpecDir && fs16.existsSync(liveSpecDir)) {
|
|
26045
|
-
const backupTarget =
|
|
26046
|
-
fs16.mkdirSync(
|
|
26251
|
+
const backupTarget = path26.join(backupDir, relative9, path26.basename(liveSpecDir));
|
|
26252
|
+
fs16.mkdirSync(path26.dirname(backupTarget), { recursive: true });
|
|
26047
26253
|
fs16.renameSync(liveSpecDir, backupTarget);
|
|
26048
26254
|
backedUp = true;
|
|
26049
26255
|
} else if (liveSpecDir && fs16.existsSync(liveSpecDir)) {
|
|
26050
26256
|
fs16.rmSync(liveSpecDir, { recursive: true, force: true });
|
|
26051
26257
|
}
|
|
26052
|
-
const target =
|
|
26053
|
-
fs16.mkdirSync(
|
|
26258
|
+
const target = path26.join(root, relative9, ".wai");
|
|
26259
|
+
fs16.mkdirSync(path26.dirname(target), { recursive: true });
|
|
26054
26260
|
if (fs16.existsSync(target)) fs16.rmSync(target, { recursive: true, force: true });
|
|
26055
26261
|
fs16.renameSync(stagedSpecDir, target);
|
|
26056
26262
|
}
|
|
@@ -26075,7 +26281,7 @@ function exportSpecTree(includeDerived, allowPartial) {
|
|
|
26075
26281
|
const skipped = [...inspection.skipped];
|
|
26076
26282
|
const roots = [{ relativePath: ".", waiDir: aiPathsAt(root).root() }];
|
|
26077
26283
|
for (const rel2 of inspection.roots) {
|
|
26078
|
-
const waiDir = aiPathsAt(
|
|
26284
|
+
const waiDir = aiPathsAt(path26.resolve(root, rel2)).root();
|
|
26079
26285
|
if (pathExists(waiDir)) {
|
|
26080
26286
|
roots.push({ relativePath: rel2, waiDir });
|
|
26081
26287
|
} else {
|
|
@@ -26106,7 +26312,7 @@ function importSpecTree(archive, options) {
|
|
|
26106
26312
|
if (!info.compatible) {
|
|
26107
26313
|
throw new Error("incompatible .waitree archive (format or minimum wairon version)");
|
|
26108
26314
|
}
|
|
26109
|
-
const destDir =
|
|
26315
|
+
const destDir = path26.resolve(options.destDir ?? getProjectRoot());
|
|
26110
26316
|
const occupied = hasSpecTree(destDir);
|
|
26111
26317
|
const authored = hasAuthoredSpecs(destDir);
|
|
26112
26318
|
if (authored && options.replaceExisting !== true) {
|
|
@@ -26137,9 +26343,9 @@ function importSpecTree(archive, options) {
|
|
|
26137
26343
|
return result;
|
|
26138
26344
|
}
|
|
26139
26345
|
function liveSpecDirFor(rootDir) {
|
|
26140
|
-
const modern =
|
|
26346
|
+
const modern = path26.join(rootDir, ".wai");
|
|
26141
26347
|
if (fs16.existsSync(modern)) return modern;
|
|
26142
|
-
const legacy =
|
|
26348
|
+
const legacy = path26.join(rootDir, ".wairon");
|
|
26143
26349
|
if (fs16.existsSync(legacy)) return legacy;
|
|
26144
26350
|
return null;
|
|
26145
26351
|
}
|
|
@@ -26281,7 +26487,7 @@ function repairForeignStepFields(apply) {
|
|
|
26281
26487
|
|
|
26282
26488
|
// src/core/approval.ts
|
|
26283
26489
|
var crypto3 = __toESM(require("crypto"));
|
|
26284
|
-
var
|
|
26490
|
+
var path27 = __toESM(require("path"));
|
|
26285
26491
|
|
|
26286
26492
|
// src/models/lock.ts
|
|
26287
26493
|
function describeApprover(who) {
|
|
@@ -26298,12 +26504,12 @@ function digest(content) {
|
|
|
26298
26504
|
return crypto3.createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
26299
26505
|
}
|
|
26300
26506
|
function currentSpecDigests(root = getProjectRoot()) {
|
|
26301
|
-
const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${
|
|
26507
|
+
const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path27.resolve(root, s.projectPath).split(path27.sep).join("/")}/`);
|
|
26302
26508
|
const out = {};
|
|
26303
26509
|
for (const [abs, content] of snapshotSpecFiles()) {
|
|
26304
|
-
const normalized =
|
|
26510
|
+
const normalized = path27.resolve(abs).split(path27.sep).join("/");
|
|
26305
26511
|
if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
|
|
26306
|
-
out[
|
|
26512
|
+
out[path27.relative(root, abs).split(path27.sep).join("/")] = digest(content);
|
|
26307
26513
|
}
|
|
26308
26514
|
return out;
|
|
26309
26515
|
}
|
|
@@ -26361,7 +26567,7 @@ function currentChildPins(mounts, root = getProjectRoot()) {
|
|
|
26361
26567
|
const pins = {};
|
|
26362
26568
|
for (const mount of mounts) {
|
|
26363
26569
|
if (!mount.projectPath || mount.id.includes("::")) continue;
|
|
26364
|
-
const child = readLockRecordAt(
|
|
26570
|
+
const child = readLockRecordAt(path27.resolve(root, mount.projectPath));
|
|
26365
26571
|
if (child) pins[mount.id] = pinOf(child.stateId);
|
|
26366
26572
|
}
|
|
26367
26573
|
return pins;
|
|
@@ -26463,7 +26669,7 @@ function localApprover() {
|
|
|
26463
26669
|
// src/utils/ai-guide.ts
|
|
26464
26670
|
var fs17 = __toESM(require("fs"));
|
|
26465
26671
|
var os5 = __toESM(require("os"));
|
|
26466
|
-
var
|
|
26672
|
+
var path28 = __toESM(require("path"));
|
|
26467
26673
|
|
|
26468
26674
|
// src/core/stamp.ts
|
|
26469
26675
|
function versionStamp() {
|
|
@@ -26523,13 +26729,13 @@ This project uses **wairon**. System specs live under \`.wai/specs/\` (L0 System
|
|
|
26523
26729
|
* **Variants**: \`gateway\`, a Portal that authenticates, authorizes, validates or rate-limits before it dispatches. Logic is an Orchestrator, and \`dependencyClass: pure | read\` bounds what it may depend on (unset = a workflow). Specialist and Gateway are retired stereotypes.
|
|
26524
26730
|
* Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
|
|
26525
26731
|
function globalGuideFilePath(targetType) {
|
|
26526
|
-
if (targetType === "claude") return
|
|
26527
|
-
if (targetType === "gemini") return
|
|
26732
|
+
if (targetType === "claude") return path28.join(process.env["CLAUDE_CONFIG_DIR"] || path28.join(os5.homedir(), ".claude"), "CLAUDE.md");
|
|
26733
|
+
if (targetType === "gemini") return path28.join(process.env["GEMINI_CONFIG_DIR"] || path28.join(os5.homedir(), ".gemini"), "GEMINI.md");
|
|
26528
26734
|
return null;
|
|
26529
26735
|
}
|
|
26530
26736
|
function localGuideFilePath(projectRoot, targetType) {
|
|
26531
|
-
if (targetType === "claude") return
|
|
26532
|
-
if (targetType === "gemini" || targetType === "agy") return
|
|
26737
|
+
if (targetType === "claude") return path28.join(projectRoot, ".claude", "CLAUDE.md");
|
|
26738
|
+
if (targetType === "gemini" || targetType === "agy") return path28.join(projectRoot, ".gemini", "GEMINI.md");
|
|
26533
26739
|
return null;
|
|
26534
26740
|
}
|
|
26535
26741
|
function injectGuide(filePath, scope) {
|
|
@@ -26544,7 +26750,7 @@ ${GUIDE_MARKER_END}
|
|
|
26544
26750
|
const existing = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8") : "";
|
|
26545
26751
|
const stripped = stripGuideSection(existing);
|
|
26546
26752
|
const newContent = stripped.trimEnd() + section;
|
|
26547
|
-
fs17.mkdirSync(
|
|
26753
|
+
fs17.mkdirSync(path28.dirname(filePath), { recursive: true });
|
|
26548
26754
|
fs17.writeFileSync(filePath, newContent, "utf-8");
|
|
26549
26755
|
}
|
|
26550
26756
|
function stripGuideSection(content) {
|
|
@@ -26555,7 +26761,7 @@ function stripGuideSection(content) {
|
|
|
26555
26761
|
}
|
|
26556
26762
|
function writeRootGuideDelegator(projectRoot, targetType) {
|
|
26557
26763
|
if (targetType === "claude") {
|
|
26558
|
-
const filePath =
|
|
26764
|
+
const filePath = path28.join(projectRoot, "CLAUDE.md");
|
|
26559
26765
|
const content = `@.claude/CLAUDE.md
|
|
26560
26766
|
|
|
26561
26767
|
# Wairon SDD Project
|
|
@@ -26570,7 +26776,7 @@ the \`wairon\` CLI is the human developer's tool, not yours.
|
|
|
26570
26776
|
`;
|
|
26571
26777
|
fs17.writeFileSync(filePath, content, "utf-8");
|
|
26572
26778
|
} else if (targetType === "gemini" || targetType === "agy") {
|
|
26573
|
-
const filePath =
|
|
26779
|
+
const filePath = path28.join(projectRoot, "GEMINI.md");
|
|
26574
26780
|
const content = `# Wairon SDD Project
|
|
26575
26781
|
${GUIDE_MARKER_START}
|
|
26576
26782
|
${versionStamp()}
|
|
@@ -26579,7 +26785,7 @@ ${GUIDE_MARKER_END}
|
|
|
26579
26785
|
`;
|
|
26580
26786
|
fs17.writeFileSync(filePath, content, "utf-8");
|
|
26581
26787
|
} else if (targetType === "cursor") {
|
|
26582
|
-
const filePath =
|
|
26788
|
+
const filePath = path28.join(projectRoot, ".cursorrules");
|
|
26583
26789
|
const content = `# Wairon SDD Project
|
|
26584
26790
|
|
|
26585
26791
|
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
@@ -26588,8 +26794,8 @@ Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
|
|
|
26588
26794
|
`;
|
|
26589
26795
|
fs17.writeFileSync(filePath, content, "utf-8");
|
|
26590
26796
|
} else if (targetType === "copilot") {
|
|
26591
|
-
const filePath =
|
|
26592
|
-
fs17.mkdirSync(
|
|
26797
|
+
const filePath = path28.join(projectRoot, ".github", "copilot-instructions.md");
|
|
26798
|
+
fs17.mkdirSync(path28.dirname(filePath), { recursive: true });
|
|
26593
26799
|
const content = `# Wairon SDD Project
|
|
26594
26800
|
|
|
26595
26801
|
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
@@ -26598,7 +26804,7 @@ Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
|
|
|
26598
26804
|
`;
|
|
26599
26805
|
fs17.writeFileSync(filePath, content, "utf-8");
|
|
26600
26806
|
} else if (targetType === "codex") {
|
|
26601
|
-
const filePath =
|
|
26807
|
+
const filePath = path28.join(projectRoot, ".codexrules");
|
|
26602
26808
|
const content = `# Wairon SDD Project
|
|
26603
26809
|
|
|
26604
26810
|
Refer to [.codex/agents/](.codex/agents/) for full instructions.
|
|
@@ -26974,18 +27180,15 @@ var logger = {
|
|
|
26974
27180
|
|
|
26975
27181
|
// src/core/skills.ts
|
|
26976
27182
|
var SKILL_NAMES = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
|
|
26977
|
-
function loadProjectConfig3() {
|
|
26978
|
-
return loadProjectConfig();
|
|
26979
|
-
}
|
|
26980
27183
|
function activeTargetTypes2() {
|
|
26981
|
-
const config =
|
|
27184
|
+
const config = loadProjectConfig();
|
|
26982
27185
|
if (!config) return [];
|
|
26983
27186
|
return activeTargetTypes(config);
|
|
26984
27187
|
}
|
|
26985
27188
|
var RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
|
|
26986
27189
|
|
|
26987
27190
|
// src/index.ts
|
|
26988
|
-
function
|
|
27191
|
+
function loadProjectConfig2() {
|
|
26989
27192
|
const config = loadProjectConfig();
|
|
26990
27193
|
if (!config) throw new ProjectNotInitializedError();
|
|
26991
27194
|
return config;
|
|
@@ -27118,13 +27321,17 @@ function loadProjectConfig4() {
|
|
|
27118
27321
|
ambiguityMessage,
|
|
27119
27322
|
approvalRecord,
|
|
27120
27323
|
approvalVerdict,
|
|
27324
|
+
assertContainedProjectPath,
|
|
27121
27325
|
assertProjectInitialized,
|
|
27122
27326
|
backendCommand,
|
|
27327
|
+
backfillChainedSubprojectConfigs,
|
|
27123
27328
|
buildCanvasDataModel,
|
|
27124
27329
|
buildProjectGraph,
|
|
27125
27330
|
buildRuleContext,
|
|
27126
27331
|
callSitesOf,
|
|
27127
27332
|
captureApprovedSpecs,
|
|
27333
|
+
checkDeclarativePack,
|
|
27334
|
+
clearLoaderIssues,
|
|
27128
27335
|
cognitiveScore,
|
|
27129
27336
|
complexityLevel,
|
|
27130
27337
|
composeAgentBrief,
|
|
@@ -27139,6 +27346,7 @@ function loadProjectConfig4() {
|
|
|
27139
27346
|
createEmptyTopologyConfig,
|
|
27140
27347
|
createProjectConfig,
|
|
27141
27348
|
currentChildPins,
|
|
27349
|
+
currentRootBinding,
|
|
27142
27350
|
declaredPackNames,
|
|
27143
27351
|
declaredProfileIds,
|
|
27144
27352
|
declaresGlobalPacks,
|
|
@@ -27151,6 +27359,7 @@ function loadProjectConfig4() {
|
|
|
27151
27359
|
deriveExecutionProfile,
|
|
27152
27360
|
derivedDocPaths,
|
|
27153
27361
|
detectDomainCandidates,
|
|
27362
|
+
diagnoseProjectPacks,
|
|
27154
27363
|
diagramSetIndex,
|
|
27155
27364
|
diffAgainstApproval,
|
|
27156
27365
|
diffSize,
|
|
@@ -27166,6 +27375,9 @@ function loadProjectConfig4() {
|
|
|
27166
27375
|
factsFor,
|
|
27167
27376
|
fieldTypeRefs,
|
|
27168
27377
|
fieldTypesOf,
|
|
27378
|
+
findChainingParent,
|
|
27379
|
+
findChainingSubprojectsMissingConfig,
|
|
27380
|
+
findLegacySpecFiles,
|
|
27169
27381
|
findProjectRoot,
|
|
27170
27382
|
findSystemRoot,
|
|
27171
27383
|
fromProjectRoot,
|
|
@@ -27175,6 +27387,7 @@ function loadProjectConfig4() {
|
|
|
27175
27387
|
generateDiagramSet,
|
|
27176
27388
|
generateSequenceDiagram,
|
|
27177
27389
|
getExporter,
|
|
27390
|
+
getLoaderIssues,
|
|
27178
27391
|
getProjectRoot,
|
|
27179
27392
|
getProjectRootOverride,
|
|
27180
27393
|
getRequestParentReach,
|
|
@@ -27182,6 +27395,7 @@ function loadProjectConfig4() {
|
|
|
27182
27395
|
getStatusReport,
|
|
27183
27396
|
globalGuideFilePath,
|
|
27184
27397
|
globalPacksDir,
|
|
27398
|
+
globalPacksEnabled,
|
|
27185
27399
|
globalTemplatesDir,
|
|
27186
27400
|
hasContext,
|
|
27187
27401
|
hasFunctionBody,
|
|
@@ -27214,6 +27428,7 @@ function loadProjectConfig4() {
|
|
|
27214
27428
|
loadInterfaceSpecs,
|
|
27215
27429
|
loadProjectConfig,
|
|
27216
27430
|
loadProjectExtensions,
|
|
27431
|
+
loadProjectVariants,
|
|
27217
27432
|
loadRegistry,
|
|
27218
27433
|
loadSpec,
|
|
27219
27434
|
loadSpecGraph,
|
|
@@ -27237,12 +27452,16 @@ function loadProjectConfig4() {
|
|
|
27237
27452
|
moveSubsystemProject,
|
|
27238
27453
|
movedChildren,
|
|
27239
27454
|
narrativeStepForeignFields,
|
|
27455
|
+
packDirEntry,
|
|
27456
|
+
packEntryLabel,
|
|
27457
|
+
packEntryRef,
|
|
27240
27458
|
packStoreDir,
|
|
27241
27459
|
parseDeclaredCall,
|
|
27242
27460
|
parseYaml,
|
|
27243
27461
|
passesIntentFloor,
|
|
27244
27462
|
pathExists,
|
|
27245
27463
|
pathKey,
|
|
27464
|
+
pinInstalledPacksAsSelections,
|
|
27246
27465
|
projectConfigExists,
|
|
27247
27466
|
provisionProject,
|
|
27248
27467
|
qualifiedTypeId,
|
|
@@ -27270,12 +27489,14 @@ function loadProjectConfig4() {
|
|
|
27270
27489
|
resolveImport,
|
|
27271
27490
|
resolveInstalledPack,
|
|
27272
27491
|
resolveSubprojectForNamespace,
|
|
27492
|
+
resolveVariantGuidance,
|
|
27273
27493
|
retireSpecialists,
|
|
27274
27494
|
runWithProjectBinding,
|
|
27275
27495
|
runWithProjectRoot,
|
|
27276
27496
|
sameContract,
|
|
27277
27497
|
saveSpec,
|
|
27278
27498
|
saveTopologyConfig,
|
|
27499
|
+
scanAllSpecs,
|
|
27279
27500
|
serializeYaml,
|
|
27280
27501
|
setExecutionTier,
|
|
27281
27502
|
setLogLevel,
|