@wairon/cli 5.1.1-dev.60 → 5.1.1-dev.61

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/index.js CHANGED
@@ -3401,7 +3401,6 @@ __export(src_exports, {
3401
3401
  BuiltinTargetSchema: () => BuiltinTargetSchema,
3402
3402
  BundleNotFoundError: () => BundleNotFoundError,
3403
3403
  COMPONENT_AUTH_SOURCE: () => COMPONENT_AUTH_SOURCE,
3404
- CONTEXT_PATHS: () => CONTEXT_PATHS,
3405
3404
  CarriedDebtKindSchema: () => CarriedDebtKindSchema,
3406
3405
  CarriedDebtSchema: () => CarriedDebtSchema,
3407
3406
  CarriedFindingSchema: () => CarriedFindingSchema,
@@ -3556,7 +3555,6 @@ __export(src_exports, {
3556
3555
  computeStateIdAt: () => computeStateIdAt,
3557
3556
  conceptNoun: () => conceptNoun,
3558
3557
  consumedContractInputs: () => consumedContractInputs,
3559
- contextDir: () => contextDir,
3560
3558
  createAgentRecord: () => createAgentRecord,
3561
3559
  createChainedSubsystem: () => createChainedSubsystem,
3562
3560
  createEmptyRegistry: () => createEmptyRegistry,
@@ -3579,6 +3577,7 @@ __export(src_exports, {
3579
3577
  deleteTypeSpec: () => deleteTypeSpec,
3580
3578
  deregisterPackRef: () => deregisterPackRef,
3581
3579
  deriveExecutionProfile: () => deriveExecutionProfile,
3580
+ derivedDocPaths: () => derivedDocPaths,
3582
3581
  describeApprover: () => describeApprover,
3583
3582
  detectDomainCandidates: () => detectDomainCandidates,
3584
3583
  diagnoseProjectPacks: () => diagnoseProjectPacks,
@@ -3633,7 +3632,6 @@ __export(src_exports, {
3633
3632
  globalPacksEnabled: () => globalPacksEnabled,
3634
3633
  globalTemplatesDir: () => globalTemplatesDir,
3635
3634
  globalVariantsDir: () => globalVariantsDir,
3636
- hasArchitectureContext: () => hasArchitectureContext,
3637
3635
  hasAuthoredSpecs: () => hasAuthoredSpecs,
3638
3636
  hasContext: () => hasContext,
3639
3637
  hasFunctionBody: () => hasFunctionBody,
@@ -3732,14 +3730,12 @@ __export(src_exports, {
3732
3730
  projectSubsystemSurface: () => projectSubsystemSurface,
3733
3731
  provisionProject: () => provisionProject,
3734
3732
  qualifiedTypeId: () => qualifiedTypeId,
3735
- readArchitectureContext: () => readArchitectureContext,
3736
3733
  readFileOrNull: () => readFileOrNull,
3737
3734
  readJsonFile: () => readJsonFile,
3738
3735
  readLockRecord: () => readLockRecord,
3739
3736
  readLockRecordAt: () => readLockRecordAt,
3740
3737
  readLockState: () => readLockState,
3741
3738
  readManifest: () => readManifest,
3742
- readProjectContext: () => readProjectContext,
3743
3739
  readResource: () => readResource,
3744
3740
  readSkillResource: () => readSkillResource,
3745
3741
  readStampVersion: () => readStampVersion,
@@ -3756,9 +3752,7 @@ __export(src_exports, {
3756
3752
  renameComponent: () => renameComponent,
3757
3753
  renameMethod: () => renameMethod,
3758
3754
  renderDiagram: () => renderDiagram,
3759
- renderDomainsDoc: () => renderDomainsDoc,
3760
3755
  renderTemplateInstructions: () => renderTemplateInstructions,
3761
- renderWaironGuide: () => renderWaironGuide,
3762
3756
  repairForeignStepFields: () => repairForeignStepFields,
3763
3757
  resolveAgentTopology: () => resolveAgentTopology,
3764
3758
  resolveBudget: () => resolveBudget,
@@ -3821,12 +3815,10 @@ __export(src_exports, {
3821
3815
  validateRegistry: () => validateRegistry,
3822
3816
  validateSddTree: () => validateSddTree,
3823
3817
  workspaceFor: () => workspaceFor,
3824
- writeArchitectureContext: () => writeArchitectureContext,
3825
3818
  writeFile: () => writeFile,
3826
3819
  writeFileIfChanged: () => writeFileIfChanged,
3827
3820
  writeJsonFile: () => writeJsonFile,
3828
3821
  writeLockRecord: () => writeLockRecord,
3829
- writeProjectContext: () => writeProjectContext,
3830
3822
  writeRootGuideDelegator: () => writeRootGuideDelegator,
3831
3823
  writeYamlFile: () => writeYamlFile
3832
3824
  });
@@ -11662,7 +11654,7 @@ function defaultTargetConfig(type) {
11662
11654
  enabled: true
11663
11655
  };
11664
11656
  }
11665
- var WAIRON_VERSION = "5.1.1-dev.60";
11657
+ var WAIRON_VERSION = "5.1.1-dev.61";
11666
11658
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
11667
11659
  var ARCHITECT_AGENT_ID = "agent-architect";
11668
11660
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -26347,390 +26339,97 @@ function readResource(resourceId) {
26347
26339
  return readSkillResource(resourceId);
26348
26340
  }
26349
26341
 
26350
- // src/utils/ai-guide.ts
26342
+ // src/core/treetransfer.ts
26351
26343
  var fs17 = __toESM(require("fs"));
26352
- var os4 = __toESM(require("os"));
26353
26344
  var path22 = __toESM(require("path"));
26354
-
26355
- // src/core/stamp.ts
26356
- function versionStamp() {
26357
- return `<!-- wairon-version: ${WAIRON_VERSION} -->`;
26358
- }
26359
- var STAMP_RE = /<!--\s*wairon-version:\s*([^\s]+)\s*-->/;
26360
- function readStampVersion(content) {
26361
- const m = content.match(STAMP_RE);
26362
- return m ? m[1] : null;
26363
- }
26364
-
26365
- // src/utils/ai-guide.ts
26366
- var GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
26367
- var GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
26368
- var GLOBAL_GUIDE_BODY = `## wairon \u2014 Spec-Driven Development (optional)
26369
-
26370
- If \`.wai/specs/\` exists, the wairon SDD workflow is active; otherwise ignore it. wairon does not orchestrate sessions \u2014 it equips yours.
26371
-
26372
- ### In SDD Projects:
26373
- - **Source of Truth**: All architecture lives in the spec tree under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 L5 Narrative). Do not edit generated agent config files under \`.claude/agents/\` (rebuilt via \`wairon generate\`).
26374
- - **Validation**: Conformance checks (stereotype rules, cycle checks, reference integrity) are run via the \`sdd_validate_tree\` MCP tool.
26375
- - **Operating Rules**:
26376
- 1. **Skills**: Use \`sdd-architect\` to design (and \`sdd-implement\`, \`sdd-narrative\`, \`sdd-auditor\`). Refer to project's local guide file for detailed constraints.
26377
- 2. **MCP Tools Only**: Author/validate specs *only* via \`sdd_*\` tools (e.g. \`sdd_initialize_system\`, \`sdd_validate_tree\`).
26378
- 3. **No CLI Exec**: Do not run the \`wairon\` CLI (human tool). Use MCP tools \`sdd_validate_tree\` and \`sdd_get_status\` instead.
26379
- 4. **Delegation**: Delegate implementation via the \`sdd-delegate\` skill \u2014 live agent briefs (\`sdd_get_agent_brief\` MCP tool / \`wairon-agent://\` resource) are composed per call and always current; no session restart. Generated agent files are an optional materialized view of the same topology. User-owned per-agent guidance may live in \`.wai/agents/<agent-id>.md\` (folded into every brief; scaffold via \`wairon agent customize <id>\`).
26380
- 5. **Design First**: Complete spec and pass \`sdd_validate_tree\` before writing code.
26381
- 6. **Consistency**: Code must match L3 interfaces and L5 narratives exactly. If the spec is wrong, stop and update the spec.
26382
- 7. **Subprojects & Namespacing**: If a subsystem uses \`projectPath\` delegation, target its specs using namespaced IDs (e.g. \`subsystem::component\`). Use leading \`::\` to target root (e.g. \`::shared::type\`) and \`super::\` to go up a level (e.g. \`super::sibling\`). wairon automatically resolves the path and strips the prefix on writes.`;
26383
- var LOCAL_GUIDE_BODY = `## Wairon \u2014 Spec-Driven Development (you are operating inside it)
26384
-
26385
- This project uses **wairon**. System specs live under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 Narrative); agent topology and code are derived from it.
26386
-
26387
- **Do NOT search files or read agent configs to learn about wairon or SDD. Use the context here and the \`sdd-architect\` skill to start.**
26388
-
26389
- **Your first move: call the \`sdd_get_status\` MCP tool** (or \`wairon/sdd_get_status\`) to see the spec tree. Do not parse files or run CLI commands manually.
26390
-
26391
- ### How you operate
26392
- - **To design/modify specs**: Use **\`sdd-architect\`** skill (in \`.claude/skills/\` or \`.gemini/skills/\`).
26393
- - **Manage specs via MCP tools only**: Use \`sdd_initialize_system\`, \`sdd_add_subsystem\`, \`sdd_add_component\`, \`sdd_define_interface\`, \`sdd_write_narrative\`, \`sdd_add_type\`, \`sdd_get_spec\`, \`sdd_delete_spec\`, \`sdd_validate_tree\`, and \`sdd_get_status\` (namespaced if needed). Do not edit specs manually.
26394
- - **Subprojects & Namespacing (Chaining)**: If a subsystem defines a \`projectPath\`, its entire \`.wai/\` spec tree is recursively loaded and namespaced with the subsystem ID as a prefix (using \`::\`, e.g. \`billing::invoice::invoice_portal\`). Use the qualified namespaced ID with the parent MCP tools; wairon will resolve the path and strip the prefix automatically.
26395
- - **Leading \`::\`**: Bypasses the local subsystem prefix to resolve absolute from the system root (e.g. \`::shared::error-type\`).
26396
- - **\`super::\`**: Goes up one parent subsystem level (e.g. \`super::sibling_comp\`, \`super::super::parent_sibling\`).
26397
- - **Do not run the \`wairon\` CLI**: Use \`sdd_validate_tree\` and \`sdd_get_status\` instead of CLI commands.
26398
- - **Handoff to implementation**: Once design is complete and validates cleanly, tell the human: *"The specs are complete and validate. Please run \`wairon lock\` to confirm and freeze them."* No session restart is needed after the lock \u2014 delegate implementation right away via the \`sdd-delegate\` skill.
26399
- - **To implement code**: Delegate via the \`sdd-delegate\` skill: fetch the component's live brief with the \`sdd_get_agent_brief\` MCP tool (or the \`wairon-agent://\` resource) and spawn a subagent from it. Briefs are composed per call from the current spec tree, so they are always current \u2014 never wait for a restart. Implementations must match L3 interfaces and L5 narratives exactly. Generated agent files under \`.claude/agents/\` are an optional materialized view of the same topology \u2014 the live briefs are canonical.
26400
-
26401
- ### Rules (enforced by \`sdd_validate_tree\`)
26402
- 1. **Design before code**: Complete spec and pass validator before writing source code.
26403
- 2. **Human-in-the-loop**: Ask user approval for each spec layer before proceeding.
26404
- 3. **Spec consistency**: If a 1:1 narrative match is incorrect or conflicts with L0 requirements, escalate a spec revision first. Never ship mismatched code.
26405
- 4. **No persistence shortcuts & strict layers**: A Portal must never depend directly on a Store, Registry, or Adapter. Portal reads MAY go through a Repository/Index facade (passthrough reads need no per-entity Orchestrator ceremony), but a Portal narrative call or dispatch-table binding that reaches a write-effect facade method is an error (\`PORTAL_WRITE_SHORTCUT\`) \u2014 writes always route through an Orchestrator. Held domain state always lives in a dedicated data component, never as fields inside an Orchestrator. Two sanctioned shapes: the RECOMMENDED Repository pattern (owns Store + Registry + Index; consumers depend on the facade), or \u2014 for genuinely simple state \u2014 a deliberately standalone Store (workflow-layer consumers only, acknowledged with a lint.allow reason on the UNOWNED_STORE warning). Never combine Store/Registry/Index roles into one component, and never fold state into a consuming component because a link was refused.
26406
-
26407
- ### Component Vocabulary
26408
- * **Blocks**: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer.
26409
- * **Patterns**: Repository \u2014 the composable pattern that \`owns\` its member blocks: one Store with its Registry, Indexes and Queries, and optionally an Adapter.
26410
- * **Variants**: \`gateway\`, a Portal that authenticates, authorizes, validates or rate-limits before it dispatches. Logic is an Orchestrator, and \`dependencyClass: pure | read\` bounds what it may depend on (unset = a workflow). Specialist and Gateway are retired stereotypes.
26411
- * Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
26412
- function globalGuideFilePath(targetType) {
26413
- if (targetType === "claude") return path22.join(process.env["CLAUDE_CONFIG_DIR"] || path22.join(os4.homedir(), ".claude"), "CLAUDE.md");
26414
- if (targetType === "gemini") return path22.join(process.env["GEMINI_CONFIG_DIR"] || path22.join(os4.homedir(), ".gemini"), "GEMINI.md");
26415
- return null;
26416
- }
26417
- function localGuideFilePath(projectRoot, targetType) {
26418
- if (targetType === "claude") return path22.join(projectRoot, ".claude", "CLAUDE.md");
26419
- if (targetType === "gemini" || targetType === "agy") return path22.join(projectRoot, ".gemini", "GEMINI.md");
26420
- return null;
26345
+ var sdkPortal = __toESM(require_dist());
26346
+ var STAGING_PREFIX = ".wai-staging-";
26347
+ var BACKUP_DIR = ".wai-backups";
26348
+ function buildTreeArchive2(roots, projectName, stateId, includeDerived) {
26349
+ return sdkPortal.buildTreeArchive(roots, projectName, stateId, includeDerived);
26421
26350
  }
26422
- function injectGuide(filePath, scope) {
26423
- const body = scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
26424
- const section = `
26425
-
26426
- ${GUIDE_MARKER_START}
26427
- ${versionStamp()}
26428
- ${body}
26429
- ${GUIDE_MARKER_END}
26430
- `;
26431
- const existing = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8") : "";
26432
- const stripped = stripGuideSection(existing);
26433
- const newContent = stripped.trimEnd() + section;
26434
- fs17.mkdirSync(path22.dirname(filePath), { recursive: true });
26435
- fs17.writeFileSync(filePath, newContent, "utf-8");
26351
+ function inspectTreeArchive2(archive) {
26352
+ return sdkPortal.inspectTreeArchive(archive);
26436
26353
  }
26437
- function stripGuideSection(content) {
26438
- const start = content.indexOf(GUIDE_MARKER_START);
26439
- const end = content.indexOf(GUIDE_MARKER_END);
26440
- if (start === -1 || end === -1) return content;
26441
- return content.slice(0, start) + content.slice(end + GUIDE_MARKER_END.length);
26354
+ function extractTreeArchive2(archive, destDir, refuseExecutableEntries) {
26355
+ const limits = void 0;
26356
+ return sdkPortal.extractTreeArchive(archive, destDir, limits, refuseExecutableEntries);
26442
26357
  }
26443
- function writeRootGuideDelegator(projectRoot, targetType) {
26444
- if (targetType === "claude") {
26445
- const filePath = path22.join(projectRoot, "CLAUDE.md");
26446
- const content = `@.claude/CLAUDE.md
26447
-
26448
- # Wairon SDD Project
26449
-
26450
- This project uses the Wairon Spec-Driven Development (SDD) framework. The imported
26451
- \`.claude/CLAUDE.md\` above is your complete operating guide \u2014 you already have the
26452
- full context, so don't search the project to learn how wairon or SDD works.
26453
-
26454
- To design or modify the system, invoke the **\`sdd-architect\`** skill
26455
- (in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
26456
- the \`wairon\` CLI is the human developer's tool, not yours.
26457
- `;
26458
- fs17.writeFileSync(filePath, content, "utf-8");
26459
- } else if (targetType === "gemini" || targetType === "agy") {
26460
- const filePath = path22.join(projectRoot, "GEMINI.md");
26461
- const content = `# Wairon SDD Project
26462
- ${GUIDE_MARKER_START}
26463
- ${versionStamp()}
26464
- ${LOCAL_GUIDE_BODY}
26465
- ${GUIDE_MARKER_END}
26466
- `;
26467
- fs17.writeFileSync(filePath, content, "utf-8");
26468
- } else if (targetType === "cursor") {
26469
- const filePath = path22.join(projectRoot, ".cursorrules");
26470
- const content = `# Wairon SDD Project
26471
-
26472
- This project uses the Wairon Spec-Driven Development (SDD) framework.
26473
-
26474
- Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
26475
- `;
26476
- fs17.writeFileSync(filePath, content, "utf-8");
26477
- } else if (targetType === "copilot") {
26478
- const filePath = path22.join(projectRoot, ".github", "copilot-instructions.md");
26479
- fs17.mkdirSync(path22.dirname(filePath), { recursive: true });
26480
- const content = `# Wairon SDD Project
26481
-
26482
- This project uses the Wairon Spec-Driven Development (SDD) framework.
26483
-
26484
- Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
26485
- `;
26486
- fs17.writeFileSync(filePath, content, "utf-8");
26487
- } else if (targetType === "codex") {
26488
- const filePath = path22.join(projectRoot, ".codexrules");
26489
- const content = `# Wairon SDD Project
26490
-
26491
- Refer to [.codex/agents/](.codex/agents/) for full instructions.
26492
- `;
26493
- fs17.writeFileSync(filePath, content, "utf-8");
26358
+ function hasSpecTree(root) {
26359
+ if (pathExists(aiPathsAt(root).projectConfig())) {
26360
+ return true;
26494
26361
  }
26362
+ return false;
26495
26363
  }
26496
- var GUIDE_TARGETS = ["claude", "gemini", "agy", "cursor", "copilot", "codex"];
26497
- function reinjectLocalGuides(projectRoot, targetTypes) {
26498
- const written = [];
26499
- for (const type of targetTypes) {
26500
- if (!GUIDE_TARGETS.includes(type)) continue;
26501
- const guidePath = localGuideFilePath(projectRoot, type);
26502
- if (guidePath) {
26503
- injectGuide(guidePath, "local");
26504
- if (!written.includes(guidePath)) written.push(guidePath);
26364
+ function hasAuthoredSpecs(root) {
26365
+ const paths = aiPathsAt(root);
26366
+ const specsDir = paths.specsDir();
26367
+ if (!pathExists(specsDir)) {
26368
+ return false;
26369
+ }
26370
+ const systemIndex = path22.resolve(paths.specsSystem());
26371
+ for (const file of listFilesRecursive(specsDir, ".yaml")) {
26372
+ if (path22.resolve(file) !== systemIndex) {
26373
+ return true;
26505
26374
  }
26506
- writeRootGuideDelegator(projectRoot, type);
26507
26375
  }
26508
- return written;
26509
- }
26510
-
26511
- // src/core/context.ts
26512
- function contextDir(...segments) {
26513
- return aiDir("context", ...segments);
26514
- }
26515
- var CONTEXT_PATHS = {
26516
- dir: () => contextDir(),
26517
- projectMd: () => contextDir("project.md"),
26518
- architectureMd: () => contextDir("architecture.md"),
26519
- domainsMd: () => contextDir("domains.md"),
26520
- waironGuideMd: () => contextDir("wairon-guide.md")
26521
- };
26522
- function hasContext() {
26523
- return pathExists(CONTEXT_PATHS.projectMd());
26524
- }
26525
- function hasArchitectureContext() {
26526
- return pathExists(CONTEXT_PATHS.architectureMd());
26527
- }
26528
- function readProjectContext() {
26529
- return readFileOrNull(CONTEXT_PATHS.projectMd());
26530
- }
26531
- function readArchitectureContext() {
26532
- return readFileOrNull(CONTEXT_PATHS.architectureMd());
26533
- }
26534
- function writeProjectContext(content) {
26535
- writeFile(CONTEXT_PATHS.projectMd(), content);
26376
+ return false;
26536
26377
  }
26537
- function writeArchitectureContext(content) {
26538
- writeFile(CONTEXT_PATHS.architectureMd(), content);
26378
+ function createStagingDir(destDir) {
26379
+ const root = path22.resolve(destDir);
26380
+ fs17.mkdirSync(root, { recursive: true });
26381
+ const stagingDir = fs17.mkdtempSync(path22.join(root, STAGING_PREFIX));
26382
+ return stagingDir;
26539
26383
  }
26540
- function renderDomainsDoc() {
26541
- const domains = resolveDomains();
26542
- const lines = [
26543
- versionStamp(),
26544
- `# Domains`,
26545
- ``,
26546
- `> Auto-generated by wairon. The human developer rebuilds this with \`wairon generate\`. `,
26547
- ``
26548
- ];
26549
- if (domains.length === 0) {
26550
- lines.push("_No domains yet. Define subsystems in the spec tree, or add free-standing domains with `wairon domains add`._");
26551
- } else {
26552
- lines.push(`**${domains.length} domain(s).**`);
26553
- lines.push("");
26554
- lines.push("| ID | Name | Source | Owned paths |");
26555
- lines.push("|----|------|--------|-------------|");
26556
- for (const d of domains) {
26557
- const name = d.name ?? d.id;
26558
- const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
26559
- lines.push(`| \`${d.id}\` | ${name} | ${source} | \`${d.ownedPaths.join("`, `") || "\u2014"}\` |`);
26384
+ function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
26385
+ const root = path22.resolve(destDir);
26386
+ const backupDir = path22.join(root, BACKUP_DIR, timestampSlug());
26387
+ let backedUp = false;
26388
+ for (const rootRel of roots) {
26389
+ const relative9 = rootRel === "." ? "" : rootRel;
26390
+ const stagedSpecDir = path22.join(stagingDir, relative9, ".wai");
26391
+ if (!fs17.existsSync(stagedSpecDir)) continue;
26392
+ const liveSpecDir = liveSpecDirFor(path22.join(root, relative9));
26393
+ if (backupExisting && liveSpecDir && fs17.existsSync(liveSpecDir)) {
26394
+ const backupTarget = path22.join(backupDir, relative9, path22.basename(liveSpecDir));
26395
+ fs17.mkdirSync(path22.dirname(backupTarget), { recursive: true });
26396
+ fs17.renameSync(liveSpecDir, backupTarget);
26397
+ backedUp = true;
26398
+ } else if (liveSpecDir && fs17.existsSync(liveSpecDir)) {
26399
+ fs17.rmSync(liveSpecDir, { recursive: true, force: true });
26560
26400
  }
26401
+ const target = path22.join(root, relative9, ".wai");
26402
+ fs17.mkdirSync(path22.dirname(target), { recursive: true });
26403
+ if (fs17.existsSync(target)) fs17.rmSync(target, { recursive: true, force: true });
26404
+ fs17.renameSync(stagedSpecDir, target);
26561
26405
  }
26562
- return lines.join("\n") + "\n";
26406
+ if (backedUp) {
26407
+ return backupDir;
26408
+ }
26409
+ return "";
26563
26410
  }
26564
- function renderWaironGuide() {
26565
- const domains = resolveDomains();
26566
- let projectName = "this project";
26411
+ function discardStagingDir(stagingDir) {
26567
26412
  try {
26568
- projectName = projectConfigRepository.load()?.name ?? projectName;
26413
+ fs17.rmSync(stagingDir, { recursive: true, force: true });
26569
26414
  } catch {
26570
26415
  }
26571
- const projectCtx = readProjectContext();
26572
- const archCtx = readArchitectureContext();
26573
- const lines = [
26574
- versionStamp(),
26575
- `<!-- wairon-generated \u2014 do not edit directly; the human developer rebuilds this with \`wairon generate\` -->`,
26576
- ``
26577
- ];
26578
- if (projectCtx) {
26579
- lines.push(`# Project Context \u2014 ${projectName}`);
26580
- lines.push("");
26581
- lines.push(projectCtx.trim());
26582
- lines.push("");
26583
- lines.push("---");
26584
- lines.push("");
26416
+ }
26417
+ function exportSpecTree(includeDerived, allowPartial) {
26418
+ const system = loadSystemSpec();
26419
+ if (!system) {
26420
+ throw new Error("no spec tree to export at this project root");
26585
26421
  }
26586
- if (archCtx) {
26587
- lines.push("# Architecture");
26588
- lines.push("");
26589
- lines.push(archCtx.trim());
26590
- lines.push("");
26591
- lines.push("---");
26592
- lines.push("");
26593
- }
26594
- lines.push(`# Domain Map (${domains.length} domain${domains.length !== 1 ? "s" : ""})`);
26595
- lines.push("");
26596
- if (domains.length === 0) {
26597
- lines.push("_No domains yet._");
26598
- } else {
26599
- lines.push("| ID | Source | Name |");
26600
- lines.push("|----|--------|------|");
26601
- for (const d of domains) {
26602
- const name = d.name ?? d.id;
26603
- const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
26604
- lines.push(`| \`${d.id}\` | ${source} | ${name} |`);
26605
- }
26606
- }
26607
- lines.push("");
26608
- lines.push("---");
26609
- lines.push("");
26610
- const mcpSettingsPath = require("path").join(process.cwd(), ".claude", "settings.json");
26611
- let mcpInstalled = false;
26612
- try {
26613
- const s = JSON.parse(require("fs").readFileSync(mcpSettingsPath, "utf8"));
26614
- mcpInstalled = !!s?.mcpServers?.wairon;
26615
- } catch {
26616
- }
26617
- if (mcpInstalled) {
26618
- lines.push("# wairon MCP Tools");
26619
- lines.push("");
26620
- lines.push("The **wairon MCP server** is active in this project. The tools are self-describing; call them directly:");
26621
- lines.push("");
26622
- lines.push("- Authoring: `sdd_initialize_system`, `sdd_add_subsystem`, `sdd_set_public_interfaces`, `sdd_set_subsystem_project_path`, `sdd_add_component`, `sdd_define_interface`, `sdd_set_endpoints`, `sdd_write_narrative`, `sdd_add_type`.");
26623
- lines.push("- Reading & maintenance: `sdd_get_spec`, `sdd_update_spec`, `sdd_delete_spec`, `sdd_validate_tree`, `sdd_get_status`.");
26624
- lines.push("- Topology: `listAgents`, `getAgent`, `listDomains`, `validateTopology`, `getProjectConfig`.");
26625
- lines.push("");
26626
- lines.push("Use these MCP tools to query and change project state \u2014 never the `wairon` CLI (that is the human developer's tool).");
26627
- lines.push("");
26628
- lines.push("---");
26629
- lines.push("");
26630
- }
26631
- lines.push(GLOBAL_GUIDE_BODY);
26632
- lines.push("");
26633
- return lines.join("\n");
26634
- }
26635
- function syncContextFiles() {
26636
- const domainsContent = renderDomainsDoc();
26637
- const guideContent = renderWaironGuide();
26638
- const domainsUpdated = writeFileIfChanged(CONTEXT_PATHS.domainsMd(), domainsContent);
26639
- const guideUpdated = writeFileIfChanged(CONTEXT_PATHS.waironGuideMd(), guideContent);
26640
- return { domainsUpdated, guideUpdated };
26641
- }
26642
-
26643
- // src/core/treetransfer.ts
26644
- var fs18 = __toESM(require("fs"));
26645
- var path23 = __toESM(require("path"));
26646
- var sdkPortal = __toESM(require_dist());
26647
- var STAGING_PREFIX = ".wai-staging-";
26648
- var BACKUP_DIR = ".wai-backups";
26649
- function buildTreeArchive2(roots, projectName, stateId, includeDerived) {
26650
- return sdkPortal.buildTreeArchive(roots, projectName, stateId, includeDerived);
26651
- }
26652
- function inspectTreeArchive2(archive) {
26653
- return sdkPortal.inspectTreeArchive(archive);
26654
- }
26655
- function extractTreeArchive2(archive, destDir, refuseExecutableEntries) {
26656
- const limits = void 0;
26657
- return sdkPortal.extractTreeArchive(archive, destDir, limits, refuseExecutableEntries);
26658
- }
26659
- function hasSpecTree(root) {
26660
- if (pathExists(aiPathsAt(root).projectConfig())) {
26661
- return true;
26662
- }
26663
- return false;
26664
- }
26665
- function hasAuthoredSpecs(root) {
26666
- const paths = aiPathsAt(root);
26667
- const specsDir = paths.specsDir();
26668
- if (!pathExists(specsDir)) {
26669
- return false;
26670
- }
26671
- const systemIndex = path23.resolve(paths.specsSystem());
26672
- for (const file of listFilesRecursive(specsDir, ".yaml")) {
26673
- if (path23.resolve(file) !== systemIndex) {
26674
- return true;
26675
- }
26676
- }
26677
- return false;
26678
- }
26679
- function createStagingDir(destDir) {
26680
- const root = path23.resolve(destDir);
26681
- fs18.mkdirSync(root, { recursive: true });
26682
- const stagingDir = fs18.mkdtempSync(path23.join(root, STAGING_PREFIX));
26683
- return stagingDir;
26684
- }
26685
- function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
26686
- const root = path23.resolve(destDir);
26687
- const backupDir = path23.join(root, BACKUP_DIR, timestampSlug());
26688
- let backedUp = false;
26689
- for (const rootRel of roots) {
26690
- const relative9 = rootRel === "." ? "" : rootRel;
26691
- const stagedSpecDir = path23.join(stagingDir, relative9, ".wai");
26692
- if (!fs18.existsSync(stagedSpecDir)) continue;
26693
- const liveSpecDir = liveSpecDirFor(path23.join(root, relative9));
26694
- if (backupExisting && liveSpecDir && fs18.existsSync(liveSpecDir)) {
26695
- const backupTarget = path23.join(backupDir, relative9, path23.basename(liveSpecDir));
26696
- fs18.mkdirSync(path23.dirname(backupTarget), { recursive: true });
26697
- fs18.renameSync(liveSpecDir, backupTarget);
26698
- backedUp = true;
26699
- } else if (liveSpecDir && fs18.existsSync(liveSpecDir)) {
26700
- fs18.rmSync(liveSpecDir, { recursive: true, force: true });
26701
- }
26702
- const target = path23.join(root, relative9, ".wai");
26703
- fs18.mkdirSync(path23.dirname(target), { recursive: true });
26704
- if (fs18.existsSync(target)) fs18.rmSync(target, { recursive: true, force: true });
26705
- fs18.renameSync(stagedSpecDir, target);
26706
- }
26707
- if (backedUp) {
26708
- return backupDir;
26709
- }
26710
- return "";
26711
- }
26712
- function discardStagingDir(stagingDir) {
26713
- try {
26714
- fs18.rmSync(stagingDir, { recursive: true, force: true });
26715
- } catch {
26716
- }
26717
- }
26718
- function exportSpecTree(includeDerived, allowPartial) {
26719
- const system = loadSystemSpec();
26720
- if (!system) {
26721
- throw new Error("no spec tree to export at this project root");
26722
- }
26723
- const inspection = inspectChainedRoots();
26724
- const root = getProjectRoot();
26725
- const skipped = [...inspection.skipped];
26726
- const roots = [{ relativePath: ".", waiDir: aiPathsAt(root).root() }];
26727
- for (const rel2 of inspection.roots) {
26728
- const waiDir = aiPathsAt(path23.resolve(root, rel2)).root();
26729
- if (pathExists(waiDir)) {
26730
- roots.push({ relativePath: rel2, waiDir });
26731
- } else {
26732
- skipped.push({ mount: rel2, projectPath: rel2, reason: "no-spec-tree" });
26733
- }
26422
+ const inspection = inspectChainedRoots();
26423
+ const root = getProjectRoot();
26424
+ const skipped = [...inspection.skipped];
26425
+ const roots = [{ relativePath: ".", waiDir: aiPathsAt(root).root() }];
26426
+ for (const rel2 of inspection.roots) {
26427
+ const waiDir = aiPathsAt(path22.resolve(root, rel2)).root();
26428
+ if (pathExists(waiDir)) {
26429
+ roots.push({ relativePath: rel2, waiDir });
26430
+ } else {
26431
+ skipped.push({ mount: rel2, projectPath: rel2, reason: "no-spec-tree" });
26432
+ }
26734
26433
  }
26735
26434
  if (skipped.length > 0 && !allowPartial) {
26736
26435
  const detail = skipped.map((s) => `${s.mount} (${s.reason})`).join(", ");
@@ -26756,7 +26455,7 @@ function importSpecTree(archive, options) {
26756
26455
  if (!info.compatible) {
26757
26456
  throw new Error("incompatible .waitree archive (format or minimum wairon version)");
26758
26457
  }
26759
- const destDir = path23.resolve(options.destDir ?? getProjectRoot());
26458
+ const destDir = path22.resolve(options.destDir ?? getProjectRoot());
26760
26459
  const occupied = hasSpecTree(destDir);
26761
26460
  const authored = hasAuthoredSpecs(destDir);
26762
26461
  if (authored && options.replaceExisting !== true) {
@@ -26787,10 +26486,10 @@ function importSpecTree(archive, options) {
26787
26486
  return result;
26788
26487
  }
26789
26488
  function liveSpecDirFor(rootDir) {
26790
- const modern = path23.join(rootDir, ".wai");
26791
- if (fs18.existsSync(modern)) return modern;
26792
- const legacy = path23.join(rootDir, ".wairon");
26793
- if (fs18.existsSync(legacy)) return legacy;
26489
+ const modern = path22.join(rootDir, ".wai");
26490
+ if (fs17.existsSync(modern)) return modern;
26491
+ const legacy = path22.join(rootDir, ".wairon");
26492
+ if (fs17.existsSync(legacy)) return legacy;
26794
26493
  return null;
26795
26494
  }
26796
26495
  function timestampSlug() {
@@ -26798,10 +26497,10 @@ function timestampSlug() {
26798
26497
  }
26799
26498
 
26800
26499
  // src/exporters/generate.ts
26801
- var path27 = __toESM(require("path"));
26500
+ var path26 = __toESM(require("path"));
26802
26501
 
26803
26502
  // src/exporters/claude.ts
26804
- var path24 = __toESM(require("path"));
26503
+ var path23 = __toESM(require("path"));
26805
26504
  var MODEL_BY_TIER = {
26806
26505
  small: "haiku",
26807
26506
  standard: "sonnet",
@@ -26840,7 +26539,7 @@ var ClaudeExporter = class {
26840
26539
  outputPath(ctx) {
26841
26540
  const { agent, target, projectRoot } = ctx;
26842
26541
  const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
26843
- return path24.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26542
+ return path23.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26844
26543
  }
26845
26544
  export(ctx) {
26846
26545
  const { agent, renderedInstructions, budget } = ctx;
@@ -26865,7 +26564,7 @@ var ClaudeExporter = class {
26865
26564
  };
26866
26565
 
26867
26566
  // src/exporters/custom.ts
26868
- var path25 = __toESM(require("path"));
26567
+ var path24 = __toESM(require("path"));
26869
26568
  var CustomExporter = class {
26870
26569
  constructor() {
26871
26570
  this.targetType = "custom";
@@ -26875,7 +26574,7 @@ var CustomExporter = class {
26875
26574
  if (!("outputDir" in target)) {
26876
26575
  throw new Error("CustomExporter requires target.outputDir");
26877
26576
  }
26878
- return path25.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26577
+ return path24.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26879
26578
  }
26880
26579
  export(ctx) {
26881
26580
  const { agent, target, renderedInstructions } = ctx;
@@ -26898,7 +26597,7 @@ var CustomExporter = class {
26898
26597
  };
26899
26598
 
26900
26599
  // src/exporters/gemini.ts
26901
- var path26 = __toESM(require("path"));
26600
+ var path25 = __toESM(require("path"));
26902
26601
  var GeminiExporter = class {
26903
26602
  constructor() {
26904
26603
  this.targetType = "gemini";
@@ -26906,7 +26605,7 @@ var GeminiExporter = class {
26906
26605
  outputPath(ctx) {
26907
26606
  const { agent, target, projectRoot } = ctx;
26908
26607
  const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
26909
- return path26.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
26608
+ return path25.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
26910
26609
  }
26911
26610
  export(ctx) {
26912
26611
  const { agent, renderedInstructions } = ctx;
@@ -27003,7 +26702,7 @@ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProj
27003
26702
  const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
27004
26703
  if (!targetConfig) continue;
27005
26704
  const ctx = { agent, projectRoot, target: targetConfig };
27006
- expected.add(path27.resolve(getExporter(targetConfig).outputPath(ctx)));
26705
+ expected.add(path26.resolve(getExporter(targetConfig).outputPath(ctx)));
27007
26706
  }
27008
26707
  }
27009
26708
  return expected;
@@ -27112,167 +26811,460 @@ function retireSpecialists(apply) {
27112
26811
  if (retype.dependencyClass) orchestrator.dependencyClass = retype.dependencyClass;
27113
26812
  saveComponentSpec(orchestrator);
27114
26813
  }
27115
- const rebasedVariants = rebaseProjectVariants("Specialist", "Orchestrator");
27116
- invalidateSpecCache();
27117
- return { retyped, rebasedVariants, applied: true };
26814
+ const rebasedVariants = rebaseProjectVariants("Specialist", "Orchestrator");
26815
+ invalidateSpecCache();
26816
+ return { retyped, rebasedVariants, applied: true };
26817
+ }
26818
+
26819
+ // src/core/narrative-repair.ts
26820
+ function repairForeignStepFields(apply) {
26821
+ const implementations = loadImplementationSpecs();
26822
+ const repairs = [];
26823
+ const changed = [];
26824
+ for (const impl of implementations) {
26825
+ let touched = false;
26826
+ for (const method of impl.methods) {
26827
+ for (const step of method.narrative) {
26828
+ const fields = narrativeStepForeignFields(step);
26829
+ if (!fields.length) continue;
26830
+ repairs.push({
26831
+ implementation: impl.id,
26832
+ method: method.name,
26833
+ stepNumber: step.stepNumber,
26834
+ stepType: step.type,
26835
+ fields
26836
+ });
26837
+ for (const field of fields) delete step[field];
26838
+ touched = true;
26839
+ }
26840
+ }
26841
+ if (touched) changed.push(impl);
26842
+ }
26843
+ if (apply && changed.length) {
26844
+ for (const impl of changed) saveImplementationSpec(impl);
26845
+ invalidateSpecCache();
26846
+ }
26847
+ return repairs;
26848
+ }
26849
+
26850
+ // src/core/approval.ts
26851
+ var crypto4 = __toESM(require("crypto"));
26852
+ var path27 = __toESM(require("path"));
26853
+ function diffSize(d) {
26854
+ return d.added.length + d.changed.length + d.removed.length;
26855
+ }
26856
+ function digest(content) {
26857
+ const normalized = content.replace(/\r\n/g, "\n");
26858
+ return crypto4.createHash("sha256").update(normalized, "utf8").digest("hex");
26859
+ }
26860
+ function currentSpecDigests(root = getProjectRoot()) {
26861
+ const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path27.resolve(root, s.projectPath).split(path27.sep).join("/")}/`);
26862
+ const out = {};
26863
+ for (const [abs, content] of snapshotSpecFiles()) {
26864
+ const normalized = path27.resolve(abs).split(path27.sep).join("/");
26865
+ if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
26866
+ out[path27.relative(root, abs).split(path27.sep).join("/")] = digest(content);
26867
+ }
26868
+ return out;
26869
+ }
26870
+ function captureApprovedSpecs(root = getProjectRoot(), scope) {
26871
+ const current2 = currentSpecDigests(root);
26872
+ if (!scope) return current2;
26873
+ const previous = readLockRecord()?.specs ?? {};
26874
+ const specs = { ...previous };
26875
+ for (const rel2 of Object.keys(previous)) {
26876
+ if (scope.paths.has(rel2) && current2[rel2] === void 0) delete specs[rel2];
26877
+ }
26878
+ for (const rel2 of scope.paths) {
26879
+ if (current2[rel2] !== void 0) specs[rel2] = current2[rel2];
26880
+ }
26881
+ return specs;
26882
+ }
26883
+ function diffAgainstApproval(root = getProjectRoot()) {
26884
+ const approved = approvedSpecs(root);
26885
+ if (!approved) return null;
26886
+ const current2 = currentSpecDigests(root);
26887
+ const added = [];
26888
+ const changed = [];
26889
+ const removed = [];
26890
+ const unchangedPaths = [];
26891
+ for (const [rel2, d] of Object.entries(current2)) {
26892
+ const before = approved[rel2];
26893
+ if (before === void 0) added.push(rel2);
26894
+ else if (before !== d) changed.push(rel2);
26895
+ else unchangedPaths.push(rel2);
26896
+ }
26897
+ for (const rel2 of Object.keys(approved)) {
26898
+ if (current2[rel2] === void 0) removed.push(rel2);
26899
+ }
26900
+ return {
26901
+ added: added.sort(),
26902
+ changed: changed.sort(),
26903
+ removed: removed.sort(),
26904
+ unchangedPaths: unchangedPaths.sort()
26905
+ };
26906
+ }
26907
+ function approvedSpecs(root) {
26908
+ return approvalRecord(root)?.specs ?? null;
26909
+ }
26910
+ function approvalRecord(root = getProjectRoot()) {
26911
+ return readLockRecordAt(root);
26912
+ }
26913
+ function settledSpecPaths(root = getProjectRoot()) {
26914
+ const diff = diffAgainstApproval(root);
26915
+ return diff ? new Set(diff.unchangedPaths) : null;
26916
+ }
26917
+ function pinOf(stateId) {
26918
+ return `${stateId.algorithm}:${stateId.digest}`;
26919
+ }
26920
+ function currentChildPins(mounts, root = getProjectRoot()) {
26921
+ const pins = {};
26922
+ for (const mount of mounts) {
26923
+ if (!mount.projectPath || mount.id.includes("::")) continue;
26924
+ const child = readLockRecordAt(path27.resolve(root, mount.projectPath));
26925
+ if (child) pins[mount.id] = pinOf(child.stateId);
26926
+ }
26927
+ return pins;
26928
+ }
26929
+ function movedChildren(mounts, root = getProjectRoot()) {
26930
+ const pinned = approvalRecord(root)?.children;
26931
+ if (!pinned) return [];
26932
+ const now = currentChildPins(mounts, root);
26933
+ const moved = [];
26934
+ for (const [id, was] of Object.entries(pinned)) {
26935
+ const current2 = now[id] ?? null;
26936
+ if (current2 !== was) moved.push({ id, pinned: was, now: current2 });
26937
+ }
26938
+ return moved;
26939
+ }
26940
+
26941
+ // src/core/approver.ts
26942
+ var import_child_process = require("child_process");
26943
+ var os4 = __toESM(require("os"));
26944
+ function gitConfig(key) {
26945
+ try {
26946
+ const value = (0, import_child_process.execFileSync)("git", ["config", "--get", key], {
26947
+ encoding: "utf8",
26948
+ stdio: ["ignore", "pipe", "ignore"],
26949
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
26950
+ }).trim();
26951
+ return value || void 0;
26952
+ } catch {
26953
+ return void 0;
26954
+ }
26955
+ }
26956
+ function machineIdentity() {
26957
+ let user = "unknown";
26958
+ try {
26959
+ user = os4.userInfo().username || user;
26960
+ } catch {
26961
+ }
26962
+ let host = "";
26963
+ try {
26964
+ host = os4.hostname();
26965
+ } catch {
26966
+ }
26967
+ return { id: host ? `${user}@${host}` : user, source: "os" };
26968
+ }
26969
+ function localApprover() {
26970
+ const name = gitConfig("user.name");
26971
+ const email = gitConfig("user.email");
26972
+ if (name && email) return { id: `${name} <${email}>`, source: "git" };
26973
+ if (email) return { id: email, source: "git" };
26974
+ return machineIdentity();
26975
+ }
26976
+
26977
+ // src/utils/ai-guide.ts
26978
+ var fs18 = __toESM(require("fs"));
26979
+ var os5 = __toESM(require("os"));
26980
+ var path28 = __toESM(require("path"));
26981
+
26982
+ // src/core/stamp.ts
26983
+ function versionStamp() {
26984
+ return `<!-- wairon-version: ${WAIRON_VERSION} -->`;
26985
+ }
26986
+ var STAMP_RE = /<!--\s*wairon-version:\s*([^\s]+)\s*-->/;
26987
+ function readStampVersion(content) {
26988
+ const m = content.match(STAMP_RE);
26989
+ return m ? m[1] : null;
26990
+ }
26991
+
26992
+ // src/utils/ai-guide.ts
26993
+ var GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
26994
+ var GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
26995
+ var GLOBAL_GUIDE_BODY = `## wairon \u2014 Spec-Driven Development (optional)
26996
+
26997
+ If \`.wai/specs/\` exists, the wairon SDD workflow is active; otherwise ignore it. wairon does not orchestrate sessions \u2014 it equips yours.
26998
+
26999
+ ### In SDD Projects:
27000
+ - **Source of Truth**: All architecture lives in the spec tree under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 L5 Narrative). Do not edit generated agent config files under \`.claude/agents/\` (rebuilt via \`wairon generate\`).
27001
+ - **Validation**: Conformance checks (stereotype rules, cycle checks, reference integrity) are run via the \`sdd_validate_tree\` MCP tool.
27002
+ - **Operating Rules**:
27003
+ 1. **Skills**: Use \`sdd-architect\` to design (and \`sdd-implement\`, \`sdd-narrative\`, \`sdd-auditor\`). Refer to project's local guide file for detailed constraints.
27004
+ 2. **MCP Tools Only**: Author/validate specs *only* via \`sdd_*\` tools (e.g. \`sdd_initialize_system\`, \`sdd_validate_tree\`).
27005
+ 3. **No CLI Exec**: Do not run the \`wairon\` CLI (human tool). Use MCP tools \`sdd_validate_tree\` and \`sdd_get_status\` instead.
27006
+ 4. **Delegation**: Delegate implementation via the \`sdd-delegate\` skill \u2014 live agent briefs (\`sdd_get_agent_brief\` MCP tool / \`wairon-agent://\` resource) are composed per call and always current; no session restart. Generated agent files are an optional materialized view of the same topology. User-owned per-agent guidance may live in \`.wai/agents/<agent-id>.md\` (folded into every brief; scaffold via \`wairon agent customize <id>\`).
27007
+ 5. **Design First**: Complete spec and pass \`sdd_validate_tree\` before writing code.
27008
+ 6. **Consistency**: Code must match L3 interfaces and L5 narratives exactly. If the spec is wrong, stop and update the spec.
27009
+ 7. **Subprojects & Namespacing**: If a subsystem uses \`projectPath\` delegation, target its specs using namespaced IDs (e.g. \`subsystem::component\`). Use leading \`::\` to target root (e.g. \`::shared::type\`) and \`super::\` to go up a level (e.g. \`super::sibling\`). wairon automatically resolves the path and strips the prefix on writes.`;
27010
+ var LOCAL_GUIDE_BODY = `## Wairon \u2014 Spec-Driven Development (you are operating inside it)
27011
+
27012
+ This project uses **wairon**. System specs live under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 Narrative); agent topology and code are derived from it.
27013
+
27014
+ **Do NOT search files or read agent configs to learn about wairon or SDD. Use the context here and the \`sdd-architect\` skill to start.**
27015
+
27016
+ **Your first move: call the \`sdd_get_status\` MCP tool** (or \`wairon/sdd_get_status\`) to see the spec tree. Do not parse files or run CLI commands manually.
27017
+
27018
+ ### How you operate
27019
+ - **To design/modify specs**: Use **\`sdd-architect\`** skill (in \`.claude/skills/\` or \`.gemini/skills/\`).
27020
+ - **Manage specs via MCP tools only**: Use \`sdd_initialize_system\`, \`sdd_add_subsystem\`, \`sdd_add_component\`, \`sdd_define_interface\`, \`sdd_write_narrative\`, \`sdd_add_type\`, \`sdd_get_spec\`, \`sdd_delete_spec\`, \`sdd_validate_tree\`, and \`sdd_get_status\` (namespaced if needed). Do not edit specs manually.
27021
+ - **Subprojects & Namespacing (Chaining)**: If a subsystem defines a \`projectPath\`, its entire \`.wai/\` spec tree is recursively loaded and namespaced with the subsystem ID as a prefix (using \`::\`, e.g. \`billing::invoice::invoice_portal\`). Use the qualified namespaced ID with the parent MCP tools; wairon will resolve the path and strip the prefix automatically.
27022
+ - **Leading \`::\`**: Bypasses the local subsystem prefix to resolve absolute from the system root (e.g. \`::shared::error-type\`).
27023
+ - **\`super::\`**: Goes up one parent subsystem level (e.g. \`super::sibling_comp\`, \`super::super::parent_sibling\`).
27024
+ - **Do not run the \`wairon\` CLI**: Use \`sdd_validate_tree\` and \`sdd_get_status\` instead of CLI commands.
27025
+ - **Handoff to implementation**: Once design is complete and validates cleanly, tell the human: *"The specs are complete and validate. Please run \`wairon lock\` to confirm and freeze them."* No session restart is needed after the lock \u2014 delegate implementation right away via the \`sdd-delegate\` skill.
27026
+ - **To implement code**: Delegate via the \`sdd-delegate\` skill: fetch the component's live brief with the \`sdd_get_agent_brief\` MCP tool (or the \`wairon-agent://\` resource) and spawn a subagent from it. Briefs are composed per call from the current spec tree, so they are always current \u2014 never wait for a restart. Implementations must match L3 interfaces and L5 narratives exactly. Generated agent files under \`.claude/agents/\` are an optional materialized view of the same topology \u2014 the live briefs are canonical.
27027
+
27028
+ ### Rules (enforced by \`sdd_validate_tree\`)
27029
+ 1. **Design before code**: Complete spec and pass validator before writing source code.
27030
+ 2. **Human-in-the-loop**: Ask user approval for each spec layer before proceeding.
27031
+ 3. **Spec consistency**: If a 1:1 narrative match is incorrect or conflicts with L0 requirements, escalate a spec revision first. Never ship mismatched code.
27032
+ 4. **No persistence shortcuts & strict layers**: A Portal must never depend directly on a Store, Registry, or Adapter. Portal reads MAY go through a Repository/Index facade (passthrough reads need no per-entity Orchestrator ceremony), but a Portal narrative call or dispatch-table binding that reaches a write-effect facade method is an error (\`PORTAL_WRITE_SHORTCUT\`) \u2014 writes always route through an Orchestrator. Held domain state always lives in a dedicated data component, never as fields inside an Orchestrator. Two sanctioned shapes: the RECOMMENDED Repository pattern (owns Store + Registry + Index; consumers depend on the facade), or \u2014 for genuinely simple state \u2014 a deliberately standalone Store (workflow-layer consumers only, acknowledged with a lint.allow reason on the UNOWNED_STORE warning). Never combine Store/Registry/Index roles into one component, and never fold state into a consuming component because a link was refused.
27033
+
27034
+ ### Component Vocabulary
27035
+ * **Blocks**: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer.
27036
+ * **Patterns**: Repository \u2014 the composable pattern that \`owns\` its member blocks: one Store with its Registry, Indexes and Queries, and optionally an Adapter.
27037
+ * **Variants**: \`gateway\`, a Portal that authenticates, authorizes, validates or rate-limits before it dispatches. Logic is an Orchestrator, and \`dependencyClass: pure | read\` bounds what it may depend on (unset = a workflow). Specialist and Gateway are retired stereotypes.
27038
+ * Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
27039
+ function globalGuideFilePath(targetType) {
27040
+ if (targetType === "claude") return path28.join(process.env["CLAUDE_CONFIG_DIR"] || path28.join(os5.homedir(), ".claude"), "CLAUDE.md");
27041
+ if (targetType === "gemini") return path28.join(process.env["GEMINI_CONFIG_DIR"] || path28.join(os5.homedir(), ".gemini"), "GEMINI.md");
27042
+ return null;
27043
+ }
27044
+ function localGuideFilePath(projectRoot, targetType) {
27045
+ if (targetType === "claude") return path28.join(projectRoot, ".claude", "CLAUDE.md");
27046
+ if (targetType === "gemini" || targetType === "agy") return path28.join(projectRoot, ".gemini", "GEMINI.md");
27047
+ return null;
27048
+ }
27049
+ function injectGuide(filePath, scope) {
27050
+ const body = scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
27051
+ const section = `
27052
+
27053
+ ${GUIDE_MARKER_START}
27054
+ ${versionStamp()}
27055
+ ${body}
27056
+ ${GUIDE_MARKER_END}
27057
+ `;
27058
+ const existing = fs18.existsSync(filePath) ? fs18.readFileSync(filePath, "utf-8") : "";
27059
+ const stripped = stripGuideSection(existing);
27060
+ const newContent = stripped.trimEnd() + section;
27061
+ fs18.mkdirSync(path28.dirname(filePath), { recursive: true });
27062
+ fs18.writeFileSync(filePath, newContent, "utf-8");
27063
+ }
27064
+ function stripGuideSection(content) {
27065
+ const start = content.indexOf(GUIDE_MARKER_START);
27066
+ const end = content.indexOf(GUIDE_MARKER_END);
27067
+ if (start === -1 || end === -1) return content;
27068
+ return content.slice(0, start) + content.slice(end + GUIDE_MARKER_END.length);
27069
+ }
27070
+ function writeRootGuideDelegator(projectRoot, targetType) {
27071
+ if (targetType === "claude") {
27072
+ const filePath = path28.join(projectRoot, "CLAUDE.md");
27073
+ const content = `@.claude/CLAUDE.md
27074
+
27075
+ # Wairon SDD Project
27076
+
27077
+ This project uses the Wairon Spec-Driven Development (SDD) framework. The imported
27078
+ \`.claude/CLAUDE.md\` above is your complete operating guide \u2014 you already have the
27079
+ full context, so don't search the project to learn how wairon or SDD works.
27080
+
27081
+ To design or modify the system, invoke the **\`sdd-architect\`** skill
27082
+ (in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
27083
+ the \`wairon\` CLI is the human developer's tool, not yours.
27084
+ `;
27085
+ fs18.writeFileSync(filePath, content, "utf-8");
27086
+ } else if (targetType === "gemini" || targetType === "agy") {
27087
+ const filePath = path28.join(projectRoot, "GEMINI.md");
27088
+ const content = `# Wairon SDD Project
27089
+ ${GUIDE_MARKER_START}
27090
+ ${versionStamp()}
27091
+ ${LOCAL_GUIDE_BODY}
27092
+ ${GUIDE_MARKER_END}
27093
+ `;
27094
+ fs18.writeFileSync(filePath, content, "utf-8");
27095
+ } else if (targetType === "cursor") {
27096
+ const filePath = path28.join(projectRoot, ".cursorrules");
27097
+ const content = `# Wairon SDD Project
27098
+
27099
+ This project uses the Wairon Spec-Driven Development (SDD) framework.
27100
+
27101
+ Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
27102
+ `;
27103
+ fs18.writeFileSync(filePath, content, "utf-8");
27104
+ } else if (targetType === "copilot") {
27105
+ const filePath = path28.join(projectRoot, ".github", "copilot-instructions.md");
27106
+ fs18.mkdirSync(path28.dirname(filePath), { recursive: true });
27107
+ const content = `# Wairon SDD Project
27108
+
27109
+ This project uses the Wairon Spec-Driven Development (SDD) framework.
27110
+
27111
+ Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
27112
+ `;
27113
+ fs18.writeFileSync(filePath, content, "utf-8");
27114
+ } else if (targetType === "codex") {
27115
+ const filePath = path28.join(projectRoot, ".codexrules");
27116
+ const content = `# Wairon SDD Project
27117
+
27118
+ Refer to [.codex/agents/](.codex/agents/) for full instructions.
27119
+ `;
27120
+ fs18.writeFileSync(filePath, content, "utf-8");
27121
+ }
27118
27122
  }
27119
-
27120
- // src/core/narrative-repair.ts
27121
- function repairForeignStepFields(apply) {
27122
- const implementations = loadImplementationSpecs();
27123
- const repairs = [];
27124
- const changed = [];
27125
- for (const impl of implementations) {
27126
- let touched = false;
27127
- for (const method of impl.methods) {
27128
- for (const step of method.narrative) {
27129
- const fields = narrativeStepForeignFields(step);
27130
- if (!fields.length) continue;
27131
- repairs.push({
27132
- implementation: impl.id,
27133
- method: method.name,
27134
- stepNumber: step.stepNumber,
27135
- stepType: step.type,
27136
- fields
27137
- });
27138
- for (const field of fields) delete step[field];
27139
- touched = true;
27140
- }
27123
+ var GUIDE_TARGETS = ["claude", "gemini", "agy", "cursor", "copilot", "codex"];
27124
+ function reinjectLocalGuides(projectRoot, targetTypes) {
27125
+ const written = [];
27126
+ for (const type of targetTypes) {
27127
+ if (!GUIDE_TARGETS.includes(type)) continue;
27128
+ const guidePath = localGuideFilePath(projectRoot, type);
27129
+ if (guidePath) {
27130
+ injectGuide(guidePath, "local");
27131
+ if (!written.includes(guidePath)) written.push(guidePath);
27141
27132
  }
27142
- if (touched) changed.push(impl);
27143
- }
27144
- if (apply && changed.length) {
27145
- for (const impl of changed) saveImplementationSpec(impl);
27146
- invalidateSpecCache();
27133
+ writeRootGuideDelegator(projectRoot, type);
27147
27134
  }
27148
- return repairs;
27135
+ return written;
27149
27136
  }
27150
27137
 
27151
- // src/core/approval.ts
27152
- var crypto4 = __toESM(require("crypto"));
27153
- var path28 = __toESM(require("path"));
27154
- function diffSize(d) {
27155
- return d.added.length + d.changed.length + d.removed.length;
27156
- }
27157
- function digest(content) {
27158
- const normalized = content.replace(/\r\n/g, "\n");
27159
- return crypto4.createHash("sha256").update(normalized, "utf8").digest("hex");
27160
- }
27161
- function currentSpecDigests(root = getProjectRoot()) {
27162
- const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path28.resolve(root, s.projectPath).split(path28.sep).join("/")}/`);
27163
- const out = {};
27164
- for (const [abs, content] of snapshotSpecFiles()) {
27165
- const normalized = path28.resolve(abs).split(path28.sep).join("/");
27166
- if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
27167
- out[path28.relative(root, abs).split(path28.sep).join("/")] = digest(content);
27168
- }
27169
- return out;
27170
- }
27171
- function captureApprovedSpecs(root = getProjectRoot(), scope) {
27172
- const current2 = currentSpecDigests(root);
27173
- if (!scope) return current2;
27174
- const previous = readLockRecord()?.specs ?? {};
27175
- const specs = { ...previous };
27176
- for (const rel2 of Object.keys(previous)) {
27177
- if (scope.paths.has(rel2) && current2[rel2] === void 0) delete specs[rel2];
27178
- }
27179
- for (const rel2 of scope.paths) {
27180
- if (current2[rel2] !== void 0) specs[rel2] = current2[rel2];
27181
- }
27182
- return specs;
27138
+ // src/core/context.ts
27139
+ function contextDir(...segments) {
27140
+ return aiDir("context", ...segments);
27183
27141
  }
27184
- function diffAgainstApproval(root = getProjectRoot()) {
27185
- const approved = approvedSpecs(root);
27186
- if (!approved) return null;
27187
- const current2 = currentSpecDigests(root);
27188
- const added = [];
27189
- const changed = [];
27190
- const removed = [];
27191
- const unchangedPaths = [];
27192
- for (const [rel2, d] of Object.entries(current2)) {
27193
- const before = approved[rel2];
27194
- if (before === void 0) added.push(rel2);
27195
- else if (before !== d) changed.push(rel2);
27196
- else unchangedPaths.push(rel2);
27197
- }
27198
- for (const rel2 of Object.keys(approved)) {
27199
- if (current2[rel2] === void 0) removed.push(rel2);
27200
- }
27201
- return {
27202
- added: added.sort(),
27203
- changed: changed.sort(),
27204
- removed: removed.sort(),
27205
- unchangedPaths: unchangedPaths.sort()
27206
- };
27142
+ var CONTEXT_PATHS = {
27143
+ dir: () => contextDir(),
27144
+ projectMd: () => contextDir("project.md"),
27145
+ architectureMd: () => contextDir("architecture.md"),
27146
+ domainsMd: () => contextDir("domains.md"),
27147
+ waironGuideMd: () => contextDir("wairon-guide.md")
27148
+ };
27149
+ function hasContext() {
27150
+ return pathExists(CONTEXT_PATHS.projectMd());
27207
27151
  }
27208
- function approvedSpecs(root) {
27209
- return approvalRecord(root)?.specs ?? null;
27152
+ function readProjectContext() {
27153
+ return readFileOrNull(CONTEXT_PATHS.projectMd());
27210
27154
  }
27211
- function approvalRecord(root = getProjectRoot()) {
27212
- return readLockRecordAt(root);
27155
+ function readArchitectureContext() {
27156
+ return readFileOrNull(CONTEXT_PATHS.architectureMd());
27213
27157
  }
27214
- function settledSpecPaths(root = getProjectRoot()) {
27215
- const diff = diffAgainstApproval(root);
27216
- return diff ? new Set(diff.unchangedPaths) : null;
27158
+ function writeDomainsDoc(content) {
27159
+ return writeFileIfChanged(CONTEXT_PATHS.domainsMd(), content);
27217
27160
  }
27218
- function pinOf(stateId) {
27219
- return `${stateId.algorithm}:${stateId.digest}`;
27161
+ function writeGuideDoc(content) {
27162
+ return writeFileIfChanged(CONTEXT_PATHS.waironGuideMd(), content);
27220
27163
  }
27221
- function currentChildPins(mounts, root = getProjectRoot()) {
27222
- const pins = {};
27223
- for (const mount of mounts) {
27224
- if (!mount.projectPath || mount.id.includes("::")) continue;
27225
- const child = readLockRecordAt(path28.resolve(root, mount.projectPath));
27226
- if (child) pins[mount.id] = pinOf(child.stateId);
27227
- }
27228
- return pins;
27164
+ function derivedDocPaths() {
27165
+ return [CONTEXT_PATHS.waironGuideMd(), CONTEXT_PATHS.domainsMd()];
27229
27166
  }
27230
- function movedChildren(mounts, root = getProjectRoot()) {
27231
- const pinned = approvalRecord(root)?.children;
27232
- if (!pinned) return [];
27233
- const now = currentChildPins(mounts, root);
27234
- const moved = [];
27235
- for (const [id, was] of Object.entries(pinned)) {
27236
- const current2 = now[id] ?? null;
27237
- if (current2 !== was) moved.push({ id, pinned: was, now: current2 });
27167
+ function renderDomainsDoc() {
27168
+ const domains = resolveDomains();
27169
+ const lines = [
27170
+ versionStamp(),
27171
+ `# Domains`,
27172
+ ``,
27173
+ `> Auto-generated by wairon. The human developer rebuilds this with \`wairon generate\`. `,
27174
+ ``
27175
+ ];
27176
+ if (domains.length === 0) {
27177
+ lines.push("_No domains yet. Define subsystems in the spec tree, or add free-standing domains with `wairon domains add`._");
27178
+ } else {
27179
+ lines.push(`**${domains.length} domain(s).**`);
27180
+ lines.push("");
27181
+ lines.push("| ID | Name | Source | Owned paths |");
27182
+ lines.push("|----|------|--------|-------------|");
27183
+ for (const d of domains) {
27184
+ const name = d.name ?? d.id;
27185
+ const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
27186
+ lines.push(`| \`${d.id}\` | ${name} | ${source} | \`${d.ownedPaths.join("`, `") || "\u2014"}\` |`);
27187
+ }
27238
27188
  }
27239
- return moved;
27189
+ return lines.join("\n") + "\n";
27240
27190
  }
27241
-
27242
- // src/core/approver.ts
27243
- var import_child_process = require("child_process");
27244
- var os5 = __toESM(require("os"));
27245
- function gitConfig(key) {
27191
+ function renderWaironGuide() {
27192
+ const domains = resolveDomains();
27193
+ let projectName = "this project";
27246
27194
  try {
27247
- const value = (0, import_child_process.execFileSync)("git", ["config", "--get", key], {
27248
- encoding: "utf8",
27249
- stdio: ["ignore", "pipe", "ignore"],
27250
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
27251
- }).trim();
27252
- return value || void 0;
27195
+ projectName = projectConfigRepository.load()?.name ?? projectName;
27253
27196
  } catch {
27254
- return void 0;
27255
27197
  }
27256
- }
27257
- function machineIdentity() {
27258
- let user = "unknown";
27259
- try {
27260
- user = os5.userInfo().username || user;
27261
- } catch {
27198
+ const projectCtx = readProjectContext();
27199
+ const archCtx = readArchitectureContext();
27200
+ const lines = [
27201
+ versionStamp(),
27202
+ `<!-- wairon-generated \u2014 do not edit directly; the human developer rebuilds this with \`wairon generate\` -->`,
27203
+ ``
27204
+ ];
27205
+ if (projectCtx) {
27206
+ lines.push(`# Project Context \u2014 ${projectName}`);
27207
+ lines.push("");
27208
+ lines.push(projectCtx.trim());
27209
+ lines.push("");
27210
+ lines.push("---");
27211
+ lines.push("");
27262
27212
  }
27263
- let host = "";
27213
+ if (archCtx) {
27214
+ lines.push("# Architecture");
27215
+ lines.push("");
27216
+ lines.push(archCtx.trim());
27217
+ lines.push("");
27218
+ lines.push("---");
27219
+ lines.push("");
27220
+ }
27221
+ lines.push(`# Domain Map (${domains.length} domain${domains.length !== 1 ? "s" : ""})`);
27222
+ lines.push("");
27223
+ if (domains.length === 0) {
27224
+ lines.push("_No domains yet._");
27225
+ } else {
27226
+ lines.push("| ID | Source | Name |");
27227
+ lines.push("|----|--------|------|");
27228
+ for (const d of domains) {
27229
+ const name = d.name ?? d.id;
27230
+ const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
27231
+ lines.push(`| \`${d.id}\` | ${source} | ${name} |`);
27232
+ }
27233
+ }
27234
+ lines.push("");
27235
+ lines.push("---");
27236
+ lines.push("");
27237
+ const mcpSettingsPath = require("path").join(process.cwd(), ".claude", "settings.json");
27238
+ let mcpInstalled = false;
27264
27239
  try {
27265
- host = os5.hostname();
27240
+ const s = JSON.parse(require("fs").readFileSync(mcpSettingsPath, "utf8"));
27241
+ mcpInstalled = !!s?.mcpServers?.wairon;
27266
27242
  } catch {
27267
27243
  }
27268
- return { id: host ? `${user}@${host}` : user, source: "os" };
27244
+ if (mcpInstalled) {
27245
+ lines.push("# wairon MCP Tools");
27246
+ lines.push("");
27247
+ lines.push("The **wairon MCP server** is active in this project. The tools are self-describing; call them directly:");
27248
+ lines.push("");
27249
+ lines.push("- Authoring: `sdd_initialize_system`, `sdd_add_subsystem`, `sdd_set_public_interfaces`, `sdd_set_subsystem_project_path`, `sdd_add_component`, `sdd_define_interface`, `sdd_set_endpoints`, `sdd_write_narrative`, `sdd_add_type`.");
27250
+ lines.push("- Reading & maintenance: `sdd_get_spec`, `sdd_update_spec`, `sdd_delete_spec`, `sdd_validate_tree`, `sdd_get_status`.");
27251
+ lines.push("- Topology: `listAgents`, `getAgent`, `listDomains`, `validateTopology`, `getProjectConfig`.");
27252
+ lines.push("");
27253
+ lines.push("Use these MCP tools to query and change project state \u2014 never the `wairon` CLI (that is the human developer's tool).");
27254
+ lines.push("");
27255
+ lines.push("---");
27256
+ lines.push("");
27257
+ }
27258
+ lines.push(GLOBAL_GUIDE_BODY);
27259
+ lines.push("");
27260
+ return lines.join("\n");
27269
27261
  }
27270
- function localApprover() {
27271
- const name = gitConfig("user.name");
27272
- const email = gitConfig("user.email");
27273
- if (name && email) return { id: `${name} <${email}>`, source: "git" };
27274
- if (email) return { id: email, source: "git" };
27275
- return machineIdentity();
27262
+ function syncContextFiles() {
27263
+ const domainsContent = renderDomainsDoc();
27264
+ const guideContent = renderWaironGuide();
27265
+ const domainsUpdated = writeDomainsDoc(domainsContent);
27266
+ const guideUpdated = writeGuideDoc(guideContent);
27267
+ return { domainsUpdated, guideUpdated };
27276
27268
  }
27277
27269
 
27278
27270
  // src/core/index.ts
@@ -27372,7 +27364,6 @@ function loadProjectConfig4() {
27372
27364
  BuiltinTargetSchema,
27373
27365
  BundleNotFoundError,
27374
27366
  COMPONENT_AUTH_SOURCE,
27375
- CONTEXT_PATHS,
27376
27367
  CarriedDebtKindSchema,
27377
27368
  CarriedDebtSchema,
27378
27369
  CarriedFindingSchema,
@@ -27527,7 +27518,6 @@ function loadProjectConfig4() {
27527
27518
  computeStateIdAt,
27528
27519
  conceptNoun,
27529
27520
  consumedContractInputs,
27530
- contextDir,
27531
27521
  createAgentRecord,
27532
27522
  createChainedSubsystem,
27533
27523
  createEmptyRegistry,
@@ -27550,6 +27540,7 @@ function loadProjectConfig4() {
27550
27540
  deleteTypeSpec,
27551
27541
  deregisterPackRef,
27552
27542
  deriveExecutionProfile,
27543
+ derivedDocPaths,
27553
27544
  describeApprover,
27554
27545
  detectDomainCandidates,
27555
27546
  diagnoseProjectPacks,
@@ -27604,7 +27595,6 @@ function loadProjectConfig4() {
27604
27595
  globalPacksEnabled,
27605
27596
  globalTemplatesDir,
27606
27597
  globalVariantsDir,
27607
- hasArchitectureContext,
27608
27598
  hasAuthoredSpecs,
27609
27599
  hasContext,
27610
27600
  hasFunctionBody,
@@ -27703,14 +27693,12 @@ function loadProjectConfig4() {
27703
27693
  projectSubsystemSurface,
27704
27694
  provisionProject,
27705
27695
  qualifiedTypeId,
27706
- readArchitectureContext,
27707
27696
  readFileOrNull,
27708
27697
  readJsonFile,
27709
27698
  readLockRecord,
27710
27699
  readLockRecordAt,
27711
27700
  readLockState,
27712
27701
  readManifest,
27713
- readProjectContext,
27714
27702
  readResource,
27715
27703
  readSkillResource,
27716
27704
  readStampVersion,
@@ -27727,9 +27715,7 @@ function loadProjectConfig4() {
27727
27715
  renameComponent,
27728
27716
  renameMethod,
27729
27717
  renderDiagram,
27730
- renderDomainsDoc,
27731
27718
  renderTemplateInstructions,
27732
- renderWaironGuide,
27733
27719
  repairForeignStepFields,
27734
27720
  resolveAgentTopology,
27735
27721
  resolveBudget,
@@ -27792,12 +27778,10 @@ function loadProjectConfig4() {
27792
27778
  validateRegistry,
27793
27779
  validateSddTree,
27794
27780
  workspaceFor,
27795
- writeArchitectureContext,
27796
27781
  writeFile,
27797
27782
  writeFileIfChanged,
27798
27783
  writeJsonFile,
27799
27784
  writeLockRecord,
27800
- writeProjectContext,
27801
27785
  writeRootGuideDelegator,
27802
27786
  writeYamlFile
27803
27787
  });