@wairon/cli 5.1.1-dev.61 → 5.1.1-dev.63
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 +1154 -1221
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +752 -2192
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
68
|
+
WAIRON_VERSION = "5.1.1-dev.63";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -1464,10 +1464,6 @@ function normalizeApprover(value) {
|
|
|
1464
1464
|
}
|
|
1465
1465
|
return { id: typeof value === "string" && value ? value : "unknown", source: "legacy" };
|
|
1466
1466
|
}
|
|
1467
|
-
function describeApprover(who) {
|
|
1468
|
-
const label = who.name ? `${who.name} (${who.id})` : who.id;
|
|
1469
|
-
return who.source === "hosted" ? `${label} [authenticated]` : label;
|
|
1470
|
-
}
|
|
1471
1467
|
function readLockRecord() {
|
|
1472
1468
|
try {
|
|
1473
1469
|
return normalizeRecord(JSON.parse(fs6.readFileSync(lockPath(), "utf8")));
|
|
@@ -8642,6 +8638,7 @@ var init_extensions = __esm({
|
|
|
8642
8638
|
init_canonical_json();
|
|
8643
8639
|
init_project();
|
|
8644
8640
|
init_packstore();
|
|
8641
|
+
init_packstore();
|
|
8645
8642
|
ProfileDefSchema = import_zod9.z.object({
|
|
8646
8643
|
family: import_zod9.z.enum(["backend-like", "frontend-like", "neutral"]).default("neutral"),
|
|
8647
8644
|
forbiddenStereotypes: import_zod9.z.array(import_zod9.z.object({ types: import_zod9.z.array(import_zod9.z.string()).min(1), reason: import_zod9.z.string().min(1) })).default([]),
|
|
@@ -22143,223 +22140,6 @@ var init_domain_curator = __esm({
|
|
|
22143
22140
|
}
|
|
22144
22141
|
});
|
|
22145
22142
|
|
|
22146
|
-
// src/core/detection.ts
|
|
22147
|
-
function detectDomainCandidates(projectRoot2, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
|
|
22148
|
-
const candidates = /* @__PURE__ */ new Map();
|
|
22149
|
-
for (const c of detectGitSubmodules(projectRoot2)) {
|
|
22150
|
-
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22151
|
-
}
|
|
22152
|
-
for (const c of detectNestedGitRepos(projectRoot2)) {
|
|
22153
|
-
if (!candidates.has(c.path)) {
|
|
22154
|
-
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22155
|
-
}
|
|
22156
|
-
}
|
|
22157
|
-
const gitPaths = new Set(
|
|
22158
|
-
Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
|
|
22159
|
-
);
|
|
22160
|
-
for (const c of detectPackageRoots(projectRoot2)) {
|
|
22161
|
-
if (candidates.has(c.path)) continue;
|
|
22162
|
-
const insideGit = Array.from(gitPaths).some(
|
|
22163
|
-
(gp) => c.path === gp || c.path.startsWith(gp + "/")
|
|
22164
|
-
);
|
|
22165
|
-
if (insideGit) continue;
|
|
22166
|
-
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22167
|
-
}
|
|
22168
|
-
const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
|
|
22169
|
-
return deduplicateIds(sorted, alreadyTrackedIds);
|
|
22170
|
-
}
|
|
22171
|
-
function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
|
|
22172
|
-
const idCount = /* @__PURE__ */ new Map();
|
|
22173
|
-
for (const id of existingIds) {
|
|
22174
|
-
idCount.set(id, (idCount.get(id) ?? 0) + 1);
|
|
22175
|
-
}
|
|
22176
|
-
for (const c of candidates) {
|
|
22177
|
-
idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
|
|
22178
|
-
}
|
|
22179
|
-
return candidates.map((c) => {
|
|
22180
|
-
if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
|
|
22181
|
-
const parts = c.path.split("/");
|
|
22182
|
-
const qualifiedId2 = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
|
|
22183
|
-
return { ...c, suggestedId: qualifiedId2 };
|
|
22184
|
-
});
|
|
22185
|
-
}
|
|
22186
|
-
function parseGitmodules(filePath) {
|
|
22187
|
-
const content = fs15.readFileSync(filePath, "utf-8");
|
|
22188
|
-
const entries = [];
|
|
22189
|
-
let current2 = {};
|
|
22190
|
-
for (const line2 of content.split("\n")) {
|
|
22191
|
-
const trimmed = line2.trim();
|
|
22192
|
-
const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
|
|
22193
|
-
if (headerMatch) {
|
|
22194
|
-
if (current2.path) entries.push(current2);
|
|
22195
|
-
current2 = { name: headerMatch[1] };
|
|
22196
|
-
continue;
|
|
22197
|
-
}
|
|
22198
|
-
const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
|
|
22199
|
-
if (keyVal) {
|
|
22200
|
-
const [, key, value] = keyVal;
|
|
22201
|
-
if (key === "path") current2.path = value.trim();
|
|
22202
|
-
if (key === "url") current2.url = value.trim();
|
|
22203
|
-
}
|
|
22204
|
-
}
|
|
22205
|
-
if (current2.path) entries.push(current2);
|
|
22206
|
-
return entries;
|
|
22207
|
-
}
|
|
22208
|
-
function detectGitSubmodules(projectRoot2) {
|
|
22209
|
-
const gitmodulesPath = path19.join(projectRoot2, ".gitmodules");
|
|
22210
|
-
if (!fs15.existsSync(gitmodulesPath)) return [];
|
|
22211
|
-
return parseGitmodules(gitmodulesPath).map((entry) => ({
|
|
22212
|
-
suggestedId: pathToId(entry.path),
|
|
22213
|
-
suggestedName: pathToName(entry.path),
|
|
22214
|
-
path: normalizePath(entry.path),
|
|
22215
|
-
type: "git-submodule",
|
|
22216
|
-
alreadyTracked: false
|
|
22217
|
-
}));
|
|
22218
|
-
}
|
|
22219
|
-
function detectNestedGitRepos(projectRoot2) {
|
|
22220
|
-
const results = [];
|
|
22221
|
-
walkForGit(projectRoot2, projectRoot2, 0, results);
|
|
22222
|
-
return results;
|
|
22223
|
-
}
|
|
22224
|
-
function walkForGit(projectRoot2, currentDir, depth, results) {
|
|
22225
|
-
if (depth > MAX_SCAN_DEPTH) return;
|
|
22226
|
-
let entries;
|
|
22227
|
-
try {
|
|
22228
|
-
entries = fs15.readdirSync(currentDir, { withFileTypes: true });
|
|
22229
|
-
} catch {
|
|
22230
|
-
return;
|
|
22231
|
-
}
|
|
22232
|
-
for (const entry of entries) {
|
|
22233
|
-
if (!entry.isDirectory()) continue;
|
|
22234
|
-
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22235
|
-
const fullPath = path19.join(currentDir, entry.name);
|
|
22236
|
-
const relPath = normalizePath(path19.relative(projectRoot2, fullPath));
|
|
22237
|
-
if (relPath === "" || relPath === ".") continue;
|
|
22238
|
-
const gitPath = path19.join(fullPath, ".git");
|
|
22239
|
-
if (fs15.existsSync(gitPath)) {
|
|
22240
|
-
results.push({
|
|
22241
|
-
suggestedId: pathToId(relPath),
|
|
22242
|
-
suggestedName: pathToName(relPath),
|
|
22243
|
-
path: relPath,
|
|
22244
|
-
type: "git-repo",
|
|
22245
|
-
alreadyTracked: false
|
|
22246
|
-
});
|
|
22247
|
-
continue;
|
|
22248
|
-
}
|
|
22249
|
-
walkForGit(projectRoot2, fullPath, depth + 1, results);
|
|
22250
|
-
}
|
|
22251
|
-
}
|
|
22252
|
-
function detectPackageRoots(projectRoot2) {
|
|
22253
|
-
const results = [];
|
|
22254
|
-
walkForPackages(projectRoot2, projectRoot2, 0, results);
|
|
22255
|
-
return results;
|
|
22256
|
-
}
|
|
22257
|
-
function walkForPackages(projectRoot2, currentDir, depth, results) {
|
|
22258
|
-
if (depth > MAX_SCAN_DEPTH) return;
|
|
22259
|
-
let entries;
|
|
22260
|
-
try {
|
|
22261
|
-
entries = fs15.readdirSync(currentDir, { withFileTypes: true });
|
|
22262
|
-
} catch {
|
|
22263
|
-
return;
|
|
22264
|
-
}
|
|
22265
|
-
for (const entry of entries) {
|
|
22266
|
-
if (!entry.isDirectory()) continue;
|
|
22267
|
-
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22268
|
-
const fullPath = path19.join(currentDir, entry.name);
|
|
22269
|
-
const relPath = normalizePath(path19.relative(projectRoot2, fullPath));
|
|
22270
|
-
if (relPath === "" || relPath === ".") continue;
|
|
22271
|
-
const hasMarker = PACKAGE_MARKERS.some((m) => fs15.existsSync(path19.join(fullPath, m)));
|
|
22272
|
-
if (hasMarker) {
|
|
22273
|
-
results.push({
|
|
22274
|
-
suggestedId: pathToId(relPath),
|
|
22275
|
-
suggestedName: pathToName(relPath),
|
|
22276
|
-
path: relPath,
|
|
22277
|
-
type: "package-root",
|
|
22278
|
-
alreadyTracked: false
|
|
22279
|
-
});
|
|
22280
|
-
}
|
|
22281
|
-
walkForPackages(projectRoot2, fullPath, depth + 1, results);
|
|
22282
|
-
}
|
|
22283
|
-
}
|
|
22284
|
-
function pathToId(relPath) {
|
|
22285
|
-
const basename15 = path19.basename(relPath);
|
|
22286
|
-
return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
22287
|
-
}
|
|
22288
|
-
function pathToName(relPath) {
|
|
22289
|
-
const id = pathToId(relPath);
|
|
22290
|
-
return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
22291
|
-
}
|
|
22292
|
-
function normalizePath(p) {
|
|
22293
|
-
return p.replace(/\\/g, "/");
|
|
22294
|
-
}
|
|
22295
|
-
var fs15, path19, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
|
|
22296
|
-
var init_detection = __esm({
|
|
22297
|
-
"src/core/detection.ts"() {
|
|
22298
|
-
"use strict";
|
|
22299
|
-
fs15 = __toESM(require("fs"));
|
|
22300
|
-
path19 = __toESM(require("path"));
|
|
22301
|
-
init_defaults();
|
|
22302
|
-
PACKAGE_MARKERS = [
|
|
22303
|
-
"package.json",
|
|
22304
|
-
"pyproject.toml",
|
|
22305
|
-
"Cargo.toml",
|
|
22306
|
-
"go.mod",
|
|
22307
|
-
"build.gradle",
|
|
22308
|
-
"build.gradle.kts",
|
|
22309
|
-
"pom.xml"
|
|
22310
|
-
];
|
|
22311
|
-
MAX_SCAN_DEPTH = 5;
|
|
22312
|
-
}
|
|
22313
|
-
});
|
|
22314
|
-
|
|
22315
|
-
// src/core/templates.ts
|
|
22316
|
-
function builtinTemplatesDir() {
|
|
22317
|
-
return path20.resolve(__dirname, "..", "templates");
|
|
22318
|
-
}
|
|
22319
|
-
function loadTemplate(id, globalOverride) {
|
|
22320
|
-
const dirs = templateSearchDirs(globalOverride);
|
|
22321
|
-
for (const dir of dirs) {
|
|
22322
|
-
const filePath = path20.join(dir, `${id}.yaml`);
|
|
22323
|
-
if (pathExists(filePath)) {
|
|
22324
|
-
const raw = readYamlFile(filePath);
|
|
22325
|
-
return { ...TemplateSchema.parse(raw), templateName: id };
|
|
22326
|
-
}
|
|
22327
|
-
}
|
|
22328
|
-
throw new TemplateNotFoundError(id);
|
|
22329
|
-
}
|
|
22330
|
-
function loadAgentOverride(agentId) {
|
|
22331
|
-
const filePath = path20.join(AI_PATHS.root(), "agents", `${agentId}.md`);
|
|
22332
|
-
return readFileOrNull(filePath);
|
|
22333
|
-
}
|
|
22334
|
-
function templateSearchDirs(globalOverride) {
|
|
22335
|
-
return [
|
|
22336
|
-
AI_PATHS.templatesDir(),
|
|
22337
|
-
// 1. project-local
|
|
22338
|
-
globalTemplatesDir(globalOverride),
|
|
22339
|
-
// 2. global user/org
|
|
22340
|
-
builtinTemplatesDir()
|
|
22341
|
-
// 3. built-in fallback
|
|
22342
|
-
];
|
|
22343
|
-
}
|
|
22344
|
-
function renderTemplateInstructions(template, vars) {
|
|
22345
|
-
return template.instructions.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
22346
|
-
return key in vars ? vars[key] : `{{${key}}}`;
|
|
22347
|
-
});
|
|
22348
|
-
}
|
|
22349
|
-
var path20;
|
|
22350
|
-
var init_templates = __esm({
|
|
22351
|
-
"src/core/templates.ts"() {
|
|
22352
|
-
"use strict";
|
|
22353
|
-
path20 = __toESM(require("path"));
|
|
22354
|
-
init_fs();
|
|
22355
|
-
init_yaml();
|
|
22356
|
-
init_errors();
|
|
22357
|
-
init_template();
|
|
22358
|
-
init_paths();
|
|
22359
|
-
init_defaults();
|
|
22360
|
-
}
|
|
22361
|
-
});
|
|
22362
|
-
|
|
22363
22143
|
// src/core/provision.ts
|
|
22364
22144
|
var provision_exports = {};
|
|
22365
22145
|
__export(provision_exports, {
|
|
@@ -22422,7 +22202,7 @@ function provisionProject(name) {
|
|
|
22422
22202
|
function ensureProjectInitialized(fallbackName) {
|
|
22423
22203
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22424
22204
|
const paths = aiPathsAt(getProjectRoot());
|
|
22425
|
-
const hasSystem =
|
|
22205
|
+
const hasSystem = fs15.existsSync(paths.specsSystem());
|
|
22426
22206
|
let name = fallbackName;
|
|
22427
22207
|
if (hasSystem) {
|
|
22428
22208
|
const existing = loadSystemSpec();
|
|
@@ -22444,11 +22224,11 @@ function ensureProjectInitialized(fallbackName) {
|
|
|
22444
22224
|
function walkChainedSubprojects(projectRoot2, onChild) {
|
|
22445
22225
|
const visited = /* @__PURE__ */ new Set();
|
|
22446
22226
|
const walk2 = (dir) => {
|
|
22447
|
-
const resolved =
|
|
22227
|
+
const resolved = path19.resolve(dir);
|
|
22448
22228
|
if (visited.has(resolved)) return;
|
|
22449
22229
|
visited.add(resolved);
|
|
22450
22230
|
const specsDir = aiPathsAt(dir).specsDir();
|
|
22451
|
-
if (!
|
|
22231
|
+
if (!fs15.existsSync(specsDir)) return;
|
|
22452
22232
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
22453
22233
|
let raw;
|
|
22454
22234
|
try {
|
|
@@ -22466,7 +22246,7 @@ function walkChainedSubprojects(projectRoot2, onChild) {
|
|
|
22466
22246
|
continue;
|
|
22467
22247
|
}
|
|
22468
22248
|
const id = raw.id;
|
|
22469
|
-
onChild(childDir, typeof id === "string" ? id :
|
|
22249
|
+
onChild(childDir, typeof id === "string" ? id : path19.basename(childDir));
|
|
22470
22250
|
walk2(childDir);
|
|
22471
22251
|
}
|
|
22472
22252
|
};
|
|
@@ -22475,7 +22255,7 @@ function walkChainedSubprojects(projectRoot2, onChild) {
|
|
|
22475
22255
|
function listDirectChainedSubprojects(projectRoot2) {
|
|
22476
22256
|
const out = [];
|
|
22477
22257
|
const specsDir = aiPathsAt(projectRoot2).specsDir();
|
|
22478
|
-
if (!
|
|
22258
|
+
if (!fs15.existsSync(specsDir)) return out;
|
|
22479
22259
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
22480
22260
|
let raw;
|
|
22481
22261
|
try {
|
|
@@ -22493,12 +22273,12 @@ function listDirectChainedSubprojects(projectRoot2) {
|
|
|
22493
22273
|
continue;
|
|
22494
22274
|
}
|
|
22495
22275
|
const id = raw.id;
|
|
22496
|
-
out.push({ dir, subsystemId: typeof id === "string" ? id :
|
|
22276
|
+
out.push({ dir, subsystemId: typeof id === "string" ? id : path19.basename(dir) });
|
|
22497
22277
|
}
|
|
22498
22278
|
return out;
|
|
22499
22279
|
}
|
|
22500
22280
|
function childHasSpecsButNoConfig(childDir) {
|
|
22501
|
-
return
|
|
22281
|
+
return fs15.existsSync(aiPathsAt(childDir).specsDir()) && !projectConfigRepositoryAt(childDir).exists();
|
|
22502
22282
|
}
|
|
22503
22283
|
function findChainingSubprojectsMissingConfig(projectRoot2) {
|
|
22504
22284
|
const missing = [];
|
|
@@ -22547,14 +22327,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
|
|
|
22547
22327
|
const oldDir = assertContainedProjectPath(root, sub.projectPath);
|
|
22548
22328
|
const newDir = assertContainedProjectPath(root, nextPath);
|
|
22549
22329
|
if (oldDir !== newDir) {
|
|
22550
|
-
if (!
|
|
22330
|
+
if (!fs15.existsSync(oldDir)) {
|
|
22551
22331
|
throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
|
|
22552
22332
|
}
|
|
22553
|
-
if (
|
|
22333
|
+
if (fs15.existsSync(newDir)) {
|
|
22554
22334
|
throw new WaironError(`Target directory already exists: ${newDir}`);
|
|
22555
22335
|
}
|
|
22556
|
-
ensureDir(
|
|
22557
|
-
|
|
22336
|
+
ensureDir(path19.dirname(newDir));
|
|
22337
|
+
fs15.renameSync(oldDir, newDir);
|
|
22558
22338
|
}
|
|
22559
22339
|
saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
22560
22340
|
invalidateSpecCache();
|
|
@@ -22563,9 +22343,9 @@ function toPosixPath(p) {
|
|
|
22563
22343
|
return p.replace(/\\/g, "/");
|
|
22564
22344
|
}
|
|
22565
22345
|
function isWithinDir(dir, file) {
|
|
22566
|
-
const d =
|
|
22567
|
-
const f =
|
|
22568
|
-
return f === d || f.startsWith(d +
|
|
22346
|
+
const d = path19.resolve(dir);
|
|
22347
|
+
const f = path19.resolve(file);
|
|
22348
|
+
return f === d || f.startsWith(d + path19.sep);
|
|
22569
22349
|
}
|
|
22570
22350
|
function externalizeSubsystem(subsystemId, projectPath) {
|
|
22571
22351
|
if (subsystemId.includes("::")) {
|
|
@@ -22577,14 +22357,14 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
22577
22357
|
}
|
|
22578
22358
|
const parentRoot = getProjectRoot();
|
|
22579
22359
|
const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
|
|
22580
|
-
const fooDir =
|
|
22581
|
-
if (!
|
|
22360
|
+
const fooDir = path19.join(parentSpecsDir, subsystemId);
|
|
22361
|
+
if (!fs15.existsSync(fooDir)) {
|
|
22582
22362
|
throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
|
|
22583
22363
|
}
|
|
22584
22364
|
const relPath = toPosixPath(projectPath);
|
|
22585
22365
|
const childDir = assertContainedProjectPath(parentRoot, relPath);
|
|
22586
|
-
const childFooDir =
|
|
22587
|
-
if (
|
|
22366
|
+
const childFooDir = path19.join(childDir, ".wai", "specs", subsystemId);
|
|
22367
|
+
if (fs15.existsSync(childFooDir)) {
|
|
22588
22368
|
throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
|
|
22589
22369
|
}
|
|
22590
22370
|
const renameMap = buildRenameMap(
|
|
@@ -22596,18 +22376,18 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
22596
22376
|
runWithProjectRoot(childDir, () => {
|
|
22597
22377
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22598
22378
|
projectConfigRepository.create(defaultProjectConfig(childSystemName, now));
|
|
22599
|
-
ensureDir(
|
|
22379
|
+
ensureDir(path19.join(childDir, ".wai", "specs"));
|
|
22600
22380
|
saveSystemSpec(bootstrapSystemSpec(childSystemName, now));
|
|
22601
22381
|
});
|
|
22602
|
-
ensureDir(
|
|
22603
|
-
|
|
22382
|
+
ensureDir(path19.dirname(childFooDir));
|
|
22383
|
+
fs15.renameSync(fooDir, childFooDir);
|
|
22604
22384
|
rebaseImplementationPaths(childFooDir, parentRoot, childDir);
|
|
22605
|
-
patchSubsystemIndex(
|
|
22385
|
+
patchSubsystemIndex(path19.join(childFooDir, ".index.yaml"), (s) => {
|
|
22606
22386
|
s.parentSystem = childSystemName;
|
|
22607
22387
|
delete s.projectPath;
|
|
22608
22388
|
});
|
|
22609
22389
|
ensureDir(fooDir);
|
|
22610
|
-
writeYamlFile(
|
|
22390
|
+
writeYamlFile(path19.join(fooDir, ".index.yaml"), {
|
|
22611
22391
|
id: subsystemId,
|
|
22612
22392
|
name: foo.name,
|
|
22613
22393
|
description: foo.description,
|
|
@@ -22634,9 +22414,9 @@ function internalizeSubsystem(subsystemId) {
|
|
|
22634
22414
|
const parentRoot = getProjectRoot();
|
|
22635
22415
|
const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
|
|
22636
22416
|
const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
|
|
22637
|
-
const childWai =
|
|
22638
|
-
const childFooDir =
|
|
22639
|
-
if (!
|
|
22417
|
+
const childWai = path19.join(childDir, ".wai");
|
|
22418
|
+
const childFooDir = path19.join(childDir, ".wai", "specs", subsystemId);
|
|
22419
|
+
if (!fs15.existsSync(childFooDir)) {
|
|
22640
22420
|
throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
|
|
22641
22421
|
}
|
|
22642
22422
|
const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
|
|
@@ -22649,16 +22429,16 @@ function internalizeSubsystem(subsystemId) {
|
|
|
22649
22429
|
false
|
|
22650
22430
|
);
|
|
22651
22431
|
const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
|
|
22652
|
-
const fooDir =
|
|
22653
|
-
|
|
22654
|
-
ensureDir(
|
|
22655
|
-
|
|
22432
|
+
const fooDir = path19.join(parentSpecsDir, subsystemId);
|
|
22433
|
+
fs15.rmSync(fooDir, { recursive: true, force: true });
|
|
22434
|
+
ensureDir(path19.dirname(fooDir));
|
|
22435
|
+
fs15.renameSync(childFooDir, fooDir);
|
|
22656
22436
|
rebaseImplementationPaths(fooDir, childDir, parentRoot);
|
|
22657
|
-
patchSubsystemIndex(
|
|
22437
|
+
patchSubsystemIndex(path19.join(fooDir, ".index.yaml"), (s) => {
|
|
22658
22438
|
s.parentSystem = parentSystemName;
|
|
22659
22439
|
delete s.projectPath;
|
|
22660
22440
|
});
|
|
22661
|
-
|
|
22441
|
+
fs15.rmSync(childWai, { recursive: true, force: true });
|
|
22662
22442
|
rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
|
|
22663
22443
|
rebaseMovedRefs(fooDir, subsystemId, "outOf");
|
|
22664
22444
|
invalidateSpecCache();
|
|
@@ -22736,8 +22516,8 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
|
|
|
22736
22516
|
let changed = false;
|
|
22737
22517
|
const rebase = (holder, key) => {
|
|
22738
22518
|
const p = holder[key];
|
|
22739
|
-
if (typeof p !== "string" || p === "" ||
|
|
22740
|
-
const next = toPosixPath(
|
|
22519
|
+
if (typeof p !== "string" || p === "" || path19.isAbsolute(p)) return;
|
|
22520
|
+
const next = toPosixPath(path19.relative(toRoot, path19.resolve(fromRoot, p)));
|
|
22741
22521
|
if (next !== p) {
|
|
22742
22522
|
holder[key] = next;
|
|
22743
22523
|
changed = true;
|
|
@@ -22753,7 +22533,7 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
|
|
|
22753
22533
|
}
|
|
22754
22534
|
}
|
|
22755
22535
|
function patchSubsystemIndex(indexPath, mutate) {
|
|
22756
|
-
if (!
|
|
22536
|
+
if (!fs15.existsSync(indexPath)) return;
|
|
22757
22537
|
const raw = readYamlFile(indexPath);
|
|
22758
22538
|
mutate(raw);
|
|
22759
22539
|
raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -22814,8 +22594,8 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
22814
22594
|
if (movedInterface) saveInterfaceSpec({ ...movedInterface, id: interfaceId, component: newId });
|
|
22815
22595
|
if (movedImplementation) {
|
|
22816
22596
|
const oldFile = getImplementationPath(movedImplementation.id);
|
|
22817
|
-
if (
|
|
22818
|
-
|
|
22597
|
+
if (path19.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path19.resolve(oldFile)) {
|
|
22598
|
+
fs15.unlinkSync(oldFile);
|
|
22819
22599
|
}
|
|
22820
22600
|
saveImplementationSpec({ ...movedImplementation, id: implementationId });
|
|
22821
22601
|
}
|
|
@@ -22825,17 +22605,17 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
22825
22605
|
invalidateSpecCache();
|
|
22826
22606
|
}
|
|
22827
22607
|
function removeSpecFile2(file, id) {
|
|
22828
|
-
if (!
|
|
22608
|
+
if (!fs15.existsSync(file)) return;
|
|
22829
22609
|
try {
|
|
22830
22610
|
if (readYamlFile(file)?.id !== id) return;
|
|
22831
22611
|
} catch {
|
|
22832
22612
|
return;
|
|
22833
22613
|
}
|
|
22834
|
-
|
|
22835
|
-
const specsRoot =
|
|
22836
|
-
for (let dir =
|
|
22837
|
-
if (
|
|
22838
|
-
|
|
22614
|
+
fs15.unlinkSync(file);
|
|
22615
|
+
const specsRoot = path19.resolve(aiPathsAt(getProjectRoot()).specsDir());
|
|
22616
|
+
for (let dir = path19.dirname(path19.resolve(file)); dir !== specsRoot && isWithinDir(specsRoot, dir); dir = path19.dirname(dir)) {
|
|
22617
|
+
if (fs15.readdirSync(dir).length > 0) break;
|
|
22618
|
+
fs15.rmdirSync(dir);
|
|
22839
22619
|
}
|
|
22840
22620
|
}
|
|
22841
22621
|
function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
@@ -22932,12 +22712,12 @@ function collectMentions(specsDir, methodName, moved) {
|
|
|
22932
22712
|
function identifierPattern(methodName) {
|
|
22933
22713
|
return new RegExp(`(?<![A-Za-z0-9_])${methodName}(?![A-Za-z0-9_])`);
|
|
22934
22714
|
}
|
|
22935
|
-
var
|
|
22715
|
+
var fs15, path19, METHOD_NAME, PROSE_FIELDS2;
|
|
22936
22716
|
var init_provision = __esm({
|
|
22937
22717
|
"src/core/provision.ts"() {
|
|
22938
22718
|
"use strict";
|
|
22939
|
-
|
|
22940
|
-
|
|
22719
|
+
fs15 = __toESM(require("fs"));
|
|
22720
|
+
path19 = __toESM(require("path"));
|
|
22941
22721
|
init_specs2();
|
|
22942
22722
|
init_paths();
|
|
22943
22723
|
init_project_config();
|
|
@@ -22960,6 +22740,223 @@ var init_provision = __esm({
|
|
|
22960
22740
|
}
|
|
22961
22741
|
});
|
|
22962
22742
|
|
|
22743
|
+
// src/core/detection.ts
|
|
22744
|
+
function detectDomainCandidates(projectRoot2, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
|
|
22745
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
22746
|
+
for (const c of detectGitSubmodules(projectRoot2)) {
|
|
22747
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22748
|
+
}
|
|
22749
|
+
for (const c of detectNestedGitRepos(projectRoot2)) {
|
|
22750
|
+
if (!candidates.has(c.path)) {
|
|
22751
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22752
|
+
}
|
|
22753
|
+
}
|
|
22754
|
+
const gitPaths = new Set(
|
|
22755
|
+
Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
|
|
22756
|
+
);
|
|
22757
|
+
for (const c of detectPackageRoots(projectRoot2)) {
|
|
22758
|
+
if (candidates.has(c.path)) continue;
|
|
22759
|
+
const insideGit = Array.from(gitPaths).some(
|
|
22760
|
+
(gp) => c.path === gp || c.path.startsWith(gp + "/")
|
|
22761
|
+
);
|
|
22762
|
+
if (insideGit) continue;
|
|
22763
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22764
|
+
}
|
|
22765
|
+
const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
|
|
22766
|
+
return deduplicateIds(sorted, alreadyTrackedIds);
|
|
22767
|
+
}
|
|
22768
|
+
function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
|
|
22769
|
+
const idCount = /* @__PURE__ */ new Map();
|
|
22770
|
+
for (const id of existingIds) {
|
|
22771
|
+
idCount.set(id, (idCount.get(id) ?? 0) + 1);
|
|
22772
|
+
}
|
|
22773
|
+
for (const c of candidates) {
|
|
22774
|
+
idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
|
|
22775
|
+
}
|
|
22776
|
+
return candidates.map((c) => {
|
|
22777
|
+
if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
|
|
22778
|
+
const parts = c.path.split("/");
|
|
22779
|
+
const qualifiedId2 = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
|
|
22780
|
+
return { ...c, suggestedId: qualifiedId2 };
|
|
22781
|
+
});
|
|
22782
|
+
}
|
|
22783
|
+
function parseGitmodules(filePath) {
|
|
22784
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
22785
|
+
const entries = [];
|
|
22786
|
+
let current2 = {};
|
|
22787
|
+
for (const line2 of content.split("\n")) {
|
|
22788
|
+
const trimmed = line2.trim();
|
|
22789
|
+
const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
|
|
22790
|
+
if (headerMatch) {
|
|
22791
|
+
if (current2.path) entries.push(current2);
|
|
22792
|
+
current2 = { name: headerMatch[1] };
|
|
22793
|
+
continue;
|
|
22794
|
+
}
|
|
22795
|
+
const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
|
|
22796
|
+
if (keyVal) {
|
|
22797
|
+
const [, key, value] = keyVal;
|
|
22798
|
+
if (key === "path") current2.path = value.trim();
|
|
22799
|
+
if (key === "url") current2.url = value.trim();
|
|
22800
|
+
}
|
|
22801
|
+
}
|
|
22802
|
+
if (current2.path) entries.push(current2);
|
|
22803
|
+
return entries;
|
|
22804
|
+
}
|
|
22805
|
+
function detectGitSubmodules(projectRoot2) {
|
|
22806
|
+
const gitmodulesPath = path20.join(projectRoot2, ".gitmodules");
|
|
22807
|
+
if (!fs16.existsSync(gitmodulesPath)) return [];
|
|
22808
|
+
return parseGitmodules(gitmodulesPath).map((entry) => ({
|
|
22809
|
+
suggestedId: pathToId(entry.path),
|
|
22810
|
+
suggestedName: pathToName(entry.path),
|
|
22811
|
+
path: normalizePath(entry.path),
|
|
22812
|
+
type: "git-submodule",
|
|
22813
|
+
alreadyTracked: false
|
|
22814
|
+
}));
|
|
22815
|
+
}
|
|
22816
|
+
function detectNestedGitRepos(projectRoot2) {
|
|
22817
|
+
const results = [];
|
|
22818
|
+
walkForGit(projectRoot2, projectRoot2, 0, results);
|
|
22819
|
+
return results;
|
|
22820
|
+
}
|
|
22821
|
+
function walkForGit(projectRoot2, currentDir, depth, results) {
|
|
22822
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
22823
|
+
let entries;
|
|
22824
|
+
try {
|
|
22825
|
+
entries = fs16.readdirSync(currentDir, { withFileTypes: true });
|
|
22826
|
+
} catch {
|
|
22827
|
+
return;
|
|
22828
|
+
}
|
|
22829
|
+
for (const entry of entries) {
|
|
22830
|
+
if (!entry.isDirectory()) continue;
|
|
22831
|
+
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22832
|
+
const fullPath = path20.join(currentDir, entry.name);
|
|
22833
|
+
const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
|
|
22834
|
+
if (relPath === "" || relPath === ".") continue;
|
|
22835
|
+
const gitPath = path20.join(fullPath, ".git");
|
|
22836
|
+
if (fs16.existsSync(gitPath)) {
|
|
22837
|
+
results.push({
|
|
22838
|
+
suggestedId: pathToId(relPath),
|
|
22839
|
+
suggestedName: pathToName(relPath),
|
|
22840
|
+
path: relPath,
|
|
22841
|
+
type: "git-repo",
|
|
22842
|
+
alreadyTracked: false
|
|
22843
|
+
});
|
|
22844
|
+
continue;
|
|
22845
|
+
}
|
|
22846
|
+
walkForGit(projectRoot2, fullPath, depth + 1, results);
|
|
22847
|
+
}
|
|
22848
|
+
}
|
|
22849
|
+
function detectPackageRoots(projectRoot2) {
|
|
22850
|
+
const results = [];
|
|
22851
|
+
walkForPackages(projectRoot2, projectRoot2, 0, results);
|
|
22852
|
+
return results;
|
|
22853
|
+
}
|
|
22854
|
+
function walkForPackages(projectRoot2, currentDir, depth, results) {
|
|
22855
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
22856
|
+
let entries;
|
|
22857
|
+
try {
|
|
22858
|
+
entries = fs16.readdirSync(currentDir, { withFileTypes: true });
|
|
22859
|
+
} catch {
|
|
22860
|
+
return;
|
|
22861
|
+
}
|
|
22862
|
+
for (const entry of entries) {
|
|
22863
|
+
if (!entry.isDirectory()) continue;
|
|
22864
|
+
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22865
|
+
const fullPath = path20.join(currentDir, entry.name);
|
|
22866
|
+
const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
|
|
22867
|
+
if (relPath === "" || relPath === ".") continue;
|
|
22868
|
+
const hasMarker = PACKAGE_MARKERS.some((m) => fs16.existsSync(path20.join(fullPath, m)));
|
|
22869
|
+
if (hasMarker) {
|
|
22870
|
+
results.push({
|
|
22871
|
+
suggestedId: pathToId(relPath),
|
|
22872
|
+
suggestedName: pathToName(relPath),
|
|
22873
|
+
path: relPath,
|
|
22874
|
+
type: "package-root",
|
|
22875
|
+
alreadyTracked: false
|
|
22876
|
+
});
|
|
22877
|
+
}
|
|
22878
|
+
walkForPackages(projectRoot2, fullPath, depth + 1, results);
|
|
22879
|
+
}
|
|
22880
|
+
}
|
|
22881
|
+
function pathToId(relPath) {
|
|
22882
|
+
const basename15 = path20.basename(relPath);
|
|
22883
|
+
return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
22884
|
+
}
|
|
22885
|
+
function pathToName(relPath) {
|
|
22886
|
+
const id = pathToId(relPath);
|
|
22887
|
+
return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
22888
|
+
}
|
|
22889
|
+
function normalizePath(p) {
|
|
22890
|
+
return p.replace(/\\/g, "/");
|
|
22891
|
+
}
|
|
22892
|
+
var fs16, path20, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
|
|
22893
|
+
var init_detection = __esm({
|
|
22894
|
+
"src/core/detection.ts"() {
|
|
22895
|
+
"use strict";
|
|
22896
|
+
fs16 = __toESM(require("fs"));
|
|
22897
|
+
path20 = __toESM(require("path"));
|
|
22898
|
+
init_defaults();
|
|
22899
|
+
PACKAGE_MARKERS = [
|
|
22900
|
+
"package.json",
|
|
22901
|
+
"pyproject.toml",
|
|
22902
|
+
"Cargo.toml",
|
|
22903
|
+
"go.mod",
|
|
22904
|
+
"build.gradle",
|
|
22905
|
+
"build.gradle.kts",
|
|
22906
|
+
"pom.xml"
|
|
22907
|
+
];
|
|
22908
|
+
MAX_SCAN_DEPTH = 5;
|
|
22909
|
+
}
|
|
22910
|
+
});
|
|
22911
|
+
|
|
22912
|
+
// src/core/templates.ts
|
|
22913
|
+
function builtinTemplatesDir() {
|
|
22914
|
+
return path21.resolve(__dirname, "..", "templates");
|
|
22915
|
+
}
|
|
22916
|
+
function loadTemplate(id, globalOverride) {
|
|
22917
|
+
const dirs = templateSearchDirs(globalOverride);
|
|
22918
|
+
for (const dir of dirs) {
|
|
22919
|
+
const filePath = path21.join(dir, `${id}.yaml`);
|
|
22920
|
+
if (pathExists(filePath)) {
|
|
22921
|
+
const raw = readYamlFile(filePath);
|
|
22922
|
+
return { ...TemplateSchema.parse(raw), templateName: id };
|
|
22923
|
+
}
|
|
22924
|
+
}
|
|
22925
|
+
throw new TemplateNotFoundError(id);
|
|
22926
|
+
}
|
|
22927
|
+
function loadAgentOverride(agentId) {
|
|
22928
|
+
const filePath = path21.join(AI_PATHS.root(), "agents", `${agentId}.md`);
|
|
22929
|
+
return readFileOrNull(filePath);
|
|
22930
|
+
}
|
|
22931
|
+
function templateSearchDirs(globalOverride) {
|
|
22932
|
+
return [
|
|
22933
|
+
AI_PATHS.templatesDir(),
|
|
22934
|
+
// 1. project-local
|
|
22935
|
+
globalTemplatesDir(globalOverride),
|
|
22936
|
+
// 2. global user/org
|
|
22937
|
+
builtinTemplatesDir()
|
|
22938
|
+
// 3. built-in fallback
|
|
22939
|
+
];
|
|
22940
|
+
}
|
|
22941
|
+
function renderTemplateInstructions(template, vars) {
|
|
22942
|
+
return template.instructions.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
22943
|
+
return key in vars ? vars[key] : `{{${key}}}`;
|
|
22944
|
+
});
|
|
22945
|
+
}
|
|
22946
|
+
var path21;
|
|
22947
|
+
var init_templates = __esm({
|
|
22948
|
+
"src/core/templates.ts"() {
|
|
22949
|
+
"use strict";
|
|
22950
|
+
path21 = __toESM(require("path"));
|
|
22951
|
+
init_fs();
|
|
22952
|
+
init_yaml();
|
|
22953
|
+
init_errors();
|
|
22954
|
+
init_template();
|
|
22955
|
+
init_paths();
|
|
22956
|
+
init_defaults();
|
|
22957
|
+
}
|
|
22958
|
+
});
|
|
22959
|
+
|
|
22963
22960
|
// src/core/execution_profile.ts
|
|
22964
22961
|
function isSweeping(p) {
|
|
22965
22962
|
return p === "**" || p === "**/*" || p.startsWith("**/");
|
|
@@ -23503,326 +23500,267 @@ var init_agent_resolver = __esm({
|
|
|
23503
23500
|
}
|
|
23504
23501
|
});
|
|
23505
23502
|
|
|
23506
|
-
// src/
|
|
23507
|
-
function
|
|
23508
|
-
|
|
23509
|
-
|
|
23510
|
-
|
|
23511
|
-
return
|
|
23503
|
+
// src/exporters/claude.ts
|
|
23504
|
+
function toolsFor(budget) {
|
|
23505
|
+
const base = TOOLS_BY_CLASS[budget.toolClass];
|
|
23506
|
+
if (!base) return void 0;
|
|
23507
|
+
if (budget.allowNestedDelegation && !base.includes("Agent")) {
|
|
23508
|
+
return [...base, "Agent"];
|
|
23509
|
+
}
|
|
23510
|
+
if (!budget.allowNestedDelegation) {
|
|
23511
|
+
return base.filter((t) => t !== "Agent");
|
|
23512
23512
|
}
|
|
23513
|
+
return base;
|
|
23513
23514
|
}
|
|
23514
|
-
function
|
|
23515
|
-
|
|
23516
|
-
return profile !== null && block.profile.includes(profile);
|
|
23515
|
+
function mcpServersFor(access) {
|
|
23516
|
+
return access === "none" ? "[]" : void 0;
|
|
23517
23517
|
}
|
|
23518
|
-
function
|
|
23519
|
-
|
|
23520
|
-
return skills.map((s) => `- \`${s.resourceUri}\` \u2014 ${s.description || s.name}`).join("\n");
|
|
23518
|
+
function yamlScalar(value) {
|
|
23519
|
+
return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
|
|
23521
23520
|
}
|
|
23522
|
-
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
|
|
23554
|
-
|
|
23555
|
-
|
|
23556
|
-
|
|
23557
|
-
|
|
23558
|
-
|
|
23559
|
-
|
|
23560
|
-
|
|
23561
|
-
|
|
23562
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
additional conformance rules. Their doctrine is enforced by the same gate.`}
|
|
23575
|
-
|
|
23576
|
-
${variants.length === 0 ? "" : `## Component variants in play
|
|
23577
|
-
|
|
23578
|
-
This project defines variants \u2014 named, base-anchored kinds carrying implementation
|
|
23579
|
-
guidance, so every component of the same kind is built alike: ${variants.map((v) => `\`${v.id}\` (a kind of ${v.base})`).join(", ")}.
|
|
23580
|
-
Tag a component with \`variant\` where it fits, and read a component's resolved
|
|
23581
|
-
guidance and its same-variant siblings from \`sdd_get_spec\` (kind: component).
|
|
23582
|
-
|
|
23583
|
-
`}## Read the skills BEFORE authoring
|
|
23584
|
-
|
|
23585
|
-
This server publishes its skills as MCP resources. **Read \`wairon-skill://sdd-architect\`
|
|
23586
|
-
before you design anything**, and the others when their turn comes \u2014 they carry the
|
|
23587
|
-
architecture standard, the narrative step reference, and the review checklist that
|
|
23588
|
-
this briefing only points at:
|
|
23589
|
-
|
|
23590
|
-
${skillPointers(skills)}
|
|
23591
|
-
|
|
23592
|
-
## Delegating implementation
|
|
23521
|
+
var path23, MODEL_BY_TIER, TOOLS_BY_CLASS, ClaudeExporter;
|
|
23522
|
+
var init_claude = __esm({
|
|
23523
|
+
"src/exporters/claude.ts"() {
|
|
23524
|
+
"use strict";
|
|
23525
|
+
path23 = __toESM(require("path"));
|
|
23526
|
+
init_fs();
|
|
23527
|
+
MODEL_BY_TIER = {
|
|
23528
|
+
small: "haiku",
|
|
23529
|
+
standard: "sonnet",
|
|
23530
|
+
large: "opus",
|
|
23531
|
+
frontier: "fable"
|
|
23532
|
+
};
|
|
23533
|
+
TOOLS_BY_CLASS = {
|
|
23534
|
+
"read-only": ["Read", "Grep", "Glob"],
|
|
23535
|
+
implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
|
|
23536
|
+
orchestrate: ["Agent", "SendMessage", "TodoWrite"],
|
|
23537
|
+
// `full` means "inherit everything" — expressed by omitting the field.
|
|
23538
|
+
full: void 0
|
|
23539
|
+
};
|
|
23540
|
+
ClaudeExporter = class {
|
|
23541
|
+
constructor(options = {}) {
|
|
23542
|
+
this.options = options;
|
|
23543
|
+
this.targetType = "claude";
|
|
23544
|
+
}
|
|
23545
|
+
outputPath(ctx) {
|
|
23546
|
+
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
23547
|
+
const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
|
|
23548
|
+
return path23.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
23549
|
+
}
|
|
23550
|
+
export(ctx) {
|
|
23551
|
+
const { agent, renderedInstructions, budget } = ctx;
|
|
23552
|
+
const filePath = this.outputPath(ctx);
|
|
23553
|
+
const frontmatter = [
|
|
23554
|
+
`name: ${agent.name}`,
|
|
23555
|
+
`description: ${yamlScalar(agent.description)}`
|
|
23556
|
+
];
|
|
23557
|
+
if (budget && this.options.emitBudget) {
|
|
23558
|
+
if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
|
|
23559
|
+
if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
|
|
23560
|
+
if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
|
|
23561
|
+
const tools = toolsFor(budget);
|
|
23562
|
+
if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
|
|
23563
|
+
const servers = mcpServersFor(budget.mcp);
|
|
23564
|
+
if (servers) frontmatter.push(`mcpServers: ${servers}`);
|
|
23565
|
+
}
|
|
23566
|
+
const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
|
|
23567
|
+
const changed = writeFileIfChanged(filePath, content);
|
|
23568
|
+
return { outputPath: filePath, content, unchanged: !changed };
|
|
23569
|
+
}
|
|
23570
|
+
};
|
|
23571
|
+
}
|
|
23572
|
+
});
|
|
23593
23573
|
|
|
23594
|
-
|
|
23595
|
-
|
|
23596
|
-
|
|
23597
|
-
|
|
23598
|
-
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
|
|
23603
|
-
|
|
23604
|
-
|
|
23605
|
-
|
|
23606
|
-
|
|
23607
|
-
|
|
23608
|
-
|
|
23609
|
-
|
|
23610
|
-
|
|
23611
|
-
|
|
23612
|
-
|
|
23613
|
-
|
|
23574
|
+
// src/exporters/custom.ts
|
|
23575
|
+
var path24, CustomExporter;
|
|
23576
|
+
var init_custom = __esm({
|
|
23577
|
+
"src/exporters/custom.ts"() {
|
|
23578
|
+
"use strict";
|
|
23579
|
+
path24 = __toESM(require("path"));
|
|
23580
|
+
init_fs();
|
|
23581
|
+
CustomExporter = class {
|
|
23582
|
+
constructor() {
|
|
23583
|
+
this.targetType = "custom";
|
|
23584
|
+
}
|
|
23585
|
+
outputPath(ctx) {
|
|
23586
|
+
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
23587
|
+
if (!("outputDir" in target)) {
|
|
23588
|
+
throw new Error("CustomExporter requires target.outputDir");
|
|
23589
|
+
}
|
|
23590
|
+
return path24.resolve(projectRoot2, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
23591
|
+
}
|
|
23592
|
+
export(ctx) {
|
|
23593
|
+
const { agent, target, renderedInstructions } = ctx;
|
|
23594
|
+
const label = "label" in target ? target.label : "Custom";
|
|
23595
|
+
const filePath = this.outputPath(ctx);
|
|
23596
|
+
const content = [
|
|
23597
|
+
"---",
|
|
23598
|
+
`name: ${agent.name}`,
|
|
23599
|
+
`description: ${agent.description}`,
|
|
23600
|
+
`id: ${agent.id}`,
|
|
23601
|
+
`target: ${label}`,
|
|
23602
|
+
"---",
|
|
23603
|
+
"",
|
|
23604
|
+
renderedInstructions,
|
|
23605
|
+
""
|
|
23606
|
+
].join("\n");
|
|
23607
|
+
const changed = writeFileIfChanged(filePath, content);
|
|
23608
|
+
return { outputPath: filePath, content, unchanged: !changed };
|
|
23609
|
+
}
|
|
23610
|
+
};
|
|
23614
23611
|
}
|
|
23615
|
-
|
|
23616
|
-
for (const block of blocks) {
|
|
23617
|
-
if (!blockApplies(block, profile)) continue;
|
|
23618
|
-
sections.push(`## From pack "${block.pack}"
|
|
23612
|
+
});
|
|
23619
23613
|
|
|
23620
|
-
|
|
23614
|
+
// src/exporters/gemini.ts
|
|
23615
|
+
function yamlString(value) {
|
|
23616
|
+
if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
|
|
23617
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
23621
23618
|
}
|
|
23622
|
-
return
|
|
23619
|
+
return value;
|
|
23623
23620
|
}
|
|
23624
|
-
var
|
|
23625
|
-
|
|
23621
|
+
var path25, GeminiExporter;
|
|
23622
|
+
var init_gemini = __esm({
|
|
23623
|
+
"src/exporters/gemini.ts"() {
|
|
23626
23624
|
"use strict";
|
|
23627
|
-
|
|
23625
|
+
path25 = __toESM(require("path"));
|
|
23626
|
+
init_fs();
|
|
23627
|
+
GeminiExporter = class {
|
|
23628
|
+
constructor() {
|
|
23629
|
+
this.targetType = "gemini";
|
|
23630
|
+
}
|
|
23631
|
+
outputPath(ctx) {
|
|
23632
|
+
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
23633
|
+
const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
|
|
23634
|
+
return path25.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
|
|
23635
|
+
}
|
|
23636
|
+
export(ctx) {
|
|
23637
|
+
const { agent, renderedInstructions } = ctx;
|
|
23638
|
+
const filePath = this.outputPath(ctx);
|
|
23639
|
+
const indentedInstructions = renderedInstructions.split("\n").map((line2) => line2.length > 0 ? ` ${line2}` : "").join("\n");
|
|
23640
|
+
const content = [
|
|
23641
|
+
`name: ${yamlString(agent.name)}`,
|
|
23642
|
+
`description: ${yamlString(agent.description)}`,
|
|
23643
|
+
`system_prompt: |`,
|
|
23644
|
+
indentedInstructions,
|
|
23645
|
+
""
|
|
23646
|
+
].join("\n");
|
|
23647
|
+
const changed = writeFileIfChanged(filePath, content);
|
|
23648
|
+
return { outputPath: filePath, content, unchanged: !changed };
|
|
23649
|
+
}
|
|
23650
|
+
};
|
|
23628
23651
|
}
|
|
23629
23652
|
});
|
|
23630
23653
|
|
|
23631
|
-
// src/
|
|
23632
|
-
function
|
|
23633
|
-
|
|
23634
|
-
|
|
23635
|
-
|
|
23636
|
-
|
|
23637
|
-
}
|
|
23638
|
-
function packSkillId(skill) {
|
|
23639
|
-
return `${packNamespace(skill.pack)}-${skill.id}`;
|
|
23640
|
-
}
|
|
23641
|
-
function packNamespace(pack) {
|
|
23642
|
-
return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
23643
|
-
}
|
|
23644
|
-
function extensionsFor(builtin, packSkills) {
|
|
23645
|
-
return packSkills.filter((s) => s.extends === builtin && fs18.existsSync(s.sourcePath));
|
|
23646
|
-
}
|
|
23647
|
-
function composeBuiltinSkill(name, packSkills) {
|
|
23648
|
-
const srcPath = skillTemplatePath(name);
|
|
23649
|
-
const base = fs18.existsSync(srcPath) ? fs18.readFileSync(srcPath, "utf-8") : "";
|
|
23650
|
-
const sections = extensionsFor(name, packSkills);
|
|
23651
|
-
if (sections.length === 0) return base;
|
|
23652
|
-
const parts = [base.trimEnd()];
|
|
23653
|
-
for (const section of sections) {
|
|
23654
|
-
const body = fs18.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
|
|
23655
|
-
parts.push(`## Platform: ${section.pack}`, body.trim());
|
|
23654
|
+
// src/exporters/registry.ts
|
|
23655
|
+
function getExporter(target) {
|
|
23656
|
+
const type = typeof target === "string" ? target : target.type;
|
|
23657
|
+
const exporter = EXPORTERS.get(type);
|
|
23658
|
+
if (!exporter) {
|
|
23659
|
+
throw new WaironError(`No exporter registered for target type: "${type}"`);
|
|
23656
23660
|
}
|
|
23657
|
-
return
|
|
23658
|
-
`;
|
|
23659
|
-
}
|
|
23660
|
-
function readFrontmatter(raw, fallbackName) {
|
|
23661
|
-
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
23662
|
-
const block = match ? match[1] : "";
|
|
23663
|
-
const field = (key) => {
|
|
23664
|
-
const m = new RegExp(`^${key}:\\s*(.*)$`, "m").exec(block);
|
|
23665
|
-
return m ? m[1].trim() : "";
|
|
23666
|
-
};
|
|
23667
|
-
return { name: field("name") || fallbackName, description: field("description") };
|
|
23668
|
-
}
|
|
23669
|
-
function builtinSkillsDir() {
|
|
23670
|
-
return path23.resolve(__dirname, "..", "templates", "skills");
|
|
23671
|
-
}
|
|
23672
|
-
function skillTemplatePath(name) {
|
|
23673
|
-
return path23.join(builtinSkillsDir(), `${name}.md`);
|
|
23661
|
+
return exporter;
|
|
23674
23662
|
}
|
|
23675
|
-
|
|
23676
|
-
|
|
23677
|
-
|
|
23663
|
+
var EXPORTERS;
|
|
23664
|
+
var init_registry2 = __esm({
|
|
23665
|
+
"src/exporters/registry.ts"() {
|
|
23666
|
+
"use strict";
|
|
23667
|
+
init_claude();
|
|
23668
|
+
init_custom();
|
|
23669
|
+
init_gemini();
|
|
23670
|
+
init_errors();
|
|
23671
|
+
EXPORTERS = /* @__PURE__ */ new Map([
|
|
23672
|
+
["claude", new ClaudeExporter({ emitBudget: true })],
|
|
23673
|
+
["gemini", new GeminiExporter()],
|
|
23674
|
+
["agy", new GeminiExporter()],
|
|
23675
|
+
["cursor", new ClaudeExporter()],
|
|
23676
|
+
["copilot", new ClaudeExporter()],
|
|
23677
|
+
["codex", new ClaudeExporter()],
|
|
23678
|
+
["custom", new CustomExporter()]
|
|
23679
|
+
]);
|
|
23678
23680
|
}
|
|
23679
|
-
|
|
23680
|
-
|
|
23681
|
-
|
|
23682
|
-
|
|
23683
|
-
|
|
23684
|
-
|
|
23685
|
-
|
|
23686
|
-
|
|
23687
|
-
|
|
23688
|
-
case "codex":
|
|
23689
|
-
return fromProjectRoot(".agents", "skills");
|
|
23690
|
-
case "cursor":
|
|
23691
|
-
return fromProjectRoot(".cursor", "skills");
|
|
23692
|
-
default:
|
|
23693
|
-
return null;
|
|
23681
|
+
});
|
|
23682
|
+
|
|
23683
|
+
// src/exporters/base.ts
|
|
23684
|
+
var WAIRON_MANAGED_MARKER, WAIRON_MANAGED_BANNER;
|
|
23685
|
+
var init_base = __esm({
|
|
23686
|
+
"src/exporters/base.ts"() {
|
|
23687
|
+
"use strict";
|
|
23688
|
+
WAIRON_MANAGED_MARKER = "wairon:managed";
|
|
23689
|
+
WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
|
|
23694
23690
|
}
|
|
23695
|
-
}
|
|
23696
|
-
|
|
23697
|
-
|
|
23698
|
-
}
|
|
23699
|
-
|
|
23700
|
-
const
|
|
23701
|
-
const
|
|
23702
|
-
|
|
23703
|
-
|
|
23704
|
-
const
|
|
23705
|
-
|
|
23706
|
-
|
|
23707
|
-
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23714
|
-
if (!
|
|
23715
|
-
const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
|
|
23716
|
-
const destPath = skillDestPath(type, destDir, name);
|
|
23717
|
-
ensureDir(path23.dirname(destPath));
|
|
23718
|
-
fs18.writeFileSync(destPath, content, "utf-8");
|
|
23719
|
-
fileCount++;
|
|
23691
|
+
});
|
|
23692
|
+
|
|
23693
|
+
// src/exporters/generate.ts
|
|
23694
|
+
function generateAgent(agent, projectConfig, options = {}) {
|
|
23695
|
+
const projectRoot2 = options.projectRoot ?? getProjectRoot();
|
|
23696
|
+
const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
|
|
23697
|
+
const rendered = `${WAIRON_MANAGED_BANNER}
|
|
23698
|
+
${composeAgentBrief(agent.id).instructions}`;
|
|
23699
|
+
const results = [];
|
|
23700
|
+
const budget = resolveBudget(
|
|
23701
|
+
deriveExecutionProfile(agent),
|
|
23702
|
+
projectConfig.execution,
|
|
23703
|
+
agent.id
|
|
23704
|
+
);
|
|
23705
|
+
for (const agentTarget of agent.targets) {
|
|
23706
|
+
const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
|
|
23707
|
+
if (!targetConfig) continue;
|
|
23708
|
+
if (options.filterTargets) {
|
|
23709
|
+
const type = "type" in targetConfig ? targetConfig.type : targetConfig;
|
|
23710
|
+
if (!options.filterTargets.includes(type)) continue;
|
|
23720
23711
|
}
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23724
|
-
|
|
23725
|
-
|
|
23726
|
-
|
|
23727
|
-
|
|
23728
|
-
|
|
23729
|
-
|
|
23730
|
-
fileCount++;
|
|
23712
|
+
if (!options.dryRun) {
|
|
23713
|
+
results.push(getExporter(targetConfig).export({
|
|
23714
|
+
agent,
|
|
23715
|
+
template,
|
|
23716
|
+
renderedInstructions: rendered,
|
|
23717
|
+
projectRoot: projectRoot2,
|
|
23718
|
+
target: targetConfig,
|
|
23719
|
+
budget
|
|
23720
|
+
}));
|
|
23731
23721
|
}
|
|
23732
23722
|
}
|
|
23733
|
-
return {
|
|
23723
|
+
return { agent, results };
|
|
23734
23724
|
}
|
|
23735
|
-
function
|
|
23736
|
-
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
for (const name of SKILL_NAMES) {
|
|
23741
|
-
const destPath = skillDestPath(type, dir, name);
|
|
23742
|
-
if (!fs18.existsSync(destPath)) {
|
|
23743
|
-
result.missing.push(name);
|
|
23744
|
-
continue;
|
|
23745
|
-
}
|
|
23746
|
-
const want = composeBuiltinSkill(name, packSkills);
|
|
23747
|
-
const have = fs18.readFileSync(destPath, "utf-8");
|
|
23748
|
-
if (have === want) result.ok.push(name);
|
|
23749
|
-
else result.stale.push(name);
|
|
23725
|
+
function generateAll(agents, projectConfig, options = {}) {
|
|
23726
|
+
let pool = agents;
|
|
23727
|
+
if (options.filterDomainIds && options.filterDomainIds.length > 0) {
|
|
23728
|
+
const ids = new Set(options.filterDomainIds);
|
|
23729
|
+
pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
|
|
23750
23730
|
}
|
|
23751
|
-
return
|
|
23752
|
-
}
|
|
23753
|
-
function activeTargetTypes2() {
|
|
23754
|
-
const config = loadProjectConfig3();
|
|
23755
|
-
if (!config) return [];
|
|
23756
|
-
return activeTargetTypes(config);
|
|
23731
|
+
return pool.map((agent) => generateAgent(agent, projectConfig, options));
|
|
23757
23732
|
}
|
|
23758
|
-
function
|
|
23759
|
-
|
|
23733
|
+
function resolveExpectedOutputPaths(agents, projectConfig, projectRoot2 = getProjectRoot()) {
|
|
23734
|
+
const expected = /* @__PURE__ */ new Set();
|
|
23735
|
+
for (const agent of agents) {
|
|
23736
|
+
for (const agentTarget of agent.targets) {
|
|
23737
|
+
const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
|
|
23738
|
+
if (!targetConfig) continue;
|
|
23739
|
+
const ctx = { agent, projectRoot: projectRoot2, target: targetConfig };
|
|
23740
|
+
expected.add(path26.resolve(getExporter(targetConfig).outputPath(ctx)));
|
|
23741
|
+
}
|
|
23742
|
+
}
|
|
23743
|
+
return expected;
|
|
23760
23744
|
}
|
|
23761
|
-
function
|
|
23762
|
-
const
|
|
23763
|
-
|
|
23764
|
-
return
|
|
23765
|
-
|
|
23766
|
-
name: fm.name,
|
|
23767
|
-
description: fm.description,
|
|
23768
|
-
version: WAIRON_VERSION,
|
|
23769
|
-
resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
|
|
23770
|
-
defaultForHostedMcp: true
|
|
23771
|
-
};
|
|
23772
|
-
});
|
|
23773
|
-
const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs18.existsSync(s.sourcePath)).map((skill) => {
|
|
23774
|
-
const id = packSkillId(skill);
|
|
23775
|
-
const fm = readFrontmatter(fs18.readFileSync(skill.sourcePath, "utf-8"), id);
|
|
23776
|
-
return {
|
|
23777
|
-
id,
|
|
23778
|
-
name: fm.name,
|
|
23779
|
-
description: fm.description,
|
|
23780
|
-
version: skill.packVersion ?? WAIRON_VERSION,
|
|
23781
|
-
resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
|
|
23782
|
-
defaultForHostedMcp: true
|
|
23783
|
-
};
|
|
23745
|
+
function resolveTargetConfig(agentTarget, projectConfig) {
|
|
23746
|
+
const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
|
|
23747
|
+
return projectConfig.targets.find((t) => {
|
|
23748
|
+
if (typeof t === "string") return t === targetType;
|
|
23749
|
+
return t.type === targetType;
|
|
23784
23750
|
});
|
|
23785
|
-
return [...builtin, ...pack];
|
|
23786
|
-
}
|
|
23787
|
-
function readSkillResource(resourceId) {
|
|
23788
|
-
const packSkills = loadProjectExtensions2().skills;
|
|
23789
|
-
if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
|
|
23790
|
-
const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
|
|
23791
|
-
if (packSkill) return fs18.readFileSync(packSkill.sourcePath, "utf-8");
|
|
23792
|
-
return fs18.readFileSync(skillTemplatePath(resourceId), "utf-8");
|
|
23793
23751
|
}
|
|
23794
|
-
|
|
23795
|
-
|
|
23796
|
-
|
|
23797
|
-
function buildServerInstructions2() {
|
|
23798
|
-
return buildServerInstructions();
|
|
23799
|
-
}
|
|
23800
|
-
function readResource(resourceId) {
|
|
23801
|
-
const known = listSkillResources().some((d) => d.id === resourceId);
|
|
23802
|
-
if (!known) throw new SkillResourceNotFoundError(resourceId);
|
|
23803
|
-
return readSkillResource(resourceId);
|
|
23804
|
-
}
|
|
23805
|
-
var path23, fs18, SKILL_NAMES, SKILL_RESOURCE_SCHEME, RESOURCE_SKILL_IDS, SkillResourceNotFoundError;
|
|
23806
|
-
var init_skills = __esm({
|
|
23807
|
-
"src/core/skills.ts"() {
|
|
23752
|
+
var path26;
|
|
23753
|
+
var init_generate = __esm({
|
|
23754
|
+
"src/exporters/generate.ts"() {
|
|
23808
23755
|
"use strict";
|
|
23809
|
-
|
|
23810
|
-
|
|
23756
|
+
path26 = __toESM(require("path"));
|
|
23757
|
+
init_templates();
|
|
23758
|
+
init_agent_resolver();
|
|
23759
|
+
init_execution_profile();
|
|
23760
|
+
init_budget_policy();
|
|
23811
23761
|
init_fs();
|
|
23812
|
-
|
|
23813
|
-
|
|
23814
|
-
init_extensions();
|
|
23815
|
-
init_instructions();
|
|
23816
|
-
init_core();
|
|
23817
|
-
SKILL_NAMES = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
|
|
23818
|
-
SKILL_RESOURCE_SCHEME = "wairon-skill";
|
|
23819
|
-
RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
|
|
23820
|
-
SkillResourceNotFoundError = class extends Error {
|
|
23821
|
-
constructor(resourceId) {
|
|
23822
|
-
super(`Unknown SDD skill resource id: "${resourceId}".`);
|
|
23823
|
-
this.name = "SkillResourceNotFoundError";
|
|
23824
|
-
}
|
|
23825
|
-
};
|
|
23762
|
+
init_registry2();
|
|
23763
|
+
init_base();
|
|
23826
23764
|
}
|
|
23827
23765
|
});
|
|
23828
23766
|
|
|
@@ -27201,41 +27139,41 @@ function hasAuthoredSpecs(root) {
|
|
|
27201
27139
|
if (!pathExists(specsDir)) {
|
|
27202
27140
|
return false;
|
|
27203
27141
|
}
|
|
27204
|
-
const systemIndex =
|
|
27142
|
+
const systemIndex = path27.resolve(paths.specsSystem());
|
|
27205
27143
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
27206
|
-
if (
|
|
27144
|
+
if (path27.resolve(file) !== systemIndex) {
|
|
27207
27145
|
return true;
|
|
27208
27146
|
}
|
|
27209
27147
|
}
|
|
27210
27148
|
return false;
|
|
27211
27149
|
}
|
|
27212
27150
|
function createStagingDir(destDir) {
|
|
27213
|
-
const root =
|
|
27214
|
-
|
|
27215
|
-
const stagingDir =
|
|
27151
|
+
const root = path27.resolve(destDir);
|
|
27152
|
+
fs18.mkdirSync(root, { recursive: true });
|
|
27153
|
+
const stagingDir = fs18.mkdtempSync(path27.join(root, STAGING_PREFIX));
|
|
27216
27154
|
return stagingDir;
|
|
27217
27155
|
}
|
|
27218
27156
|
function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
|
|
27219
|
-
const root =
|
|
27220
|
-
const backupDir =
|
|
27157
|
+
const root = path27.resolve(destDir);
|
|
27158
|
+
const backupDir = path27.join(root, BACKUP_DIR, timestampSlug());
|
|
27221
27159
|
let backedUp = false;
|
|
27222
27160
|
for (const rootRel of roots) {
|
|
27223
27161
|
const relative15 = rootRel === "." ? "" : rootRel;
|
|
27224
|
-
const stagedSpecDir =
|
|
27225
|
-
if (!
|
|
27226
|
-
const liveSpecDir = liveSpecDirFor(
|
|
27227
|
-
if (backupExisting && liveSpecDir &&
|
|
27228
|
-
const backupTarget =
|
|
27229
|
-
|
|
27230
|
-
|
|
27162
|
+
const stagedSpecDir = path27.join(stagingDir, relative15, ".wai");
|
|
27163
|
+
if (!fs18.existsSync(stagedSpecDir)) continue;
|
|
27164
|
+
const liveSpecDir = liveSpecDirFor(path27.join(root, relative15));
|
|
27165
|
+
if (backupExisting && liveSpecDir && fs18.existsSync(liveSpecDir)) {
|
|
27166
|
+
const backupTarget = path27.join(backupDir, relative15, path27.basename(liveSpecDir));
|
|
27167
|
+
fs18.mkdirSync(path27.dirname(backupTarget), { recursive: true });
|
|
27168
|
+
fs18.renameSync(liveSpecDir, backupTarget);
|
|
27231
27169
|
backedUp = true;
|
|
27232
|
-
} else if (liveSpecDir &&
|
|
27233
|
-
|
|
27170
|
+
} else if (liveSpecDir && fs18.existsSync(liveSpecDir)) {
|
|
27171
|
+
fs18.rmSync(liveSpecDir, { recursive: true, force: true });
|
|
27234
27172
|
}
|
|
27235
|
-
const target =
|
|
27236
|
-
|
|
27237
|
-
if (
|
|
27238
|
-
|
|
27173
|
+
const target = path27.join(root, relative15, ".wai");
|
|
27174
|
+
fs18.mkdirSync(path27.dirname(target), { recursive: true });
|
|
27175
|
+
if (fs18.existsSync(target)) fs18.rmSync(target, { recursive: true, force: true });
|
|
27176
|
+
fs18.renameSync(stagedSpecDir, target);
|
|
27239
27177
|
}
|
|
27240
27178
|
if (backedUp) {
|
|
27241
27179
|
return backupDir;
|
|
@@ -27244,7 +27182,7 @@ function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
|
|
|
27244
27182
|
}
|
|
27245
27183
|
function discardStagingDir(stagingDir) {
|
|
27246
27184
|
try {
|
|
27247
|
-
|
|
27185
|
+
fs18.rmSync(stagingDir, { recursive: true, force: true });
|
|
27248
27186
|
} catch {
|
|
27249
27187
|
}
|
|
27250
27188
|
}
|
|
@@ -27258,7 +27196,7 @@ function exportSpecTree(includeDerived, allowPartial) {
|
|
|
27258
27196
|
const skipped = [...inspection.skipped];
|
|
27259
27197
|
const roots = [{ relativePath: ".", waiDir: aiPathsAt(root).root() }];
|
|
27260
27198
|
for (const rel2 of inspection.roots) {
|
|
27261
|
-
const waiDir = aiPathsAt(
|
|
27199
|
+
const waiDir = aiPathsAt(path27.resolve(root, rel2)).root();
|
|
27262
27200
|
if (pathExists(waiDir)) {
|
|
27263
27201
|
roots.push({ relativePath: rel2, waiDir });
|
|
27264
27202
|
} else {
|
|
@@ -27289,7 +27227,7 @@ function importSpecTree(archive, options) {
|
|
|
27289
27227
|
if (!info.compatible) {
|
|
27290
27228
|
throw new Error("incompatible .waitree archive (format or minimum wairon version)");
|
|
27291
27229
|
}
|
|
27292
|
-
const destDir =
|
|
27230
|
+
const destDir = path27.resolve(options.destDir ?? getProjectRoot());
|
|
27293
27231
|
const occupied = hasSpecTree(destDir);
|
|
27294
27232
|
const authored = hasAuthoredSpecs(destDir);
|
|
27295
27233
|
if (authored && options.replaceExisting !== true) {
|
|
@@ -27320,21 +27258,21 @@ function importSpecTree(archive, options) {
|
|
|
27320
27258
|
return result;
|
|
27321
27259
|
}
|
|
27322
27260
|
function liveSpecDirFor(rootDir) {
|
|
27323
|
-
const modern =
|
|
27324
|
-
if (
|
|
27325
|
-
const legacy =
|
|
27326
|
-
if (
|
|
27261
|
+
const modern = path27.join(rootDir, ".wai");
|
|
27262
|
+
if (fs18.existsSync(modern)) return modern;
|
|
27263
|
+
const legacy = path27.join(rootDir, ".wairon");
|
|
27264
|
+
if (fs18.existsSync(legacy)) return legacy;
|
|
27327
27265
|
return null;
|
|
27328
27266
|
}
|
|
27329
27267
|
function timestampSlug() {
|
|
27330
27268
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
27331
27269
|
}
|
|
27332
|
-
var
|
|
27270
|
+
var fs18, path27, sdkPortal, STAGING_PREFIX, BACKUP_DIR;
|
|
27333
27271
|
var init_treetransfer = __esm({
|
|
27334
27272
|
"src/core/treetransfer.ts"() {
|
|
27335
27273
|
"use strict";
|
|
27336
|
-
|
|
27337
|
-
|
|
27274
|
+
fs18 = __toESM(require("fs"));
|
|
27275
|
+
path27 = __toESM(require("path"));
|
|
27338
27276
|
sdkPortal = __toESM(require_dist());
|
|
27339
27277
|
init_paths();
|
|
27340
27278
|
init_fs();
|
|
@@ -27345,270 +27283,6 @@ var init_treetransfer = __esm({
|
|
|
27345
27283
|
}
|
|
27346
27284
|
});
|
|
27347
27285
|
|
|
27348
|
-
// src/exporters/claude.ts
|
|
27349
|
-
function toolsFor(budget) {
|
|
27350
|
-
const base = TOOLS_BY_CLASS[budget.toolClass];
|
|
27351
|
-
if (!base) return void 0;
|
|
27352
|
-
if (budget.allowNestedDelegation && !base.includes("Agent")) {
|
|
27353
|
-
return [...base, "Agent"];
|
|
27354
|
-
}
|
|
27355
|
-
if (!budget.allowNestedDelegation) {
|
|
27356
|
-
return base.filter((t) => t !== "Agent");
|
|
27357
|
-
}
|
|
27358
|
-
return base;
|
|
27359
|
-
}
|
|
27360
|
-
function mcpServersFor(access) {
|
|
27361
|
-
return access === "none" ? "[]" : void 0;
|
|
27362
|
-
}
|
|
27363
|
-
function yamlScalar(value) {
|
|
27364
|
-
return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
|
|
27365
|
-
}
|
|
27366
|
-
var path25, MODEL_BY_TIER, TOOLS_BY_CLASS, ClaudeExporter;
|
|
27367
|
-
var init_claude = __esm({
|
|
27368
|
-
"src/exporters/claude.ts"() {
|
|
27369
|
-
"use strict";
|
|
27370
|
-
path25 = __toESM(require("path"));
|
|
27371
|
-
init_fs();
|
|
27372
|
-
MODEL_BY_TIER = {
|
|
27373
|
-
small: "haiku",
|
|
27374
|
-
standard: "sonnet",
|
|
27375
|
-
large: "opus",
|
|
27376
|
-
frontier: "fable"
|
|
27377
|
-
};
|
|
27378
|
-
TOOLS_BY_CLASS = {
|
|
27379
|
-
"read-only": ["Read", "Grep", "Glob"],
|
|
27380
|
-
implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
|
|
27381
|
-
orchestrate: ["Agent", "SendMessage", "TodoWrite"],
|
|
27382
|
-
// `full` means "inherit everything" — expressed by omitting the field.
|
|
27383
|
-
full: void 0
|
|
27384
|
-
};
|
|
27385
|
-
ClaudeExporter = class {
|
|
27386
|
-
constructor(options = {}) {
|
|
27387
|
-
this.options = options;
|
|
27388
|
-
this.targetType = "claude";
|
|
27389
|
-
}
|
|
27390
|
-
outputPath(ctx) {
|
|
27391
|
-
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
27392
|
-
const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
|
|
27393
|
-
return path25.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
27394
|
-
}
|
|
27395
|
-
export(ctx) {
|
|
27396
|
-
const { agent, renderedInstructions, budget } = ctx;
|
|
27397
|
-
const filePath = this.outputPath(ctx);
|
|
27398
|
-
const frontmatter = [
|
|
27399
|
-
`name: ${agent.name}`,
|
|
27400
|
-
`description: ${yamlScalar(agent.description)}`
|
|
27401
|
-
];
|
|
27402
|
-
if (budget && this.options.emitBudget) {
|
|
27403
|
-
if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
|
|
27404
|
-
if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
|
|
27405
|
-
if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
|
|
27406
|
-
const tools = toolsFor(budget);
|
|
27407
|
-
if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
|
|
27408
|
-
const servers = mcpServersFor(budget.mcp);
|
|
27409
|
-
if (servers) frontmatter.push(`mcpServers: ${servers}`);
|
|
27410
|
-
}
|
|
27411
|
-
const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
|
|
27412
|
-
const changed = writeFileIfChanged(filePath, content);
|
|
27413
|
-
return { outputPath: filePath, content, unchanged: !changed };
|
|
27414
|
-
}
|
|
27415
|
-
};
|
|
27416
|
-
}
|
|
27417
|
-
});
|
|
27418
|
-
|
|
27419
|
-
// src/exporters/custom.ts
|
|
27420
|
-
var path26, CustomExporter;
|
|
27421
|
-
var init_custom = __esm({
|
|
27422
|
-
"src/exporters/custom.ts"() {
|
|
27423
|
-
"use strict";
|
|
27424
|
-
path26 = __toESM(require("path"));
|
|
27425
|
-
init_fs();
|
|
27426
|
-
CustomExporter = class {
|
|
27427
|
-
constructor() {
|
|
27428
|
-
this.targetType = "custom";
|
|
27429
|
-
}
|
|
27430
|
-
outputPath(ctx) {
|
|
27431
|
-
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
27432
|
-
if (!("outputDir" in target)) {
|
|
27433
|
-
throw new Error("CustomExporter requires target.outputDir");
|
|
27434
|
-
}
|
|
27435
|
-
return path26.resolve(projectRoot2, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
|
|
27436
|
-
}
|
|
27437
|
-
export(ctx) {
|
|
27438
|
-
const { agent, target, renderedInstructions } = ctx;
|
|
27439
|
-
const label = "label" in target ? target.label : "Custom";
|
|
27440
|
-
const filePath = this.outputPath(ctx);
|
|
27441
|
-
const content = [
|
|
27442
|
-
"---",
|
|
27443
|
-
`name: ${agent.name}`,
|
|
27444
|
-
`description: ${agent.description}`,
|
|
27445
|
-
`id: ${agent.id}`,
|
|
27446
|
-
`target: ${label}`,
|
|
27447
|
-
"---",
|
|
27448
|
-
"",
|
|
27449
|
-
renderedInstructions,
|
|
27450
|
-
""
|
|
27451
|
-
].join("\n");
|
|
27452
|
-
const changed = writeFileIfChanged(filePath, content);
|
|
27453
|
-
return { outputPath: filePath, content, unchanged: !changed };
|
|
27454
|
-
}
|
|
27455
|
-
};
|
|
27456
|
-
}
|
|
27457
|
-
});
|
|
27458
|
-
|
|
27459
|
-
// src/exporters/gemini.ts
|
|
27460
|
-
function yamlString(value) {
|
|
27461
|
-
if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
|
|
27462
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
27463
|
-
}
|
|
27464
|
-
return value;
|
|
27465
|
-
}
|
|
27466
|
-
var path27, GeminiExporter;
|
|
27467
|
-
var init_gemini = __esm({
|
|
27468
|
-
"src/exporters/gemini.ts"() {
|
|
27469
|
-
"use strict";
|
|
27470
|
-
path27 = __toESM(require("path"));
|
|
27471
|
-
init_fs();
|
|
27472
|
-
GeminiExporter = class {
|
|
27473
|
-
constructor() {
|
|
27474
|
-
this.targetType = "gemini";
|
|
27475
|
-
}
|
|
27476
|
-
outputPath(ctx) {
|
|
27477
|
-
const { agent, target, projectRoot: projectRoot2 } = ctx;
|
|
27478
|
-
const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
|
|
27479
|
-
return path27.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
|
|
27480
|
-
}
|
|
27481
|
-
export(ctx) {
|
|
27482
|
-
const { agent, renderedInstructions } = ctx;
|
|
27483
|
-
const filePath = this.outputPath(ctx);
|
|
27484
|
-
const indentedInstructions = renderedInstructions.split("\n").map((line2) => line2.length > 0 ? ` ${line2}` : "").join("\n");
|
|
27485
|
-
const content = [
|
|
27486
|
-
`name: ${yamlString(agent.name)}`,
|
|
27487
|
-
`description: ${yamlString(agent.description)}`,
|
|
27488
|
-
`system_prompt: |`,
|
|
27489
|
-
indentedInstructions,
|
|
27490
|
-
""
|
|
27491
|
-
].join("\n");
|
|
27492
|
-
const changed = writeFileIfChanged(filePath, content);
|
|
27493
|
-
return { outputPath: filePath, content, unchanged: !changed };
|
|
27494
|
-
}
|
|
27495
|
-
};
|
|
27496
|
-
}
|
|
27497
|
-
});
|
|
27498
|
-
|
|
27499
|
-
// src/exporters/registry.ts
|
|
27500
|
-
function getExporter(target) {
|
|
27501
|
-
const type = typeof target === "string" ? target : target.type;
|
|
27502
|
-
const exporter = EXPORTERS.get(type);
|
|
27503
|
-
if (!exporter) {
|
|
27504
|
-
throw new WaironError(`No exporter registered for target type: "${type}"`);
|
|
27505
|
-
}
|
|
27506
|
-
return exporter;
|
|
27507
|
-
}
|
|
27508
|
-
var EXPORTERS;
|
|
27509
|
-
var init_registry2 = __esm({
|
|
27510
|
-
"src/exporters/registry.ts"() {
|
|
27511
|
-
"use strict";
|
|
27512
|
-
init_claude();
|
|
27513
|
-
init_custom();
|
|
27514
|
-
init_gemini();
|
|
27515
|
-
init_errors();
|
|
27516
|
-
EXPORTERS = /* @__PURE__ */ new Map([
|
|
27517
|
-
["claude", new ClaudeExporter({ emitBudget: true })],
|
|
27518
|
-
["gemini", new GeminiExporter()],
|
|
27519
|
-
["agy", new GeminiExporter()],
|
|
27520
|
-
["cursor", new ClaudeExporter()],
|
|
27521
|
-
["copilot", new ClaudeExporter()],
|
|
27522
|
-
["codex", new ClaudeExporter()],
|
|
27523
|
-
["custom", new CustomExporter()]
|
|
27524
|
-
]);
|
|
27525
|
-
}
|
|
27526
|
-
});
|
|
27527
|
-
|
|
27528
|
-
// src/exporters/base.ts
|
|
27529
|
-
var WAIRON_MANAGED_MARKER, WAIRON_MANAGED_BANNER;
|
|
27530
|
-
var init_base = __esm({
|
|
27531
|
-
"src/exporters/base.ts"() {
|
|
27532
|
-
"use strict";
|
|
27533
|
-
WAIRON_MANAGED_MARKER = "wairon:managed";
|
|
27534
|
-
WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
|
|
27535
|
-
}
|
|
27536
|
-
});
|
|
27537
|
-
|
|
27538
|
-
// src/exporters/generate.ts
|
|
27539
|
-
function generateAgent(agent, projectConfig, options = {}) {
|
|
27540
|
-
const projectRoot2 = options.projectRoot ?? getProjectRoot();
|
|
27541
|
-
const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
|
|
27542
|
-
const rendered = `${WAIRON_MANAGED_BANNER}
|
|
27543
|
-
${composeAgentBrief(agent.id).instructions}`;
|
|
27544
|
-
const results = [];
|
|
27545
|
-
const budget = resolveBudget(
|
|
27546
|
-
deriveExecutionProfile(agent),
|
|
27547
|
-
projectConfig.execution,
|
|
27548
|
-
agent.id
|
|
27549
|
-
);
|
|
27550
|
-
for (const agentTarget of agent.targets) {
|
|
27551
|
-
const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
|
|
27552
|
-
if (!targetConfig) continue;
|
|
27553
|
-
if (options.filterTargets) {
|
|
27554
|
-
const type = "type" in targetConfig ? targetConfig.type : targetConfig;
|
|
27555
|
-
if (!options.filterTargets.includes(type)) continue;
|
|
27556
|
-
}
|
|
27557
|
-
if (!options.dryRun) {
|
|
27558
|
-
results.push(getExporter(targetConfig).export({
|
|
27559
|
-
agent,
|
|
27560
|
-
template,
|
|
27561
|
-
renderedInstructions: rendered,
|
|
27562
|
-
projectRoot: projectRoot2,
|
|
27563
|
-
target: targetConfig,
|
|
27564
|
-
budget
|
|
27565
|
-
}));
|
|
27566
|
-
}
|
|
27567
|
-
}
|
|
27568
|
-
return { agent, results };
|
|
27569
|
-
}
|
|
27570
|
-
function generateAll(agents, projectConfig, options = {}) {
|
|
27571
|
-
let pool = agents;
|
|
27572
|
-
if (options.filterDomainIds && options.filterDomainIds.length > 0) {
|
|
27573
|
-
const ids = new Set(options.filterDomainIds);
|
|
27574
|
-
pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
|
|
27575
|
-
}
|
|
27576
|
-
return pool.map((agent) => generateAgent(agent, projectConfig, options));
|
|
27577
|
-
}
|
|
27578
|
-
function resolveExpectedOutputPaths(agents, projectConfig, projectRoot2 = getProjectRoot()) {
|
|
27579
|
-
const expected = /* @__PURE__ */ new Set();
|
|
27580
|
-
for (const agent of agents) {
|
|
27581
|
-
for (const agentTarget of agent.targets) {
|
|
27582
|
-
const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
|
|
27583
|
-
if (!targetConfig) continue;
|
|
27584
|
-
const ctx = { agent, projectRoot: projectRoot2, target: targetConfig };
|
|
27585
|
-
expected.add(path28.resolve(getExporter(targetConfig).outputPath(ctx)));
|
|
27586
|
-
}
|
|
27587
|
-
}
|
|
27588
|
-
return expected;
|
|
27589
|
-
}
|
|
27590
|
-
function resolveTargetConfig(agentTarget, projectConfig) {
|
|
27591
|
-
const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
|
|
27592
|
-
return projectConfig.targets.find((t) => {
|
|
27593
|
-
if (typeof t === "string") return t === targetType;
|
|
27594
|
-
return t.type === targetType;
|
|
27595
|
-
});
|
|
27596
|
-
}
|
|
27597
|
-
var path28;
|
|
27598
|
-
var init_generate = __esm({
|
|
27599
|
-
"src/exporters/generate.ts"() {
|
|
27600
|
-
"use strict";
|
|
27601
|
-
path28 = __toESM(require("path"));
|
|
27602
|
-
init_templates();
|
|
27603
|
-
init_agent_resolver();
|
|
27604
|
-
init_execution_profile();
|
|
27605
|
-
init_budget_policy();
|
|
27606
|
-
init_fs();
|
|
27607
|
-
init_registry2();
|
|
27608
|
-
init_base();
|
|
27609
|
-
}
|
|
27610
|
-
});
|
|
27611
|
-
|
|
27612
27286
|
// src/core/stereotype-migration.ts
|
|
27613
27287
|
function retireSpecialists(apply) {
|
|
27614
27288
|
const components = loadComponentSpecs();
|
|
@@ -27756,6 +27430,17 @@ var init_narrative_repair = __esm({
|
|
|
27756
27430
|
}
|
|
27757
27431
|
});
|
|
27758
27432
|
|
|
27433
|
+
// src/models/lock.ts
|
|
27434
|
+
function describeApprover(who) {
|
|
27435
|
+
const label = who.name ? `${who.name} (${who.id})` : who.id;
|
|
27436
|
+
return who.source === "hosted" ? `${label} [authenticated]` : label;
|
|
27437
|
+
}
|
|
27438
|
+
var init_lock = __esm({
|
|
27439
|
+
"src/models/lock.ts"() {
|
|
27440
|
+
"use strict";
|
|
27441
|
+
}
|
|
27442
|
+
});
|
|
27443
|
+
|
|
27759
27444
|
// src/core/approval.ts
|
|
27760
27445
|
function diffSize(d) {
|
|
27761
27446
|
return d.added.length + d.changed.length + d.removed.length;
|
|
@@ -27765,12 +27450,12 @@ function digest(content) {
|
|
|
27765
27450
|
return crypto4.createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
27766
27451
|
}
|
|
27767
27452
|
function currentSpecDigests(root = getProjectRoot()) {
|
|
27768
|
-
const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${
|
|
27453
|
+
const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path28.resolve(root, s.projectPath).split(path28.sep).join("/")}/`);
|
|
27769
27454
|
const out = {};
|
|
27770
27455
|
for (const [abs, content] of snapshotSpecFiles()) {
|
|
27771
|
-
const normalized =
|
|
27456
|
+
const normalized = path28.resolve(abs).split(path28.sep).join("/");
|
|
27772
27457
|
if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
|
|
27773
|
-
out[
|
|
27458
|
+
out[path28.relative(root, abs).split(path28.sep).join("/")] = digest(content);
|
|
27774
27459
|
}
|
|
27775
27460
|
return out;
|
|
27776
27461
|
}
|
|
@@ -27828,7 +27513,7 @@ function currentChildPins(mounts, root = getProjectRoot()) {
|
|
|
27828
27513
|
const pins = {};
|
|
27829
27514
|
for (const mount of mounts) {
|
|
27830
27515
|
if (!mount.projectPath || mount.id.includes("::")) continue;
|
|
27831
|
-
const child = readLockRecordAt(
|
|
27516
|
+
const child = readLockRecordAt(path28.resolve(root, mount.projectPath));
|
|
27832
27517
|
if (child) pins[mount.id] = pinOf(child.stateId);
|
|
27833
27518
|
}
|
|
27834
27519
|
return pins;
|
|
@@ -27844,15 +27529,62 @@ function movedChildren(mounts, root = getProjectRoot()) {
|
|
|
27844
27529
|
}
|
|
27845
27530
|
return moved;
|
|
27846
27531
|
}
|
|
27847
|
-
|
|
27532
|
+
function approvalVerdict() {
|
|
27533
|
+
const quiet = { text: "", drifted: false };
|
|
27534
|
+
try {
|
|
27535
|
+
const approval = approvalRecord();
|
|
27536
|
+
if (!approval) return quiet;
|
|
27537
|
+
const by = describeApprover(approval.lockedBy);
|
|
27538
|
+
const moved = movedChildren(loadSubsystemSpecs());
|
|
27539
|
+
const childNote = moved.length ? `
|
|
27540
|
+
${moved.length} chained child project(s) moved since approval: ${moved.map((m) => m.id).join(", ")}.` : "";
|
|
27541
|
+
const diff = diffAgainstApproval();
|
|
27542
|
+
if (!diff) {
|
|
27543
|
+
return {
|
|
27544
|
+
text: `
|
|
27545
|
+
Approved: ${approval.lockedAt} by ${by} \u2014 this lock predates per-spec approval, so drift is only visible at whole-tree level. Re-lock to record it.${childNote}
|
|
27546
|
+
`,
|
|
27547
|
+
drifted: moved.length > 0
|
|
27548
|
+
};
|
|
27549
|
+
}
|
|
27550
|
+
if (diffSize(diff) === 0) {
|
|
27551
|
+
return {
|
|
27552
|
+
text: `
|
|
27553
|
+
Approved: ${approval.lockedAt} by ${by} \u2014 no spec has changed since.${childNote}
|
|
27554
|
+
`,
|
|
27555
|
+
drifted: moved.length > 0
|
|
27556
|
+
};
|
|
27557
|
+
}
|
|
27558
|
+
const parts = [];
|
|
27559
|
+
if (diff.changed.length) parts.push(`${diff.changed.length} changed`);
|
|
27560
|
+
if (diff.added.length) parts.push(`${diff.added.length} added`);
|
|
27561
|
+
if (diff.removed.length) parts.push(`${diff.removed.length} removed`);
|
|
27562
|
+
const named = [...diff.changed, ...diff.added, ...diff.removed].slice(0, 5);
|
|
27563
|
+
const rest = diffSize(diff) - named.length;
|
|
27564
|
+
const n = diffSize(diff);
|
|
27565
|
+
const noun = `${n} spec${n === 1 ? "" : "s"}`;
|
|
27566
|
+
const headline = parts.length === 1 ? `${noun} ${parts[0].slice(String(diffSize(diff)).length + 1)} since approval` : `${noun} changed since approval (${parts.join(", ")})`;
|
|
27567
|
+
return {
|
|
27568
|
+
text: `
|
|
27569
|
+
${headline} \u2014 approved ${approval.lockedAt} by ${by}:
|
|
27570
|
+
` + named.map((p) => ` ${p}`).join("\n") + (rest > 0 ? `
|
|
27571
|
+
\u2026 and ${rest} more` : "") + childNote + "\n",
|
|
27572
|
+
drifted: true
|
|
27573
|
+
};
|
|
27574
|
+
} catch {
|
|
27575
|
+
return quiet;
|
|
27576
|
+
}
|
|
27577
|
+
}
|
|
27578
|
+
var crypto4, path28;
|
|
27848
27579
|
var init_approval = __esm({
|
|
27849
27580
|
"src/core/approval.ts"() {
|
|
27850
27581
|
"use strict";
|
|
27851
27582
|
crypto4 = __toESM(require("crypto"));
|
|
27852
|
-
|
|
27583
|
+
path28 = __toESM(require("path"));
|
|
27853
27584
|
init_fs();
|
|
27854
27585
|
init_specs2();
|
|
27855
27586
|
init_lockfile();
|
|
27587
|
+
init_lock();
|
|
27856
27588
|
}
|
|
27857
27589
|
});
|
|
27858
27590
|
|
|
@@ -27917,13 +27649,13 @@ var init_stamp = __esm({
|
|
|
27917
27649
|
|
|
27918
27650
|
// src/utils/ai-guide.ts
|
|
27919
27651
|
function globalGuideFilePath(targetType) {
|
|
27920
|
-
if (targetType === "claude") return
|
|
27921
|
-
if (targetType === "gemini") return
|
|
27652
|
+
if (targetType === "claude") return path29.join(process.env["CLAUDE_CONFIG_DIR"] || path29.join(os6.homedir(), ".claude"), "CLAUDE.md");
|
|
27653
|
+
if (targetType === "gemini") return path29.join(process.env["GEMINI_CONFIG_DIR"] || path29.join(os6.homedir(), ".gemini"), "GEMINI.md");
|
|
27922
27654
|
return null;
|
|
27923
27655
|
}
|
|
27924
27656
|
function localGuideFilePath(projectRoot2, targetType) {
|
|
27925
|
-
if (targetType === "claude") return
|
|
27926
|
-
if (targetType === "gemini" || targetType === "agy") return
|
|
27657
|
+
if (targetType === "claude") return path29.join(projectRoot2, ".claude", "CLAUDE.md");
|
|
27658
|
+
if (targetType === "gemini" || targetType === "agy") return path29.join(projectRoot2, ".gemini", "GEMINI.md");
|
|
27927
27659
|
return null;
|
|
27928
27660
|
}
|
|
27929
27661
|
function injectGuide(filePath, scope) {
|
|
@@ -27935,11 +27667,11 @@ ${versionStamp()}
|
|
|
27935
27667
|
${body}
|
|
27936
27668
|
${GUIDE_MARKER_END}
|
|
27937
27669
|
`;
|
|
27938
|
-
const existing =
|
|
27670
|
+
const existing = fs19.existsSync(filePath) ? fs19.readFileSync(filePath, "utf-8") : "";
|
|
27939
27671
|
const stripped = stripGuideSection(existing);
|
|
27940
27672
|
const newContent = stripped.trimEnd() + section;
|
|
27941
|
-
|
|
27942
|
-
|
|
27673
|
+
fs19.mkdirSync(path29.dirname(filePath), { recursive: true });
|
|
27674
|
+
fs19.writeFileSync(filePath, newContent, "utf-8");
|
|
27943
27675
|
}
|
|
27944
27676
|
function stripGuideSection(content) {
|
|
27945
27677
|
const start2 = content.indexOf(GUIDE_MARKER_START);
|
|
@@ -27949,7 +27681,7 @@ function stripGuideSection(content) {
|
|
|
27949
27681
|
}
|
|
27950
27682
|
function writeRootGuideDelegator(projectRoot2, targetType) {
|
|
27951
27683
|
if (targetType === "claude") {
|
|
27952
|
-
const filePath =
|
|
27684
|
+
const filePath = path29.join(projectRoot2, "CLAUDE.md");
|
|
27953
27685
|
const content = `@.claude/CLAUDE.md
|
|
27954
27686
|
|
|
27955
27687
|
# Wairon SDD Project
|
|
@@ -27962,42 +27694,42 @@ To design or modify the system, invoke the **\`sdd-architect\`** skill
|
|
|
27962
27694
|
(in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
|
|
27963
27695
|
the \`wairon\` CLI is the human developer's tool, not yours.
|
|
27964
27696
|
`;
|
|
27965
|
-
|
|
27697
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
27966
27698
|
} else if (targetType === "gemini" || targetType === "agy") {
|
|
27967
|
-
const filePath =
|
|
27699
|
+
const filePath = path29.join(projectRoot2, "GEMINI.md");
|
|
27968
27700
|
const content = `# Wairon SDD Project
|
|
27969
27701
|
${GUIDE_MARKER_START}
|
|
27970
27702
|
${versionStamp()}
|
|
27971
27703
|
${LOCAL_GUIDE_BODY}
|
|
27972
27704
|
${GUIDE_MARKER_END}
|
|
27973
27705
|
`;
|
|
27974
|
-
|
|
27706
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
27975
27707
|
} else if (targetType === "cursor") {
|
|
27976
|
-
const filePath =
|
|
27708
|
+
const filePath = path29.join(projectRoot2, ".cursorrules");
|
|
27977
27709
|
const content = `# Wairon SDD Project
|
|
27978
27710
|
|
|
27979
27711
|
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
27980
27712
|
|
|
27981
27713
|
Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
|
|
27982
27714
|
`;
|
|
27983
|
-
|
|
27715
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
27984
27716
|
} else if (targetType === "copilot") {
|
|
27985
|
-
const filePath =
|
|
27986
|
-
|
|
27717
|
+
const filePath = path29.join(projectRoot2, ".github", "copilot-instructions.md");
|
|
27718
|
+
fs19.mkdirSync(path29.dirname(filePath), { recursive: true });
|
|
27987
27719
|
const content = `# Wairon SDD Project
|
|
27988
27720
|
|
|
27989
27721
|
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
27990
27722
|
|
|
27991
27723
|
Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
|
|
27992
27724
|
`;
|
|
27993
|
-
|
|
27725
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
27994
27726
|
} else if (targetType === "codex") {
|
|
27995
|
-
const filePath =
|
|
27727
|
+
const filePath = path29.join(projectRoot2, ".codexrules");
|
|
27996
27728
|
const content = `# Wairon SDD Project
|
|
27997
27729
|
|
|
27998
27730
|
Refer to [.codex/agents/](.codex/agents/) for full instructions.
|
|
27999
27731
|
`;
|
|
28000
|
-
|
|
27732
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
28001
27733
|
}
|
|
28002
27734
|
}
|
|
28003
27735
|
function reinjectLocalGuides(projectRoot2, targetTypes) {
|
|
@@ -28013,13 +27745,13 @@ function reinjectLocalGuides(projectRoot2, targetTypes) {
|
|
|
28013
27745
|
}
|
|
28014
27746
|
return written;
|
|
28015
27747
|
}
|
|
28016
|
-
var
|
|
27748
|
+
var fs19, os6, path29, GUIDE_MARKER_START, GUIDE_MARKER_END, GLOBAL_GUIDE_BODY, LOCAL_GUIDE_BODY, GUIDE_TARGETS;
|
|
28017
27749
|
var init_ai_guide = __esm({
|
|
28018
27750
|
"src/utils/ai-guide.ts"() {
|
|
28019
27751
|
"use strict";
|
|
28020
|
-
|
|
27752
|
+
fs19 = __toESM(require("fs"));
|
|
28021
27753
|
os6 = __toESM(require("os"));
|
|
28022
|
-
|
|
27754
|
+
path29 = __toESM(require("path"));
|
|
28023
27755
|
init_stamp();
|
|
28024
27756
|
GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
|
|
28025
27757
|
GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
|
|
@@ -28214,263 +27946,34 @@ var init_context = __esm({
|
|
|
28214
27946
|
}
|
|
28215
27947
|
});
|
|
28216
27948
|
|
|
28217
|
-
// src/core/
|
|
28218
|
-
function
|
|
28219
|
-
return
|
|
28220
|
-
|
|
28221
|
-
|
|
28222
|
-
|
|
28223
|
-
|
|
28224
|
-
|
|
28225
|
-
|
|
28226
|
-
|
|
28227
|
-
function loadProjectConfig() {
|
|
28228
|
-
return projectConfigRepository.load();
|
|
28229
|
-
}
|
|
28230
|
-
function projectConfigExists() {
|
|
28231
|
-
return projectConfigRepository.exists();
|
|
28232
|
-
}
|
|
28233
|
-
var init_core = __esm({
|
|
28234
|
-
"src/core/index.ts"() {
|
|
28235
|
-
"use strict";
|
|
28236
|
-
init_project_config();
|
|
28237
|
-
init_domain_projector();
|
|
28238
|
-
init_domain_curator();
|
|
28239
|
-
init_detection();
|
|
28240
|
-
init_templates();
|
|
28241
|
-
init_validation();
|
|
28242
|
-
init_extensions();
|
|
28243
|
-
init_variants();
|
|
28244
|
-
init_rules();
|
|
28245
|
-
init_specs2();
|
|
28246
|
-
init_provision();
|
|
28247
|
-
init_diagram();
|
|
28248
|
-
init_lockfile();
|
|
28249
|
-
init_statehash();
|
|
28250
|
-
init_agent_resolver();
|
|
28251
|
-
init_skills();
|
|
28252
|
-
init_surfaces();
|
|
28253
|
-
init_openapi();
|
|
28254
|
-
init_packstore();
|
|
28255
|
-
init_treetransfer();
|
|
28256
|
-
init_extensions();
|
|
28257
|
-
init_agent_resolver();
|
|
28258
|
-
init_generate();
|
|
28259
|
-
init_treetransfer();
|
|
28260
|
-
init_provision();
|
|
28261
|
-
init_stereotype_migration();
|
|
28262
|
-
init_narrative_repair();
|
|
28263
|
-
init_approval();
|
|
28264
|
-
init_approver();
|
|
28265
|
-
init_specs2();
|
|
28266
|
-
init_project_config();
|
|
28267
|
-
init_execution_profile();
|
|
28268
|
-
init_budget_policy();
|
|
28269
|
-
init_ai_guide();
|
|
28270
|
-
init_stamp();
|
|
28271
|
-
init_context();
|
|
28272
|
-
}
|
|
28273
|
-
});
|
|
28274
|
-
|
|
28275
|
-
// src/commands/status.ts
|
|
28276
|
-
async function runStatus(options = {}) {
|
|
28277
|
-
assertProjectInitialized();
|
|
28278
|
-
scanAllSpecs({ recursive: options.recursive ?? true });
|
|
28279
|
-
const system = loadSystemSpec();
|
|
28280
|
-
const loaderErrors = getLoaderIssues();
|
|
28281
|
-
if (loaderErrors.length > 0) {
|
|
28282
|
-
logger.error("Failed to parse specification files:");
|
|
28283
|
-
for (const issue2 of loaderErrors) {
|
|
28284
|
-
const prefix = issue2.specId ? import_chalk4.default.gray(`[${issue2.specId}] `) : "";
|
|
28285
|
-
logger.error(`${prefix}[${issue2.code}] ${issue2.message}`);
|
|
28286
|
-
}
|
|
28287
|
-
process.exit(1);
|
|
28288
|
-
}
|
|
28289
|
-
let subsystems = loadSubsystemSpecs();
|
|
28290
|
-
let components = loadComponentSpecs();
|
|
28291
|
-
let interfaces = loadInterfaceSpecs();
|
|
28292
|
-
let implementations = loadImplementationSpecs();
|
|
28293
|
-
if (options.subsystem) {
|
|
28294
|
-
subsystems = subsystems.filter((s) => s.id === options.subsystem || s.id.startsWith(`${options.subsystem}::`));
|
|
28295
|
-
components = components.filter((c) => c.subsystem === options.subsystem || c.subsystem.startsWith(`${options.subsystem}::`));
|
|
28296
|
-
interfaces = interfaces.filter((i) => {
|
|
28297
|
-
const c = components.find((comp) => comp.id === i.component);
|
|
28298
|
-
return c !== void 0;
|
|
28299
|
-
});
|
|
28300
|
-
implementations = implementations.filter((im) => {
|
|
28301
|
-
const inf = interfaces.find((i) => i.id === im.contract);
|
|
28302
|
-
return inf !== void 0;
|
|
28303
|
-
});
|
|
28304
|
-
}
|
|
28305
|
-
if (!system) {
|
|
28306
|
-
logger.error("L0 System specification (system.yaml) is missing. Run `wairon init` first.");
|
|
28307
|
-
process.exit(1);
|
|
28308
|
-
}
|
|
28309
|
-
logger.header("Architecture Status Dashboard");
|
|
28310
|
-
logger.blank();
|
|
28311
|
-
const componentScores = /* @__PURE__ */ new Map();
|
|
28312
|
-
for (const comp of components) {
|
|
28313
|
-
let score = 20;
|
|
28314
|
-
const intf = interfaces.find((i) => i.component === comp.id);
|
|
28315
|
-
if (intf) {
|
|
28316
|
-
score += 30;
|
|
28317
|
-
}
|
|
28318
|
-
const impl = implementations.find((im) => intf && im.contract === intf.id);
|
|
28319
|
-
if (impl) {
|
|
28320
|
-
score += 30;
|
|
28321
|
-
const sourceFiles = implementationSourceFiles(impl);
|
|
28322
|
-
if (sourceFiles.length > 0 && sourceFiles.every((f) => pathExists(fromProjectRoot(f)))) {
|
|
28323
|
-
score += 20;
|
|
28324
|
-
}
|
|
28325
|
-
}
|
|
28326
|
-
const isDraft = comp.status === "draft" || comp.status === "design" || intf && (intf.status === "draft" || intf.status === "design") || impl && (impl.status === "draft" || impl.status === "design");
|
|
28327
|
-
if (isDraft) {
|
|
28328
|
-
score = Math.min(score, 50);
|
|
28329
|
-
}
|
|
28330
|
-
componentScores.set(comp.id, score);
|
|
28331
|
-
}
|
|
28332
|
-
const getSubsystemScore = (subId) => {
|
|
28333
|
-
const sub = subsystems.find((s) => s.id === subId);
|
|
28334
|
-
if (!sub) return 0;
|
|
28335
|
-
const subComps = components.filter((c) => c.subsystem === subId);
|
|
28336
|
-
if (subComps.length === 0) return 0;
|
|
28337
|
-
const totalScore = subComps.reduce((acc, c) => acc + (componentScores.get(c.id) ?? 0), 0);
|
|
28338
|
-
let avg = Math.round(totalScore / subComps.length);
|
|
28339
|
-
if (sub.status === "draft" || sub.status === "design") {
|
|
28340
|
-
avg = Math.min(avg, 50);
|
|
28341
|
-
}
|
|
28342
|
-
return avg;
|
|
27949
|
+
// src/core/status.ts
|
|
27950
|
+
function fillDecor(decor) {
|
|
27951
|
+
return {
|
|
27952
|
+
structure: decor?.structure ?? asWritten,
|
|
27953
|
+
emphasis: decor?.emphasis ?? asWritten,
|
|
27954
|
+
layer: decor?.layer ?? ((_kind, text2) => text2),
|
|
27955
|
+
score: decor?.score ?? ((_pct, text2) => text2),
|
|
27956
|
+
draft: decor?.draft ?? asWritten,
|
|
27957
|
+
present: decor?.present ?? asWritten,
|
|
27958
|
+
missing: decor?.missing ?? asWritten
|
|
28343
27959
|
};
|
|
28344
|
-
const totalSubsystemsScore = subsystems.reduce((acc, s) => acc + getSubsystemScore(s.id), 0);
|
|
28345
|
-
const systemScore = subsystems.length > 0 ? Math.round(totalSubsystemsScore / subsystems.length) : 0;
|
|
28346
|
-
const systemColor = systemScore === 100 ? import_chalk4.default.green : systemScore >= 50 ? import_chalk4.default.yellow : import_chalk4.default.red;
|
|
28347
|
-
console.log(`${import_chalk4.default.bold.blue("\u25CF System:")} ${import_chalk4.default.bold(system.name)} ${systemColor(`(${systemScore}% Complete)`)}`);
|
|
28348
|
-
for (let i = 0; i < subsystems.length; i++) {
|
|
28349
|
-
const sub = subsystems[i];
|
|
28350
|
-
const isLastSub = i === subsystems.length - 1;
|
|
28351
|
-
const subPrefix = isLastSub ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28352
|
-
const subIndent = isLastSub ? " " : "\u2502 ";
|
|
28353
|
-
const subScore = getSubsystemScore(sub.id);
|
|
28354
|
-
const subStatusStr = sub.status !== "complete" ? import_chalk4.default.yellow(` [${sub.status}]`) : "";
|
|
28355
|
-
const subScoreColor = subScore === 100 ? import_chalk4.default.green : subScore >= 50 ? import_chalk4.default.yellow : import_chalk4.default.red;
|
|
28356
|
-
console.log(`${import_chalk4.default.gray(subPrefix)}${import_chalk4.default.bold.cyan(`[Subsystem] ${sub.id}`)}${subStatusStr} ${subScoreColor(`(${subScore}%)`)}`);
|
|
28357
|
-
const subComps = components.filter((c) => c.subsystem === sub.id);
|
|
28358
|
-
for (let j = 0; j < subComps.length; j++) {
|
|
28359
|
-
const comp = subComps[j];
|
|
28360
|
-
const isLastComp = j === subComps.length - 1;
|
|
28361
|
-
const compPrefix = isLastComp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28362
|
-
const compIndent = isLastComp ? " " : "\u2502 ";
|
|
28363
|
-
const compScore = componentScores.get(comp.id) ?? 0;
|
|
28364
|
-
const compStatusStr = comp.status !== "complete" ? import_chalk4.default.yellow(` [${comp.status}]`) : "";
|
|
28365
|
-
const compScoreColor = compScore === 100 ? import_chalk4.default.green : compScore >= 50 ? import_chalk4.default.yellow : import_chalk4.default.red;
|
|
28366
|
-
console.log(`${import_chalk4.default.gray(subIndent + compPrefix)}${import_chalk4.default.magenta(`[Component: ${comp.componentType}] ${comp.id}`)}${compStatusStr} ${compScoreColor(`(${compScore}%)`)}`);
|
|
28367
|
-
const intf = interfaces.find((inf) => inf.component === comp.id);
|
|
28368
|
-
const impl = implementations.find((im) => intf && im.contract === intf.id);
|
|
28369
|
-
const intfPrefix = intf && impl ? "\u251C\u2500\u2500 " : "\u2514\u2500\u2500 ";
|
|
28370
|
-
if (intf) {
|
|
28371
|
-
const intfStatusStr = intf.status !== "complete" ? import_chalk4.default.yellow(` [${intf.status}]`) : "";
|
|
28372
|
-
console.log(`${import_chalk4.default.gray(subIndent + compIndent + intfPrefix)}${import_chalk4.default.blue(`Interface: ${intf.id}`)}${intfStatusStr} (${intf.methods.length} methods)`);
|
|
28373
|
-
} else {
|
|
28374
|
-
console.log(`${import_chalk4.default.gray(subIndent + compIndent + intfPrefix)}${import_chalk4.default.red("Interface: Missing (-30%)")}`);
|
|
28375
|
-
}
|
|
28376
|
-
if (impl) {
|
|
28377
|
-
const implStatusStr = impl.status !== "complete" ? import_chalk4.default.yellow(` [${impl.status}]`) : "";
|
|
28378
|
-
const methodsWithOwnPath = impl.methods.filter((m) => m.sourcePath);
|
|
28379
|
-
let pathStr;
|
|
28380
|
-
if (impl.sourcePath) {
|
|
28381
|
-
pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? import_chalk4.default.green(` -> ${impl.sourcePath}`) : import_chalk4.default.red(` -> ${impl.sourcePath} (File Missing!)`);
|
|
28382
|
-
} else if (methodsWithOwnPath.length > 0) {
|
|
28383
|
-
pathStr = "";
|
|
28384
|
-
} else {
|
|
28385
|
-
pathStr = import_chalk4.default.gray(" (No source path)");
|
|
28386
|
-
}
|
|
28387
|
-
console.log(`${import_chalk4.default.gray(subIndent + compIndent + "\u2514\u2500\u2500 ")}${import_chalk4.default.green(`Implementation: ${impl.id}`)}${implStatusStr}${pathStr}`);
|
|
28388
|
-
const methodIndent = subIndent + compIndent + " ";
|
|
28389
|
-
for (let k = 0; k < methodsWithOwnPath.length; k++) {
|
|
28390
|
-
const method2 = methodsWithOwnPath[k];
|
|
28391
|
-
const isLastMethod = k === methodsWithOwnPath.length - 1;
|
|
28392
|
-
const methodPrefix = isLastMethod ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28393
|
-
const methodPath = method2.sourcePath;
|
|
28394
|
-
const methodLine = pathExists(fromProjectRoot(methodPath)) ? import_chalk4.default.green(`method ${method2.name} -> ${methodPath}`) : import_chalk4.default.red(`method ${method2.name} -> ${methodPath} (File Missing!)`);
|
|
28395
|
-
console.log(`${import_chalk4.default.gray(methodIndent + methodPrefix)}${methodLine}`);
|
|
28396
|
-
}
|
|
28397
|
-
} else {
|
|
28398
|
-
console.log(`${import_chalk4.default.gray(subIndent + compIndent + "\u2514\u2500\u2500 ")}${import_chalk4.default.red("Implementation: Missing (-30%)")}`);
|
|
28399
|
-
}
|
|
28400
|
-
}
|
|
28401
|
-
}
|
|
28402
|
-
const lock = lockReport();
|
|
28403
|
-
if (lock.text.trim()) {
|
|
28404
|
-
logger.blank();
|
|
28405
|
-
if (lock.drifted) logger.warn(lock.text.trim());
|
|
28406
|
-
else logger.info(lock.text.trim());
|
|
28407
|
-
}
|
|
28408
|
-
logger.blank();
|
|
28409
|
-
}
|
|
28410
|
-
function lockLine() {
|
|
28411
|
-
return lockReport().text;
|
|
28412
|
-
}
|
|
28413
|
-
function lockReport() {
|
|
28414
|
-
const quiet = { text: "", drifted: false };
|
|
28415
|
-
try {
|
|
28416
|
-
const approval = approvalRecord();
|
|
28417
|
-
if (!approval) return quiet;
|
|
28418
|
-
const by = describeApprover(approval.lockedBy);
|
|
28419
|
-
const moved = movedChildren(loadSubsystemSpecs());
|
|
28420
|
-
const childNote = moved.length ? `
|
|
28421
|
-
${moved.length} chained child project(s) moved since approval: ${moved.map((m) => m.id).join(", ")}.` : "";
|
|
28422
|
-
const diff = diffAgainstApproval();
|
|
28423
|
-
if (!diff) {
|
|
28424
|
-
return {
|
|
28425
|
-
text: `
|
|
28426
|
-
Approved: ${approval.lockedAt} by ${by} \u2014 this lock predates per-spec approval, so drift is only visible at whole-tree level. Re-lock to record it.${childNote}
|
|
28427
|
-
`,
|
|
28428
|
-
drifted: moved.length > 0
|
|
28429
|
-
};
|
|
28430
|
-
}
|
|
28431
|
-
if (diffSize(diff) === 0) {
|
|
28432
|
-
return {
|
|
28433
|
-
text: `
|
|
28434
|
-
Approved: ${approval.lockedAt} by ${by} \u2014 no spec has changed since.${childNote}
|
|
28435
|
-
`,
|
|
28436
|
-
drifted: moved.length > 0
|
|
28437
|
-
};
|
|
28438
|
-
}
|
|
28439
|
-
const parts = [];
|
|
28440
|
-
if (diff.changed.length) parts.push(`${diff.changed.length} changed`);
|
|
28441
|
-
if (diff.added.length) parts.push(`${diff.added.length} added`);
|
|
28442
|
-
if (diff.removed.length) parts.push(`${diff.removed.length} removed`);
|
|
28443
|
-
const named = [...diff.changed, ...diff.added, ...diff.removed].slice(0, 5);
|
|
28444
|
-
const rest = diffSize(diff) - named.length;
|
|
28445
|
-
const n = diffSize(diff);
|
|
28446
|
-
const noun = `${n} spec${n === 1 ? "" : "s"}`;
|
|
28447
|
-
const headline = parts.length === 1 ? `${noun} ${parts[0].slice(String(diffSize(diff)).length + 1)} since approval` : `${noun} changed since approval (${parts.join(", ")})`;
|
|
28448
|
-
return {
|
|
28449
|
-
text: `
|
|
28450
|
-
${headline} \u2014 approved ${approval.lockedAt} by ${by}:
|
|
28451
|
-
` + named.map((p) => ` ${p}`).join("\n") + (rest > 0 ? `
|
|
28452
|
-
\u2026 and ${rest} more` : "") + childNote + "\n",
|
|
28453
|
-
drifted: true
|
|
28454
|
-
};
|
|
28455
|
-
} catch {
|
|
28456
|
-
return quiet;
|
|
28457
|
-
}
|
|
28458
27960
|
}
|
|
28459
|
-
function getStatusReport(options = {}) {
|
|
27961
|
+
function getStatusReport(options = {}, decor) {
|
|
27962
|
+
const mark = fillDecor(decor);
|
|
28460
27963
|
scanAllSpecs({ recursive: options.recursive ?? true });
|
|
28461
27964
|
const system = loadSystemSpec();
|
|
28462
27965
|
const loaderErrors = getLoaderIssues();
|
|
28463
27966
|
if (loaderErrors.length > 0) {
|
|
28464
27967
|
let errText2 = "Failed to parse specification files:\n";
|
|
28465
27968
|
for (const issue2 of loaderErrors) {
|
|
28466
|
-
const prefix = issue2.specId ? `[${issue2.specId}] ` : "";
|
|
27969
|
+
const prefix = issue2.specId ? mark.structure(`[${issue2.specId}] `) : "";
|
|
28467
27970
|
errText2 += `${prefix}[${issue2.code}] ${issue2.message}
|
|
28468
27971
|
`;
|
|
28469
27972
|
}
|
|
28470
|
-
return errText2;
|
|
27973
|
+
return { text: errText2, failed: true };
|
|
28471
27974
|
}
|
|
28472
27975
|
if (!system) {
|
|
28473
|
-
return "L0 System specification (system.yaml) is missing.";
|
|
27976
|
+
return { text: "L0 System specification (system.yaml) is missing.", failed: true };
|
|
28474
27977
|
}
|
|
28475
27978
|
let subsystems = loadSubsystemSpecs();
|
|
28476
27979
|
let components = loadComponentSpecs();
|
|
@@ -28524,7 +28027,7 @@ function getStatusReport(options = {}) {
|
|
|
28524
28027
|
};
|
|
28525
28028
|
const totalSubsystemsScore = subsystems.reduce((acc, s) => acc + getSubsystemScore(s.id), 0);
|
|
28526
28029
|
const systemScore = subsystems.length > 0 ? Math.round(totalSubsystemsScore / subsystems.length) : 0;
|
|
28527
|
-
output +=
|
|
28030
|
+
output += `${mark.layer("system", "\u25CF System:")} ${mark.emphasis(system.name)} ${mark.score(systemScore, `(${systemScore}% Complete)`)}
|
|
28528
28031
|
`;
|
|
28529
28032
|
for (let i = 0; i < subsystems.length; i++) {
|
|
28530
28033
|
const sub = subsystems[i];
|
|
@@ -28532,8 +28035,8 @@ function getStatusReport(options = {}) {
|
|
|
28532
28035
|
const subPrefix = isLastSub ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28533
28036
|
const subIndent = isLastSub ? " " : "\u2502 ";
|
|
28534
28037
|
const subScore = getSubsystemScore(sub.id);
|
|
28535
|
-
const subStatusStr = sub.status !== "complete" ? ` [${sub.status}]` : "";
|
|
28536
|
-
output += `${subPrefix}[Subsystem] ${sub.id}${subStatusStr} (${subScore}%)
|
|
28038
|
+
const subStatusStr = sub.status !== "complete" ? mark.draft(` [${sub.status}]`) : "";
|
|
28039
|
+
output += `${mark.structure(subPrefix)}${mark.layer("subsystem", `[Subsystem] ${sub.id}`)}${subStatusStr} ${mark.score(subScore, `(${subScore}%)`)}
|
|
28537
28040
|
`;
|
|
28538
28041
|
const subComps = components.filter((c) => c.subsystem === sub.id);
|
|
28539
28042
|
for (let j = 0; j < subComps.length; j++) {
|
|
@@ -28542,32 +28045,32 @@ function getStatusReport(options = {}) {
|
|
|
28542
28045
|
const compPrefix = isLastComp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28543
28046
|
const compIndent = isLastComp ? " " : "\u2502 ";
|
|
28544
28047
|
const compScore = componentScores.get(comp.id) ?? 0;
|
|
28545
|
-
const compStatusStr = comp.status !== "complete" ? ` [${comp.status}]` : "";
|
|
28546
|
-
output += `${subIndent}${
|
|
28048
|
+
const compStatusStr = comp.status !== "complete" ? mark.draft(` [${comp.status}]`) : "";
|
|
28049
|
+
output += `${mark.structure(subIndent + compPrefix)}${mark.layer("component", `[Component: ${comp.componentType}] ${comp.id}`)}${compStatusStr} ${mark.score(compScore, `(${compScore}%)`)}
|
|
28547
28050
|
`;
|
|
28548
28051
|
const intf = interfaces.find((inf) => inf.component === comp.id);
|
|
28549
28052
|
const impl = implementations.find((im) => intf && im.contract === intf.id);
|
|
28550
28053
|
const intfPrefix = intf && impl ? "\u251C\u2500\u2500 " : "\u2514\u2500\u2500 ";
|
|
28551
28054
|
if (intf) {
|
|
28552
|
-
const intfStatusStr = intf.status !== "complete" ? ` [${intf.status}]` : "";
|
|
28553
|
-
output += `${subIndent
|
|
28055
|
+
const intfStatusStr = intf.status !== "complete" ? mark.draft(` [${intf.status}]`) : "";
|
|
28056
|
+
output += `${mark.structure(subIndent + compIndent + intfPrefix)}${mark.layer("interface", `Interface: ${intf.id}`)}${intfStatusStr} (${intf.methods.length} methods)
|
|
28554
28057
|
`;
|
|
28555
28058
|
} else {
|
|
28556
|
-
output += `${subIndent
|
|
28059
|
+
output += `${mark.structure(subIndent + compIndent + intfPrefix)}${mark.missing("Interface: Missing (-30%)")}
|
|
28557
28060
|
`;
|
|
28558
28061
|
}
|
|
28559
28062
|
if (impl) {
|
|
28560
|
-
const implStatusStr = impl.status !== "complete" ? ` [${impl.status}]` : "";
|
|
28063
|
+
const implStatusStr = impl.status !== "complete" ? mark.draft(` [${impl.status}]`) : "";
|
|
28561
28064
|
const methodsWithOwnPath = impl.methods.filter((m) => m.sourcePath);
|
|
28562
28065
|
let pathStr;
|
|
28563
28066
|
if (impl.sourcePath) {
|
|
28564
|
-
pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? ` -> ${impl.sourcePath}` : ` -> ${impl.sourcePath} (File Missing!)
|
|
28067
|
+
pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? mark.present(` -> ${impl.sourcePath}`) : mark.missing(` -> ${impl.sourcePath} (File Missing!)`);
|
|
28565
28068
|
} else if (methodsWithOwnPath.length > 0) {
|
|
28566
28069
|
pathStr = "";
|
|
28567
28070
|
} else {
|
|
28568
|
-
pathStr = " (No source path)";
|
|
28071
|
+
pathStr = mark.structure(" (No source path)");
|
|
28569
28072
|
}
|
|
28570
|
-
output += `${subIndent
|
|
28073
|
+
output += `${mark.structure(subIndent + compIndent + "\u2514\u2500\u2500 ")}${mark.layer("implementation", `Implementation: ${impl.id}`)}${implStatusStr}${pathStr}
|
|
28571
28074
|
`;
|
|
28572
28075
|
const methodIndent = `${subIndent}${compIndent} `;
|
|
28573
28076
|
for (let k = 0; k < methodsWithOwnPath.length; k++) {
|
|
@@ -28575,31 +28078,400 @@ function getStatusReport(options = {}) {
|
|
|
28575
28078
|
const isLastMethod = k === methodsWithOwnPath.length - 1;
|
|
28576
28079
|
const methodPrefix = isLastMethod ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
28577
28080
|
const methodPath = method2.sourcePath;
|
|
28578
|
-
const
|
|
28579
|
-
output += `${methodIndent
|
|
28081
|
+
const methodLine = pathExists(fromProjectRoot(methodPath)) ? mark.present(`method ${method2.name} -> ${methodPath}`) : mark.missing(`method ${method2.name} -> ${methodPath} (File Missing!)`);
|
|
28082
|
+
output += `${mark.structure(methodIndent + methodPrefix)}${methodLine}
|
|
28580
28083
|
`;
|
|
28581
28084
|
}
|
|
28582
28085
|
} else {
|
|
28583
|
-
output += `${subIndent
|
|
28086
|
+
output += `${mark.structure(subIndent + compIndent + "\u2514\u2500\u2500 ")}${mark.missing("Implementation: Missing (-30%)")}
|
|
28584
28087
|
`;
|
|
28585
28088
|
}
|
|
28586
28089
|
}
|
|
28587
28090
|
}
|
|
28588
|
-
output
|
|
28589
|
-
return output;
|
|
28091
|
+
return { text: output, failed: false };
|
|
28590
28092
|
}
|
|
28591
|
-
var
|
|
28093
|
+
var asWritten;
|
|
28592
28094
|
var init_status = __esm({
|
|
28593
|
-
"src/
|
|
28095
|
+
"src/core/status.ts"() {
|
|
28594
28096
|
"use strict";
|
|
28595
|
-
|
|
28596
|
-
|
|
28597
|
-
init_paths();
|
|
28097
|
+
init_specs2();
|
|
28098
|
+
init_specs();
|
|
28598
28099
|
init_fs();
|
|
28100
|
+
asWritten = (text2) => text2;
|
|
28101
|
+
}
|
|
28102
|
+
});
|
|
28103
|
+
|
|
28104
|
+
// src/core/index.ts
|
|
28105
|
+
function resolveDomains2() {
|
|
28106
|
+
return resolveDomains();
|
|
28107
|
+
}
|
|
28108
|
+
function addDomain(domain) {
|
|
28109
|
+
registerDomain(domain);
|
|
28110
|
+
}
|
|
28111
|
+
function removeDomain(id) {
|
|
28112
|
+
unregisterDomain(id);
|
|
28113
|
+
}
|
|
28114
|
+
function loadProjectConfig() {
|
|
28115
|
+
return projectConfigRepository.load();
|
|
28116
|
+
}
|
|
28117
|
+
function projectConfigExists() {
|
|
28118
|
+
return projectConfigRepository.exists();
|
|
28119
|
+
}
|
|
28120
|
+
var init_core = __esm({
|
|
28121
|
+
"src/core/index.ts"() {
|
|
28122
|
+
"use strict";
|
|
28123
|
+
init_project_config();
|
|
28124
|
+
init_domain_projector();
|
|
28125
|
+
init_domain_curator();
|
|
28126
|
+
init_rules();
|
|
28599
28127
|
init_specs2();
|
|
28600
|
-
|
|
28128
|
+
init_provision();
|
|
28129
|
+
init_statehash();
|
|
28601
28130
|
init_lockfile();
|
|
28602
|
-
|
|
28131
|
+
init_diagram();
|
|
28132
|
+
init_diagram();
|
|
28133
|
+
init_detection();
|
|
28134
|
+
init_extensions();
|
|
28135
|
+
init_packstore();
|
|
28136
|
+
init_agent_resolver();
|
|
28137
|
+
init_generate();
|
|
28138
|
+
init_treetransfer();
|
|
28139
|
+
init_provision();
|
|
28140
|
+
init_stereotype_migration();
|
|
28141
|
+
init_narrative_repair();
|
|
28142
|
+
init_approval();
|
|
28143
|
+
init_approver();
|
|
28144
|
+
init_specs2();
|
|
28145
|
+
init_project_config();
|
|
28146
|
+
init_execution_profile();
|
|
28147
|
+
init_budget_policy();
|
|
28148
|
+
init_ai_guide();
|
|
28149
|
+
init_stamp();
|
|
28150
|
+
init_context();
|
|
28151
|
+
init_status();
|
|
28152
|
+
}
|
|
28153
|
+
});
|
|
28154
|
+
|
|
28155
|
+
// src/core/instructions.ts
|
|
28156
|
+
function governingProfile() {
|
|
28157
|
+
try {
|
|
28158
|
+
return loadProjectConfig4()?.projectType ?? null;
|
|
28159
|
+
} catch {
|
|
28160
|
+
return null;
|
|
28161
|
+
}
|
|
28162
|
+
}
|
|
28163
|
+
function blockApplies(block, profile) {
|
|
28164
|
+
if (!block.profile || block.profile.length === 0) return true;
|
|
28165
|
+
return profile !== null && block.profile.includes(profile);
|
|
28166
|
+
}
|
|
28167
|
+
function skillPointers(skills) {
|
|
28168
|
+
if (skills.length === 0) return "(none published by this server)";
|
|
28169
|
+
return skills.map((s) => `- \`${s.resourceUri}\` \u2014 ${s.description || s.name}`).join("\n");
|
|
28170
|
+
}
|
|
28171
|
+
function waironInstructions(profile, packNames, skills, variants) {
|
|
28172
|
+
return `# wairon \u2014 Spec-Driven Development (SDD)
|
|
28173
|
+
|
|
28174
|
+
This server owns one system's **spec tree**: its architecture, specified top-down
|
|
28175
|
+
and machine-checked. Author it ONLY through this server's \`sdd_*\` tools \u2014 never by
|
|
28176
|
+
writing spec files directly, and never via the \`wairon\` CLI (that is the human
|
|
28177
|
+
developer's tool).
|
|
28178
|
+
|
|
28179
|
+
## The tree: L0 \u2192 L5
|
|
28180
|
+
|
|
28181
|
+
- **L0 System** \u2014 vision, boundaries, global requirements, target language.
|
|
28182
|
+
- **L1 Subsystem** \u2014 an isolated service, its \`publicInterfaces\`, its trusted links.
|
|
28183
|
+
- **L2 Component** \u2014 ONE building block (\`Portal\`, \`Orchestrator\`, \`Supervisor\`,
|
|
28184
|
+
\`Actor\`, \`Store\`, \`Index\`, \`Query\`, \`Registry\`, \`Adapter\`, \`Observer\`, and
|
|
28185
|
+
\`View\` for UIs) or pattern (\`Repository\`, and \`FeatureComponent\` or
|
|
28186
|
+
\`RouterComponent\` for UIs), plus \`owns\` (a pattern's private members) and
|
|
28187
|
+
\`dependsOn\` (collaborators). Logic is an \`Orchestrator\` whose \`dependencyClass\`
|
|
28188
|
+
(\`pure\` or \`read\`; unset, a workflow) bounds what it may depend on; a gateway is
|
|
28189
|
+
a \`Portal\` with the \`gateway\` variant. \`Specialist\` and \`Gateway\` are retired.
|
|
28190
|
+
- **L3 Interface** \u2014 the contract: method signatures with structured \`params\`,
|
|
28191
|
+
plus wire \`endpoint\` bindings for a Portal's methods.
|
|
28192
|
+
- **L4 Implementation** \u2014 a concrete realization of one L3 contract: narrative
|
|
28193
|
+
detail level, bound \`technologies\` (the vendor swap seam), optional \`sourcePath\`.
|
|
28194
|
+
- **L5 Narrative** \u2014 each method's logic as a FLAT numbered step list; \`call\` steps
|
|
28195
|
+
resolve to real dependency methods, and flow steps jump by step number.
|
|
28196
|
+
|
|
28197
|
+
These stereotypes are not labels \u2014 they carry enforced dependency rules (e.g. a
|
|
28198
|
+
Portal may not depend on a Store; state lives in a Store, never as fields inside
|
|
28199
|
+
an Orchestrator). \`sdd_validate_tree\` is the gate, and it is the authority on
|
|
28200
|
+
whether a design is legal.
|
|
28201
|
+
|
|
28202
|
+
## Authoring order
|
|
28203
|
+
|
|
28204
|
+
1. \`sdd_initialize_system\` (L0), then \`sdd_add_subsystem\` (L1).
|
|
28205
|
+
2. Then, **one subsystem at a time**: \`sdd_add_component\` (L2) \u2192 \`sdd_define_interface\`
|
|
28206
|
+
(L3) \u2192 \`sdd_set_endpoints\` for Portals \u2192 \`sdd_write_narrative\` (L4+L5).
|
|
28207
|
+
3. Run \`sdd_validate_tree\` as you go \u2014 early and per subsystem, not once at the end.
|
|
28208
|
+
\`sdd_get_status\` reports completeness; \`sdd_get_spec\` reads any spec back as JSON.
|
|
28209
|
+
4. Edit granularly with \`sdd_update_spec\` (it renumbers narrative steps and
|
|
28210
|
+
relocates jump targets for you).
|
|
28211
|
+
|
|
28212
|
+
## The tool schemas are the field reference
|
|
28213
|
+
|
|
28214
|
+
Every \`sdd_*\` tool's input schema is self-describing and authoritative \u2014 read the
|
|
28215
|
+
schema rather than guessing field names, and prefer structured \`params\` over prose
|
|
28216
|
+
signatures. Specs are ${profile === null ? "validated against the project's configured profile" : `governed by the **\`${profile}\`** profile`}, which decides which stereotypes are legal
|
|
28217
|
+
here, which narrative flow constructs the target language supports, and which
|
|
28218
|
+
extra rules apply. A subsystem may override the profile for itself.
|
|
28219
|
+
|
|
28220
|
+
## Loaded extension packs
|
|
28221
|
+
|
|
28222
|
+
${packNames.length === 0 ? "None \u2014 only wairon's built-in doctrine applies." : `${packNames.map((n) => `\`${n}\``).join(", ")} \u2014 these inject profiles, language tables, patterns, and
|
|
28223
|
+
additional conformance rules. Their doctrine is enforced by the same gate.`}
|
|
28224
|
+
|
|
28225
|
+
${variants.length === 0 ? "" : `## Component variants in play
|
|
28226
|
+
|
|
28227
|
+
This project defines variants \u2014 named, base-anchored kinds carrying implementation
|
|
28228
|
+
guidance, so every component of the same kind is built alike: ${variants.map((v) => `\`${v.id}\` (a kind of ${v.base})`).join(", ")}.
|
|
28229
|
+
Tag a component with \`variant\` where it fits, and read a component's resolved
|
|
28230
|
+
guidance and its same-variant siblings from \`sdd_get_spec\` (kind: component).
|
|
28231
|
+
|
|
28232
|
+
`}## Read the skills BEFORE authoring
|
|
28233
|
+
|
|
28234
|
+
This server publishes its skills as MCP resources. **Read \`wairon-skill://sdd-architect\`
|
|
28235
|
+
before you design anything**, and the others when their turn comes \u2014 they carry the
|
|
28236
|
+
architecture standard, the narrative step reference, and the review checklist that
|
|
28237
|
+
this briefing only points at:
|
|
28238
|
+
|
|
28239
|
+
${skillPointers(skills)}
|
|
28240
|
+
|
|
28241
|
+
## Delegating implementation
|
|
28242
|
+
|
|
28243
|
+
Delegate component work from a LIVE agent brief, never a generated file: discover
|
|
28244
|
+
agents via \`listAgents\` (or the \`wairon-agent://\` resources), fetch the target's
|
|
28245
|
+
brief with \`sdd_get_agent_brief\`, and spawn a scoped subagent from it \u2014 its
|
|
28246
|
+
\`instructions\` as prompt, its \`ownedPaths\` as write fence. Briefs are composed
|
|
28247
|
+
from the current spec tree on every call, so a re-lock never requires a session
|
|
28248
|
+
restart \u2014 fetch fresh per delegation. \`wairon-skill://sdd-delegate\` carries the
|
|
28249
|
+
full flow.`;
|
|
28250
|
+
}
|
|
28251
|
+
function buildServerInstructions() {
|
|
28252
|
+
const profile = governingProfile();
|
|
28253
|
+
let skills = [];
|
|
28254
|
+
let blocks = [];
|
|
28255
|
+
let packNames = [];
|
|
28256
|
+
const variants = [];
|
|
28257
|
+
try {
|
|
28258
|
+
skills = listSkillResources();
|
|
28259
|
+
const extensions = loadProjectExtensions2();
|
|
28260
|
+
blocks = extensions.instructions;
|
|
28261
|
+
packNames = extensions.packNames;
|
|
28262
|
+
} catch {
|
|
28263
|
+
}
|
|
28264
|
+
const sections = [waironInstructions(profile, packNames, skills, variants)];
|
|
28265
|
+
for (const block of blocks) {
|
|
28266
|
+
if (!blockApplies(block, profile)) continue;
|
|
28267
|
+
sections.push(`## From pack "${block.pack}"
|
|
28268
|
+
|
|
28269
|
+
${block.text.trim()}`);
|
|
28270
|
+
}
|
|
28271
|
+
return sections.join("\n\n");
|
|
28272
|
+
}
|
|
28273
|
+
var init_instructions = __esm({
|
|
28274
|
+
"src/core/instructions.ts"() {
|
|
28275
|
+
"use strict";
|
|
28276
|
+
init_skills();
|
|
28277
|
+
}
|
|
28278
|
+
});
|
|
28279
|
+
|
|
28280
|
+
// src/core/skills.ts
|
|
28281
|
+
function loadProjectExtensions2() {
|
|
28282
|
+
return loadProjectExtensions();
|
|
28283
|
+
}
|
|
28284
|
+
function loadProjectConfig4() {
|
|
28285
|
+
return loadProjectConfig();
|
|
28286
|
+
}
|
|
28287
|
+
function packSkillId(skill) {
|
|
28288
|
+
return `${packNamespace(skill.pack)}-${skill.id}`;
|
|
28289
|
+
}
|
|
28290
|
+
function packNamespace(pack) {
|
|
28291
|
+
return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
28292
|
+
}
|
|
28293
|
+
function extensionsFor(builtin, packSkills) {
|
|
28294
|
+
return packSkills.filter((s) => s.extends === builtin && fs20.existsSync(s.sourcePath));
|
|
28295
|
+
}
|
|
28296
|
+
function composeBuiltinSkill(name, packSkills) {
|
|
28297
|
+
const srcPath = skillTemplatePath(name);
|
|
28298
|
+
const base = fs20.existsSync(srcPath) ? fs20.readFileSync(srcPath, "utf-8") : "";
|
|
28299
|
+
const sections = extensionsFor(name, packSkills);
|
|
28300
|
+
if (sections.length === 0) return base;
|
|
28301
|
+
const parts = [base.trimEnd()];
|
|
28302
|
+
for (const section of sections) {
|
|
28303
|
+
const body = fs20.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
|
|
28304
|
+
parts.push(`## Platform: ${section.pack}`, body.trim());
|
|
28305
|
+
}
|
|
28306
|
+
return `${parts.join("\n\n")}
|
|
28307
|
+
`;
|
|
28308
|
+
}
|
|
28309
|
+
function readFrontmatter(raw, fallbackName) {
|
|
28310
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
28311
|
+
const block = match ? match[1] : "";
|
|
28312
|
+
const field = (key) => {
|
|
28313
|
+
const m = new RegExp(`^${key}:\\s*(.*)$`, "m").exec(block);
|
|
28314
|
+
return m ? m[1].trim() : "";
|
|
28315
|
+
};
|
|
28316
|
+
return { name: field("name") || fallbackName, description: field("description") };
|
|
28317
|
+
}
|
|
28318
|
+
function builtinSkillsDir() {
|
|
28319
|
+
return path31.resolve(__dirname, "..", "templates", "skills");
|
|
28320
|
+
}
|
|
28321
|
+
function skillTemplatePath(name) {
|
|
28322
|
+
return path31.join(builtinSkillsDir(), `${name}.md`);
|
|
28323
|
+
}
|
|
28324
|
+
function skillDestPath(type, destDir, name) {
|
|
28325
|
+
if (type === "claude" || type === "codex" || type === "gemini" || type === "agy") {
|
|
28326
|
+
return path31.join(destDir, name, "SKILL.md");
|
|
28327
|
+
}
|
|
28328
|
+
return path31.join(destDir, `${name}.md`);
|
|
28329
|
+
}
|
|
28330
|
+
function skillsDirForTarget(type) {
|
|
28331
|
+
switch (type) {
|
|
28332
|
+
case "claude":
|
|
28333
|
+
return fromProjectRoot(".claude", "skills");
|
|
28334
|
+
case "gemini":
|
|
28335
|
+
// Gemini-based Antigravity
|
|
28336
|
+
case "agy":
|
|
28337
|
+
case "codex":
|
|
28338
|
+
return fromProjectRoot(".agents", "skills");
|
|
28339
|
+
case "cursor":
|
|
28340
|
+
return fromProjectRoot(".cursor", "skills");
|
|
28341
|
+
default:
|
|
28342
|
+
return null;
|
|
28343
|
+
}
|
|
28344
|
+
}
|
|
28345
|
+
function listSkillNames() {
|
|
28346
|
+
return [...SKILL_NAMES];
|
|
28347
|
+
}
|
|
28348
|
+
function exportSddSkills(targetTypes) {
|
|
28349
|
+
const types = targetTypes ?? activeTargetTypes2();
|
|
28350
|
+
const destinations = [];
|
|
28351
|
+
const skipped = [];
|
|
28352
|
+
let fileCount = 0;
|
|
28353
|
+
const packSkills = loadProjectExtensions2().skills;
|
|
28354
|
+
for (const type of types) {
|
|
28355
|
+
const destDir = skillsDirForTarget(type);
|
|
28356
|
+
if (!destDir) {
|
|
28357
|
+
skipped.push(type);
|
|
28358
|
+
continue;
|
|
28359
|
+
}
|
|
28360
|
+
ensureDir(destDir);
|
|
28361
|
+
destinations.push(destDir);
|
|
28362
|
+
for (const name of SKILL_NAMES) {
|
|
28363
|
+
if (!fs20.existsSync(skillTemplatePath(name))) continue;
|
|
28364
|
+
const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
|
|
28365
|
+
const destPath = skillDestPath(type, destDir, name);
|
|
28366
|
+
ensureDir(path31.dirname(destPath));
|
|
28367
|
+
fs20.writeFileSync(destPath, content, "utf-8");
|
|
28368
|
+
fileCount++;
|
|
28369
|
+
}
|
|
28370
|
+
for (const skill of packSkills) {
|
|
28371
|
+
if (skill.extends !== void 0) continue;
|
|
28372
|
+
if (!skill.targets.includes(type)) continue;
|
|
28373
|
+
if (!fs20.existsSync(skill.sourcePath)) continue;
|
|
28374
|
+
const id = packSkillId(skill);
|
|
28375
|
+
const content = fs20.readFileSync(skill.sourcePath, "utf-8");
|
|
28376
|
+
const destPath = skillDestPath(type, destDir, id);
|
|
28377
|
+
ensureDir(path31.dirname(destPath));
|
|
28378
|
+
fs20.writeFileSync(destPath, content, "utf-8");
|
|
28379
|
+
fileCount++;
|
|
28380
|
+
}
|
|
28381
|
+
}
|
|
28382
|
+
return { destinations, fileCount, skipped };
|
|
28383
|
+
}
|
|
28384
|
+
function checkSkillFreshness(type) {
|
|
28385
|
+
const dir = skillsDirForTarget(type);
|
|
28386
|
+
const result = { dir, missing: [], stale: [], ok: [] };
|
|
28387
|
+
if (!dir) return result;
|
|
28388
|
+
const packSkills = loadProjectExtensions2().skills.filter((s) => s.targets.includes(type));
|
|
28389
|
+
for (const name of SKILL_NAMES) {
|
|
28390
|
+
const destPath = skillDestPath(type, dir, name);
|
|
28391
|
+
if (!fs20.existsSync(destPath)) {
|
|
28392
|
+
result.missing.push(name);
|
|
28393
|
+
continue;
|
|
28394
|
+
}
|
|
28395
|
+
const want = composeBuiltinSkill(name, packSkills);
|
|
28396
|
+
const have = fs20.readFileSync(destPath, "utf-8");
|
|
28397
|
+
if (have === want) result.ok.push(name);
|
|
28398
|
+
else result.stale.push(name);
|
|
28399
|
+
}
|
|
28400
|
+
return result;
|
|
28401
|
+
}
|
|
28402
|
+
function activeTargetTypes2() {
|
|
28403
|
+
const config = loadProjectConfig4();
|
|
28404
|
+
if (!config) return [];
|
|
28405
|
+
return activeTargetTypes(config);
|
|
28406
|
+
}
|
|
28407
|
+
function readSkillFrontmatter(name) {
|
|
28408
|
+
return readFrontmatter(fs20.readFileSync(skillTemplatePath(name), "utf-8"), name);
|
|
28409
|
+
}
|
|
28410
|
+
function listSkillResources() {
|
|
28411
|
+
const builtin = RESOURCE_SKILL_IDS.map((id) => {
|
|
28412
|
+
const fm = readSkillFrontmatter(id);
|
|
28413
|
+
return {
|
|
28414
|
+
id,
|
|
28415
|
+
name: fm.name,
|
|
28416
|
+
description: fm.description,
|
|
28417
|
+
version: WAIRON_VERSION,
|
|
28418
|
+
resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
|
|
28419
|
+
defaultForHostedMcp: true
|
|
28420
|
+
};
|
|
28421
|
+
});
|
|
28422
|
+
const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs20.existsSync(s.sourcePath)).map((skill) => {
|
|
28423
|
+
const id = packSkillId(skill);
|
|
28424
|
+
const fm = readFrontmatter(fs20.readFileSync(skill.sourcePath, "utf-8"), id);
|
|
28425
|
+
return {
|
|
28426
|
+
id,
|
|
28427
|
+
name: fm.name,
|
|
28428
|
+
description: fm.description,
|
|
28429
|
+
version: skill.packVersion ?? WAIRON_VERSION,
|
|
28430
|
+
resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
|
|
28431
|
+
defaultForHostedMcp: true
|
|
28432
|
+
};
|
|
28433
|
+
});
|
|
28434
|
+
return [...builtin, ...pack];
|
|
28435
|
+
}
|
|
28436
|
+
function readSkillResource(resourceId) {
|
|
28437
|
+
const packSkills = loadProjectExtensions2().skills;
|
|
28438
|
+
if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
|
|
28439
|
+
const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
|
|
28440
|
+
if (packSkill) return fs20.readFileSync(packSkill.sourcePath, "utf-8");
|
|
28441
|
+
return fs20.readFileSync(skillTemplatePath(resourceId), "utf-8");
|
|
28442
|
+
}
|
|
28443
|
+
function listResources() {
|
|
28444
|
+
return listSkillResources();
|
|
28445
|
+
}
|
|
28446
|
+
function buildServerInstructions2() {
|
|
28447
|
+
return buildServerInstructions();
|
|
28448
|
+
}
|
|
28449
|
+
function readResource(resourceId) {
|
|
28450
|
+
const known = listSkillResources().some((d) => d.id === resourceId);
|
|
28451
|
+
if (!known) throw new SkillResourceNotFoundError(resourceId);
|
|
28452
|
+
return readSkillResource(resourceId);
|
|
28453
|
+
}
|
|
28454
|
+
var path31, fs20, SKILL_NAMES, SKILL_RESOURCE_SCHEME, RESOURCE_SKILL_IDS, SkillResourceNotFoundError;
|
|
28455
|
+
var init_skills = __esm({
|
|
28456
|
+
"src/core/skills.ts"() {
|
|
28457
|
+
"use strict";
|
|
28458
|
+
path31 = __toESM(require("path"));
|
|
28459
|
+
fs20 = __toESM(require("fs"));
|
|
28460
|
+
init_fs();
|
|
28461
|
+
init_defaults();
|
|
28462
|
+
init_project();
|
|
28463
|
+
init_extensions();
|
|
28464
|
+
init_instructions();
|
|
28465
|
+
init_core();
|
|
28466
|
+
SKILL_NAMES = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
|
|
28467
|
+
SKILL_RESOURCE_SCHEME = "wairon-skill";
|
|
28468
|
+
RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
|
|
28469
|
+
SkillResourceNotFoundError = class extends Error {
|
|
28470
|
+
constructor(resourceId) {
|
|
28471
|
+
super(`Unknown SDD skill resource id: "${resourceId}".`);
|
|
28472
|
+
this.name = "SkillResourceNotFoundError";
|
|
28473
|
+
}
|
|
28474
|
+
};
|
|
28603
28475
|
}
|
|
28604
28476
|
});
|
|
28605
28477
|
|
|
@@ -30143,7 +30015,9 @@ function createMcpServer(options = {}) {
|
|
|
30143
30015
|
subsystem,
|
|
30144
30016
|
recursive: recursive ?? true
|
|
30145
30017
|
});
|
|
30146
|
-
|
|
30018
|
+
const family = statusFamilyContext();
|
|
30019
|
+
const verdict = approvalVerdict();
|
|
30020
|
+
return text(`${family}${report2.text}${verdict.text}`);
|
|
30147
30021
|
} catch (e) {
|
|
30148
30022
|
return errText(String(e));
|
|
30149
30023
|
}
|
|
@@ -30342,7 +30216,7 @@ var init_server = __esm({
|
|
|
30342
30216
|
init_fs();
|
|
30343
30217
|
init_yaml();
|
|
30344
30218
|
init_errors();
|
|
30345
|
-
|
|
30219
|
+
init_core();
|
|
30346
30220
|
init_core();
|
|
30347
30221
|
init_defaults();
|
|
30348
30222
|
init_narrative_labels();
|
|
@@ -30695,7 +30569,7 @@ async function runMcpInstall(options = {}) {
|
|
|
30695
30569
|
const desiredEntry = options.hostedUrl ? hostedMcpEntry(options) : useDirectNode ? { command: "node", args: [scriptPath, "mcp", "serve"], env } : { command: "wairon", args: ["mcp", "serve"], env };
|
|
30696
30570
|
const existingEntry = mcpServers["wairon"];
|
|
30697
30571
|
if (existingEntry && JSON.stringify(existingEntry) === JSON.stringify(desiredEntry)) {
|
|
30698
|
-
logger.info(`wairon MCP server already registered (up to date) for ${agentLabel} in ${
|
|
30572
|
+
logger.info(`wairon MCP server already registered (up to date) for ${agentLabel} in ${import_chalk4.default.gray(settingsPath)}.`);
|
|
30699
30573
|
continue;
|
|
30700
30574
|
}
|
|
30701
30575
|
const wasStale = !!existingEntry;
|
|
@@ -30703,7 +30577,7 @@ async function runMcpInstall(options = {}) {
|
|
|
30703
30577
|
settings["mcpServers"] = mcpServers;
|
|
30704
30578
|
if (!fs22.existsSync(configBase)) fs22.mkdirSync(configBase, { recursive: true });
|
|
30705
30579
|
fs22.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
30706
|
-
logger.success(`wairon MCP server ${wasStale ? "updated (was stale)" : "registered"} for ${agentLabel} in ${
|
|
30580
|
+
logger.success(`wairon MCP server ${wasStale ? "updated (was stale)" : "registered"} for ${agentLabel} in ${import_chalk4.default.cyan(settingsPath)}.`);
|
|
30707
30581
|
logger.blank();
|
|
30708
30582
|
logger.info("AI tools using this config will have access to these wairon tools:");
|
|
30709
30583
|
logger.info(" listAgents \xB7 getAgent \xB7 listDomains \xB7 validateTopology \xB7 getProjectConfig");
|
|
@@ -30711,13 +30585,13 @@ async function runMcpInstall(options = {}) {
|
|
|
30711
30585
|
logger.info(" sdd_write_narrative \xB7 sdd_validate_tree \xB7 sdd_get_status");
|
|
30712
30586
|
logger.blank();
|
|
30713
30587
|
const restartApp = backend === "gemini" ? "Antigravity CLI (agy)" : "claude";
|
|
30714
|
-
logger.info(`Restart ${
|
|
30588
|
+
logger.info(`Restart ${import_chalk4.default.bold(restartApp)} (or reload MCP servers) to activate.`);
|
|
30715
30589
|
if (backend === "claude" && !useGlobal) {
|
|
30716
30590
|
logger.warn('Claude shows project .mcp.json servers as "\u23F8 Pending approval" \u2014 approve wairon once on next launch (or run `claude` and accept the trust prompt).');
|
|
30717
30591
|
}
|
|
30718
30592
|
if (backend === "gemini" && !useGlobal) {
|
|
30719
30593
|
logger.warn("Note: Antigravity (agy) reads MCP servers from its global ~/.gemini/antigravity-cli/mcp_config.json, not this project file.");
|
|
30720
|
-
logger.warn("If the agent cannot see the sdd_* tools, run: " +
|
|
30594
|
+
logger.warn("If the agent cannot see the sdd_* tools, run: " + import_chalk4.default.bold("wairon mcp install --backend gemini --global"));
|
|
30721
30595
|
}
|
|
30722
30596
|
logger.blank();
|
|
30723
30597
|
}
|
|
@@ -30731,7 +30605,7 @@ async function runMcpStatus() {
|
|
|
30731
30605
|
const geminiProject = path33.join(process.cwd(), ".gemini", "settings.json");
|
|
30732
30606
|
const geminiGlobal = path33.join(geminiGlobalDir(), "antigravity-cli", "mcp_config.json");
|
|
30733
30607
|
logger.blank();
|
|
30734
|
-
logger.info(`${
|
|
30608
|
+
logger.info(`${import_chalk4.default.bold("wairon MCP Server")}`);
|
|
30735
30609
|
logger.blank();
|
|
30736
30610
|
const checks = [
|
|
30737
30611
|
{ label: "Claude (project)", filePath: claudeProject, fallbackName: ".mcp.json" },
|
|
@@ -30741,28 +30615,28 @@ async function runMcpStatus() {
|
|
|
30741
30615
|
];
|
|
30742
30616
|
for (const { label, filePath, fallbackName } of checks) {
|
|
30743
30617
|
if (!fs22.existsSync(filePath)) {
|
|
30744
|
-
console.log(` ${label}: ${
|
|
30618
|
+
console.log(` ${label}: ${import_chalk4.default.gray(`${fallbackName} not found`)}`);
|
|
30745
30619
|
continue;
|
|
30746
30620
|
}
|
|
30747
30621
|
try {
|
|
30748
30622
|
const s = JSON.parse(fs22.readFileSync(filePath, "utf8"));
|
|
30749
30623
|
const registered = !!s["mcpServers"]?.["wairon"];
|
|
30750
|
-
const mark = registered ?
|
|
30751
|
-
console.log(` ${label}: ${mark} ${
|
|
30624
|
+
const mark = registered ? import_chalk4.default.green("\u2713 registered") : import_chalk4.default.gray("not registered");
|
|
30625
|
+
console.log(` ${label}: ${mark} ${import_chalk4.default.gray(filePath)}`);
|
|
30752
30626
|
} catch {
|
|
30753
|
-
console.log(` ${label}: ${
|
|
30627
|
+
console.log(` ${label}: ${import_chalk4.default.red("parse error")} ${import_chalk4.default.gray(filePath)}`);
|
|
30754
30628
|
}
|
|
30755
30629
|
}
|
|
30756
30630
|
logger.blank();
|
|
30757
|
-
logger.info(`Project: ${
|
|
30631
|
+
logger.info(`Project: ${import_chalk4.default.bold(projectConfig.name)}`);
|
|
30758
30632
|
logger.blank();
|
|
30759
|
-
logger.info(`To register for Claude: ${
|
|
30760
|
-
logger.info(`To register for Antigravity (agy): ${
|
|
30761
|
-
logger.info(`To start manually: ${
|
|
30633
|
+
logger.info(`To register for Claude: ${import_chalk4.default.bold("wairon mcp install --backend claude")}`);
|
|
30634
|
+
logger.info(`To register for Antigravity (agy): ${import_chalk4.default.bold("wairon mcp install --backend gemini")}`);
|
|
30635
|
+
logger.info(`To start manually: ${import_chalk4.default.bold("wairon mcp serve")}`);
|
|
30762
30636
|
logger.blank();
|
|
30763
30637
|
const mcpDir = aiDir("mcp");
|
|
30764
30638
|
if (fs22.existsSync(mcpDir)) {
|
|
30765
|
-
logger.info(`MCP state dir: ${
|
|
30639
|
+
logger.info(`MCP state dir: ${import_chalk4.default.gray(mcpDir)}`);
|
|
30766
30640
|
}
|
|
30767
30641
|
}
|
|
30768
30642
|
function hostedMcpEntry(options) {
|
|
@@ -30783,7 +30657,7 @@ function removeLegacyGlobalPlugin() {
|
|
|
30783
30657
|
try {
|
|
30784
30658
|
if (fs22.existsSync(pluginDir)) {
|
|
30785
30659
|
fs22.rmSync(pluginDir, { recursive: true, force: true });
|
|
30786
|
-
logger.info(`Removed legacy global Antigravity plugin at ${
|
|
30660
|
+
logger.info(`Removed legacy global Antigravity plugin at ${import_chalk4.default.gray(pluginDir)} (it collides with the wairon MCP server).`);
|
|
30787
30661
|
return true;
|
|
30788
30662
|
}
|
|
30789
30663
|
} catch (e) {
|
|
@@ -30791,14 +30665,14 @@ function removeLegacyGlobalPlugin() {
|
|
|
30791
30665
|
}
|
|
30792
30666
|
return false;
|
|
30793
30667
|
}
|
|
30794
|
-
var fs22, os7, path33,
|
|
30668
|
+
var fs22, os7, path33, import_chalk4;
|
|
30795
30669
|
var init_mcp = __esm({
|
|
30796
30670
|
"src/commands/mcp.ts"() {
|
|
30797
30671
|
"use strict";
|
|
30798
30672
|
fs22 = __toESM(require("fs"));
|
|
30799
30673
|
os7 = __toESM(require("os"));
|
|
30800
30674
|
path33 = __toESM(require("path"));
|
|
30801
|
-
|
|
30675
|
+
import_chalk4 = __toESM(require("chalk"));
|
|
30802
30676
|
init_logger();
|
|
30803
30677
|
init_paths();
|
|
30804
30678
|
init_core();
|
|
@@ -31032,7 +30906,7 @@ function isSupportedAlias(name) {
|
|
|
31032
30906
|
|
|
31033
30907
|
// src/commands/init.ts
|
|
31034
30908
|
var path34 = __toESM(require("path"));
|
|
31035
|
-
var
|
|
30909
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
31036
30910
|
var import_inquirer = __toESM(require("inquirer"));
|
|
31037
30911
|
init_logger();
|
|
31038
30912
|
init_errors();
|
|
@@ -31041,7 +30915,7 @@ init_yaml();
|
|
|
31041
30915
|
init_paths();
|
|
31042
30916
|
|
|
31043
30917
|
// src/commands/subsystem.ts
|
|
31044
|
-
var
|
|
30918
|
+
var path30 = __toESM(require("path"));
|
|
31045
30919
|
init_logger();
|
|
31046
30920
|
init_errors();
|
|
31047
30921
|
init_fs();
|
|
@@ -31057,7 +30931,7 @@ function exportSpecTree2(includeDerived, allowPartial) {
|
|
|
31057
30931
|
function importSpecTree2(archive, options) {
|
|
31058
30932
|
return importSpecTree(archive, options);
|
|
31059
30933
|
}
|
|
31060
|
-
function
|
|
30934
|
+
function loadProjectConfig3() {
|
|
31061
30935
|
return loadProjectConfig();
|
|
31062
30936
|
}
|
|
31063
30937
|
function createProjectConfig2(config) {
|
|
@@ -31150,6 +31024,12 @@ function hasContext2() {
|
|
|
31150
31024
|
function derivedDocPaths2() {
|
|
31151
31025
|
return derivedDocPaths();
|
|
31152
31026
|
}
|
|
31027
|
+
function getStatusReport2(options, decor) {
|
|
31028
|
+
return getStatusReport(options, decor);
|
|
31029
|
+
}
|
|
31030
|
+
function approvalVerdict2() {
|
|
31031
|
+
return approvalVerdict();
|
|
31032
|
+
}
|
|
31153
31033
|
async function runSubsystemAdd(id, options = {}) {
|
|
31154
31034
|
logger.header("wairon subsystem add");
|
|
31155
31035
|
if (!projectConfigExists2()) {
|
|
@@ -31179,9 +31059,9 @@ async function runSubsystemAdd(id, options = {}) {
|
|
|
31179
31059
|
updatedAt: now
|
|
31180
31060
|
};
|
|
31181
31061
|
createChainedSubsystem2(subsystem, displayName);
|
|
31182
|
-
const childDir =
|
|
31062
|
+
const childDir = path30.resolve(getProjectRoot(), options.projectPath);
|
|
31183
31063
|
logger.success(`Added external subsystem "${id}" \u2192 ${options.projectPath}`);
|
|
31184
|
-
logger.info(`Scaffolded child project at ${
|
|
31064
|
+
logger.info(`Scaffolded child project at ${path30.relative(process.cwd(), childDir) || "."}`);
|
|
31185
31065
|
logger.info(`Design its spec tree from this parent using namespaced ids (e.g. ${id}::<component>).`);
|
|
31186
31066
|
}
|
|
31187
31067
|
async function runSubsystemMove(id, options = {}) {
|
|
@@ -31204,9 +31084,9 @@ async function runSubsystemExternalize(id, options = {}) {
|
|
|
31204
31084
|
throw new WaironError("--project-path (the subproject destination) is required.");
|
|
31205
31085
|
}
|
|
31206
31086
|
externalizeSubsystem(id, options.projectPath);
|
|
31207
|
-
const childDir =
|
|
31087
|
+
const childDir = path30.resolve(getProjectRoot(), options.projectPath);
|
|
31208
31088
|
logger.success(`Externalized subsystem "${id}" \u2192 ${options.projectPath}`);
|
|
31209
|
-
logger.info(`Moved its specs into ${
|
|
31089
|
+
logger.info(`Moved its specs into ${path30.relative(process.cwd(), childDir) || "."} (now a standalone subproject).`);
|
|
31210
31090
|
logger.info("Move the source code there yourself, then run `wairon validate` to confirm the tree.");
|
|
31211
31091
|
}
|
|
31212
31092
|
async function runSubsystemInternalize(id) {
|
|
@@ -31444,10 +31324,10 @@ async function runInitInteractive() {
|
|
|
31444
31324
|
logger.blank();
|
|
31445
31325
|
logger.header("Init summary");
|
|
31446
31326
|
logger.blank();
|
|
31447
|
-
console.log(` ${
|
|
31448
|
-
console.log(` ${
|
|
31449
|
-
console.log(` ${
|
|
31450
|
-
console.log(` ${
|
|
31327
|
+
console.log(` ${import_chalk5.default.bold("Project:")} ${projectName}`);
|
|
31328
|
+
console.log(` ${import_chalk5.default.bold("Profile:")} ${projectType}`);
|
|
31329
|
+
console.log(` ${import_chalk5.default.bold("Targets:")} ${targets.map((t) => t.type).join(", ")}`);
|
|
31330
|
+
console.log(` ${import_chalk5.default.bold("Guide:")} Auto-inject local AI rules card (${selectedTypes.filter((t) => ["claude", "gemini", "agy"].includes(t)).join(", ") || "none"})`);
|
|
31451
31331
|
logger.blank();
|
|
31452
31332
|
const { confirmed } = await import_inquirer.default.prompt([
|
|
31453
31333
|
{
|
|
@@ -31786,7 +31666,7 @@ async function runGenerate(options = {}) {
|
|
|
31786
31666
|
}
|
|
31787
31667
|
async function generateLayer(options = {}) {
|
|
31788
31668
|
assertProjectInitialized();
|
|
31789
|
-
const projectConfig =
|
|
31669
|
+
const projectConfig = loadProjectConfig3();
|
|
31790
31670
|
if (!projectConfig) throw new ProjectNotInitializedError();
|
|
31791
31671
|
const agents = resolveAgentTopology2();
|
|
31792
31672
|
if (agents.length === 0) {
|
|
@@ -31885,6 +31765,7 @@ init_logger();
|
|
|
31885
31765
|
init_defaults();
|
|
31886
31766
|
var path36 = __toESM(require("path"));
|
|
31887
31767
|
init_core();
|
|
31768
|
+
init_lock();
|
|
31888
31769
|
init_fs();
|
|
31889
31770
|
init_validation();
|
|
31890
31771
|
function checkApproval(strict) {
|
|
@@ -31979,7 +31860,7 @@ async function runLock(options = {}, gate) {
|
|
|
31979
31860
|
}
|
|
31980
31861
|
|
|
31981
31862
|
// src/commands/validate.ts
|
|
31982
|
-
var
|
|
31863
|
+
var import_chalk6 = __toESM(require("chalk"));
|
|
31983
31864
|
init_logger();
|
|
31984
31865
|
init_agent_resolver();
|
|
31985
31866
|
init_paths();
|
|
@@ -32049,7 +31930,7 @@ async function runValidate(options = {}) {
|
|
|
32049
31930
|
logger.success("Registry is valid.");
|
|
32050
31931
|
} else {
|
|
32051
31932
|
for (const issue2 of regResult.issues) {
|
|
32052
|
-
const prefix = issue2.agentId ?
|
|
31933
|
+
const prefix = issue2.agentId ? import_chalk6.default.gray(`[${issue2.agentId}] `) : "";
|
|
32053
31934
|
if (issue2.severity === "error") {
|
|
32054
31935
|
logger.error(`${prefix}[${issue2.code}] ${issue2.message}`);
|
|
32055
31936
|
hasErrors = true;
|
|
@@ -32084,7 +31965,7 @@ async function runValidate(options = {}) {
|
|
|
32084
31965
|
let skippedErrors = 0;
|
|
32085
31966
|
let skippedWarnings = 0;
|
|
32086
31967
|
for (const issue2 of sddResult.issues) {
|
|
32087
|
-
const prefix = issue2.specId ?
|
|
31968
|
+
const prefix = issue2.specId ? import_chalk6.default.gray(`[${issue2.specId}] `) : "";
|
|
32088
31969
|
if (issue2.severity === "error") {
|
|
32089
31970
|
hasErrors = true;
|
|
32090
31971
|
if (errorCount < MAX_PRINT) {
|
|
@@ -32118,12 +31999,12 @@ async function runValidate(options = {}) {
|
|
|
32118
31999
|
const summary = carriedDebtSummary(projectConfig.rules?.conformance?.carried);
|
|
32119
32000
|
if (summary) {
|
|
32120
32001
|
logger.blank();
|
|
32121
|
-
logger.info(
|
|
32122
|
-
for (const note of summary.revisits) logger.info(
|
|
32002
|
+
logger.info(import_chalk6.default.yellow(summary.line));
|
|
32003
|
+
for (const note of summary.revisits) logger.info(import_chalk6.default.gray(note));
|
|
32123
32004
|
}
|
|
32124
32005
|
logger.blank();
|
|
32125
32006
|
if (options.ci && waivedWarnings > 0) {
|
|
32126
|
-
logger.info(
|
|
32007
|
+
logger.info(import_chalk6.default.gray(`${waivedWarnings} draft-related warning(s) (non-fatal in --ci): excluded from the failure decision because the referenced specs are in draft/design status.`));
|
|
32127
32008
|
}
|
|
32128
32009
|
const failOnWarnings = !!options.ci && hasFatalWarnings;
|
|
32129
32010
|
if (hasErrors || failOnWarnings) {
|
|
@@ -32131,7 +32012,7 @@ async function runValidate(options = {}) {
|
|
|
32131
32012
|
logger.error("Validation failed: warnings are treated as errors in --ci mode.");
|
|
32132
32013
|
} else {
|
|
32133
32014
|
logger.error("Validation failed. Fix the errors above.");
|
|
32134
|
-
logger.info(
|
|
32015
|
+
logger.info(import_chalk6.default.cyan("Tip: If you need to temporarily bypass an architectural rule, you can override its severity level in your `.wai/project.yaml` config (e.g. `rules.sddRuleSeverity.CIRCULAR_DEPENDENCY: warning`)."));
|
|
32135
32016
|
}
|
|
32136
32017
|
process.exit(1);
|
|
32137
32018
|
} else {
|
|
@@ -32148,7 +32029,7 @@ init_paths();
|
|
|
32148
32029
|
init_fs();
|
|
32149
32030
|
|
|
32150
32031
|
// src/commands/list.ts
|
|
32151
|
-
var
|
|
32032
|
+
var import_chalk7 = __toESM(require("chalk"));
|
|
32152
32033
|
init_logger();
|
|
32153
32034
|
init_paths();
|
|
32154
32035
|
async function runList() {
|
|
@@ -32166,26 +32047,26 @@ async function runList() {
|
|
|
32166
32047
|
}
|
|
32167
32048
|
}
|
|
32168
32049
|
function printAgent(agent) {
|
|
32169
|
-
const status2 = agent.status === "active" ?
|
|
32170
|
-
console.log(`${
|
|
32050
|
+
const status2 = agent.status === "active" ? import_chalk7.default.green(agent.status) : agent.status === "draft" ? import_chalk7.default.yellow(agent.status) : import_chalk7.default.gray(agent.status);
|
|
32051
|
+
console.log(`${import_chalk7.default.bold(agent.id)} ${import_chalk7.default.gray(`[${agent.template}]`)} ${status2}`);
|
|
32171
32052
|
console.log(` ${agent.description}`);
|
|
32172
32053
|
if (agent.ownedPaths.length > 0) {
|
|
32173
|
-
console.log(
|
|
32054
|
+
console.log(import_chalk7.default.gray(` owns: ${agent.ownedPaths.join(", ")}`));
|
|
32174
32055
|
}
|
|
32175
32056
|
if (agent.tags.length > 0) {
|
|
32176
|
-
console.log(
|
|
32057
|
+
console.log(import_chalk7.default.gray(` tags: ${agent.tags.join(", ")}`));
|
|
32177
32058
|
}
|
|
32178
32059
|
const targetLabels = agent.targets.map((t) => {
|
|
32179
32060
|
if (typeof t === "string") return t;
|
|
32180
32061
|
const obj = t;
|
|
32181
32062
|
return obj.label ? `${obj.type}(${obj.label})` : obj.type;
|
|
32182
32063
|
});
|
|
32183
|
-
console.log(
|
|
32064
|
+
console.log(import_chalk7.default.gray(` targets: ${targetLabels.join(", ")}`));
|
|
32184
32065
|
console.log();
|
|
32185
32066
|
}
|
|
32186
32067
|
|
|
32187
32068
|
// src/commands/show.ts
|
|
32188
|
-
var
|
|
32069
|
+
var import_chalk8 = __toESM(require("chalk"));
|
|
32189
32070
|
init_logger();
|
|
32190
32071
|
init_paths();
|
|
32191
32072
|
init_errors();
|
|
@@ -32198,60 +32079,60 @@ async function runShow(agentId) {
|
|
|
32198
32079
|
printAgentDetails(agent);
|
|
32199
32080
|
}
|
|
32200
32081
|
function printAgentDetails(agent) {
|
|
32201
|
-
const statusColor = agent.status === "active" ?
|
|
32082
|
+
const statusColor = agent.status === "active" ? import_chalk8.default.green : agent.status === "draft" ? import_chalk8.default.yellow : import_chalk8.default.gray;
|
|
32202
32083
|
logger.header(agent.name);
|
|
32203
32084
|
console.log();
|
|
32204
|
-
console.log(`${
|
|
32205
|
-
console.log(`${
|
|
32206
|
-
console.log(`${
|
|
32085
|
+
console.log(`${import_chalk8.default.bold("ID")} ${agent.id}`);
|
|
32086
|
+
console.log(`${import_chalk8.default.bold("Status")} ${statusColor(agent.status)}`);
|
|
32087
|
+
console.log(`${import_chalk8.default.bold("Template")} ${agent.template}`);
|
|
32207
32088
|
if (agent.bundleOrigin) {
|
|
32208
|
-
console.log(`${
|
|
32089
|
+
console.log(`${import_chalk8.default.bold("Bundle")} ${agent.bundleOrigin}`);
|
|
32209
32090
|
}
|
|
32210
32091
|
if (agent.domainRoot) {
|
|
32211
|
-
console.log(`${
|
|
32092
|
+
console.log(`${import_chalk8.default.bold("Domain")} ${agent.domainRoot}`);
|
|
32212
32093
|
}
|
|
32213
32094
|
console.log();
|
|
32214
|
-
console.log(`${
|
|
32095
|
+
console.log(`${import_chalk8.default.bold("Description")}`);
|
|
32215
32096
|
console.log(` ${agent.description}`);
|
|
32216
32097
|
console.log();
|
|
32217
|
-
console.log(`${
|
|
32098
|
+
console.log(`${import_chalk8.default.bold("Reason")}`);
|
|
32218
32099
|
console.log(` ${agent.creationReason}`);
|
|
32219
32100
|
console.log();
|
|
32220
32101
|
if (agent.ownedPaths.length > 0) {
|
|
32221
|
-
console.log(`${
|
|
32102
|
+
console.log(`${import_chalk8.default.bold("Owned paths")}`);
|
|
32222
32103
|
for (const p of agent.ownedPaths) {
|
|
32223
|
-
console.log(` ${
|
|
32104
|
+
console.log(` ${import_chalk8.default.cyan(p)}`);
|
|
32224
32105
|
}
|
|
32225
32106
|
console.log();
|
|
32226
32107
|
}
|
|
32227
32108
|
if (agent.readPaths.length > 0) {
|
|
32228
|
-
console.log(`${
|
|
32109
|
+
console.log(`${import_chalk8.default.bold("Read paths")}`);
|
|
32229
32110
|
for (const p of agent.readPaths) {
|
|
32230
|
-
console.log(` ${
|
|
32111
|
+
console.log(` ${import_chalk8.default.gray(p)}`);
|
|
32231
32112
|
}
|
|
32232
32113
|
console.log();
|
|
32233
32114
|
}
|
|
32234
32115
|
if (agent.writePaths.length > 0) {
|
|
32235
|
-
console.log(`${
|
|
32116
|
+
console.log(`${import_chalk8.default.bold("Write paths")}`);
|
|
32236
32117
|
for (const p of agent.writePaths) {
|
|
32237
|
-
console.log(` ${
|
|
32118
|
+
console.log(` ${import_chalk8.default.gray(p)}`);
|
|
32238
32119
|
}
|
|
32239
32120
|
console.log();
|
|
32240
32121
|
}
|
|
32241
32122
|
if (agent.tags.length > 0) {
|
|
32242
|
-
console.log(`${
|
|
32123
|
+
console.log(`${import_chalk8.default.bold("Tags")} ${agent.tags.map((t) => import_chalk8.default.magenta(t)).join(", ")}`);
|
|
32243
32124
|
}
|
|
32244
32125
|
if (agent.dependencies.length > 0) {
|
|
32245
|
-
console.log(`${
|
|
32126
|
+
console.log(`${import_chalk8.default.bold("Depends on")} ${agent.dependencies.join(", ")}`);
|
|
32246
32127
|
}
|
|
32247
32128
|
const targetLabels = agent.targets.map((t) => {
|
|
32248
32129
|
if (typeof t === "string") return t;
|
|
32249
32130
|
const obj = t;
|
|
32250
32131
|
return obj.label ? `${obj.type}(${obj.label})` : obj.type;
|
|
32251
32132
|
});
|
|
32252
|
-
console.log(`${
|
|
32133
|
+
console.log(`${import_chalk8.default.bold("Targets")} ${targetLabels.join(", ")}`);
|
|
32253
32134
|
console.log();
|
|
32254
|
-
console.log(
|
|
32135
|
+
console.log(import_chalk8.default.gray(`Created: ${agent.createdAt} Updated: ${agent.updatedAt}`));
|
|
32255
32136
|
}
|
|
32256
32137
|
|
|
32257
32138
|
// src/cli/index.ts
|
|
@@ -32595,8 +32476,60 @@ function cleanStaleBinary(oldPath) {
|
|
|
32595
32476
|
}
|
|
32596
32477
|
var isNewer = isNewerVersion;
|
|
32597
32478
|
|
|
32598
|
-
// src/
|
|
32599
|
-
|
|
32479
|
+
// src/commands/status.ts
|
|
32480
|
+
var import_chalk9 = __toESM(require("chalk"));
|
|
32481
|
+
init_logger();
|
|
32482
|
+
init_paths();
|
|
32483
|
+
var LAYER_COLOUR = {
|
|
32484
|
+
system: (text2) => import_chalk9.default.bold.blue(text2),
|
|
32485
|
+
subsystem: (text2) => import_chalk9.default.bold.cyan(text2),
|
|
32486
|
+
component: (text2) => import_chalk9.default.magenta(text2),
|
|
32487
|
+
interface: (text2) => import_chalk9.default.blue(text2),
|
|
32488
|
+
implementation: (text2) => import_chalk9.default.green(text2)
|
|
32489
|
+
};
|
|
32490
|
+
function scoreColour(pct) {
|
|
32491
|
+
if (pct === 100) return (text2) => import_chalk9.default.green(text2);
|
|
32492
|
+
if (pct >= 50) return (text2) => import_chalk9.default.yellow(text2);
|
|
32493
|
+
return (text2) => import_chalk9.default.red(text2);
|
|
32494
|
+
}
|
|
32495
|
+
var TERMINAL_DECOR = {
|
|
32496
|
+
structure: (text2) => import_chalk9.default.gray(text2),
|
|
32497
|
+
emphasis: (text2) => import_chalk9.default.bold(text2),
|
|
32498
|
+
layer: (kind, text2) => (LAYER_COLOUR[kind] ?? ((plain) => plain))(text2),
|
|
32499
|
+
score: (pct, text2) => scoreColour(pct)(text2),
|
|
32500
|
+
draft: (text2) => import_chalk9.default.yellow(text2),
|
|
32501
|
+
present: (text2) => import_chalk9.default.green(text2),
|
|
32502
|
+
missing: (text2) => import_chalk9.default.red(text2)
|
|
32503
|
+
};
|
|
32504
|
+
var NO_SYSTEM_SPEC = "L0 System specification (system.yaml) is missing.";
|
|
32505
|
+
var INIT_HINT = " Run `wairon init` first.";
|
|
32506
|
+
function refuseUnreadableTree(explanation) {
|
|
32507
|
+
const lines = withoutTrailingNewline(explanation).split("\n");
|
|
32508
|
+
const last = lines.length - 1;
|
|
32509
|
+
if (lines[last] === NO_SYSTEM_SPEC) lines[last] += INIT_HINT;
|
|
32510
|
+
for (const line2 of lines) logger.error(line2);
|
|
32511
|
+
process.exit(1);
|
|
32512
|
+
}
|
|
32513
|
+
function withoutTrailingNewline(text2) {
|
|
32514
|
+
return text2.endsWith("\n") ? text2.slice(0, -1) : text2;
|
|
32515
|
+
}
|
|
32516
|
+
async function runStatus(options = {}) {
|
|
32517
|
+
assertProjectInitialized();
|
|
32518
|
+
const report2 = getStatusReport2(options, TERMINAL_DECOR);
|
|
32519
|
+
if (report2.failed) {
|
|
32520
|
+
refuseUnreadableTree(report2.text);
|
|
32521
|
+
}
|
|
32522
|
+
logger.header("Architecture Status Dashboard");
|
|
32523
|
+
logger.blank();
|
|
32524
|
+
console.log(withoutTrailingNewline(report2.text));
|
|
32525
|
+
const lock = approvalVerdict2();
|
|
32526
|
+
if (lock.text.trim()) {
|
|
32527
|
+
logger.blank();
|
|
32528
|
+
if (lock.drifted) logger.warn(lock.text.trim());
|
|
32529
|
+
else logger.info(lock.text.trim());
|
|
32530
|
+
}
|
|
32531
|
+
logger.blank();
|
|
32532
|
+
}
|
|
32600
32533
|
|
|
32601
32534
|
// src/commands/domains.ts
|
|
32602
32535
|
var import_chalk11 = __toESM(require("chalk"));
|
|
@@ -32982,7 +32915,7 @@ init_fs();
|
|
|
32982
32915
|
init_provision();
|
|
32983
32916
|
init_skills();
|
|
32984
32917
|
init_specs2();
|
|
32985
|
-
|
|
32918
|
+
init_lock();
|
|
32986
32919
|
init_extensions();
|
|
32987
32920
|
init_mcp();
|
|
32988
32921
|
function icon(mark) {
|
|
@@ -33038,7 +32971,7 @@ async function runDoctor(options = {}) {
|
|
|
33038
32971
|
let targets = [];
|
|
33039
32972
|
let configOk = false;
|
|
33040
32973
|
try {
|
|
33041
|
-
if (!
|
|
32974
|
+
if (!loadProjectConfig3()) throw new ProjectNotInitializedError();
|
|
33042
32975
|
configOk = true;
|
|
33043
32976
|
line(tally, "ok", ".wai/project.yaml is valid");
|
|
33044
32977
|
} catch (e) {
|
|
@@ -33074,7 +33007,7 @@ async function runDoctor(options = {}) {
|
|
|
33074
33007
|
if (hasSystemSpec && configOk) {
|
|
33075
33008
|
console.log(import_chalk12.default.bold("Spec tree"));
|
|
33076
33009
|
try {
|
|
33077
|
-
const cfg =
|
|
33010
|
+
const cfg = loadProjectConfig3();
|
|
33078
33011
|
if (!cfg) throw new ProjectNotInitializedError();
|
|
33079
33012
|
const result = validateSddTree(cfg.rules, cfg.projectType);
|
|
33080
33013
|
const errs = result.issues.filter((i) => i.severity === "error").length;
|
|
@@ -33256,7 +33189,7 @@ async function applyFixes() {
|
|
|
33256
33189
|
if (!projectConfigExists2()) return;
|
|
33257
33190
|
let targets;
|
|
33258
33191
|
try {
|
|
33259
|
-
if (!
|
|
33192
|
+
if (!loadProjectConfig3()) throw new ProjectNotInitializedError();
|
|
33260
33193
|
targets = activeTargetTypes2();
|
|
33261
33194
|
} catch (e) {
|
|
33262
33195
|
logger.warn(`--fix skipped: .wai/project.yaml is invalid (${e instanceof Error ? e.message : String(e)}). Fix it first.`);
|
|
@@ -48418,7 +48351,7 @@ var TIER_COLOR = {
|
|
|
48418
48351
|
};
|
|
48419
48352
|
async function showExecution() {
|
|
48420
48353
|
assertInitialized();
|
|
48421
|
-
const config =
|
|
48354
|
+
const config = loadProjectConfig3();
|
|
48422
48355
|
if (!config) throw new ProjectNotInitializedError();
|
|
48423
48356
|
const tier = config.execution.tier;
|
|
48424
48357
|
logger.header("Execution budgets");
|
|
@@ -48480,7 +48413,7 @@ async function setExecutionTier3(raw) {
|
|
|
48480
48413
|
);
|
|
48481
48414
|
}
|
|
48482
48415
|
const tier = parsed.data;
|
|
48483
|
-
const config =
|
|
48416
|
+
const config = loadProjectConfig3();
|
|
48484
48417
|
if (!config) throw new ProjectNotInitializedError();
|
|
48485
48418
|
const previous = config.execution.tier;
|
|
48486
48419
|
if (previous === tier) {
|
|
@@ -48533,7 +48466,7 @@ async function runLock2(options) {
|
|
|
48533
48466
|
logger.error("No SDD spec tree found (.wai/specs). Nothing to lock.");
|
|
48534
48467
|
process.exit(1);
|
|
48535
48468
|
}
|
|
48536
|
-
const projectConfig =
|
|
48469
|
+
const projectConfig = loadProjectConfig3();
|
|
48537
48470
|
if (!projectConfig) throw new ProjectNotInitializedError();
|
|
48538
48471
|
logger.info("Analyzing and validating specifications in-memory...");
|
|
48539
48472
|
const dry = validateAsComplete({
|