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

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
@@ -2497,7 +2497,7 @@ var require_dist = __commonJS({
2497
2497
  scaffoldPack: () => scaffoldPack2
2498
2498
  });
2499
2499
  module2.exports = __toCommonJS2(src_exports2);
2500
- var path29 = __toESM2(require("path"));
2500
+ var path28 = __toESM2(require("path"));
2501
2501
  var import_js_yaml3 = require("js-yaml");
2502
2502
  var import_js_yaml = require("js-yaml");
2503
2503
  var import_crypto = require("crypto");
@@ -3060,8 +3060,8 @@ var require_dist = __commonJS({
3060
3060
  function slug(name) {
3061
3061
  return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
3062
3062
  }
3063
- var fs19 = __toESM2(require("fs"));
3064
- var path30 = __toESM2(require("path"));
3063
+ var fs18 = __toESM2(require("fs"));
3064
+ var path29 = __toESM2(require("path"));
3065
3065
  var import_fflate = require_node();
3066
3066
  var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".hg", ".svn"]);
3067
3067
  function listEntries(archive) {
@@ -3099,9 +3099,9 @@ var require_dist = __commonJS({
3099
3099
  }
3100
3100
  function writeTree(destDir, files) {
3101
3101
  for (const file of files) {
3102
- const absolute = path30.join(destDir, file.path);
3103
- fs19.mkdirSync(path30.dirname(absolute), { recursive: true });
3104
- fs19.writeFileSync(absolute, file.contents);
3102
+ const absolute = path29.join(destDir, file.path);
3103
+ fs18.mkdirSync(path29.dirname(absolute), { recursive: true });
3104
+ fs18.writeFileSync(absolute, file.contents);
3105
3105
  }
3106
3106
  }
3107
3107
  function classifyKind(name, symlinks) {
@@ -3110,14 +3110,14 @@ var require_dist = __commonJS({
3110
3110
  return "file";
3111
3111
  }
3112
3112
  function walkPackDir(root, current2, out) {
3113
- for (const entry of fs19.readdirSync(current2, { withFileTypes: true })) {
3113
+ for (const entry of fs18.readdirSync(current2, { withFileTypes: true })) {
3114
3114
  if (entry.isDirectory()) {
3115
3115
  if (SKIP_DIRS.has(entry.name)) continue;
3116
- walkPackDir(root, path30.join(current2, entry.name), out);
3116
+ walkPackDir(root, path29.join(current2, entry.name), out);
3117
3117
  } else if (entry.isFile()) {
3118
- const absolute = path30.join(current2, entry.name);
3119
- const relative22 = path30.relative(root, absolute).split(path30.sep).join("/");
3120
- out.push({ path: relative22, contents: fs19.readFileSync(absolute) });
3118
+ const absolute = path29.join(current2, entry.name);
3119
+ const relative22 = path29.relative(root, absolute).split(path29.sep).join("/");
3120
+ out.push({ path: relative22, contents: fs18.readFileSync(absolute) });
3121
3121
  }
3122
3122
  }
3123
3123
  }
@@ -3167,7 +3167,7 @@ var require_dist = __commonJS({
3167
3167
  function scaffoldPack(request) {
3168
3168
  const files = render(request);
3169
3169
  writeTree(request.targetDir, files);
3170
- return files.map((file) => path29.join(request.targetDir, file.path));
3170
+ return files.map((file) => path28.join(request.targetDir, file.path));
3171
3171
  }
3172
3172
  function buildPack(sourceDir) {
3173
3173
  const files = readPackDir(sourceDir);
@@ -3224,7 +3224,7 @@ var require_dist = __commonJS({
3224
3224
  }
3225
3225
  const manifest = parseManifest(decode(envelope.contents));
3226
3226
  verifyIntegrity2(manifest, files);
3227
- const directory = path29.resolve(destDir);
3227
+ const directory = path28.resolve(destDir);
3228
3228
  writeTree(directory, files);
3229
3229
  const result = {
3230
3230
  directory,
@@ -3302,7 +3302,7 @@ var require_dist = __commonJS({
3302
3302
  }
3303
3303
  const manifest = parseTreeManifest(decode(envelope.contents));
3304
3304
  verifyTreeIntegrity(manifest, files);
3305
- const directory = path29.resolve(destDir);
3305
+ const directory = path28.resolve(destDir);
3306
3306
  writeTree(directory, files);
3307
3307
  const result = {
3308
3308
  destDir: directory,
@@ -3317,7 +3317,7 @@ var require_dist = __commonJS({
3317
3317
  return normalized === "." ? ".wai/" : `${normalized}/.wai/`;
3318
3318
  }
3319
3319
  function normalizeRootPath(relativePath) {
3320
- const posix2 = relativePath.split(path29.sep).join("/").replace(/^\.\//, "").replace(/\/+$/, "");
3320
+ const posix2 = relativePath.split(path28.sep).join("/").replace(/^\.\//, "").replace(/\/+$/, "");
3321
3321
  return posix2 === "" || posix2 === "." ? "." : posix2;
3322
3322
  }
3323
3323
  function slugify(projectName) {
@@ -3392,7 +3392,6 @@ __export(src_exports, {
3392
3392
  AgentRecordSchema: () => AgentRecordSchema,
3393
3393
  AgentStatusSchema: () => AgentStatusSchema,
3394
3394
  AgentTemplateSchema: () => AgentTemplateSchema,
3395
- AssertionSelectorSchema: () => AssertionSelectorSchema,
3396
3395
  BACKEND_COMMANDS: () => BACKEND_COMMANDS,
3397
3396
  BUILTIN_PROFILES: () => BUILTIN_PROFILES,
3398
3397
  BUILTIN_TYPES: () => BUILTIN_TYPES,
@@ -3400,8 +3399,6 @@ __export(src_exports, {
3400
3399
  BuiltinTargetConfigSchema: () => BuiltinTargetConfigSchema,
3401
3400
  BuiltinTargetSchema: () => BuiltinTargetSchema,
3402
3401
  BundleNotFoundError: () => BundleNotFoundError,
3403
- COMPONENT_AUTH_SOURCE: () => COMPONENT_AUTH_SOURCE,
3404
- CONTEXT_PATHS: () => CONTEXT_PATHS,
3405
3402
  CarriedDebtKindSchema: () => CarriedDebtKindSchema,
3406
3403
  CarriedDebtSchema: () => CarriedDebtSchema,
3407
3404
  CarriedFindingSchema: () => CarriedFindingSchema,
@@ -3418,7 +3415,6 @@ __export(src_exports, {
3418
3415
  CustomTargetSchema: () => CustomTargetSchema,
3419
3416
  DEFAULT_TARGET_DIRS: () => DEFAULT_TARGET_DIRS,
3420
3417
  DatabaseSpecSchema: () => DatabaseSpecSchema,
3421
- DeclarativePackSchema: () => DeclarativePackSchema,
3422
3418
  DependencyClassSchema: () => DependencyClassSchema,
3423
3419
  DesignDepthSchema: () => DesignDepthSchema,
3424
3420
  DiagramConfigSchema: () => DiagramConfigSchema,
@@ -3434,7 +3430,6 @@ __export(src_exports, {
3434
3430
  ExternalLinkTypeSchema: () => ExternalLinkTypeSchema,
3435
3431
  FindingDeclarationSchema: () => FindingDeclarationSchema,
3436
3432
  GITHUB_REPO: () => GITHUB_REPO,
3437
- GLOBAL_PACKS_DEFAULT: () => GLOBAL_PACKS_DEFAULT,
3438
3433
  GeminiExporter: () => GeminiExporter,
3439
3434
  GroupSpecSchema: () => GroupSpecSchema,
3440
3435
  GuaranteeSchema: () => GuaranteeSchema,
@@ -3442,7 +3437,6 @@ __export(src_exports, {
3442
3437
  ImplementationSpecSchema: () => ImplementationSpecSchema,
3443
3438
  InterfaceSpecSchema: () => InterfaceSpecSchema,
3444
3439
  InvariantSchema: () => InvariantSchema,
3445
- LanguagePackDefSchema: () => LanguagePackDefSchema,
3446
3440
  LifecycleEntrypointSchema: () => LifecycleEntrypointSchema,
3447
3441
  LintAllowSchema: () => LintAllowSchema,
3448
3442
  LintConfigSchema: () => LintConfigSchema,
@@ -3456,21 +3450,15 @@ __export(src_exports, {
3456
3450
  NarrativeStepSchema: () => NarrativeStepSchema,
3457
3451
  NarrativeStepTypeSchema: () => NarrativeStepTypeSchema,
3458
3452
  OutputTargetSchema: () => OutputTargetSchema,
3459
- PACK_DIR_ENTRIES: () => PACK_DIR_ENTRIES,
3460
3453
  PATTERN_TYPES: () => PATTERN_TYPES,
3461
3454
  PROJECT_KINDS: () => PROJECT_KINDS,
3462
- PackAssertionSchema: () => PackAssertionSchema,
3463
- PackInstructionBlockSchema: () => PackInstructionBlockSchema,
3464
3455
  PackSelectionSchema: () => PackSelectionSchema,
3465
- PackSkillSchema: () => PackSkillSchema,
3466
3456
  ParallelBranchSchema: () => ParallelBranchSchema,
3467
3457
  PathsConfigSchema: () => PathsConfigSchema,
3468
- PatternDefSchema: () => PatternDefSchema,
3469
3458
  PatternRefSchema: () => PatternRefSchema,
3470
3459
  PortalAuthSchema: () => PortalAuthSchema,
3471
3460
  PortalAuthSchemeSchema: () => PortalAuthSchemeSchema,
3472
3461
  PortalTypeSchema: () => PortalTypeSchema,
3473
- ProfileDefSchema: () => ProfileDefSchema,
3474
3462
  ProfileSelectionSubjectSchema: () => ProfileSelectionSubjectSchema,
3475
3463
  ProjectConfigSchema: () => ProjectConfigSchema,
3476
3464
  ProjectNotInitializedError: () => ProjectNotInitializedError,
@@ -3489,10 +3477,8 @@ __export(src_exports, {
3489
3477
  STEP_TYPE_FIELDS: () => STEP_TYPE_FIELDS,
3490
3478
  SUPPORTED_ALIASES: () => SUPPORTED_ALIASES,
3491
3479
  SURFACE_AUDIENCES: () => SURFACE_AUDIENCES,
3492
- SkillResourceNotFoundError: () => SkillResourceNotFoundError,
3493
3480
  SpecIdSchema: () => SpecIdSchema,
3494
3481
  SpecStatusSchema: () => SpecStatusSchema,
3495
- SpecWorkspace: () => SpecWorkspace,
3496
3482
  SubsystemSpecSchema: () => SubsystemSpecSchema,
3497
3483
  SurfaceAudienceSchema: () => SurfaceAudienceSchema,
3498
3484
  SurfaceContractEntrySchema: () => SurfaceContractEntrySchema,
@@ -3512,9 +3498,6 @@ __export(src_exports, {
3512
3498
  TypeKindSchema: () => TypeKindSchema,
3513
3499
  TypeMethodSchema: () => TypeMethodSchema,
3514
3500
  TypeSpecSchema: () => TypeSpecSchema,
3515
- UNVERSIONED: () => UNVERSIONED,
3516
- UnknownAgentError: () => UnknownAgentError,
3517
- VariantDefSchema: () => VariantDefSchema,
3518
3501
  WAIRON_MANAGED_BANNER: () => WAIRON_MANAGED_BANNER,
3519
3502
  WAIRON_MANAGED_MARKER: () => WAIRON_MANAGED_MARKER,
3520
3503
  WAIRON_VERSION: () => WAIRON_VERSION,
@@ -3525,44 +3508,28 @@ __export(src_exports, {
3525
3508
  aiDirAt: () => aiDirAt,
3526
3509
  aiPathsAt: () => aiPathsAt,
3527
3510
  ambiguityMessage: () => ambiguityMessage,
3528
- applySpecStatus: () => applySpecStatus,
3529
3511
  approvalRecord: () => approvalRecord,
3530
- assertContainedProjectPath: () => assertContainedProjectPath,
3512
+ approvalVerdict: () => approvalVerdict,
3531
3513
  assertProjectInitialized: () => assertProjectInitialized,
3532
- assertionFullCode: () => assertionFullCode,
3533
- audienceRank: () => audienceRank,
3534
3514
  backendCommand: () => backendCommand,
3535
- backfillChainedSubprojectConfigs: () => backfillChainedSubprojectConfigs,
3536
3515
  buildCanvasDataModel: () => buildCanvasDataModel,
3537
- buildGraphModel: () => buildGraphModel,
3538
3516
  buildProjectGraph: () => buildProjectGraph,
3539
3517
  buildRuleContext: () => buildRuleContext,
3540
- buildServerInstructions: () => buildServerInstructions2,
3541
- buildTreeArchive: () => buildTreeArchive2,
3542
3518
  callSitesOf: () => callSitesOf,
3543
3519
  captureApprovedSpecs: () => captureApprovedSpecs,
3544
- checkSkillFreshness: () => checkSkillFreshness,
3545
- clearLoaderIssues: () => clearLoaderIssues,
3546
3520
  cognitiveScore: () => cognitiveScore,
3547
- collectPromotableSpecs: () => collectPromotableSpecs,
3548
- commitStagedTree: () => commitStagedTree,
3549
3521
  complexityLevel: () => complexityLevel,
3550
3522
  composeAgentBrief: () => composeAgentBrief,
3551
3523
  composeRuleSequence: () => composeRuleSequence,
3552
- composeVariantGuidance: () => composeVariantGuidance,
3553
- computeGateStateId: () => computeGateStateId,
3554
- computePackDigest: () => computePackDigest,
3555
3524
  computeStateId: () => computeStateId,
3556
3525
  computeStateIdAt: () => computeStateIdAt,
3557
3526
  conceptNoun: () => conceptNoun,
3558
3527
  consumedContractInputs: () => consumedContractInputs,
3559
- contextDir: () => contextDir,
3560
3528
  createAgentRecord: () => createAgentRecord,
3561
3529
  createChainedSubsystem: () => createChainedSubsystem,
3562
3530
  createEmptyRegistry: () => createEmptyRegistry,
3563
3531
  createEmptyTopologyConfig: () => createEmptyTopologyConfig,
3564
3532
  createProjectConfig: () => createProjectConfig,
3565
- createStagingDir: () => createStagingDir,
3566
3533
  currentChildPins: () => currentChildPins,
3567
3534
  declaredPackNames: () => declaredPackNames,
3568
3535
  declaredProfileIds: () => declaredProfileIds,
@@ -3572,129 +3539,82 @@ __export(src_exports, {
3572
3539
  defaultPackSelections: () => defaultPackSelections,
3573
3540
  defaultTargetConfig: () => defaultTargetConfig,
3574
3541
  deleteComponentSpec: () => deleteComponentSpec,
3575
- deleteGroupSpec: () => deleteGroupSpec,
3576
3542
  deleteImplementationSpec: () => deleteImplementationSpec,
3577
3543
  deleteInterfaceSpec: () => deleteInterfaceSpec,
3578
3544
  deleteSubsystemSpec: () => deleteSubsystemSpec,
3579
3545
  deleteTypeSpec: () => deleteTypeSpec,
3580
3546
  deregisterPackRef: () => deregisterPackRef,
3581
3547
  deriveExecutionProfile: () => deriveExecutionProfile,
3582
- describeApprover: () => describeApprover,
3548
+ derivedDocPaths: () => derivedDocPaths,
3583
3549
  detectDomainCandidates: () => detectDomainCandidates,
3584
- diagnoseProjectPacks: () => diagnoseProjectPacks,
3585
3550
  diagramSetIndex: () => diagramSetIndex,
3586
3551
  diffAgainstApproval: () => diffAgainstApproval,
3587
3552
  diffSize: () => diffSize,
3588
- discardStagingDir: () => discardStagingDir,
3589
3553
  discoverPacks: () => discoverPacks,
3590
3554
  dryRunSerializeSpecs: () => dryRunSerializeSpecs,
3591
3555
  effectiveDetail: () => effectiveDetail,
3592
3556
  emptyExtensions: () => emptyExtensions,
3593
3557
  ensureDir: () => ensureDir,
3594
3558
  ensureProjectInitialized: () => ensureProjectInitialized,
3595
- exportSddSkills: () => exportSddSkills,
3596
3559
  exportSpecTree: () => exportSpecTree,
3597
- exportSurface: () => exportSurface,
3598
3560
  externalizeSubsystem: () => externalizeSubsystem,
3599
- extractTreeArchive: () => extractTreeArchive2,
3600
3561
  extractTypeIdentifiers: () => extractTypeIdentifiers,
3601
3562
  factsFor: () => factsFor,
3602
3563
  fieldTypeRefs: () => fieldTypeRefs,
3603
3564
  fieldTypesOf: () => fieldTypesOf,
3604
- findChainingParent: () => findChainingParent,
3605
- findChainingSubprojectsMissingConfig: () => findChainingSubprojectsMissingConfig,
3606
- findLegacySpecFiles: () => findLegacySpecFiles,
3607
3565
  findProjectRoot: () => findProjectRoot,
3608
3566
  findSystemRoot: () => findSystemRoot,
3609
- findTestsReferencing: () => findTestsReferencing2,
3610
- fromOpenApi: () => fromOpenApi,
3611
3567
  fromProjectRoot: () => fromProjectRoot,
3612
3568
  generateAgent: () => generateAgent,
3613
3569
  generateAll: () => generateAll,
3614
3570
  generateComponentDiagram: () => generateComponentDiagram,
3615
3571
  generateDiagramSet: () => generateDiagramSet,
3616
3572
  generateSequenceDiagram: () => generateSequenceDiagram,
3617
- getComponentPath: () => getComponentPath,
3618
3573
  getExporter: () => getExporter,
3619
- getGroupPath: () => getGroupPath,
3620
- getImplementationPath: () => getImplementationPath,
3621
- getInterfacePath: () => getInterfacePath,
3622
- getLoaderIssues: () => getLoaderIssues,
3623
3574
  getProjectRoot: () => getProjectRoot,
3624
3575
  getProjectRootOverride: () => getProjectRootOverride,
3625
3576
  getRequestParentReach: () => getRequestParentReach,
3626
3577
  getRequestProjectRoot: () => getRequestProjectRoot,
3627
- getSnapshot: () => getSnapshot,
3628
- getSubprojectPrefix: () => getSubprojectPrefix,
3629
- getSubsystemPath: () => getSubsystemPath,
3630
- getTypePath: () => getTypePath,
3578
+ getStatusReport: () => getStatusReport,
3631
3579
  globalGuideFilePath: () => globalGuideFilePath,
3632
3580
  globalPacksDir: () => globalPacksDir,
3633
- globalPacksEnabled: () => globalPacksEnabled,
3634
3581
  globalTemplatesDir: () => globalTemplatesDir,
3635
- globalVariantsDir: () => globalVariantsDir,
3636
- hasArchitectureContext: () => hasArchitectureContext,
3637
- hasAuthoredSpecs: () => hasAuthoredSpecs,
3638
3582
  hasContext: () => hasContext,
3639
3583
  hasFunctionBody: () => hasFunctionBody,
3640
- hasSpecTree: () => hasSpecTree,
3641
3584
  headNoun: () => headNoun,
3642
3585
  holdsState: () => holdsState,
3643
3586
  implementationSourceFiles: () => implementationSourceFiles,
3644
3587
  importBindingOf: () => importBindingOf,
3645
3588
  importSpecTree: () => importSpecTree,
3646
- importSurface: () => importSurface,
3647
- ineffectiveDeltaPaths: () => ineffectiveDeltaPaths,
3648
3589
  injectGuide: () => injectGuide,
3649
- inspectChainedRoots: () => inspectChainedRoots,
3650
- inspectTreeArchive: () => inspectTreeArchive2,
3651
3590
  installPackFromDirectory: () => installPackFromDirectory,
3652
3591
  interfaceGenericParameters: () => interfaceGenericParameters,
3653
3592
  internalizeSubsystem: () => internalizeSubsystem,
3654
- invalidateSpecCache: () => invalidateSpecCache,
3655
3593
  isDraftSubsystem: () => isDraftSubsystem,
3656
3594
  isLogic: () => isLogic,
3657
- isOpenApiDocument: () => isOpenApiDocument,
3658
3595
  isPattern: () => isPattern,
3659
3596
  isProjectInitialized: () => isProjectInitialized,
3660
3597
  isProvidedBy: () => isProvidedBy,
3661
3598
  isRetired: () => isRetired,
3662
- listChainedRoots: () => listChainedRoots,
3663
3599
  listDirectChainedSubprojects: () => listDirectChainedSubprojects,
3664
- listExternalInterfaces: () => listExternalInterfaces,
3665
3600
  listFiles: () => listFiles,
3666
3601
  listFilesRecursive: () => listFilesRecursive,
3667
3602
  listInstalledPacks: () => listInstalledPacks,
3668
- listMountSnapshots: () => listMountSnapshots,
3669
- listProjectVariants: () => listProjectVariants,
3670
- listResources: () => listResources,
3671
- listRules: () => listRules2,
3672
- listSkillNames: () => listSkillNames,
3673
- listSkillResources: () => listSkillResources,
3674
- listSnapshots: () => listSnapshots,
3675
- listTemplateIds: () => listTemplateIds,
3676
- loadAgentOverride: () => loadAgentOverride,
3677
3603
  loadComponentSpec: () => loadComponentSpec,
3678
3604
  loadComponentSpecs: () => loadComponentSpecs,
3679
3605
  loadExtensionPacks: () => loadExtensionPacks,
3680
3606
  loadExtensions: () => loadExtensions,
3681
- loadGroupSpec: () => loadGroupSpec,
3682
- loadGroupSpecs: () => loadGroupSpecs,
3683
3607
  loadImplementationSpec: () => loadImplementationSpec,
3684
3608
  loadImplementationSpecs: () => loadImplementationSpecs,
3685
3609
  loadInterfaceSpec: () => loadInterfaceSpec,
3686
3610
  loadInterfaceSpecs: () => loadInterfaceSpecs,
3687
- loadMountSurfaceSnapshots: () => loadMountSurfaceSnapshots,
3688
3611
  loadProjectConfig: () => loadProjectConfig4,
3689
3612
  loadProjectExtensions: () => loadProjectExtensions,
3690
- loadProjectVariants: () => loadProjectVariants,
3691
3613
  loadRegistry: () => loadRegistry,
3692
3614
  loadSpecGraph: () => loadSpecGraph,
3693
3615
  loadSubsystemSpec: () => loadSubsystemSpec,
3694
3616
  loadSubsystemSpecs: () => loadSubsystemSpecs,
3695
- loadSurfaceSnapshots: () => loadSurfaceSnapshots,
3696
3617
  loadSystemSpec: () => loadSystemSpec,
3697
- loadTemplate: () => loadTemplate,
3698
3618
  loadTopologyConfig: () => loadTopologyConfig,
3699
3619
  loadTypeSpec: () => loadTypeSpec,
3700
3620
  loadTypeSpecs: () => loadTypeSpecs,
@@ -3712,53 +3632,30 @@ __export(src_exports, {
3712
3632
  moveSubsystemProject: () => moveSubsystemProject,
3713
3633
  movedChildren: () => movedChildren,
3714
3634
  narrativeStepForeignFields: () => narrativeStepForeignFields,
3715
- normalizeApprover: () => normalizeApprover,
3716
- normalizeComponentLayout: () => normalizeComponentLayout,
3717
- packDirEntry: () => packDirEntry,
3718
- packEntryLabel: () => packEntryLabel,
3719
- packEntryRef: () => packEntryRef,
3720
3635
  packStoreDir: () => packStoreDir,
3721
3636
  parseDeclaredCall: () => parseDeclaredCall,
3722
- parseTemplate: () => parseTemplate,
3723
3637
  parseYaml: () => parseYaml,
3724
3638
  passesIntentFloor: () => passesIntentFloor,
3725
3639
  pathExists: () => pathExists,
3726
3640
  pathKey: () => pathKey,
3727
- pinFamilySurfaces: () => pinFamilySurfaces,
3728
- pinInstalledPacksAsSelections: () => pinInstalledPacksAsSelections,
3729
- projectChildSurface: () => projectChildSurface,
3730
3641
  projectConfigExists: () => projectConfigExists,
3731
- projectOwnSurface: () => projectOwnSurface,
3732
- projectSubsystemSurface: () => projectSubsystemSurface,
3733
3642
  provisionProject: () => provisionProject,
3734
3643
  qualifiedTypeId: () => qualifiedTypeId,
3735
- readArchitectureContext: () => readArchitectureContext,
3736
3644
  readFileOrNull: () => readFileOrNull,
3737
3645
  readJsonFile: () => readJsonFile,
3738
3646
  readLockRecord: () => readLockRecord,
3739
- readLockRecordAt: () => readLockRecordAt,
3740
3647
  readLockState: () => readLockState,
3741
- readManifest: () => readManifest,
3742
- readProjectContext: () => readProjectContext,
3743
- readResource: () => readResource,
3744
- readSkillResource: () => readSkillResource,
3745
3648
  readStampVersion: () => readStampVersion,
3746
3649
  readYamlFile: () => readYamlFile,
3747
- rebaseProjectVariants: () => rebaseProjectVariants,
3748
- rebaseReference: () => rebaseReference,
3749
3650
  recordProfileSelection: () => recordProfileSelection,
3750
3651
  registerExporter: () => registerExporter,
3751
3652
  registerPackRef: () => registerPackRef,
3752
3653
  reinjectLocalGuides: () => reinjectLocalGuides,
3753
3654
  removeDomain: () => removeDomain,
3754
3655
  removePackSelection: () => removePackSelection,
3755
- removeSnapshot: () => removeSnapshot,
3756
3656
  renameComponent: () => renameComponent,
3757
3657
  renameMethod: () => renameMethod,
3758
3658
  renderDiagram: () => renderDiagram,
3759
- renderDomainsDoc: () => renderDomainsDoc,
3760
- renderTemplateInstructions: () => renderTemplateInstructions,
3761
- renderWaironGuide: () => renderWaironGuide,
3762
3659
  repairForeignStepFields: () => repairForeignStepFields,
3763
3660
  resolveAgentTopology: () => resolveAgentTopology,
3764
3661
  resolveBudget: () => resolveBudget,
@@ -3767,47 +3664,31 @@ __export(src_exports, {
3767
3664
  resolveExpectedOutputPaths: () => resolveExpectedOutputPaths,
3768
3665
  resolveImport: () => resolveImport,
3769
3666
  resolveInstalledPack: () => resolveInstalledPack,
3770
- resolvePackRef: () => resolvePackRef,
3771
3667
  resolveSubprojectForNamespace: () => resolveSubprojectForNamespace,
3772
- resolveVariantGuidance: () => resolveVariantGuidance,
3773
- restoreSpecFiles: () => restoreSpecFiles,
3774
3668
  retireSpecialists: () => retireSpecialists,
3775
- rewriteSpecRefs: () => rewriteSpecRefs,
3776
3669
  runWithProjectBinding: () => runWithProjectBinding,
3777
3670
  runWithProjectRoot: () => runWithProjectRoot,
3778
3671
  sameContract: () => sameContract,
3779
3672
  saveComponentSpec: () => saveComponentSpec,
3780
- saveGroupSpec: () => saveGroupSpec,
3781
3673
  saveImplementationSpec: () => saveImplementationSpec,
3782
3674
  saveInterfaceSpec: () => saveInterfaceSpec,
3783
- saveSnapshot: () => saveSnapshot,
3784
3675
  saveSubsystemSpec: () => saveSubsystemSpec,
3785
3676
  saveSystemSpec: () => saveSystemSpec,
3786
3677
  saveTopologyConfig: () => saveTopologyConfig,
3787
3678
  saveTypeSpec: () => saveTypeSpec,
3788
- scanAllSpecs: () => scanAllSpecs,
3789
3679
  serializeYaml: () => serializeYaml,
3790
3680
  setExecutionTier: () => setExecutionTier,
3791
3681
  setLogLevel: () => setLogLevel,
3792
3682
  setProjectRoot: () => setProjectRoot,
3793
3683
  setProjectType: () => setProjectType,
3794
3684
  settledSpecPaths: () => settledSpecPaths,
3795
- skillExtendErrors: () => skillExtendErrors,
3796
- skillsDirForTarget: () => skillsDirForTarget,
3797
- snapshotSpecFiles: () => snapshotSpecFiles,
3798
- specChanges: () => specChanges,
3799
- specKind: () => specKind,
3800
3685
  specPathsInScope: () => specPathsInScope,
3801
3686
  splitNamespace: () => splitNamespace,
3802
- stateIdEquals: () => stateIdEquals,
3803
- stateIdString: () => stateIdString,
3804
3687
  stepConfigVerdict: () => stepConfigVerdict,
3805
3688
  stepFieldsFor: () => stepFieldsFor,
3806
3689
  stepGraph: () => stepGraph,
3807
3690
  syncContextFiles: () => syncContextFiles,
3808
3691
  toMarkdown: () => toMarkdown,
3809
- toOpenApi: () => toOpenApi,
3810
- toOpenApiSet: () => toOpenApiSet,
3811
3692
  typeBindingOf: () => typeBindingOf,
3812
3693
  typeGenericParameters: () => typeGenericParameters,
3813
3694
  typeMatchesRef: () => typeMatchesRef,
@@ -3815,18 +3696,11 @@ __export(src_exports, {
3815
3696
  uninstallPack: () => uninstallPack,
3816
3697
  updateSpec: () => updateSpec,
3817
3698
  upsertPackSelection: () => upsertPackSelection,
3818
- validateAsComplete: () => validateAsComplete,
3819
- validateComponentCandidate: () => validateComponentCandidate,
3820
- validateProjectConfig: () => validateProjectConfig,
3821
- validateRegistry: () => validateRegistry,
3822
3699
  validateSddTree: () => validateSddTree,
3823
- workspaceFor: () => workspaceFor,
3824
- writeArchitectureContext: () => writeArchitectureContext,
3825
3700
  writeFile: () => writeFile,
3826
3701
  writeFileIfChanged: () => writeFileIfChanged,
3827
3702
  writeJsonFile: () => writeJsonFile,
3828
3703
  writeLockRecord: () => writeLockRecord,
3829
- writeProjectContext: () => writeProjectContext,
3830
3704
  writeRootGuideDelegator: () => writeRootGuideDelegator,
3831
3705
  writeYamlFile: () => writeYamlFile
3832
3706
  });
@@ -4718,17 +4592,17 @@ function overlayKnownFields(schema, typed, onDisk) {
4718
4592
  }
4719
4593
  return typed;
4720
4594
  }
4721
- function overlayLevel(typed, onDisk, schemaFor2) {
4595
+ function overlayLevel(typed, onDisk, schemaFor) {
4722
4596
  const document = isPlainObject(onDisk) ? onDisk : {};
4723
4597
  const out = {};
4724
4598
  for (const [key, stored] of Object.entries(document)) {
4725
- const schema = schemaFor2(key);
4599
+ const schema = schemaFor(key);
4726
4600
  if (schema === null) out[key] = stored;
4727
4601
  else if (typed[key] !== void 0) out[key] = overlayKnownFields(schema, typed[key], stored);
4728
4602
  }
4729
4603
  for (const [key, value] of Object.entries(typed)) {
4730
4604
  if (hasOwn(document, key) || value === void 0) continue;
4731
- const schema = schemaFor2(key);
4605
+ const schema = schemaFor(key);
4732
4606
  if (schema !== null) out[key] = overlayKnownFields(schema, value, void 0);
4733
4607
  }
4734
4608
  return out;
@@ -5085,10 +4959,6 @@ function normalizeApprover(value) {
5085
4959
  }
5086
4960
  return { id: typeof value === "string" && value ? value : "unknown", source: "legacy" };
5087
4961
  }
5088
- function describeApprover(who) {
5089
- const label = who.name ? `${who.name} (${who.id})` : who.id;
5090
- return who.source === "hosted" ? `${label} [authenticated]` : label;
5091
- }
5092
4962
  function readLockRecord() {
5093
4963
  try {
5094
4964
  return normalizeRecord(JSON.parse(fs4.readFileSync(lockPath(), "utf8")));
@@ -6406,10 +6276,10 @@ function stepGraph(method) {
6406
6276
  const s = byNum.get(n);
6407
6277
  if (s.type !== "parallel" || s.endStep === void 0 || !s.branches?.length) continue;
6408
6278
  const entries = s.branches.map((b) => b.step).sort((a, b) => a - b);
6409
- const join18 = fallNext(s.endStep);
6279
+ const join17 = fallNext(s.endStep);
6410
6280
  for (let i = 0; i < entries.length; i++) {
6411
6281
  const armEnd = i + 1 < entries.length ? prevOf(entries[i + 1]) : s.endStep;
6412
- if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join18);
6282
+ if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join17);
6413
6283
  }
6414
6284
  }
6415
6285
  const successorsOf = (n) => {
@@ -11662,7 +11532,7 @@ function defaultTargetConfig(type) {
11662
11532
  enabled: true
11663
11533
  };
11664
11534
  }
11665
- var WAIRON_VERSION = "5.1.1-dev.60";
11535
+ var WAIRON_VERSION = "5.1.1-dev.62";
11666
11536
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
11667
11537
  var ARCHITECT_AGENT_ID = "agent-architect";
11668
11538
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -12196,66 +12066,6 @@ function defaultPackSelections() {
12196
12066
  return [];
12197
12067
  }
12198
12068
  }
12199
- function diagnoseProjectPacks() {
12200
- const empty = { globalsUndeclared: false, notApplied: [], unresolved: [], globalsApplied: [] };
12201
- try {
12202
- const config = projectConfigRepository.load();
12203
- if (!config) return empty;
12204
- const globalsUndeclared = !projectConfigRepository.declaresGlobalPacks();
12205
- const projectRoot = getProjectRoot();
12206
- const entries = config.extensions?.packs ?? [];
12207
- const unresolved = [];
12208
- const selectedNames = /* @__PURE__ */ new Set();
12209
- for (const entry of entries) {
12210
- if (typeof entry === "string") continue;
12211
- selectedNames.add(entry.name);
12212
- const resolution = resolveSelection(entry, projectRoot);
12213
- if (resolution.failure) {
12214
- unresolved.push({ label: packEntryLabel(entry), message: `[${resolution.failure.code}] ${resolution.failure.message}` });
12215
- }
12216
- }
12217
- const installed = listInstalledPacks();
12218
- const globalsOn = globalPacksEnabled(config);
12219
- const globalsApplied = [];
12220
- if (globalsOn) {
12221
- for (const ref of discoverPacks(globalPacksDir())) {
12222
- const match = installed.find((p) => path10.resolve(p.path) === path10.resolve(ref));
12223
- if (match) globalsApplied.push({ name: match.name, version: match.version });
12224
- }
12225
- }
12226
- const applying = /* @__PURE__ */ new Set([...selectedNames, ...globalsApplied.map((p) => p.name)]);
12227
- const notApplied = installed.filter((p) => !applying.has(p.name)).map((p) => ({ name: p.name, version: p.version, origin: p.origin }));
12228
- return { globalsUndeclared, notApplied, unresolved, globalsApplied };
12229
- } catch {
12230
- return empty;
12231
- }
12232
- }
12233
- function pinInstalledPacksAsSelections() {
12234
- const diagnosis = diagnoseProjectPacks();
12235
- if (!diagnosis.globalsUndeclared || diagnosis.notApplied.length === 0) return [];
12236
- const added = [];
12237
- const selections = [];
12238
- for (const pack of diagnosis.notApplied) {
12239
- selections.push({
12240
- name: pack.name,
12241
- version: pack.version,
12242
- // Carry the origin so the selection can be obtained elsewhere; a local
12243
- // path is not fetchable, so it is deliberately not recorded as a source.
12244
- ...pack.origin && /^[a-z][a-z0-9+.-]*:\/\//i.test(pack.origin) ? { source: pack.origin } : {}
12245
- });
12246
- added.push(`${pack.name}@${pack.version}`);
12247
- }
12248
- projectConfigRepository.pinGlobalPacksAsSelections(selections);
12249
- return added;
12250
- }
12251
- function packEntryLabel(entry) {
12252
- if (typeof entry === "string") return entry;
12253
- return entry.version ? `${entry.name}@${entry.version}` : entry.name;
12254
- }
12255
- function packEntryRef(entry, projectRoot) {
12256
- if (typeof entry === "string") return entry;
12257
- return resolveSelection(entry, projectRoot).ref ?? null;
12258
- }
12259
12069
  function resolveSelection(selection, projectRoot) {
12260
12070
  const wanted = selection.version ? `${selection.name}@${selection.version}` : selection.name;
12261
12071
  const fail = (code, message) => ({ failure: { code, severity: "error", name: selection.name, message } });
@@ -12369,21 +12179,21 @@ function buildCodeIndex(model) {
12369
12179
  const declarations = /* @__PURE__ */ new Map();
12370
12180
  const anchors = /* @__PURE__ */ new Map();
12371
12181
  const findingAnchors = /* @__PURE__ */ new Map();
12372
- const namesAt = (cache, path29, make) => {
12373
- const cached = cache.get(path29);
12182
+ const namesAt = (cache, path28, make) => {
12183
+ const cached = cache.get(path28);
12374
12184
  if (cached) return cached;
12375
- const f = facts.get(path29);
12185
+ const f = facts.get(path28);
12376
12186
  if (!f) return NO_NAMES;
12377
12187
  const built = make(f);
12378
- cache.set(path29, built);
12188
+ cache.set(path28, built);
12379
12189
  return built;
12380
12190
  };
12381
12191
  const republished = /* @__PURE__ */ new Map();
12382
- const republishedFrom = (path29) => {
12383
- const cached = republished.get(path29);
12192
+ const republishedFrom = (path28) => {
12193
+ const cached = republished.get(path28);
12384
12194
  if (cached) return cached;
12385
- const out = /* @__PURE__ */ new Set([path29]);
12386
- const queue = [path29];
12195
+ const out = /* @__PURE__ */ new Set([path28]);
12196
+ const queue = [path28];
12387
12197
  while (queue.length) {
12388
12198
  const from = queue.pop();
12389
12199
  const f = facts.get(from);
@@ -12396,7 +12206,7 @@ function buildCodeIndex(model) {
12396
12206
  }
12397
12207
  }
12398
12208
  }
12399
- republished.set(path29, out);
12209
+ republished.set(path28, out);
12400
12210
  return out;
12401
12211
  };
12402
12212
  const NO_ORIGIN = /* @__PURE__ */ new Set();
@@ -12405,9 +12215,9 @@ function buildCodeIndex(model) {
12405
12215
  return to ? republishedFrom(to) : NO_ORIGIN;
12406
12216
  };
12407
12217
  const scopeOf = (site, from) => {
12408
- const path29 = pathKey(site.from ?? from);
12409
- const f = facts.get(path29);
12410
- return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path: path29, facts: f } : void 0;
12218
+ const path28 = pathKey(site.from ?? from);
12219
+ const f = facts.get(path28);
12220
+ return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path: path28, facts: f } : void 0;
12411
12221
  };
12412
12222
  const originOf = (site, from) => {
12413
12223
  const resolved = scopeOf(site, from);
@@ -12446,14 +12256,14 @@ function buildCodeIndex(model) {
12446
12256
  if (site.via) for (const typeName of localTypesOf(f, site.via)) widenThroughType(typeName);
12447
12257
  return out;
12448
12258
  };
12449
- const declarationsAt = (path29) => namesAt(declarations, pathKey(path29), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
12259
+ const declarationsAt = (path28) => namesAt(declarations, pathKey(path28), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
12450
12260
  return {
12451
12261
  paths,
12452
12262
  exactPaths,
12453
- factsAt: (path29) => facts.get(pathKey(path29)),
12263
+ factsAt: (path28) => facts.get(pathKey(path28)),
12454
12264
  declarationsAt,
12455
- anchorsAt: (path29) => namesAt(anchors, pathKey(path29), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames, ...f.anchoredNames])),
12456
- findingAnchorsAt: (path29) => namesAt(findingAnchors, pathKey(path29), (f) => new Set(f.anchoredNames)),
12265
+ anchorsAt: (path28) => namesAt(anchors, pathKey(path28), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames, ...f.anchoredNames])),
12266
+ findingAnchorsAt: (path28) => namesAt(findingAnchors, pathKey(path28), (f) => new Set(f.anchoredNames)),
12457
12267
  originOf,
12458
12268
  possibleOriginsOf
12459
12269
  };
@@ -12491,10 +12301,10 @@ function buildRealizationIndex(ctx) {
12491
12301
  return {
12492
12302
  paths,
12493
12303
  implementationsOf: (compId) => implsByComponent.get(compId) ?? NONE_IMPL,
12494
- implementationsAt: (path29) => implsByPath.get(pathKey(path29)) ?? NONE_IMPL,
12304
+ implementationsAt: (path28) => implsByPath.get(pathKey(path28)) ?? NONE_IMPL,
12495
12305
  filesOf: (compId) => filesByComponent.get(compId) ?? NONE_PATH,
12496
12306
  filesIn: (subsystemId) => filesBySubsystem.get(subsystemId) ?? NONE_PATH,
12497
- componentsAt: (path29) => componentsByPath.get(pathKey(path29)) ?? NONE_COMP
12307
+ componentsAt: (path28) => componentsByPath.get(pathKey(path28)) ?? NONE_COMP
12498
12308
  };
12499
12309
  }
12500
12310
  function buildImportGraph(index, universe) {
@@ -12506,22 +12316,22 @@ function buildImportGraph(index, universe) {
12506
12316
  if (to && to !== from) into.add(to);
12507
12317
  }
12508
12318
  };
12509
- const importsOf = (path29) => {
12510
- const cached = imports.get(path29);
12319
+ const importsOf = (path28) => {
12320
+ const cached = imports.get(path28);
12511
12321
  if (cached) return cached;
12512
- const facts = index.factsAt(path29);
12322
+ const facts = index.factsAt(path28);
12513
12323
  const out = /* @__PURE__ */ new Set();
12514
- if (facts?.status === "analyzed") resolveAll(path29, facts.imports, out);
12515
- imports.set(path29, out);
12324
+ if (facts?.status === "analyzed") resolveAll(path28, facts.imports, out);
12325
+ imports.set(path28, out);
12516
12326
  return out;
12517
12327
  };
12518
- const tracesOf = (path29) => {
12519
- const cached = traces.get(path29);
12328
+ const tracesOf = (path28) => {
12329
+ const cached = traces.get(path28);
12520
12330
  if (cached) return cached;
12521
- const facts = index.factsAt(path29);
12522
- const out = new Set(importsOf(path29));
12523
- if (facts?.status === "analyzed") resolveAll(path29, facts.reexports, out);
12524
- traces.set(path29, out);
12331
+ const facts = index.factsAt(path28);
12332
+ const out = new Set(importsOf(path28));
12333
+ if (facts?.status === "analyzed") resolveAll(path28, facts.reexports, out);
12334
+ traces.set(path28, out);
12525
12335
  return out;
12526
12336
  };
12527
12337
  return {
@@ -13832,11 +13642,11 @@ var unconditionalCallCyclesRule = {
13832
13642
  const memberEdges = keys.flatMap((k) => (adjacency.get(k) ?? []).filter((e) => inScc.has(e.toKey)));
13833
13643
  if (memberEdges.length === 0) continue;
13834
13644
  const anchor = [...memberEdges].sort((a, b) => byCodeUnit(a.fromKey, b.fromKey) || byCodeUnit(a.impl.id, b.impl.id) || a.stepNumber - b.stepNumber)[0];
13835
- const path29 = [...keys].sort(byCodeUnit).join(" \u2192 ");
13645
+ const path28 = [...keys].sort(byCodeUnit).join(" \u2192 ");
13836
13646
  ctx.addIssue(
13837
13647
  "warning",
13838
13648
  "UNCONDITIONAL_CALL_CYCLE",
13839
- `Call cycle with no guard: ${path29} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
13649
+ `Call cycle with no guard: ${path28} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
13840
13650
  anchor.impl.id,
13841
13651
  memberEdges.some((e) => ctx.isImplementationDraft(e.impl))
13842
13652
  );
@@ -16578,11 +16388,11 @@ var hiddenStateRule = {
16578
16388
  byPath.set(key, list);
16579
16389
  }
16580
16390
  }
16581
- for (const path29 of code.exactPaths) {
16582
- const facts = code.factsAt(path29);
16391
+ for (const path28 of code.exactPaths) {
16392
+ const facts = code.factsAt(path28);
16583
16393
  const bindings = facts.topLevelMutableBindings ?? [];
16584
16394
  if (bindings.length === 0) continue;
16585
- const mapped = byPath.get(path29) ?? [];
16395
+ const mapped = byPath.get(path28) ?? [];
16586
16396
  if (mapped.length === 0) continue;
16587
16397
  if (!mapped.every((m) => isStatelessLogic(m.component))) continue;
16588
16398
  const anchor = [...mapped].sort((a, b) => a.impl.id.localeCompare(b.impl.id))[0];
@@ -16648,7 +16458,7 @@ var dependencyConformanceRule = {
16648
16458
  }
16649
16459
  return false;
16650
16460
  };
16651
- const draftAt = (path29) => realization.implementationsAt(path29).some((impl) => ctx.isImplementationDraft(impl));
16461
+ const draftAt = (path28) => realization.implementationsAt(path28).some((impl) => ctx.isImplementationDraft(impl));
16652
16462
  for (const fromPath of mappedPaths) {
16653
16463
  const fromComponents = realization.componentsAt(fromPath);
16654
16464
  for (const toPath of graph.importsOf(fromPath)) {
@@ -18356,9 +18166,6 @@ function ruleSequence() {
18356
18166
  const audits = [carriedDebtRule, lintAllowsRule].filter((r) => ruleSet.includes(r));
18357
18167
  return [...ruleSet.filter((r) => !audits.includes(r)), ...audits];
18358
18168
  }
18359
- function specScopedRules() {
18360
- return ruleSequence().filter((r) => r.scope === "spec");
18361
- }
18362
18169
  function knownIssueCodes() {
18363
18170
  return listRules().flatMap((r) => r.codes);
18364
18171
  }
@@ -19001,48 +18808,6 @@ function buildCodeModel(implementations, types, projectRoot, sourceRoots = [], e
19001
18808
  }
19002
18809
  return { files, projectRoot, rootFiles };
19003
18810
  }
19004
- function readTestFiles(testRoots, projectRoot) {
19005
- const scanned = [];
19006
- for (const key of walkDeclaredRoots(testRoots, [], projectRoot)) {
19007
- let text;
19008
- try {
19009
- const buffer = fs9.readFileSync(path11.resolve(projectRoot, key));
19010
- if (looksBinary(buffer)) continue;
19011
- text = buffer.toString("utf8");
19012
- } catch {
19013
- continue;
19014
- }
19015
- const imports = /* @__PURE__ */ new Set();
19016
- for (const m of text.matchAll(NAMED_IMPORT_BINDINGS_RE)) {
19017
- for (const name of boundNames(m[1] ?? "", false)) imports.add(name);
19018
- }
19019
- const words2 = /* @__PURE__ */ new Set();
19020
- for (const m of text.matchAll(IDENTIFIER_RE)) words2.add(m[0]);
19021
- scanned.push({ path: key, imports, words: words2 });
19022
- }
19023
- return scanned;
19024
- }
19025
- function findTestsReferencing(methods, projectRoot, testRoots = []) {
19026
- const scanned = readTestFiles(testRoots, projectRoot);
19027
- if (scanned.length === 0) return [];
19028
- const indiscriminateAbove = scanned.length / 10;
19029
- const found = [];
19030
- for (const method of methods) {
19031
- const symbol = method.symbol ?? method.name;
19032
- const imported = scanned.filter((f) => f.imports.has(symbol)).map((f) => f.path);
19033
- const mentioned = scanned.filter((f) => !f.imports.has(symbol) && f.words.has(symbol)).map((f) => f.path);
19034
- const indiscriminate = mentioned.length > indiscriminateAbove;
19035
- if (imported.length === 0 && mentioned.length === 0) continue;
19036
- found.push({
19037
- method: method.name,
19038
- symbol,
19039
- imported,
19040
- mentioned: indiscriminate ? [] : mentioned,
19041
- indiscriminate
19042
- });
19043
- }
19044
- return found;
19045
- }
19046
18811
 
19047
18812
  // src/core/rules/index.ts
19048
18813
  function composeRuleSequence(extraRules = []) {
@@ -19537,119 +19302,6 @@ function buildRuleContext(opts) {
19537
19302
  return ctx;
19538
19303
  }
19539
19304
 
19540
- // src/core/rules/candidate.ts
19541
- function stubSystem() {
19542
- const now = (/* @__PURE__ */ new Date()).toISOString();
19543
- return {
19544
- schemaVersion: "1.0.0",
19545
- name: "candidate",
19546
- vision: "",
19547
- boundaries: [],
19548
- globalRequirements: [],
19549
- databases: [],
19550
- createdAt: now,
19551
- updatedAt: now
19552
- };
19553
- }
19554
- function validateComponentCandidate(candidate, opts = {}) {
19555
- const issues = [];
19556
- registerBuiltinRules();
19557
- if (opts.extensions?.rules?.length) registerPackRules(opts.extensions.rules);
19558
- const knownCodes = /* @__PURE__ */ new Set([
19559
- ...knownIssueCodes().map((rc) => rc.code),
19560
- ...(opts.extensions?.assertions ?? []).map((a) => a.fullCode)
19561
- ]);
19562
- const ctx = buildRuleContext({
19563
- system: stubSystem(),
19564
- subsystems: [],
19565
- components: [candidate],
19566
- interfaces: [],
19567
- implementations: [],
19568
- types: [],
19569
- rules: opts.rules,
19570
- projectType: opts.projectType ?? "backend",
19571
- extensions: opts.extensions,
19572
- // Only a tree-scoped rule reads these (roundtrip-serialization); no
19573
- // spec-scoped rule does, so a candidate carries none.
19574
- roundTripIssues: [],
19575
- knownIssueCodes: knownCodes,
19576
- issues
19577
- });
19578
- for (const rule of specScopedRules()) {
19579
- rule.check(ctx);
19580
- }
19581
- const own = issues.filter((i) => !i.specId || i.specId === candidate.id);
19582
- return {
19583
- errors: own.filter((i) => i.severity === "error"),
19584
- warnings: own.filter((i) => i.severity === "warning")
19585
- };
19586
- }
19587
-
19588
- // src/core/rules/gate-identity.ts
19589
- var crypto3 = __toESM(require("crypto"));
19590
- var GATE_ALGORITHM = "sha256+content+doctrine+inputs";
19591
- function doctrineIdentity(doctrine, builtinRules, gate) {
19592
- const byKey = (items, key) => [...items].sort((a, b) => compareOrdinal(key(a), key(b)));
19593
- return {
19594
- /**
19595
- * The BUILTIN rule set, by identity rather than by wairon version.
19596
- *
19597
- * A binary upgrade changes the gate only when the rules change, so hashing the
19598
- * version would invalidate every lock on every patch while hashing nothing
19599
- * would let a minor that ADDS a rule leave locks asserting they passed a gate
19600
- * that no longer exists. Keying on the registry means a release that touches no
19601
- * rule keeps every lock valid, and one that adds, removes, or re-grades a code
19602
- * invalidates exactly the locks it should.
19603
- *
19604
- * Residual gap, accepted knowingly: a rule whose IMPLEMENTATION grows stricter
19605
- * without its name, codes, or default severity changing is not caught. Folding
19606
- * in the wairon version would catch it at the cost of churning every lock on
19607
- * every release — the trade this projection deliberately declines.
19608
- */
19609
- builtinRules: byKey(
19610
- builtinRules.map((r) => ({
19611
- name: r.name,
19612
- codes: byKey(r.codes.map((c) => ({ code: c.code, severity: c.defaultSeverity })), (c) => c.code)
19613
- })),
19614
- (r) => r.name
19615
- ),
19616
- /**
19617
- * Which profile GOVERNS, and the project's own rule tuning. Both decide
19618
- * verdicts — a projectType switch changes the doctrine family outright, and
19619
- * `rules` carries severity overrides, complexity caps, and designDepth.
19620
- */
19621
- projectType: gate.projectType ?? null,
19622
- rulesConfig: gate.rules ?? null,
19623
- packs: byKey(
19624
- doctrine.packs.map((p) => ({ name: p.name, version: p.version ?? null, scope: p.scope })),
19625
- (p) => `${p.name}@${p.version ?? ""}#${p.scope}`
19626
- ),
19627
- // Merged records already encode pack precedence, so their resolved content is
19628
- // the identity — a load-order change that flips a collision winner shows up here.
19629
- profiles: doctrine.profiles,
19630
- languages: doctrine.languages,
19631
- patterns: byKey(
19632
- doctrine.patterns.map((p) => ({ id: p.id, version: p.version, pack: p.pack })),
19633
- (p) => `${p.pack}/${p.id}@${p.version}`
19634
- ),
19635
- guarantees: [...doctrine.guarantees].sort(),
19636
- assertions: byKey(doctrine.assertions.map((a) => ({ ...a })), (a) => a.fullCode),
19637
- rules: byKey(
19638
- doctrine.rules.map((r) => ({ name: r.name, codes: r.codes.map((c) => c.code).sort() })),
19639
- (r) => r.name
19640
- )
19641
- };
19642
- }
19643
- function computeGateIdentity(content, doctrine, builtinRules, inputs, gate) {
19644
- const payload = {
19645
- content: content.digest,
19646
- doctrine: doctrineIdentity(doctrine, builtinRules, gate),
19647
- inputs: [...inputs].sort()
19648
- };
19649
- const digest2 = crypto3.createHash("sha256").update(canonicalize(payload)).digest("hex");
19650
- return { algorithm: GATE_ALGORITHM, digest: digest2 };
19651
- }
19652
-
19653
19305
  // src/core/variants.ts
19654
19306
  var fs10 = __toESM(require("fs"));
19655
19307
  var os3 = __toESM(require("os"));
@@ -19803,523 +19455,14 @@ function rebasedText(content, fromBase, toBase, rebasedContent) {
19803
19455
  var fs11 = __toESM(require("fs"));
19804
19456
  var path13 = __toESM(require("path"));
19805
19457
 
19806
- // src/utils/filenames.ts
19807
- function safeFilenamePart(value) {
19808
- return value.replace(/[^a-zA-Z0-9._-]/g, "-");
19809
- }
19810
-
19811
19458
  // src/core/openapi.ts
19812
19459
  var yaml2 = __toESM(require("js-yaml"));
19813
- var PRIMITIVES = {
19814
- string: { type: "string" },
19815
- number: { type: "number" },
19816
- float: { type: "number" },
19817
- decimal: { type: "number" },
19818
- int: { type: "integer" },
19819
- integer: { type: "integer" },
19820
- boolean: { type: "boolean" },
19821
- bool: { type: "boolean" },
19822
- date: { type: "string", format: "date-time" },
19823
- datetime: { type: "string", format: "date-time" },
19824
- uuid: { type: "string", format: "uuid" },
19825
- json: { type: "object" },
19826
- object: { type: "object" },
19827
- any: {},
19828
- unknown: {},
19829
- void: {}
19830
- };
19831
- function schemaFor(typeRef, closureIds) {
19832
- const trimmed = typeRef.trim().replace(/^promise\s*<(.+)>$/i, "$1").trim();
19833
- const arrayMatch = /^(.+)\[\]$/.exec(trimmed);
19834
- if (arrayMatch) {
19835
- return { type: "array", items: schemaFor(arrayMatch[1], closureIds) };
19836
- }
19837
- const lower = trimmed.toLowerCase();
19838
- if (lower in PRIMITIVES) {
19839
- const p = PRIMITIVES[lower];
19840
- return p.type ? { ...p } : {};
19841
- }
19842
- const local = trimmed.split(/::|\./).pop().toLowerCase().replace(/[^a-z0-9_-]/g, "");
19843
- const hit = [...closureIds].find((id) => id.toLowerCase() === local);
19844
- if (hit) return { $ref: `#/components/schemas/${hit}` };
19845
- return { type: "object", description: `Unresolved type: ${trimmed}` };
19846
- }
19847
- function operationFor(method, closureIds) {
19848
- const endpoint = method.endpoint;
19849
- const httpVerb = endpoint && endpoint.transport === "HTTP" ? endpoint.method.toLowerCase() : "post";
19850
- const bodyVerbs = /* @__PURE__ */ new Set(["post", "put", "patch"]);
19851
- const params = method.params ?? [];
19852
- const op = {
19853
- operationId: method.name,
19854
- summary: method.description,
19855
- responses: {
19856
- "200": {
19857
- description: method.returns || "Success",
19858
- ...method.returns && method.returns.toLowerCase() !== "void" ? { content: { "application/json": { schema: schemaFor(method.returns, closureIds) } } } : {}
19859
- }
19860
- }
19861
- };
19862
- if (method.guarantees?.length) op["x-wairon-guarantees"] = method.guarantees;
19863
- if (method.effect) op["x-wairon-effect"] = method.effect;
19864
- if (method.ext && Object.keys(method.ext).length) op["x-wairon-ext"] = method.ext;
19865
- if (params.length) {
19866
- if (bodyVerbs.has(httpVerb)) {
19867
- op.requestBody = {
19868
- required: true,
19869
- content: {
19870
- "application/json": {
19871
- schema: {
19872
- type: "object",
19873
- properties: Object.fromEntries(params.map((p) => [p.name, schemaFor(p.type, closureIds)])),
19874
- required: params.filter((p) => !p.optional).map((p) => p.name)
19875
- }
19876
- }
19877
- }
19878
- };
19879
- } else {
19880
- op.parameters = params.map((p) => ({
19881
- name: p.name,
19882
- in: "query",
19883
- required: !p.optional,
19884
- ...p.description ? { description: p.description } : {},
19885
- schema: schemaFor(p.type, closureIds)
19886
- }));
19887
- }
19888
- }
19889
- return op;
19890
- }
19891
- function securitySchemeObject(auth) {
19892
- if (auth.scheme === "none") return null;
19893
- const desc = auth.description ? { description: auth.description } : {};
19894
- switch (auth.scheme) {
19895
- case "apiKey":
19896
- return { type: "apiKey", in: auth.in ?? "header", name: auth.name ?? "X-API-Key", ...desc };
19897
- case "bearer":
19898
- return { type: "http", scheme: "bearer", ...auth.bearerFormat ? { bearerFormat: auth.bearerFormat } : {}, ...desc };
19899
- case "basic":
19900
- return { type: "http", scheme: "basic", ...desc };
19901
- case "oauth2": {
19902
- const flow = { scopes: Object.fromEntries((auth.scopes ?? []).map((s) => [s.name, s.description])) };
19903
- if (auth.authorizationUrl) flow.authorizationUrl = auth.authorizationUrl;
19904
- if (auth.tokenUrl) flow.tokenUrl = auth.tokenUrl;
19905
- if (auth.refreshUrl) flow.refreshUrl = auth.refreshUrl;
19906
- return { type: "oauth2", flows: { [auth.flow ?? "authorizationCode"]: flow }, ...desc };
19907
- }
19908
- case "openIdConnect":
19909
- return { type: "openIdConnect", openIdConnectUrl: auth.openIdConnectUrl ?? "", ...desc };
19910
- case "custom":
19911
- return { type: "apiKey", in: auth.in ?? "header", name: auth.name ?? "Authorization", description: auth.description ?? auth.example ?? "Custom authentication scheme." };
19912
- default:
19913
- return null;
19914
- }
19915
- }
19916
- function schemeBaseName(scheme) {
19917
- return { apiKey: "ApiKeyAuth", bearer: "BearerAuth", basic: "BasicAuth", oauth2: "OAuth2", openIdConnect: "OpenIdConnect", custom: "CustomAuth" }[scheme] ?? "Auth";
19918
- }
19919
- function buildSecurity(entries) {
19920
- const schemes = {};
19921
- const nameByContent = /* @__PURE__ */ new Map();
19922
- const securityByEntry = /* @__PURE__ */ new Map();
19923
- for (const entry of entries) {
19924
- if (!entry.auth) continue;
19925
- const obj = securitySchemeObject(entry.auth);
19926
- if (!obj) continue;
19927
- const content = JSON.stringify(obj);
19928
- let name = nameByContent.get(content);
19929
- if (!name) {
19930
- name = schemeBaseName(entry.auth.scheme);
19931
- for (let n = 2; schemes[name]; n++) name = schemeBaseName(entry.auth.scheme) + n;
19932
- schemes[name] = obj;
19933
- nameByContent.set(content, name);
19934
- }
19935
- const scopeNames = entry.auth.scheme === "oauth2" ? (entry.auth.scopes ?? []).map((s) => s.name) : [];
19936
- securityByEntry.set(entry.id, { [name]: scopeNames });
19937
- }
19938
- return { schemes, securityByEntry };
19939
- }
19940
- function httpEntriesOf(snapshot) {
19941
- return snapshot.interfaces.filter((e) => e.type === "REST" || e.methods.some((m) => m.endpoint?.transport === "HTTP"));
19942
- }
19943
- function renderDoc(snapshot, entries, closureIds, opts = {}) {
19944
- const { schemes, securityByEntry } = buildSecurity(entries);
19945
- const paths = {};
19946
- for (const entry of entries) {
19947
- const security = securityByEntry.get(entry.id);
19948
- for (const method of entry.methods) {
19949
- const endpoint = method.endpoint;
19950
- if (!endpoint || endpoint.transport !== "HTTP") continue;
19951
- const p = endpoint.path.startsWith("/") ? endpoint.path : `/${endpoint.path}`;
19952
- paths[p] = paths[p] ?? {};
19953
- paths[p][endpoint.method.toLowerCase()] = {
19954
- tags: [entry.id],
19955
- ...operationFor(method, closureIds),
19956
- ...security ? { security: [security] } : {}
19957
- };
19958
- }
19959
- }
19960
- const schemas = {};
19961
- for (const t of snapshot.types) {
19962
- schemas[t.id] = {
19963
- type: "object",
19964
- title: t.name,
19965
- properties: Object.fromEntries(t.fields.map((f) => [f.name, schemaFor(f.type, closureIds)])),
19966
- required: t.fields.filter((f) => !f.optional).map((f) => f.name)
19967
- };
19968
- }
19969
- const components = {};
19970
- if (Object.keys(schemas).length) components.schemas = schemas;
19971
- if (Object.keys(schemes).length) components.securitySchemes = schemes;
19972
- const basePaths = [...new Set(entries.map((e) => e.basePath).filter((b) => !!b))];
19973
- const servers = opts.servers && basePaths.length === 1 ? [{ url: basePaths[0] }] : void 0;
19974
- return {
19975
- openapi: "3.1.0",
19976
- info: {
19977
- title: opts.title ?? snapshot.projectName,
19978
- version: snapshot.version ?? "0.0.0",
19979
- ...snapshot.stateId ? { "x-wairon-state-id": snapshot.stateId } : {},
19980
- "x-wairon-origin": snapshot.origin,
19981
- "x-wairon-generated-at": snapshot.generatedAt
19982
- },
19983
- ...servers ? { servers } : {},
19984
- paths,
19985
- ...Object.keys(components).length ? { components } : {}
19986
- };
19987
- }
19988
- function toOpenApi(snapshot) {
19989
- const closureIds = new Set(snapshot.types.map((t) => t.id));
19990
- return JSON.stringify(renderDoc(snapshot, httpEntriesOf(snapshot), closureIds), null, 2);
19991
- }
19992
- function toOpenApiSet(snapshot) {
19993
- const closureIds = new Set(snapshot.types.map((t) => t.id));
19994
- const byPortal = /* @__PURE__ */ new Map();
19995
- const order = [];
19996
- for (const entry of httpEntriesOf(snapshot)) {
19997
- if (!byPortal.has(entry.component)) {
19998
- byPortal.set(entry.component, []);
19999
- order.push(entry.component);
20000
- }
20001
- byPortal.get(entry.component).push(entry);
20002
- }
20003
- return order.map((portalId) => {
20004
- const entries = byPortal.get(portalId);
20005
- const name = entries[0]?.name ?? portalId;
20006
- return { portalId, name, document: JSON.stringify(renderDoc(snapshot, entries, closureIds, { title: name, servers: true }), null, 2) };
20007
- });
20008
- }
20009
- function isOpenApiDocument(body) {
20010
- try {
20011
- const parsed = yaml2.load(body);
20012
- return !!parsed && typeof parsed === "object" && typeof parsed.openapi === "string";
20013
- } catch {
20014
- return false;
20015
- }
20016
- }
20017
- function typeRefFromSchema(schema) {
20018
- if (!schema) return "json";
20019
- const ref = schema.$ref;
20020
- if (typeof ref === "string") return ref.split("/").pop() ?? "json";
20021
- if (schema.type === "array") {
20022
- return `${typeRefFromSchema(schema.items)}[]`;
20023
- }
20024
- const t = schema.type;
20025
- if (t === "integer") return "int";
20026
- if (typeof t === "string" && t !== "object") return t;
20027
- return "json";
20028
- }
20029
- function authFromSecurityScheme(scheme) {
20030
- const desc = typeof scheme.description === "string" ? { description: scheme.description } : {};
20031
- if (scheme.type === "apiKey") {
20032
- return {
20033
- scheme: "apiKey",
20034
- ...scheme.in === "header" || scheme.in === "query" || scheme.in === "cookie" ? { in: scheme.in } : {},
20035
- ...typeof scheme.name === "string" ? { name: scheme.name } : {},
20036
- ...desc
20037
- };
20038
- }
20039
- if (scheme.type === "http") {
20040
- if (scheme.scheme === "bearer") return { scheme: "bearer", ...typeof scheme.bearerFormat === "string" ? { bearerFormat: scheme.bearerFormat } : {}, ...desc };
20041
- if (scheme.scheme === "basic") return { scheme: "basic", ...desc };
20042
- }
20043
- if (scheme.type === "oauth2") {
20044
- const flows = scheme.flows ?? {};
20045
- const flowKey = Object.keys(flows)[0];
20046
- const f = flows[flowKey] ?? {};
20047
- return {
20048
- scheme: "oauth2",
20049
- ...flowKey === "authorizationCode" || flowKey === "clientCredentials" || flowKey === "implicit" || flowKey === "password" ? { flow: flowKey } : {},
20050
- ...typeof f.authorizationUrl === "string" ? { authorizationUrl: f.authorizationUrl } : {},
20051
- ...typeof f.tokenUrl === "string" ? { tokenUrl: f.tokenUrl } : {},
20052
- ...typeof f.refreshUrl === "string" ? { refreshUrl: f.refreshUrl } : {},
20053
- scopes: Object.entries(f.scopes ?? {}).map(([name, description]) => ({ name, description })),
20054
- ...desc
20055
- };
20056
- }
20057
- if (scheme.type === "openIdConnect") {
20058
- return { scheme: "openIdConnect", openIdConnectUrl: typeof scheme.openIdConnectUrl === "string" ? scheme.openIdConnectUrl : "", ...desc };
20059
- }
20060
- return void 0;
20061
- }
20062
- function fromOpenApi(document, projectName) {
20063
- let parsed;
20064
- try {
20065
- parsed = yaml2.load(document);
20066
- } catch (e) {
20067
- throw new Error(`Invalid surface document: not parseable as JSON/YAML (${e instanceof Error ? e.message : String(e)})`);
20068
- }
20069
- if (!parsed || typeof parsed !== "object" || typeof parsed.openapi !== "string" || typeof parsed.paths !== "object") {
20070
- throw new Error('Invalid surface document: missing OpenAPI "openapi"/"paths" structure.');
20071
- }
20072
- const info = parsed.info ?? {};
20073
- const methods = [];
20074
- for (const [rawPath, ops] of Object.entries(parsed.paths)) {
20075
- for (const [verb, opRaw] of Object.entries(ops ?? {})) {
20076
- if (!["get", "post", "put", "delete", "patch", "options", "head"].includes(verb)) continue;
20077
- const op = opRaw ?? {};
20078
- const name = typeof op.operationId === "string" && /^[a-zA-Z0-9_]+$/.test(op.operationId) ? op.operationId : `${verb}_${rawPath.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
20079
- const params = [];
20080
- for (const p of op.parameters ?? []) {
20081
- if (typeof p.name !== "string") continue;
20082
- params.push({
20083
- name: p.name,
20084
- type: typeRefFromSchema(p.schema),
20085
- ...p.required === true ? {} : { optional: true },
20086
- ...typeof p.description === "string" ? { description: p.description } : {}
20087
- });
20088
- }
20089
- const bodySchema = op.requestBody?.content?.["application/json"]?.schema;
20090
- if (bodySchema) {
20091
- const props = bodySchema.properties ?? {};
20092
- const required = new Set(bodySchema.required ?? []);
20093
- if (Object.keys(props).length) {
20094
- for (const [pname, pschema] of Object.entries(props)) {
20095
- params.push({ name: pname, type: typeRefFromSchema(pschema), ...required.has(pname) ? {} : { optional: true } });
20096
- }
20097
- } else {
20098
- params.push({ name: "body", type: typeRefFromSchema(bodySchema) });
20099
- }
20100
- }
20101
- const okResponse = op.responses?.["200"] ?? op.responses?.["201"];
20102
- const responseSchema = okResponse?.content?.["application/json"]?.schema;
20103
- const returns = responseSchema ? typeRefFromSchema(responseSchema) : "void";
20104
- const rawGuarantees = op["x-wairon-guarantees"];
20105
- const guarantees = Array.isArray(rawGuarantees) ? rawGuarantees.filter((g) => typeof g === "string" && g.length > 0) : [];
20106
- const rawEffect = op["x-wairon-effect"];
20107
- const effect = rawEffect === "read" || rawEffect === "write" ? rawEffect : void 0;
20108
- const rawExt = op["x-wairon-ext"];
20109
- const ext = rawExt && typeof rawExt === "object" && !Array.isArray(rawExt) ? rawExt : void 0;
20110
- methods.push({
20111
- name,
20112
- description: typeof op.summary === "string" ? op.summary : typeof op.description === "string" ? op.description : name,
20113
- signature: `${name}(${params.map((p) => `${p.name}: ${p.type}`).join(", ")}): ${returns}`,
20114
- returns,
20115
- params,
20116
- endpoint: { transport: "HTTP", method: verb.toUpperCase(), path: rawPath },
20117
- ...guarantees.length ? { guarantees } : {},
20118
- ...effect ? { effect } : {},
20119
- ...ext ? { ext } : {}
20120
- });
20121
- }
20122
- }
20123
- const types = [];
20124
- const schemas = parsed.components?.schemas ?? {};
20125
- for (const [id, schema] of Object.entries(schemas)) {
20126
- const props = schema.properties ?? {};
20127
- const required = new Set(schema.required ?? []);
20128
- types.push({
20129
- id,
20130
- name: typeof schema.title === "string" ? schema.title : id,
20131
- kind: "value-object",
20132
- fields: Object.entries(props).map(([fname, fschema]) => ({
20133
- name: fname,
20134
- type: typeRefFromSchema(fschema),
20135
- ...required.has(fname) ? {} : { optional: true }
20136
- }))
20137
- });
20138
- }
20139
- const securitySchemes = parsed.components?.securitySchemes ?? {};
20140
- const firstScheme = Object.values(securitySchemes)[0];
20141
- const importedAuth = firstScheme ? authFromSecurityScheme(firstScheme) : void 0;
20142
- const entry = {
20143
- id: `${projectName}-api`,
20144
- name: typeof info.title === "string" ? info.title : projectName,
20145
- audience: "external",
20146
- type: "REST",
20147
- component: `${projectName}-api`,
20148
- methods,
20149
- details: typeof info.description === "string" ? info.description : `Imported OpenAPI surface of ${projectName}.`,
20150
- ...typeof info.version === "string" ? { version: info.version } : {},
20151
- ...importedAuth ? { auth: importedAuth } : {}
20152
- };
20153
- return SurfaceSnapshotSchema.parse({
20154
- projectName,
20155
- origin: "authored",
20156
- ...typeof info.version === "string" ? { version: info.version } : {},
20157
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
20158
- interfaces: [entry],
20159
- types
20160
- });
20161
- }
20162
19460
 
20163
19461
  // src/core/surfaces.ts
20164
19462
  var SURFACES_DIRNAME = "surfaces";
20165
19463
  function surfacesDir(rootDir) {
20166
19464
  return path13.join(rootDir, ".wai", SURFACES_DIRNAME);
20167
19465
  }
20168
- function audienceRank(audience) {
20169
- const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
20170
- return idx === -1 ? SURFACE_AUDIENCES.indexOf("instance") : idx;
20171
- }
20172
- function stateIdString() {
20173
- const s = computeStateId();
20174
- return `${s.algorithm}:${s.digest}`;
20175
- }
20176
- function computeTypeClosure(entries, types) {
20177
- const included = /* @__PURE__ */ new Map();
20178
- const queue = [];
20179
- const enqueueRef = (ref) => {
20180
- if (BUILTIN_TYPES.has(ref.toLowerCase())) return;
20181
- for (const spec of types) {
20182
- const qualifiedId = spec.subsystem && !spec.id.startsWith(`${spec.subsystem}::`) ? `${spec.subsystem}::${spec.id}` : spec.id;
20183
- if (matchTypeRef(ref, qualifiedId) && !included.has(spec.id)) {
20184
- included.set(spec.id, spec);
20185
- queue.push(spec.id);
20186
- }
20187
- }
20188
- };
20189
- for (const entry of entries) {
20190
- for (const m of entry.methods) {
20191
- for (const ref of methodTypeRefs(m)) enqueueRef(ref);
20192
- }
20193
- }
20194
- while (queue.length) {
20195
- const spec = included.get(queue.shift());
20196
- for (const field of spec.fields) {
20197
- for (const ref of extractTypeIdentifiers(field.type)) enqueueRef(ref);
20198
- }
20199
- }
20200
- return [...included.values()].map((t) => ({
20201
- id: t.id,
20202
- name: t.name,
20203
- kind: t.kind,
20204
- fields: t.fields.map((f) => ({
20205
- name: f.name,
20206
- type: f.type,
20207
- ...f.description ? { description: f.description } : {},
20208
- ...f.optional ? { optional: true } : {}
20209
- }))
20210
- }));
20211
- }
20212
- function projectOwnSurface(maxAudience) {
20213
- const system = loadSystemSpec();
20214
- if (!system) {
20215
- throw new Error("Cannot project a surface: the L0 system spec is missing.");
20216
- }
20217
- const subsystems = loadSubsystemSpecs();
20218
- const components = loadComponentSpecs();
20219
- const interfaces = loadInterfaceSpecs();
20220
- const types = loadTypeSpecs();
20221
- const floor = audienceRank(maxAudience);
20222
- const rawEntries = system.publicInterfaces ?? [];
20223
- const entries = [];
20224
- for (const raw of rawEntries) {
20225
- const audience = raw.audience ?? "instance";
20226
- if (audienceRank(audience) < floor) continue;
20227
- if (!raw.component) continue;
20228
- const comp = components.find((c) => c.id === raw.component);
20229
- if (!comp) continue;
20230
- const compInterfaces = interfaces.filter((i) => i.component === comp.id && (!raw.interface || i.id === raw.interface));
20231
- const methods = compInterfaces.flatMap((i) => i.methods);
20232
- const subsystemType = subsystems.find((s) => s.id === comp.subsystem)?.publicInterfaces.find((pi) => pi.component === comp.id)?.type;
20233
- entries.push({
20234
- id: raw.id ?? raw.interface ?? comp.id,
20235
- name: raw.name ?? comp.name,
20236
- audience,
20237
- type: raw.type ?? subsystemType ?? "Custom",
20238
- component: comp.id,
20239
- methods,
20240
- ...comp.dispatch && comp.dispatch.length ? { dispatch: comp.dispatch } : {},
20241
- // Project the backing Portal's auth + basePath so the codec can emit
20242
- // OpenAPI security + per-portal servers self-contained from the snapshot.
20243
- ...comp.auth && comp.auth.scheme !== "none" ? { auth: comp.auth } : {},
20244
- ...comp.basePath ? { basePath: comp.basePath } : {},
20245
- details: raw.details ?? "",
20246
- ...raw.version ? { version: raw.version } : {},
20247
- ...raw.stability ? { stability: raw.stability } : {}
20248
- });
20249
- }
20250
- return SurfaceSnapshotSchema.parse({
20251
- projectName: system.name,
20252
- origin: "generated",
20253
- stateId: stateIdString(),
20254
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
20255
- interfaces: entries,
20256
- types: computeTypeClosure(entries, types)
20257
- });
20258
- }
20259
- function projectChildSurface() {
20260
- return projectOwnSurface("project");
20261
- }
20262
- function localName(id) {
20263
- return id.split("::").pop();
20264
- }
20265
- var CROSS_BOUNDARY_TARGETS = /* @__PURE__ */ new Set(["Portal", "Observer"]);
20266
- function projectSubsystemSurface(subsystemId) {
20267
- const system = loadSystemSpec();
20268
- if (!system) {
20269
- throw new Error("Cannot project a subsystem surface: the L0 system spec is missing.");
20270
- }
20271
- const subsystems = loadSubsystemSpecs();
20272
- const target = subsystems.find((s) => s.id === subsystemId);
20273
- if (!target) {
20274
- throw new Error(`Cannot project a subsystem surface: subsystem "${subsystemId}" does not exist.`);
20275
- }
20276
- const components = loadComponentSpecs();
20277
- const interfaces = loadInterfaceSpecs();
20278
- const types = loadTypeSpecs();
20279
- const entries = [];
20280
- const unprojectable = [];
20281
- for (const pub of target.publicInterfaces ?? []) {
20282
- if (!pub.component) continue;
20283
- const comp = components.find((c) => c.id === pub.component || c.id === `${subsystemId}::${pub.component}`);
20284
- if (!comp) continue;
20285
- if (!CROSS_BOUNDARY_TARGETS.has(comp.componentType)) {
20286
- unprojectable.push({ component: pub.component, componentType: comp.componentType });
20287
- continue;
20288
- }
20289
- const compInterfaces = interfaces.filter((i) => i.component === comp.id && (!pub.interface || i.id === pub.interface || i.id === `${subsystemId}::${pub.interface}`));
20290
- const methods = compInterfaces.flatMap((i) => i.methods);
20291
- entries.push({
20292
- id: localName(pub.interface ?? comp.id),
20293
- name: comp.name,
20294
- // Family ceiling: a sibling surface is consumable by the system family only.
20295
- audience: "project",
20296
- type: pub.type ?? "Custom",
20297
- // The snapshot carries the LOCAL portal name — consumers resolve cross-tree
20298
- // refs by their final segment.
20299
- component: localName(comp.id),
20300
- methods,
20301
- ...comp.dispatch && comp.dispatch.length ? { dispatch: comp.dispatch } : {},
20302
- // Project the backing component's auth + basePath so the codec can emit
20303
- // OpenAPI security + per-portal servers self-contained from the snapshot.
20304
- ...comp.auth && comp.auth.scheme !== "none" ? { auth: comp.auth } : {},
20305
- ...comp.basePath ? { basePath: comp.basePath } : {},
20306
- details: pub.details ?? ""
20307
- });
20308
- }
20309
- for (const skipped of unprojectable) {
20310
- console.error(
20311
- `[surfaces] skipped "${subsystemId}::${skipped.component}": a published ${skipped.componentType} can never serve a cross-boundary caller, so it stays out of every chained child's sibling surface \u2014 publish this surface through a Portal, or an Observer (for events).`
20312
- );
20313
- }
20314
- return SurfaceSnapshotSchema.parse({
20315
- projectName: `${system.name}::${subsystemId}`,
20316
- origin: "generated",
20317
- stateId: stateIdString(),
20318
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
20319
- interfaces: entries,
20320
- types: computeTypeClosure(entries, types)
20321
- });
20322
- }
20323
19466
  function listSnapshots(rootDir = getProjectRoot()) {
20324
19467
  const dir = surfacesDir(rootDir);
20325
19468
  if (!fs11.existsSync(dir)) return [];
@@ -20333,54 +19476,6 @@ function listSnapshots(rootDir = getProjectRoot()) {
20333
19476
  }
20334
19477
  return out;
20335
19478
  }
20336
- function getSnapshot(projectName, rootDir = getProjectRoot()) {
20337
- return listSnapshots(rootDir).find((s) => s.projectName === projectName) ?? null;
20338
- }
20339
- function snapshotFilename(projectName) {
20340
- return `${safeFilenamePart(projectName)}.yaml`;
20341
- }
20342
- function writeSnapshotIfChanged(snapshot, rootDir) {
20343
- const dir = surfacesDir(rootDir);
20344
- fs11.mkdirSync(dir, { recursive: true });
20345
- const p = path13.join(dir, snapshotFilename(snapshot.projectName));
20346
- const next = SurfaceSnapshotSchema.parse(snapshot);
20347
- if (fs11.existsSync(p)) {
20348
- try {
20349
- const existing = SurfaceSnapshotSchema.parse(readYamlFile(p));
20350
- if (surfaceContentKey(existing) === surfaceContentKey(next)) {
20351
- return { path: p, changed: false };
20352
- }
20353
- } catch {
20354
- }
20355
- }
20356
- writeYamlFile(p, next);
20357
- return { path: p, changed: true };
20358
- }
20359
- function saveSnapshot(snapshot, rootDir = getProjectRoot()) {
20360
- return writeSnapshotIfChanged(snapshot, rootDir).path;
20361
- }
20362
- function removeSnapshot(projectName, rootDir = getProjectRoot()) {
20363
- const dir = surfacesDir(rootDir);
20364
- const direct = path13.join(dir, snapshotFilename(projectName));
20365
- if (fs11.existsSync(direct)) {
20366
- fs11.unlinkSync(direct);
20367
- return true;
20368
- }
20369
- if (!fs11.existsSync(dir)) return false;
20370
- for (const file of fs11.readdirSync(dir)) {
20371
- if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
20372
- const p = path13.join(dir, file);
20373
- try {
20374
- const snap = SurfaceSnapshotSchema.parse(readYamlFile(p));
20375
- if (snap.projectName === projectName) {
20376
- fs11.unlinkSync(p);
20377
- return true;
20378
- }
20379
- } catch {
20380
- }
20381
- }
20382
- return false;
20383
- }
20384
19479
  function loadSurfaceSnapshots() {
20385
19480
  return listSnapshots();
20386
19481
  }
@@ -20398,136 +19493,12 @@ function listMountSnapshots(mounts) {
20398
19493
  function loadMountSurfaceSnapshots(mounts) {
20399
19494
  return listMountSnapshots(mounts);
20400
19495
  }
20401
- function selectPortalSpec(renderedSet, portalId) {
20402
- const hit = renderedSet.find((spec) => spec.portalId === portalId);
20403
- if (!hit) {
20404
- const known = renderedSet.map((s) => s.portalId).join(", ");
20405
- throw new Error(`Unknown portal "${portalId}" \u2014 this surface renders: ${known || "(no portals)"}.`);
20406
- }
20407
- return [hit];
20408
- }
20409
- function perPortalPath(resolvedOut, portalId) {
20410
- const ext = path13.extname(resolvedOut);
20411
- const stem = ext ? resolvedOut.slice(0, -ext.length) : resolvedOut;
20412
- return `${stem}.${safeFilenamePart(portalId)}${ext}`;
20413
- }
20414
- function writeSurfaceFile(outPath, snapshot, renderedSet) {
20415
- const resolved = path13.resolve(outPath);
20416
- fs11.mkdirSync(path13.dirname(resolved), { recursive: true });
20417
- if (!renderedSet || renderedSet.length === 0) {
20418
- writeYamlFile(resolved, snapshot);
20419
- return [resolved];
20420
- }
20421
- if (renderedSet.length === 1) {
20422
- fs11.writeFileSync(resolved, renderedSet[0].document);
20423
- return [resolved];
20424
- }
20425
- return renderedSet.map((spec) => {
20426
- const target = perPortalPath(resolved, spec.portalId);
20427
- fs11.writeFileSync(target, spec.document);
20428
- return target;
20429
- });
20430
- }
20431
- function exportResult(snapshot, renderedSet, writtenPaths) {
20432
- const rendered = renderedSet?.length === 1 ? renderedSet[0].document : void 0;
20433
- return {
20434
- snapshot,
20435
- ...rendered !== void 0 ? { rendered } : {},
20436
- ...renderedSet ? { renderedSet } : {},
20437
- ...writtenPaths.length === 1 ? { writtenTo: writtenPaths[0] } : {},
20438
- ...writtenPaths.length ? { writtenPaths } : {}
20439
- };
20440
- }
20441
- function exportSurface(maxAudience, format, outPath, portalId) {
20442
- const snapshot = projectOwnSurface(maxAudience);
20443
- let renderedSet = format === "openapi" ? toOpenApiSet(snapshot) : void 0;
20444
- if (renderedSet && portalId) renderedSet = selectPortalSpec(renderedSet, portalId);
20445
- const writtenPaths = outPath ? writeSurfaceFile(outPath, snapshot, renderedSet) : [];
20446
- return exportResult(snapshot, renderedSet, writtenPaths);
20447
- }
20448
- function importSurface(sourcePath, origin) {
20449
- const resolved = path13.resolve(sourcePath);
20450
- if (!fs11.existsSync(resolved)) {
20451
- throw new Error(`Surface document not found: ${resolved}`);
20452
- }
20453
- const body = fs11.readFileSync(resolved, "utf8");
20454
- let snapshot;
20455
- if (isOpenApiDocument(body)) {
20456
- const projectName = path13.basename(resolved).replace(/\.(json|ya?ml)$/i, "");
20457
- snapshot = fromOpenApi(body, projectName);
20458
- snapshot = { ...snapshot, origin };
20459
- } else {
20460
- snapshot = SurfaceSnapshotSchema.parse(readYamlFile(resolved));
20461
- snapshot = { ...snapshot, origin };
20462
- }
20463
- saveSnapshot(snapshot);
20464
- return snapshot;
20465
- }
20466
- function projectFamilySurfaces(parent) {
20467
- return runWithProjectRoot(parent.parentRoot, () => {
20468
- invalidateSpecCache();
20469
- const siblings = loadSubsystemSpecs().filter((s) => !s.id.includes("::") && s.id !== parent.subsystemId);
20470
- return [projectChildSurface(), ...siblings.map((s) => projectSubsystemSurface(s.id))];
20471
- });
20472
- }
20473
- function pinFamilySurfaces() {
20474
- const parent = resolveChainingParent();
20475
- if (!parent) return null;
20476
- const childRoot = getProjectRoot();
20477
- const projected = projectFamilySurfaces(parent);
20478
- const before = new Map(listSnapshots(childRoot).map((s) => [s.projectName, surfaceContentKey(s)]));
20479
- const changed = [];
20480
- for (const snapshot of projected) {
20481
- const stored = saveSnapshot(snapshot, childRoot);
20482
- if (before.get(snapshot.projectName) !== surfaceContentKey(SurfaceSnapshotSchema.parse(snapshot))) {
20483
- changed.push(stored);
20484
- }
20485
- }
20486
- return changed;
20487
- }
20488
- function projectedFamilyContent(parent) {
20489
- try {
20490
- return new Map(projectFamilySurfaces(parent).map((s) => [s.projectName, surfaceContentKey(s)]));
20491
- } catch {
20492
- return null;
20493
- }
20494
- }
20495
- function listExternalInterfaces() {
20496
- const snapshots = listSnapshots();
20497
- const chainingParent = resolveChainingParent();
20498
- const projected = chainingParent ? projectedFamilyContent(chainingParent) : null;
20499
- return snapshots.map((snapshot) => {
20500
- const generated = snapshot.origin === "generated";
20501
- const sourceKind = !generated ? "foreign" : snapshot.projectName.includes("::") ? "sibling" : "parent";
20502
- const freshness = generated && projected ? projected.get(snapshot.projectName) === surfaceContentKey(snapshot) ? "fresh" : "stale" : "unverifiable";
20503
- return {
20504
- projectName: snapshot.projectName,
20505
- origin: snapshot.origin,
20506
- sourceKind,
20507
- generatedAt: snapshot.generatedAt,
20508
- ...snapshot.stateId ? { stateId: snapshot.stateId } : {},
20509
- ...snapshot.version ? { version: snapshot.version } : {},
20510
- freshness,
20511
- interfaceIds: snapshot.interfaces.map((e) => e.id)
20512
- };
20513
- });
20514
- }
20515
- function surfaceContentKey(snapshot) {
20516
- const { stateId, generatedAt, origin, ...content } = snapshot;
20517
- return JSON.stringify(content);
20518
- }
20519
19496
 
20520
19497
  // src/core/validation.ts
20521
19498
  var path14 = __toESM(require("path"));
20522
19499
  function loadProjectConfig2() {
20523
19500
  return loadProjectConfig();
20524
19501
  }
20525
- function computeStateId2() {
20526
- return computeStateId();
20527
- }
20528
- function consumedContractInputs2() {
20529
- return consumedContractInputs();
20530
- }
20531
19502
  function projectPackSelections() {
20532
19503
  try {
20533
19504
  return (loadProjectConfig2()?.extensions?.packs ?? []).filter((e) => typeof e !== "string");
@@ -20535,9 +19506,6 @@ function projectPackSelections() {
20535
19506
  return [];
20536
19507
  }
20537
19508
  }
20538
- function findTestsReferencing2(methods, projectRoot, testRoots = []) {
20539
- return findTestsReferencing(methods, projectRoot, testRoots);
20540
- }
20541
19509
  var RESOLUTION_FAILURE_CODES = /* @__PURE__ */ new Set([
20542
19510
  "UNDEFINED_TYPE_REFERENCE",
20543
19511
  "INVALID_DEPENDENCY_REFERENCE",
@@ -20576,90 +19544,6 @@ function stricterSeverities(parent, child) {
20576
19544
  function issue(severity, code, message, agentId, specId) {
20577
19545
  return { severity, code, message, agentId, specId };
20578
19546
  }
20579
- function validateRegistry(registry, rules) {
20580
- const issues = [];
20581
- const idCounts = /* @__PURE__ */ new Map();
20582
- for (const agent of registry.agents) {
20583
- idCounts.set(agent.id, (idCounts.get(agent.id) ?? 0) + 1);
20584
- }
20585
- for (const [id, count] of idCounts) {
20586
- if (count > 1) {
20587
- issues.push(issue("error", "DUPLICATE_AGENT_ID", `Duplicate agent id: "${id}"`, id));
20588
- }
20589
- }
20590
- for (const agent of registry.agents) {
20591
- validateAgent(agent, rules, issues);
20592
- }
20593
- if (rules.noOverlappingOwnership) {
20594
- checkOverlappingOwnership(registry.agents, issues);
20595
- }
20596
- return {
20597
- valid: issues.every((i) => i.severity !== "error"),
20598
- issues
20599
- };
20600
- }
20601
- function validateAgent(agent, rules, issues) {
20602
- const isMeta = agent.tags.some((t) => rules.metaAgentTags.includes(t));
20603
- if (rules.requireOwnedPaths && !isMeta && agent.ownedPaths.length === 0) {
20604
- issues.push(
20605
- issue(
20606
- "warning",
20607
- "NO_OWNED_PATHS",
20608
- `Agent "${agent.id}" has no ownedPaths. Add paths or tag as meta/guardian.`,
20609
- agent.id
20610
- )
20611
- );
20612
- }
20613
- if (agent.targets.length === 0) {
20614
- issues.push(
20615
- issue("warning", "NO_TARGETS", `Agent "${agent.id}" has no output targets configured.`, agent.id)
20616
- );
20617
- }
20618
- }
20619
- function checkOverlappingOwnership(agents, issues) {
20620
- const pathToAgents = /* @__PURE__ */ new Map();
20621
- for (const agent of agents) {
20622
- for (const p of agent.ownedPaths) {
20623
- const owners = pathToAgents.get(p) ?? [];
20624
- owners.push(agent.id);
20625
- pathToAgents.set(p, owners);
20626
- }
20627
- }
20628
- for (const [p, owners] of pathToAgents) {
20629
- if (owners.length > 1) {
20630
- issues.push(
20631
- issue(
20632
- "error",
20633
- "OVERLAPPING_OWNERSHIP",
20634
- `Path "${p}" is claimed by multiple agents: ${owners.join(", ")}`
20635
- )
20636
- );
20637
- }
20638
- }
20639
- }
20640
- function validateProjectConfig(config) {
20641
- const issues = [];
20642
- if (config.targets.length === 0) {
20643
- issues.push(issue("error", "NO_TARGETS", "No output targets configured in project.yaml"));
20644
- }
20645
- const enabled = config.targets.filter((t) => {
20646
- if (typeof t === "string") return true;
20647
- return t.enabled !== false;
20648
- });
20649
- if (enabled.length === 0) {
20650
- issues.push(issue("error", "NO_ENABLED_TARGETS", "All configured targets are disabled"));
20651
- }
20652
- return {
20653
- valid: issues.every((i) => i.severity !== "error"),
20654
- issues
20655
- };
20656
- }
20657
- function listRules2() {
20658
- const extensions = loadProjectExtensions();
20659
- registerBuiltinRules();
20660
- registerPackRules(extensions.rules);
20661
- return ruleSequence();
20662
- }
20663
19547
  function validateSddTree(rulesOrOptions, projectType = "backend") {
20664
19548
  let rules = rulesOrOptions;
20665
19549
  let scopeSubsystem;
@@ -20897,22 +19781,6 @@ function settledStatusBearing(loaded) {
20897
19781
  take(loaded.implementations, index.paths.implementation);
20898
19782
  return out;
20899
19783
  }
20900
- function validateAsComplete(options) {
20901
- return validateSddTree({ ...options ?? {}, treatAllAsComplete: true });
20902
- }
20903
- function computeGateStateId() {
20904
- const content = computeStateId2();
20905
- const extensions = loadProjectExtensions();
20906
- let gate = {};
20907
- try {
20908
- const config = loadProjectConfig2();
20909
- if (config) gate = { projectType: config.projectType, rules: config.rules };
20910
- } catch {
20911
- }
20912
- const inputs = consumedContractInputs2();
20913
- registerBuiltinRules();
20914
- return computeGateIdentity(content, extensions, ruleSequence(), inputs, gate);
20915
- }
20916
19784
 
20917
19785
  // src/core/diagram.ts
20918
19786
  function renderDiagram(format) {
@@ -22058,13 +20926,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
22058
20926
  const isPlain = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
22059
20927
  const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
22060
20928
  const at = (prefix, key) => prefix ? `${prefix}.${key}` : key;
22061
- const say = (path29, why) => {
22062
- out.push(`${path29} \u2014 ${why}`);
20929
+ const say = (path28, why) => {
20930
+ out.push(`${path28} \u2014 ${why}`);
22063
20931
  };
22064
- const walkValue = (d, m, s, path29, field) => {
20932
+ const walkValue = (d, m, s, path28, field) => {
22065
20933
  if (Array.isArray(d)) {
22066
20934
  if (!Array.isArray(m)) {
22067
- say(path29, "the level does not have this field, so the write dropped it");
20935
+ say(path28, "the level does not have this field, so the write dropped it");
22068
20936
  return;
22069
20937
  }
22070
20938
  if (field === "narrative" && d.some(carriesEditMarker)) return;
@@ -22072,32 +20940,32 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
22072
20940
  if (carriesEditMarker(element)) continue;
22073
20941
  const key = reportIdentityOf(field, element);
22074
20942
  if (key === null) {
22075
- if (!same(m, d)) say(path29, "the level does not keep this value, so the write dropped it");
22076
- else if (same(s, d)) say(path29, "the stored spec already held this value");
20943
+ if (!same(m, d)) say(path28, "the level does not keep this value, so the write dropped it");
20944
+ else if (same(s, d)) say(path28, "the stored spec already held this value");
22077
20945
  return;
22078
20946
  }
22079
20947
  const mMatch = m.find((i) => reportIdentityOf(field, i) === key);
22080
20948
  const sMatch = Array.isArray(s) ? s.find((i) => reportIdentityOf(field, i) === key) : void 0;
22081
20949
  if (mMatch === void 0) {
22082
- say(at(path29, key), "the write did not store this element");
20950
+ say(at(path28, key), "the write did not store this element");
22083
20951
  continue;
22084
20952
  }
22085
- walk2(element, mMatch, sMatch, at(path29, key), field);
20953
+ walk2(element, mMatch, sMatch, at(path28, key), field);
22086
20954
  }
22087
20955
  return;
22088
20956
  }
22089
20957
  if (isPlain(d)) {
22090
20958
  if (!isPlain(m)) {
22091
- say(path29, "the level does not have this field, so the write dropped it");
20959
+ say(path28, "the level does not have this field, so the write dropped it");
22092
20960
  return;
22093
20961
  }
22094
- walk2(d, m, s, path29, field);
20962
+ walk2(d, m, s, path28, field);
22095
20963
  return;
22096
20964
  }
22097
- if (!same(m, d)) say(path29, "the write did not store it \u2014 the level's schema does not keep this value");
22098
- else if (same(s, d)) say(path29, "the stored spec already held this value");
20965
+ if (!same(m, d)) say(path28, "the write did not store it \u2014 the level's schema does not keep this value");
20966
+ else if (same(s, d)) say(path28, "the stored spec already held this value");
22099
20967
  };
22100
- function walk2(d, m, s, path29, container) {
20968
+ function walk2(d, m, s, path28, container) {
22101
20969
  for (const [key, value] of Object.entries(d)) {
22102
20970
  if (DELTA_VERBS.has(key) || JUMP_LABEL_TWINS.has(key)) continue;
22103
20971
  if (key === "label" && LABEL_TWIN_CONTAINERS.has(container)) continue;
@@ -22107,13 +20975,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
22107
20975
  if (typeof name !== "string") continue;
22108
20976
  const had = isPlain(s) && s[name] !== void 0;
22109
20977
  const still = isPlain(m) && m[name] !== void 0;
22110
- if (!had) say(at(path29, name), "unset named a field the stored spec did not have");
22111
- else if (still) say(at(path29, name), "unset did not remove it");
20978
+ if (!had) say(at(path28, name), "unset named a field the stored spec did not have");
20979
+ else if (still) say(at(path28, name), "unset did not remove it");
22112
20980
  }
22113
20981
  continue;
22114
20982
  }
22115
20983
  if (value === void 0 || value === null) continue;
22116
- const here = at(path29, key);
20984
+ const here = at(path28, key);
22117
20985
  const mValue = isPlain(m) ? m[key] : void 0;
22118
20986
  const sValue = isPlain(s) ? s[key] : void 0;
22119
20987
  if (mValue === void 0) {
@@ -24452,9 +23320,6 @@ function scanAllSpecs(options) {
24452
23320
  function resolveSubprojectForNamespace(namespace) {
24453
23321
  return current().resolveSubprojectForNamespace(namespace);
24454
23322
  }
24455
- function getSubprojectPrefix(qualifiedId) {
24456
- return current().getSubprojectPrefix(qualifiedId);
24457
- }
24458
23323
  function getSubsystemPath(id) {
24459
23324
  return current().getSubsystemPath(id);
24460
23325
  }
@@ -24467,12 +23332,6 @@ function getInterfacePath(id, componentId) {
24467
23332
  function getImplementationPath(id, contractId) {
24468
23333
  return current().getImplementationPath(id, contractId);
24469
23334
  }
24470
- function getTypePath(id, subsystemId, group) {
24471
- return current().getTypePath(id, subsystemId, group);
24472
- }
24473
- function getGroupPath(id, subsystemId) {
24474
- return current().getGroupPath(id, subsystemId);
24475
- }
24476
23335
  function loadSystemSpec() {
24477
23336
  return current().loadSystemSpec();
24478
23337
  }
@@ -24503,9 +23362,6 @@ function saveComponentSpec(spec, opts) {
24503
23362
  function deleteComponentSpec(id) {
24504
23363
  return current().deleteComponentSpec(id);
24505
23364
  }
24506
- function normalizeComponentLayout() {
24507
- return current().normalizeComponentLayout();
24508
- }
24509
23365
  function loadInterfaceSpecs() {
24510
23366
  return current().loadInterfaceSpecs();
24511
23367
  }
@@ -24617,38 +23473,12 @@ function computeStateIdAt(root) {
24617
23473
  function deleteTypeSpec(id) {
24618
23474
  return current().deleteTypeSpec(id);
24619
23475
  }
24620
- function loadGroupSpecs() {
24621
- return current().loadGroupSpecs();
24622
- }
24623
- function loadGroupSpec(id) {
24624
- return current().loadGroupSpec(id);
24625
- }
24626
- function saveGroupSpec(spec) {
24627
- current().saveGroupSpec(spec);
24628
- }
24629
- function deleteGroupSpec(id) {
24630
- return current().deleteGroupSpec(id);
24631
- }
24632
- function collectPromotableSpecs(scopeSubsystem) {
24633
- return current().collectPromotableSpecs(scopeSubsystem);
24634
- }
24635
- function applySpecStatus(kind, id, status) {
24636
- current().applySpecStatus(kind, id, status);
24637
- }
24638
23476
  function specPathsInScope(scopeSubsystem) {
24639
23477
  return current().specPathsInScope(scopeSubsystem);
24640
23478
  }
24641
23479
  function snapshotSpecFiles() {
24642
23480
  return current().snapshotSpecFiles();
24643
23481
  }
24644
- function restoreSpecFiles(snapshot) {
24645
- for (const [file, content] of snapshot) {
24646
- fs12.writeFileSync(file, content);
24647
- }
24648
- }
24649
- function findLegacySpecFiles() {
24650
- return current().findLegacySpecFiles();
24651
- }
24652
23482
  function updateSpec(kind, id, delta, hooks, dryRun) {
24653
23483
  return current().updateSpec(kind, id, delta, hooks, dryRun);
24654
23484
  }
@@ -24742,219 +23572,9 @@ function unregisterDomain(id) {
24742
23572
  removeFreeStanding(id);
24743
23573
  }
24744
23574
 
24745
- // src/core/detection.ts
23575
+ // src/core/provision.ts
24746
23576
  var fs13 = __toESM(require("fs"));
24747
23577
  var path17 = __toESM(require("path"));
24748
- var PACKAGE_MARKERS = [
24749
- "package.json",
24750
- "pyproject.toml",
24751
- "Cargo.toml",
24752
- "go.mod",
24753
- "build.gradle",
24754
- "build.gradle.kts",
24755
- "pom.xml"
24756
- ];
24757
- var MAX_SCAN_DEPTH = 5;
24758
- function detectDomainCandidates(projectRoot, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
24759
- const candidates = /* @__PURE__ */ new Map();
24760
- for (const c of detectGitSubmodules(projectRoot)) {
24761
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24762
- }
24763
- for (const c of detectNestedGitRepos(projectRoot)) {
24764
- if (!candidates.has(c.path)) {
24765
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24766
- }
24767
- }
24768
- const gitPaths = new Set(
24769
- Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
24770
- );
24771
- for (const c of detectPackageRoots(projectRoot)) {
24772
- if (candidates.has(c.path)) continue;
24773
- const insideGit = Array.from(gitPaths).some(
24774
- (gp) => c.path === gp || c.path.startsWith(gp + "/")
24775
- );
24776
- if (insideGit) continue;
24777
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24778
- }
24779
- const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
24780
- return deduplicateIds(sorted, alreadyTrackedIds);
24781
- }
24782
- function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
24783
- const idCount = /* @__PURE__ */ new Map();
24784
- for (const id of existingIds) {
24785
- idCount.set(id, (idCount.get(id) ?? 0) + 1);
24786
- }
24787
- for (const c of candidates) {
24788
- idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
24789
- }
24790
- return candidates.map((c) => {
24791
- if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
24792
- const parts = c.path.split("/");
24793
- const qualifiedId = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
24794
- return { ...c, suggestedId: qualifiedId };
24795
- });
24796
- }
24797
- function parseGitmodules(filePath) {
24798
- const content = fs13.readFileSync(filePath, "utf-8");
24799
- const entries = [];
24800
- let current2 = {};
24801
- for (const line of content.split("\n")) {
24802
- const trimmed = line.trim();
24803
- const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
24804
- if (headerMatch) {
24805
- if (current2.path) entries.push(current2);
24806
- current2 = { name: headerMatch[1] };
24807
- continue;
24808
- }
24809
- const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
24810
- if (keyVal) {
24811
- const [, key, value] = keyVal;
24812
- if (key === "path") current2.path = value.trim();
24813
- if (key === "url") current2.url = value.trim();
24814
- }
24815
- }
24816
- if (current2.path) entries.push(current2);
24817
- return entries;
24818
- }
24819
- function detectGitSubmodules(projectRoot) {
24820
- const gitmodulesPath = path17.join(projectRoot, ".gitmodules");
24821
- if (!fs13.existsSync(gitmodulesPath)) return [];
24822
- return parseGitmodules(gitmodulesPath).map((entry) => ({
24823
- suggestedId: pathToId(entry.path),
24824
- suggestedName: pathToName(entry.path),
24825
- path: normalizePath(entry.path),
24826
- type: "git-submodule",
24827
- alreadyTracked: false
24828
- }));
24829
- }
24830
- function detectNestedGitRepos(projectRoot) {
24831
- const results = [];
24832
- walkForGit(projectRoot, projectRoot, 0, results);
24833
- return results;
24834
- }
24835
- function walkForGit(projectRoot, currentDir, depth, results) {
24836
- if (depth > MAX_SCAN_DEPTH) return;
24837
- let entries;
24838
- try {
24839
- entries = fs13.readdirSync(currentDir, { withFileTypes: true });
24840
- } catch {
24841
- return;
24842
- }
24843
- for (const entry of entries) {
24844
- if (!entry.isDirectory()) continue;
24845
- if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
24846
- const fullPath = path17.join(currentDir, entry.name);
24847
- const relPath = normalizePath(path17.relative(projectRoot, fullPath));
24848
- if (relPath === "" || relPath === ".") continue;
24849
- const gitPath = path17.join(fullPath, ".git");
24850
- if (fs13.existsSync(gitPath)) {
24851
- results.push({
24852
- suggestedId: pathToId(relPath),
24853
- suggestedName: pathToName(relPath),
24854
- path: relPath,
24855
- type: "git-repo",
24856
- alreadyTracked: false
24857
- });
24858
- continue;
24859
- }
24860
- walkForGit(projectRoot, fullPath, depth + 1, results);
24861
- }
24862
- }
24863
- function detectPackageRoots(projectRoot) {
24864
- const results = [];
24865
- walkForPackages(projectRoot, projectRoot, 0, results);
24866
- return results;
24867
- }
24868
- function walkForPackages(projectRoot, currentDir, depth, results) {
24869
- if (depth > MAX_SCAN_DEPTH) return;
24870
- let entries;
24871
- try {
24872
- entries = fs13.readdirSync(currentDir, { withFileTypes: true });
24873
- } catch {
24874
- return;
24875
- }
24876
- for (const entry of entries) {
24877
- if (!entry.isDirectory()) continue;
24878
- if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
24879
- const fullPath = path17.join(currentDir, entry.name);
24880
- const relPath = normalizePath(path17.relative(projectRoot, fullPath));
24881
- if (relPath === "" || relPath === ".") continue;
24882
- const hasMarker = PACKAGE_MARKERS.some((m) => fs13.existsSync(path17.join(fullPath, m)));
24883
- if (hasMarker) {
24884
- results.push({
24885
- suggestedId: pathToId(relPath),
24886
- suggestedName: pathToName(relPath),
24887
- path: relPath,
24888
- type: "package-root",
24889
- alreadyTracked: false
24890
- });
24891
- }
24892
- walkForPackages(projectRoot, fullPath, depth + 1, results);
24893
- }
24894
- }
24895
- function pathToId(relPath) {
24896
- const basename11 = path17.basename(relPath);
24897
- return basename11.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
24898
- }
24899
- function pathToName(relPath) {
24900
- const id = pathToId(relPath);
24901
- return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
24902
- }
24903
- function normalizePath(p) {
24904
- return p.replace(/\\/g, "/");
24905
- }
24906
-
24907
- // src/core/templates.ts
24908
- var path18 = __toESM(require("path"));
24909
- function builtinTemplatesDir() {
24910
- return path18.resolve(__dirname, "..", "templates");
24911
- }
24912
- function loadTemplate(id, globalOverride) {
24913
- const dirs = templateSearchDirs(globalOverride);
24914
- for (const dir of dirs) {
24915
- const filePath = path18.join(dir, `${id}.yaml`);
24916
- if (pathExists(filePath)) {
24917
- const raw = readYamlFile(filePath);
24918
- return { ...TemplateSchema.parse(raw), templateName: id };
24919
- }
24920
- }
24921
- throw new TemplateNotFoundError(id);
24922
- }
24923
- function loadAgentOverride(agentId) {
24924
- const filePath = path18.join(AI_PATHS.root(), "agents", `${agentId}.md`);
24925
- return readFileOrNull(filePath);
24926
- }
24927
- function listTemplateIds(globalOverride) {
24928
- const seen = /* @__PURE__ */ new Set();
24929
- for (const dir of templateSearchDirs(globalOverride)) {
24930
- for (const file of listFiles(dir, ".yaml")) {
24931
- seen.add(path18.basename(file, ".yaml"));
24932
- }
24933
- }
24934
- return Array.from(seen).sort();
24935
- }
24936
- function templateSearchDirs(globalOverride) {
24937
- return [
24938
- AI_PATHS.templatesDir(),
24939
- // 1. project-local
24940
- globalTemplatesDir(globalOverride),
24941
- // 2. global user/org
24942
- builtinTemplatesDir()
24943
- // 3. built-in fallback
24944
- ];
24945
- }
24946
- function renderTemplateInstructions(template, vars) {
24947
- return template.instructions.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
24948
- return key in vars ? vars[key] : `{{${key}}}`;
24949
- });
24950
- }
24951
- function parseTemplate(yamlContent) {
24952
- return TemplateSchema.parse(parseYaml(yamlContent));
24953
- }
24954
-
24955
- // src/core/provision.ts
24956
- var fs14 = __toESM(require("fs"));
24957
- var path19 = __toESM(require("path"));
24958
23578
  function defaultProjectConfig(name, now) {
24959
23579
  return {
24960
23580
  schemaVersion: "1.0.0",
@@ -25002,7 +23622,7 @@ function provisionProject(name) {
25002
23622
  function ensureProjectInitialized(fallbackName) {
25003
23623
  const now = (/* @__PURE__ */ new Date()).toISOString();
25004
23624
  const paths = aiPathsAt(getProjectRoot());
25005
- const hasSystem = fs14.existsSync(paths.specsSystem());
23625
+ const hasSystem = fs13.existsSync(paths.specsSystem());
25006
23626
  let name = fallbackName;
25007
23627
  if (hasSystem) {
25008
23628
  const existing = loadSystemSpec();
@@ -25021,41 +23641,10 @@ function ensureProjectInitialized(fallbackName) {
25021
23641
  if (wroteConfig || wroteSystem) invalidateSpecCache();
25022
23642
  return { wroteConfig, wroteSystem };
25023
23643
  }
25024
- function walkChainedSubprojects(projectRoot, onChild) {
25025
- const visited = /* @__PURE__ */ new Set();
25026
- const walk2 = (dir) => {
25027
- const resolved = path19.resolve(dir);
25028
- if (visited.has(resolved)) return;
25029
- visited.add(resolved);
25030
- const specsDir = aiPathsAt(dir).specsDir();
25031
- if (!fs14.existsSync(specsDir)) return;
25032
- for (const file of listFilesRecursive(specsDir, ".yaml")) {
25033
- let raw;
25034
- try {
25035
- raw = readYamlFile(file);
25036
- } catch {
25037
- continue;
25038
- }
25039
- if (!(raw && typeof raw === "object" && "parentSystem" in raw)) continue;
25040
- const pp = raw.projectPath;
25041
- if (typeof pp !== "string" || pp.trim() === "") continue;
25042
- let childDir;
25043
- try {
25044
- childDir = assertContainedProjectPath(dir, pp);
25045
- } catch {
25046
- continue;
25047
- }
25048
- const id = raw.id;
25049
- onChild(childDir, typeof id === "string" ? id : path19.basename(childDir));
25050
- walk2(childDir);
25051
- }
25052
- };
25053
- walk2(projectRoot);
25054
- }
25055
23644
  function listDirectChainedSubprojects(projectRoot) {
25056
23645
  const out = [];
25057
23646
  const specsDir = aiPathsAt(projectRoot).specsDir();
25058
- if (!fs14.existsSync(specsDir)) return out;
23647
+ if (!fs13.existsSync(specsDir)) return out;
25059
23648
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
25060
23649
  let raw;
25061
23650
  try {
@@ -25073,32 +23662,10 @@ function listDirectChainedSubprojects(projectRoot) {
25073
23662
  continue;
25074
23663
  }
25075
23664
  const id = raw.id;
25076
- out.push({ dir, subsystemId: typeof id === "string" ? id : path19.basename(dir) });
23665
+ out.push({ dir, subsystemId: typeof id === "string" ? id : path17.basename(dir) });
25077
23666
  }
25078
23667
  return out;
25079
23668
  }
25080
- function childHasSpecsButNoConfig(childDir) {
25081
- return fs14.existsSync(aiPathsAt(childDir).specsDir()) && !projectConfigRepositoryAt(childDir).exists();
25082
- }
25083
- function findChainingSubprojectsMissingConfig(projectRoot) {
25084
- const missing = [];
25085
- walkChainedSubprojects(projectRoot, (childDir) => {
25086
- if (childHasSpecsButNoConfig(childDir)) missing.push(childDir);
25087
- });
25088
- return missing;
25089
- }
25090
- function backfillChainedSubprojectConfigs(projectRoot) {
25091
- const backfilled = [];
25092
- walkChainedSubprojects(projectRoot, (childDir, subsystemId) => {
25093
- if (childHasSpecsButNoConfig(childDir)) {
25094
- runWithProjectRoot(childDir, () => {
25095
- ensureProjectInitialized(subsystemId);
25096
- });
25097
- backfilled.push(childDir);
25098
- }
25099
- });
25100
- return backfilled;
25101
- }
25102
23669
  function createChainedSubsystem(subsystem, projectName) {
25103
23670
  if (!subsystem.projectPath || subsystem.projectPath.trim() === "") {
25104
23671
  throw new WaironError("projectPath is required to create a chained subsystem.");
@@ -25127,14 +23694,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
25127
23694
  const oldDir = assertContainedProjectPath(root, sub.projectPath);
25128
23695
  const newDir = assertContainedProjectPath(root, nextPath);
25129
23696
  if (oldDir !== newDir) {
25130
- if (!fs14.existsSync(oldDir)) {
23697
+ if (!fs13.existsSync(oldDir)) {
25131
23698
  throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
25132
23699
  }
25133
- if (fs14.existsSync(newDir)) {
23700
+ if (fs13.existsSync(newDir)) {
25134
23701
  throw new WaironError(`Target directory already exists: ${newDir}`);
25135
23702
  }
25136
- ensureDir(path19.dirname(newDir));
25137
- fs14.renameSync(oldDir, newDir);
23703
+ ensureDir(path17.dirname(newDir));
23704
+ fs13.renameSync(oldDir, newDir);
25138
23705
  }
25139
23706
  saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
25140
23707
  invalidateSpecCache();
@@ -25143,9 +23710,9 @@ function toPosixPath(p) {
25143
23710
  return p.replace(/\\/g, "/");
25144
23711
  }
25145
23712
  function isWithinDir(dir, file) {
25146
- const d = path19.resolve(dir);
25147
- const f = path19.resolve(file);
25148
- return f === d || f.startsWith(d + path19.sep);
23713
+ const d = path17.resolve(dir);
23714
+ const f = path17.resolve(file);
23715
+ return f === d || f.startsWith(d + path17.sep);
25149
23716
  }
25150
23717
  function externalizeSubsystem(subsystemId, projectPath) {
25151
23718
  if (subsystemId.includes("::")) {
@@ -25157,14 +23724,14 @@ function externalizeSubsystem(subsystemId, projectPath) {
25157
23724
  }
25158
23725
  const parentRoot = getProjectRoot();
25159
23726
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
25160
- const fooDir = path19.join(parentSpecsDir, subsystemId);
25161
- if (!fs14.existsSync(fooDir)) {
23727
+ const fooDir = path17.join(parentSpecsDir, subsystemId);
23728
+ if (!fs13.existsSync(fooDir)) {
25162
23729
  throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
25163
23730
  }
25164
23731
  const relPath = toPosixPath(projectPath);
25165
23732
  const childDir = assertContainedProjectPath(parentRoot, relPath);
25166
- const childFooDir = path19.join(childDir, ".wai", "specs", subsystemId);
25167
- if (fs14.existsSync(childFooDir)) {
23733
+ const childFooDir = path17.join(childDir, ".wai", "specs", subsystemId);
23734
+ if (fs13.existsSync(childFooDir)) {
25168
23735
  throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
25169
23736
  }
25170
23737
  const renameMap = buildRenameMap(
@@ -25176,18 +23743,18 @@ function externalizeSubsystem(subsystemId, projectPath) {
25176
23743
  runWithProjectRoot(childDir, () => {
25177
23744
  const now = (/* @__PURE__ */ new Date()).toISOString();
25178
23745
  projectConfigRepository.create(defaultProjectConfig(childSystemName, now));
25179
- ensureDir(path19.join(childDir, ".wai", "specs"));
23746
+ ensureDir(path17.join(childDir, ".wai", "specs"));
25180
23747
  saveSystemSpec(bootstrapSystemSpec(childSystemName, now));
25181
23748
  });
25182
- ensureDir(path19.dirname(childFooDir));
25183
- fs14.renameSync(fooDir, childFooDir);
23749
+ ensureDir(path17.dirname(childFooDir));
23750
+ fs13.renameSync(fooDir, childFooDir);
25184
23751
  rebaseImplementationPaths(childFooDir, parentRoot, childDir);
25185
- patchSubsystemIndex(path19.join(childFooDir, ".index.yaml"), (s) => {
23752
+ patchSubsystemIndex(path17.join(childFooDir, ".index.yaml"), (s) => {
25186
23753
  s.parentSystem = childSystemName;
25187
23754
  delete s.projectPath;
25188
23755
  });
25189
23756
  ensureDir(fooDir);
25190
- writeYamlFile(path19.join(fooDir, ".index.yaml"), {
23757
+ writeYamlFile(path17.join(fooDir, ".index.yaml"), {
25191
23758
  id: subsystemId,
25192
23759
  name: foo.name,
25193
23760
  description: foo.description,
@@ -25214,9 +23781,9 @@ function internalizeSubsystem(subsystemId) {
25214
23781
  const parentRoot = getProjectRoot();
25215
23782
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
25216
23783
  const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
25217
- const childWai = path19.join(childDir, ".wai");
25218
- const childFooDir = path19.join(childDir, ".wai", "specs", subsystemId);
25219
- if (!fs14.existsSync(childFooDir)) {
23784
+ const childWai = path17.join(childDir, ".wai");
23785
+ const childFooDir = path17.join(childDir, ".wai", "specs", subsystemId);
23786
+ if (!fs13.existsSync(childFooDir)) {
25220
23787
  throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
25221
23788
  }
25222
23789
  const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
@@ -25229,16 +23796,16 @@ function internalizeSubsystem(subsystemId) {
25229
23796
  false
25230
23797
  );
25231
23798
  const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
25232
- const fooDir = path19.join(parentSpecsDir, subsystemId);
25233
- fs14.rmSync(fooDir, { recursive: true, force: true });
25234
- ensureDir(path19.dirname(fooDir));
25235
- fs14.renameSync(childFooDir, fooDir);
23799
+ const fooDir = path17.join(parentSpecsDir, subsystemId);
23800
+ fs13.rmSync(fooDir, { recursive: true, force: true });
23801
+ ensureDir(path17.dirname(fooDir));
23802
+ fs13.renameSync(childFooDir, fooDir);
25236
23803
  rebaseImplementationPaths(fooDir, childDir, parentRoot);
25237
- patchSubsystemIndex(path19.join(fooDir, ".index.yaml"), (s) => {
23804
+ patchSubsystemIndex(path17.join(fooDir, ".index.yaml"), (s) => {
25238
23805
  s.parentSystem = parentSystemName;
25239
23806
  delete s.projectPath;
25240
23807
  });
25241
- fs14.rmSync(childWai, { recursive: true, force: true });
23808
+ fs13.rmSync(childWai, { recursive: true, force: true });
25242
23809
  rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
25243
23810
  rebaseMovedRefs(fooDir, subsystemId, "outOf");
25244
23811
  invalidateSpecCache();
@@ -25316,8 +23883,8 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
25316
23883
  let changed = false;
25317
23884
  const rebase = (holder, key) => {
25318
23885
  const p = holder[key];
25319
- if (typeof p !== "string" || p === "" || path19.isAbsolute(p)) return;
25320
- const next = toPosixPath(path19.relative(toRoot, path19.resolve(fromRoot, p)));
23886
+ if (typeof p !== "string" || p === "" || path17.isAbsolute(p)) return;
23887
+ const next = toPosixPath(path17.relative(toRoot, path17.resolve(fromRoot, p)));
25321
23888
  if (next !== p) {
25322
23889
  holder[key] = next;
25323
23890
  changed = true;
@@ -25333,7 +23900,7 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
25333
23900
  }
25334
23901
  }
25335
23902
  function patchSubsystemIndex(indexPath, mutate) {
25336
- if (!fs14.existsSync(indexPath)) return;
23903
+ if (!fs13.existsSync(indexPath)) return;
25337
23904
  const raw = readYamlFile(indexPath);
25338
23905
  mutate(raw);
25339
23906
  raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -25394,8 +23961,8 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
25394
23961
  if (movedInterface) saveInterfaceSpec({ ...movedInterface, id: interfaceId, component: newId });
25395
23962
  if (movedImplementation) {
25396
23963
  const oldFile = getImplementationPath(movedImplementation.id);
25397
- if (path19.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path19.resolve(oldFile)) {
25398
- fs14.unlinkSync(oldFile);
23964
+ if (path17.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path17.resolve(oldFile)) {
23965
+ fs13.unlinkSync(oldFile);
25399
23966
  }
25400
23967
  saveImplementationSpec({ ...movedImplementation, id: implementationId });
25401
23968
  }
@@ -25405,17 +23972,17 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
25405
23972
  invalidateSpecCache();
25406
23973
  }
25407
23974
  function removeSpecFile2(file, id) {
25408
- if (!fs14.existsSync(file)) return;
23975
+ if (!fs13.existsSync(file)) return;
25409
23976
  try {
25410
23977
  if (readYamlFile(file)?.id !== id) return;
25411
23978
  } catch {
25412
23979
  return;
25413
23980
  }
25414
- fs14.unlinkSync(file);
25415
- const specsRoot = path19.resolve(aiPathsAt(getProjectRoot()).specsDir());
25416
- for (let dir = path19.dirname(path19.resolve(file)); dir !== specsRoot && isWithinDir(specsRoot, dir); dir = path19.dirname(dir)) {
25417
- if (fs14.readdirSync(dir).length > 0) break;
25418
- fs14.rmdirSync(dir);
23981
+ fs13.unlinkSync(file);
23982
+ const specsRoot = path17.resolve(aiPathsAt(getProjectRoot()).specsDir());
23983
+ for (let dir = path17.dirname(path17.resolve(file)); dir !== specsRoot && isWithinDir(specsRoot, dir); dir = path17.dirname(dir)) {
23984
+ if (fs13.readdirSync(dir).length > 0) break;
23985
+ fs13.rmdirSync(dir);
25419
23986
  }
25420
23987
  }
25421
23988
  var METHOD_NAME = /^[a-z][a-zA-Z0-9]*$/;
@@ -25525,10 +24092,208 @@ function identifierPattern(methodName) {
25525
24092
  return new RegExp(`(?<![A-Za-z0-9_])${methodName}(?![A-Za-z0-9_])`);
25526
24093
  }
25527
24094
 
24095
+ // src/core/detection.ts
24096
+ var fs14 = __toESM(require("fs"));
24097
+ var path18 = __toESM(require("path"));
24098
+ var PACKAGE_MARKERS = [
24099
+ "package.json",
24100
+ "pyproject.toml",
24101
+ "Cargo.toml",
24102
+ "go.mod",
24103
+ "build.gradle",
24104
+ "build.gradle.kts",
24105
+ "pom.xml"
24106
+ ];
24107
+ var MAX_SCAN_DEPTH = 5;
24108
+ function detectDomainCandidates(projectRoot, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
24109
+ const candidates = /* @__PURE__ */ new Map();
24110
+ for (const c of detectGitSubmodules(projectRoot)) {
24111
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24112
+ }
24113
+ for (const c of detectNestedGitRepos(projectRoot)) {
24114
+ if (!candidates.has(c.path)) {
24115
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24116
+ }
24117
+ }
24118
+ const gitPaths = new Set(
24119
+ Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
24120
+ );
24121
+ for (const c of detectPackageRoots(projectRoot)) {
24122
+ if (candidates.has(c.path)) continue;
24123
+ const insideGit = Array.from(gitPaths).some(
24124
+ (gp) => c.path === gp || c.path.startsWith(gp + "/")
24125
+ );
24126
+ if (insideGit) continue;
24127
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
24128
+ }
24129
+ const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
24130
+ return deduplicateIds(sorted, alreadyTrackedIds);
24131
+ }
24132
+ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
24133
+ const idCount = /* @__PURE__ */ new Map();
24134
+ for (const id of existingIds) {
24135
+ idCount.set(id, (idCount.get(id) ?? 0) + 1);
24136
+ }
24137
+ for (const c of candidates) {
24138
+ idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
24139
+ }
24140
+ return candidates.map((c) => {
24141
+ if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
24142
+ const parts = c.path.split("/");
24143
+ const qualifiedId = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
24144
+ return { ...c, suggestedId: qualifiedId };
24145
+ });
24146
+ }
24147
+ function parseGitmodules(filePath) {
24148
+ const content = fs14.readFileSync(filePath, "utf-8");
24149
+ const entries = [];
24150
+ let current2 = {};
24151
+ for (const line of content.split("\n")) {
24152
+ const trimmed = line.trim();
24153
+ const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
24154
+ if (headerMatch) {
24155
+ if (current2.path) entries.push(current2);
24156
+ current2 = { name: headerMatch[1] };
24157
+ continue;
24158
+ }
24159
+ const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
24160
+ if (keyVal) {
24161
+ const [, key, value] = keyVal;
24162
+ if (key === "path") current2.path = value.trim();
24163
+ if (key === "url") current2.url = value.trim();
24164
+ }
24165
+ }
24166
+ if (current2.path) entries.push(current2);
24167
+ return entries;
24168
+ }
24169
+ function detectGitSubmodules(projectRoot) {
24170
+ const gitmodulesPath = path18.join(projectRoot, ".gitmodules");
24171
+ if (!fs14.existsSync(gitmodulesPath)) return [];
24172
+ return parseGitmodules(gitmodulesPath).map((entry) => ({
24173
+ suggestedId: pathToId(entry.path),
24174
+ suggestedName: pathToName(entry.path),
24175
+ path: normalizePath(entry.path),
24176
+ type: "git-submodule",
24177
+ alreadyTracked: false
24178
+ }));
24179
+ }
24180
+ function detectNestedGitRepos(projectRoot) {
24181
+ const results = [];
24182
+ walkForGit(projectRoot, projectRoot, 0, results);
24183
+ return results;
24184
+ }
24185
+ function walkForGit(projectRoot, currentDir, depth, results) {
24186
+ if (depth > MAX_SCAN_DEPTH) return;
24187
+ let entries;
24188
+ try {
24189
+ entries = fs14.readdirSync(currentDir, { withFileTypes: true });
24190
+ } catch {
24191
+ return;
24192
+ }
24193
+ for (const entry of entries) {
24194
+ if (!entry.isDirectory()) continue;
24195
+ if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
24196
+ const fullPath = path18.join(currentDir, entry.name);
24197
+ const relPath = normalizePath(path18.relative(projectRoot, fullPath));
24198
+ if (relPath === "" || relPath === ".") continue;
24199
+ const gitPath = path18.join(fullPath, ".git");
24200
+ if (fs14.existsSync(gitPath)) {
24201
+ results.push({
24202
+ suggestedId: pathToId(relPath),
24203
+ suggestedName: pathToName(relPath),
24204
+ path: relPath,
24205
+ type: "git-repo",
24206
+ alreadyTracked: false
24207
+ });
24208
+ continue;
24209
+ }
24210
+ walkForGit(projectRoot, fullPath, depth + 1, results);
24211
+ }
24212
+ }
24213
+ function detectPackageRoots(projectRoot) {
24214
+ const results = [];
24215
+ walkForPackages(projectRoot, projectRoot, 0, results);
24216
+ return results;
24217
+ }
24218
+ function walkForPackages(projectRoot, currentDir, depth, results) {
24219
+ if (depth > MAX_SCAN_DEPTH) return;
24220
+ let entries;
24221
+ try {
24222
+ entries = fs14.readdirSync(currentDir, { withFileTypes: true });
24223
+ } catch {
24224
+ return;
24225
+ }
24226
+ for (const entry of entries) {
24227
+ if (!entry.isDirectory()) continue;
24228
+ if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
24229
+ const fullPath = path18.join(currentDir, entry.name);
24230
+ const relPath = normalizePath(path18.relative(projectRoot, fullPath));
24231
+ if (relPath === "" || relPath === ".") continue;
24232
+ const hasMarker = PACKAGE_MARKERS.some((m) => fs14.existsSync(path18.join(fullPath, m)));
24233
+ if (hasMarker) {
24234
+ results.push({
24235
+ suggestedId: pathToId(relPath),
24236
+ suggestedName: pathToName(relPath),
24237
+ path: relPath,
24238
+ type: "package-root",
24239
+ alreadyTracked: false
24240
+ });
24241
+ }
24242
+ walkForPackages(projectRoot, fullPath, depth + 1, results);
24243
+ }
24244
+ }
24245
+ function pathToId(relPath) {
24246
+ const basename11 = path18.basename(relPath);
24247
+ return basename11.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
24248
+ }
24249
+ function pathToName(relPath) {
24250
+ const id = pathToId(relPath);
24251
+ return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
24252
+ }
24253
+ function normalizePath(p) {
24254
+ return p.replace(/\\/g, "/");
24255
+ }
24256
+
25528
24257
  // src/core/agent_resolver.ts
25529
24258
  var path20 = __toESM(require("path"));
25530
24259
  var fs15 = __toESM(require("fs"));
25531
24260
 
24261
+ // src/core/templates.ts
24262
+ var path19 = __toESM(require("path"));
24263
+ function builtinTemplatesDir() {
24264
+ return path19.resolve(__dirname, "..", "templates");
24265
+ }
24266
+ function loadTemplate(id, globalOverride) {
24267
+ const dirs = templateSearchDirs(globalOverride);
24268
+ for (const dir of dirs) {
24269
+ const filePath = path19.join(dir, `${id}.yaml`);
24270
+ if (pathExists(filePath)) {
24271
+ const raw = readYamlFile(filePath);
24272
+ return { ...TemplateSchema.parse(raw), templateName: id };
24273
+ }
24274
+ }
24275
+ throw new TemplateNotFoundError(id);
24276
+ }
24277
+ function loadAgentOverride(agentId) {
24278
+ const filePath = path19.join(AI_PATHS.root(), "agents", `${agentId}.md`);
24279
+ return readFileOrNull(filePath);
24280
+ }
24281
+ function templateSearchDirs(globalOverride) {
24282
+ return [
24283
+ AI_PATHS.templatesDir(),
24284
+ // 1. project-local
24285
+ globalTemplatesDir(globalOverride),
24286
+ // 2. global user/org
24287
+ builtinTemplatesDir()
24288
+ // 3. built-in fallback
24289
+ ];
24290
+ }
24291
+ function renderTemplateInstructions(template, vars) {
24292
+ return template.instructions.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
24293
+ return key in vars ? vars[key] : `{{${key}}}`;
24294
+ });
24295
+ }
24296
+
25532
24297
  // src/core/execution_profile.ts
25533
24298
  var MECHANICAL_STEREOTYPES = /* @__PURE__ */ new Set(["store", "index", "registry", "adapter"]);
25534
24299
  var DEEP_STEREOTYPES = /* @__PURE__ */ new Set(["orchestrator", "supervisor", "specialist"]);
@@ -26040,609 +24805,228 @@ function loadRegistry() {
26040
24805
  };
26041
24806
  }
26042
24807
 
26043
- // src/core/skills.ts
26044
- var path21 = __toESM(require("path"));
26045
- var fs16 = __toESM(require("fs"));
24808
+ // src/exporters/generate.ts
24809
+ var path24 = __toESM(require("path"));
26046
24810
 
26047
- // src/core/instructions.ts
26048
- function governingProfile() {
26049
- try {
26050
- return loadProjectConfig3()?.projectType ?? null;
26051
- } catch {
26052
- return null;
26053
- }
26054
- }
26055
- function blockApplies(block, profile) {
26056
- if (!block.profile || block.profile.length === 0) return true;
26057
- return profile !== null && block.profile.includes(profile);
26058
- }
26059
- function skillPointers(skills) {
26060
- if (skills.length === 0) return "(none published by this server)";
26061
- return skills.map((s) => `- \`${s.resourceUri}\` \u2014 ${s.description || s.name}`).join("\n");
26062
- }
26063
- function waironInstructions(profile, packNames, skills, variants) {
26064
- return `# wairon \u2014 Spec-Driven Development (SDD)
26065
-
26066
- This server owns one system's **spec tree**: its architecture, specified top-down
26067
- and machine-checked. Author it ONLY through this server's \`sdd_*\` tools \u2014 never by
26068
- writing spec files directly, and never via the \`wairon\` CLI (that is the human
26069
- developer's tool).
26070
-
26071
- ## The tree: L0 \u2192 L5
26072
-
26073
- - **L0 System** \u2014 vision, boundaries, global requirements, target language.
26074
- - **L1 Subsystem** \u2014 an isolated service, its \`publicInterfaces\`, its trusted links.
26075
- - **L2 Component** \u2014 ONE building block (\`Portal\`, \`Orchestrator\`, \`Supervisor\`,
26076
- \`Actor\`, \`Store\`, \`Index\`, \`Query\`, \`Registry\`, \`Adapter\`, \`Observer\`, and
26077
- \`View\` for UIs) or pattern (\`Repository\`, and \`FeatureComponent\` or
26078
- \`RouterComponent\` for UIs), plus \`owns\` (a pattern's private members) and
26079
- \`dependsOn\` (collaborators). Logic is an \`Orchestrator\` whose \`dependencyClass\`
26080
- (\`pure\` or \`read\`; unset, a workflow) bounds what it may depend on; a gateway is
26081
- a \`Portal\` with the \`gateway\` variant. \`Specialist\` and \`Gateway\` are retired.
26082
- - **L3 Interface** \u2014 the contract: method signatures with structured \`params\`,
26083
- plus wire \`endpoint\` bindings for a Portal's methods.
26084
- - **L4 Implementation** \u2014 a concrete realization of one L3 contract: narrative
26085
- detail level, bound \`technologies\` (the vendor swap seam), optional \`sourcePath\`.
26086
- - **L5 Narrative** \u2014 each method's logic as a FLAT numbered step list; \`call\` steps
26087
- resolve to real dependency methods, and flow steps jump by step number.
26088
-
26089
- These stereotypes are not labels \u2014 they carry enforced dependency rules (e.g. a
26090
- Portal may not depend on a Store; state lives in a Store, never as fields inside
26091
- an Orchestrator). \`sdd_validate_tree\` is the gate, and it is the authority on
26092
- whether a design is legal.
26093
-
26094
- ## Authoring order
26095
-
26096
- 1. \`sdd_initialize_system\` (L0), then \`sdd_add_subsystem\` (L1).
26097
- 2. Then, **one subsystem at a time**: \`sdd_add_component\` (L2) \u2192 \`sdd_define_interface\`
26098
- (L3) \u2192 \`sdd_set_endpoints\` for Portals \u2192 \`sdd_write_narrative\` (L4+L5).
26099
- 3. Run \`sdd_validate_tree\` as you go \u2014 early and per subsystem, not once at the end.
26100
- \`sdd_get_status\` reports completeness; \`sdd_get_spec\` reads any spec back as JSON.
26101
- 4. Edit granularly with \`sdd_update_spec\` (it renumbers narrative steps and
26102
- relocates jump targets for you).
26103
-
26104
- ## The tool schemas are the field reference
26105
-
26106
- Every \`sdd_*\` tool's input schema is self-describing and authoritative \u2014 read the
26107
- schema rather than guessing field names, and prefer structured \`params\` over prose
26108
- signatures. Specs are ${profile === null ? "validated against the project's configured profile" : `governed by the **\`${profile}\`** profile`}, which decides which stereotypes are legal
26109
- here, which narrative flow constructs the target language supports, and which
26110
- extra rules apply. A subsystem may override the profile for itself.
26111
-
26112
- ## Loaded extension packs
26113
-
26114
- ${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
26115
- additional conformance rules. Their doctrine is enforced by the same gate.`}
26116
-
26117
- ${variants.length === 0 ? "" : `## Component variants in play
26118
-
26119
- This project defines variants \u2014 named, base-anchored kinds carrying implementation
26120
- guidance, so every component of the same kind is built alike: ${variants.map((v) => `\`${v.id}\` (a kind of ${v.base})`).join(", ")}.
26121
- Tag a component with \`variant\` where it fits, and read a component's resolved
26122
- guidance and its same-variant siblings from \`sdd_get_spec\` (kind: component).
26123
-
26124
- `}## Read the skills BEFORE authoring
26125
-
26126
- This server publishes its skills as MCP resources. **Read \`wairon-skill://sdd-architect\`
26127
- before you design anything**, and the others when their turn comes \u2014 they carry the
26128
- architecture standard, the narrative step reference, and the review checklist that
26129
- this briefing only points at:
26130
-
26131
- ${skillPointers(skills)}
26132
-
26133
- ## Delegating implementation
26134
-
26135
- Delegate component work from a LIVE agent brief, never a generated file: discover
26136
- agents via \`listAgents\` (or the \`wairon-agent://\` resources), fetch the target's
26137
- brief with \`sdd_get_agent_brief\`, and spawn a scoped subagent from it \u2014 its
26138
- \`instructions\` as prompt, its \`ownedPaths\` as write fence. Briefs are composed
26139
- from the current spec tree on every call, so a re-lock never requires a session
26140
- restart \u2014 fetch fresh per delegation. \`wairon-skill://sdd-delegate\` carries the
26141
- full flow.`;
26142
- }
26143
- function buildServerInstructions() {
26144
- const profile = governingProfile();
26145
- let skills = [];
26146
- let blocks = [];
26147
- let packNames = [];
26148
- const variants = [];
26149
- try {
26150
- skills = listSkillResources();
26151
- const extensions = loadProjectExtensions2();
26152
- blocks = extensions.instructions;
26153
- packNames = extensions.packNames;
26154
- } catch {
24811
+ // src/exporters/claude.ts
24812
+ var path21 = __toESM(require("path"));
24813
+ var MODEL_BY_TIER = {
24814
+ small: "haiku",
24815
+ standard: "sonnet",
24816
+ large: "opus",
24817
+ frontier: "fable"
24818
+ };
24819
+ var TOOLS_BY_CLASS = {
24820
+ "read-only": ["Read", "Grep", "Glob"],
24821
+ implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
24822
+ orchestrate: ["Agent", "SendMessage", "TodoWrite"],
24823
+ // `full` means "inherit everything" — expressed by omitting the field.
24824
+ full: void 0
24825
+ };
24826
+ function toolsFor(budget) {
24827
+ const base = TOOLS_BY_CLASS[budget.toolClass];
24828
+ if (!base) return void 0;
24829
+ if (budget.allowNestedDelegation && !base.includes("Agent")) {
24830
+ return [...base, "Agent"];
26155
24831
  }
26156
- const sections = [waironInstructions(profile, packNames, skills, variants)];
26157
- for (const block of blocks) {
26158
- if (!blockApplies(block, profile)) continue;
26159
- sections.push(`## From pack "${block.pack}"
26160
-
26161
- ${block.text.trim()}`);
24832
+ if (!budget.allowNestedDelegation) {
24833
+ return base.filter((t) => t !== "Agent");
26162
24834
  }
26163
- return sections.join("\n\n");
26164
- }
26165
-
26166
- // src/core/skills.ts
26167
- var SKILL_NAMES = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
26168
- function loadProjectExtensions2() {
26169
- return loadProjectExtensions();
26170
- }
26171
- function loadProjectConfig3() {
26172
- return loadProjectConfig();
26173
- }
26174
- function packSkillId(skill) {
26175
- return `${packNamespace(skill.pack)}-${skill.id}`;
26176
- }
26177
- function packNamespace(pack) {
26178
- return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
24835
+ return base;
26179
24836
  }
26180
- function extensionsFor(builtin, packSkills) {
26181
- return packSkills.filter((s) => s.extends === builtin && fs16.existsSync(s.sourcePath));
24837
+ function mcpServersFor(access) {
24838
+ return access === "none" ? "[]" : void 0;
26182
24839
  }
26183
- function composeBuiltinSkill(name, packSkills) {
26184
- const srcPath = skillTemplatePath(name);
26185
- const base = fs16.existsSync(srcPath) ? fs16.readFileSync(srcPath, "utf-8") : "";
26186
- const sections = extensionsFor(name, packSkills);
26187
- if (sections.length === 0) return base;
26188
- const parts = [base.trimEnd()];
26189
- for (const section of sections) {
26190
- const body = fs16.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
26191
- parts.push(`## Platform: ${section.pack}`, body.trim());
26192
- }
26193
- return `${parts.join("\n\n")}
26194
- `;
24840
+ function yamlScalar(value) {
24841
+ return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
26195
24842
  }
26196
- function readFrontmatter(raw, fallbackName) {
26197
- const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
26198
- const block = match ? match[1] : "";
26199
- const field = (key) => {
26200
- const m = new RegExp(`^${key}:\\s*(.*)$`, "m").exec(block);
26201
- return m ? m[1].trim() : "";
26202
- };
26203
- return { name: field("name") || fallbackName, description: field("description") };
26204
- }
26205
- function builtinSkillsDir() {
26206
- return path21.resolve(__dirname, "..", "templates", "skills");
26207
- }
26208
- function skillTemplatePath(name) {
26209
- return path21.join(builtinSkillsDir(), `${name}.md`);
26210
- }
26211
- function skillDestPath(type, destDir, name) {
26212
- if (type === "claude" || type === "codex" || type === "gemini" || type === "agy") {
26213
- return path21.join(destDir, name, "SKILL.md");
26214
- }
26215
- return path21.join(destDir, `${name}.md`);
26216
- }
26217
- function skillsDirForTarget(type) {
26218
- switch (type) {
26219
- case "claude":
26220
- return fromProjectRoot(".claude", "skills");
26221
- case "gemini":
26222
- // Gemini-based Antigravity
26223
- case "agy":
26224
- case "codex":
26225
- return fromProjectRoot(".agents", "skills");
26226
- case "cursor":
26227
- return fromProjectRoot(".cursor", "skills");
26228
- default:
26229
- return null;
24843
+ var ClaudeExporter = class {
24844
+ constructor(options = {}) {
24845
+ this.options = options;
24846
+ this.targetType = "claude";
26230
24847
  }
26231
- }
26232
- function listSkillNames() {
26233
- return [...SKILL_NAMES];
26234
- }
26235
- function exportSddSkills(targetTypes) {
26236
- const types = targetTypes ?? activeTargetTypes2();
26237
- const destinations = [];
26238
- const skipped = [];
26239
- let fileCount = 0;
26240
- const packSkills = loadProjectExtensions2().skills;
26241
- for (const type of types) {
26242
- const destDir = skillsDirForTarget(type);
26243
- if (!destDir) {
26244
- skipped.push(type);
26245
- continue;
26246
- }
26247
- ensureDir(destDir);
26248
- destinations.push(destDir);
26249
- for (const name of SKILL_NAMES) {
26250
- if (!fs16.existsSync(skillTemplatePath(name))) continue;
26251
- const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
26252
- const destPath = skillDestPath(type, destDir, name);
26253
- ensureDir(path21.dirname(destPath));
26254
- fs16.writeFileSync(destPath, content, "utf-8");
26255
- fileCount++;
26256
- }
26257
- for (const skill of packSkills) {
26258
- if (skill.extends !== void 0) continue;
26259
- if (!skill.targets.includes(type)) continue;
26260
- if (!fs16.existsSync(skill.sourcePath)) continue;
26261
- const id = packSkillId(skill);
26262
- const content = fs16.readFileSync(skill.sourcePath, "utf-8");
26263
- const destPath = skillDestPath(type, destDir, id);
26264
- ensureDir(path21.dirname(destPath));
26265
- fs16.writeFileSync(destPath, content, "utf-8");
26266
- fileCount++;
26267
- }
26268
- }
26269
- return { destinations, fileCount, skipped };
26270
- }
26271
- function checkSkillFreshness(type) {
26272
- const dir = skillsDirForTarget(type);
26273
- const result = { dir, missing: [], stale: [], ok: [] };
26274
- if (!dir) return result;
26275
- const packSkills = loadProjectExtensions2().skills.filter((s) => s.targets.includes(type));
26276
- for (const name of SKILL_NAMES) {
26277
- const destPath = skillDestPath(type, dir, name);
26278
- if (!fs16.existsSync(destPath)) {
26279
- result.missing.push(name);
26280
- continue;
26281
- }
26282
- const want = composeBuiltinSkill(name, packSkills);
26283
- const have = fs16.readFileSync(destPath, "utf-8");
26284
- if (have === want) result.ok.push(name);
26285
- else result.stale.push(name);
24848
+ outputPath(ctx) {
24849
+ const { agent, target, projectRoot } = ctx;
24850
+ const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
24851
+ return path21.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26286
24852
  }
26287
- return result;
26288
- }
26289
- function activeTargetTypes2() {
26290
- const config = loadProjectConfig3();
26291
- if (!config) return [];
26292
- return activeTargetTypes(config);
26293
- }
26294
- var SKILL_RESOURCE_SCHEME = "wairon-skill";
26295
- var RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
26296
- var SkillResourceNotFoundError = class extends Error {
26297
- constructor(resourceId) {
26298
- super(`Unknown SDD skill resource id: "${resourceId}".`);
26299
- this.name = "SkillResourceNotFoundError";
24853
+ export(ctx) {
24854
+ const { agent, renderedInstructions, budget } = ctx;
24855
+ const filePath = this.outputPath(ctx);
24856
+ const frontmatter = [
24857
+ `name: ${agent.name}`,
24858
+ `description: ${yamlScalar(agent.description)}`
24859
+ ];
24860
+ if (budget && this.options.emitBudget) {
24861
+ if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
24862
+ if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
24863
+ if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
24864
+ const tools = toolsFor(budget);
24865
+ if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
24866
+ const servers = mcpServersFor(budget.mcp);
24867
+ if (servers) frontmatter.push(`mcpServers: ${servers}`);
24868
+ }
24869
+ const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
24870
+ const changed = writeFileIfChanged(filePath, content);
24871
+ return { outputPath: filePath, content, unchanged: !changed };
26300
24872
  }
26301
24873
  };
26302
- function readSkillFrontmatter(name) {
26303
- return readFrontmatter(fs16.readFileSync(skillTemplatePath(name), "utf-8"), name);
26304
- }
26305
- function listSkillResources() {
26306
- const builtin = RESOURCE_SKILL_IDS.map((id) => {
26307
- const fm = readSkillFrontmatter(id);
26308
- return {
26309
- id,
26310
- name: fm.name,
26311
- description: fm.description,
26312
- version: WAIRON_VERSION,
26313
- resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
26314
- defaultForHostedMcp: true
26315
- };
26316
- });
26317
- const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs16.existsSync(s.sourcePath)).map((skill) => {
26318
- const id = packSkillId(skill);
26319
- const fm = readFrontmatter(fs16.readFileSync(skill.sourcePath, "utf-8"), id);
26320
- return {
26321
- id,
26322
- name: fm.name,
26323
- description: fm.description,
26324
- version: skill.packVersion ?? WAIRON_VERSION,
26325
- resourceUri: `${SKILL_RESOURCE_SCHEME}://${id}`,
26326
- defaultForHostedMcp: true
26327
- };
26328
- });
26329
- return [...builtin, ...pack];
26330
- }
26331
- function readSkillResource(resourceId) {
26332
- const packSkills = loadProjectExtensions2().skills;
26333
- if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
26334
- const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
26335
- if (packSkill) return fs16.readFileSync(packSkill.sourcePath, "utf-8");
26336
- return fs16.readFileSync(skillTemplatePath(resourceId), "utf-8");
26337
- }
26338
- function listResources() {
26339
- return listSkillResources();
26340
- }
26341
- function buildServerInstructions2() {
26342
- return buildServerInstructions();
26343
- }
26344
- function readResource(resourceId) {
26345
- const known = listSkillResources().some((d) => d.id === resourceId);
26346
- if (!known) throw new SkillResourceNotFoundError(resourceId);
26347
- return readSkillResource(resourceId);
26348
- }
26349
24874
 
26350
- // src/utils/ai-guide.ts
26351
- var fs17 = __toESM(require("fs"));
26352
- var os4 = __toESM(require("os"));
24875
+ // src/exporters/custom.ts
26353
24876
  var path22 = __toESM(require("path"));
24877
+ var CustomExporter = class {
24878
+ constructor() {
24879
+ this.targetType = "custom";
24880
+ }
24881
+ outputPath(ctx) {
24882
+ const { agent, target, projectRoot } = ctx;
24883
+ if (!("outputDir" in target)) {
24884
+ throw new Error("CustomExporter requires target.outputDir");
24885
+ }
24886
+ return path22.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
24887
+ }
24888
+ export(ctx) {
24889
+ const { agent, target, renderedInstructions } = ctx;
24890
+ const label = "label" in target ? target.label : "Custom";
24891
+ const filePath = this.outputPath(ctx);
24892
+ const content = [
24893
+ "---",
24894
+ `name: ${agent.name}`,
24895
+ `description: ${agent.description}`,
24896
+ `id: ${agent.id}`,
24897
+ `target: ${label}`,
24898
+ "---",
24899
+ "",
24900
+ renderedInstructions,
24901
+ ""
24902
+ ].join("\n");
24903
+ const changed = writeFileIfChanged(filePath, content);
24904
+ return { outputPath: filePath, content, unchanged: !changed };
24905
+ }
24906
+ };
26354
24907
 
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;
24908
+ // src/exporters/gemini.ts
24909
+ var path23 = __toESM(require("path"));
24910
+ var GeminiExporter = class {
24911
+ constructor() {
24912
+ this.targetType = "gemini";
24913
+ }
24914
+ outputPath(ctx) {
24915
+ const { agent, target, projectRoot } = ctx;
24916
+ const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
24917
+ return path23.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
24918
+ }
24919
+ export(ctx) {
24920
+ const { agent, renderedInstructions } = ctx;
24921
+ const filePath = this.outputPath(ctx);
24922
+ const indentedInstructions = renderedInstructions.split("\n").map((line) => line.length > 0 ? ` ${line}` : "").join("\n");
24923
+ const content = [
24924
+ `name: ${yamlString(agent.name)}`,
24925
+ `description: ${yamlString(agent.description)}`,
24926
+ `system_prompt: |`,
24927
+ indentedInstructions,
24928
+ ""
24929
+ ].join("\n");
24930
+ const changed = writeFileIfChanged(filePath, content);
24931
+ return { outputPath: filePath, content, unchanged: !changed };
24932
+ }
24933
+ };
24934
+ function yamlString(value) {
24935
+ if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
24936
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
24937
+ }
24938
+ return value;
26363
24939
  }
26364
24940
 
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.
24941
+ // src/exporters/registry.ts
24942
+ var EXPORTERS = /* @__PURE__ */ new Map([
24943
+ ["claude", new ClaudeExporter({ emitBudget: true })],
24944
+ ["gemini", new GeminiExporter()],
24945
+ ["agy", new GeminiExporter()],
24946
+ ["cursor", new ClaudeExporter()],
24947
+ ["copilot", new ClaudeExporter()],
24948
+ ["codex", new ClaudeExporter()],
24949
+ ["custom", new CustomExporter()]
24950
+ ]);
24951
+ function getExporter(target) {
24952
+ const type = typeof target === "string" ? target : target.type;
24953
+ const exporter = EXPORTERS.get(type);
24954
+ if (!exporter) {
24955
+ throw new WaironError(`No exporter registered for target type: "${type}"`);
24956
+ }
24957
+ return exporter;
24958
+ }
24959
+ function registerExporter(type, exporter) {
24960
+ EXPORTERS.set(type, exporter);
24961
+ }
26400
24962
 
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.
24963
+ // src/exporters/base.ts
24964
+ var WAIRON_MANAGED_MARKER = "wairon:managed";
24965
+ var WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
26406
24966
 
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;
24967
+ // src/exporters/generate.ts
24968
+ function generateAgent(agent, projectConfig, options = {}) {
24969
+ const projectRoot = options.projectRoot ?? getProjectRoot();
24970
+ const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
24971
+ const rendered = `${WAIRON_MANAGED_BANNER}
24972
+ ${composeAgentBrief(agent.id).instructions}`;
24973
+ const results = [];
24974
+ const budget = resolveBudget(
24975
+ deriveExecutionProfile(agent),
24976
+ projectConfig.execution,
24977
+ agent.id
24978
+ );
24979
+ for (const agentTarget of agent.targets) {
24980
+ const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
24981
+ if (!targetConfig) continue;
24982
+ if (options.filterTargets) {
24983
+ const type = "type" in targetConfig ? targetConfig.type : targetConfig;
24984
+ if (!options.filterTargets.includes(type)) continue;
24985
+ }
24986
+ if (!options.dryRun) {
24987
+ results.push(getExporter(targetConfig).export({
24988
+ agent,
24989
+ template,
24990
+ renderedInstructions: rendered,
24991
+ projectRoot,
24992
+ target: targetConfig,
24993
+ budget
24994
+ }));
24995
+ }
24996
+ }
24997
+ return { agent, results };
26416
24998
  }
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;
24999
+ function generateAll(agents, projectConfig, options = {}) {
25000
+ let pool = agents;
25001
+ if (options.filterDomainIds && options.filterDomainIds.length > 0) {
25002
+ const ids = new Set(options.filterDomainIds);
25003
+ pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
25004
+ }
25005
+ return pool.map((agent) => generateAgent(agent, projectConfig, options));
26421
25006
  }
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");
25007
+ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProjectRoot()) {
25008
+ const expected = /* @__PURE__ */ new Set();
25009
+ for (const agent of agents) {
25010
+ for (const agentTarget of agent.targets) {
25011
+ const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
25012
+ if (!targetConfig) continue;
25013
+ const ctx = { agent, projectRoot, target: targetConfig };
25014
+ expected.add(path24.resolve(getExporter(targetConfig).outputPath(ctx)));
25015
+ }
25016
+ }
25017
+ return expected;
26436
25018
  }
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);
26442
- }
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");
26494
- }
26495
- }
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);
26505
- }
26506
- writeRootGuideDelegator(projectRoot, type);
26507
- }
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);
26536
- }
26537
- function writeArchitectureContext(content) {
26538
- writeFile(CONTEXT_PATHS.architectureMd(), content);
26539
- }
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"}\` |`);
26560
- }
26561
- }
26562
- return lines.join("\n") + "\n";
26563
- }
26564
- function renderWaironGuide() {
26565
- const domains = resolveDomains();
26566
- let projectName = "this project";
26567
- try {
26568
- projectName = projectConfigRepository.load()?.name ?? projectName;
26569
- } catch {
26570
- }
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("");
26585
- }
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 };
25019
+ function resolveTargetConfig(agentTarget, projectConfig) {
25020
+ const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
25021
+ return projectConfig.targets.find((t) => {
25022
+ if (typeof t === "string") return t === targetType;
25023
+ return t.type === targetType;
25024
+ });
26641
25025
  }
26642
25026
 
26643
25027
  // src/core/treetransfer.ts
26644
- var fs18 = __toESM(require("fs"));
26645
- var path23 = __toESM(require("path"));
25028
+ var fs16 = __toESM(require("fs"));
25029
+ var path25 = __toESM(require("path"));
26646
25030
  var sdkPortal = __toESM(require_dist());
26647
25031
  var STAGING_PREFIX = ".wai-staging-";
26648
25032
  var BACKUP_DIR = ".wai-backups";
@@ -26668,41 +25052,41 @@ function hasAuthoredSpecs(root) {
26668
25052
  if (!pathExists(specsDir)) {
26669
25053
  return false;
26670
25054
  }
26671
- const systemIndex = path23.resolve(paths.specsSystem());
25055
+ const systemIndex = path25.resolve(paths.specsSystem());
26672
25056
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
26673
- if (path23.resolve(file) !== systemIndex) {
25057
+ if (path25.resolve(file) !== systemIndex) {
26674
25058
  return true;
26675
25059
  }
26676
25060
  }
26677
25061
  return false;
26678
25062
  }
26679
25063
  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));
25064
+ const root = path25.resolve(destDir);
25065
+ fs16.mkdirSync(root, { recursive: true });
25066
+ const stagingDir = fs16.mkdtempSync(path25.join(root, STAGING_PREFIX));
26683
25067
  return stagingDir;
26684
25068
  }
26685
25069
  function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
26686
- const root = path23.resolve(destDir);
26687
- const backupDir = path23.join(root, BACKUP_DIR, timestampSlug());
25070
+ const root = path25.resolve(destDir);
25071
+ const backupDir = path25.join(root, BACKUP_DIR, timestampSlug());
26688
25072
  let backedUp = false;
26689
25073
  for (const rootRel of roots) {
26690
25074
  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);
25075
+ const stagedSpecDir = path25.join(stagingDir, relative9, ".wai");
25076
+ if (!fs16.existsSync(stagedSpecDir)) continue;
25077
+ const liveSpecDir = liveSpecDirFor(path25.join(root, relative9));
25078
+ if (backupExisting && liveSpecDir && fs16.existsSync(liveSpecDir)) {
25079
+ const backupTarget = path25.join(backupDir, relative9, path25.basename(liveSpecDir));
25080
+ fs16.mkdirSync(path25.dirname(backupTarget), { recursive: true });
25081
+ fs16.renameSync(liveSpecDir, backupTarget);
26698
25082
  backedUp = true;
26699
- } else if (liveSpecDir && fs18.existsSync(liveSpecDir)) {
26700
- fs18.rmSync(liveSpecDir, { recursive: true, force: true });
25083
+ } else if (liveSpecDir && fs16.existsSync(liveSpecDir)) {
25084
+ fs16.rmSync(liveSpecDir, { recursive: true, force: true });
26701
25085
  }
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);
25086
+ const target = path25.join(root, relative9, ".wai");
25087
+ fs16.mkdirSync(path25.dirname(target), { recursive: true });
25088
+ if (fs16.existsSync(target)) fs16.rmSync(target, { recursive: true, force: true });
25089
+ fs16.renameSync(stagedSpecDir, target);
26706
25090
  }
26707
25091
  if (backedUp) {
26708
25092
  return backupDir;
@@ -26711,7 +25095,7 @@ function commitStagedTree(stagingDir, destDir, roots, backupExisting) {
26711
25095
  }
26712
25096
  function discardStagingDir(stagingDir) {
26713
25097
  try {
26714
- fs18.rmSync(stagingDir, { recursive: true, force: true });
25098
+ fs16.rmSync(stagingDir, { recursive: true, force: true });
26715
25099
  } catch {
26716
25100
  }
26717
25101
  }
@@ -26725,7 +25109,7 @@ function exportSpecTree(includeDerived, allowPartial) {
26725
25109
  const skipped = [...inspection.skipped];
26726
25110
  const roots = [{ relativePath: ".", waiDir: aiPathsAt(root).root() }];
26727
25111
  for (const rel2 of inspection.roots) {
26728
- const waiDir = aiPathsAt(path23.resolve(root, rel2)).root();
25112
+ const waiDir = aiPathsAt(path25.resolve(root, rel2)).root();
26729
25113
  if (pathExists(waiDir)) {
26730
25114
  roots.push({ relativePath: rel2, waiDir });
26731
25115
  } else {
@@ -26756,7 +25140,7 @@ function importSpecTree(archive, options) {
26756
25140
  if (!info.compatible) {
26757
25141
  throw new Error("incompatible .waitree archive (format or minimum wairon version)");
26758
25142
  }
26759
- const destDir = path23.resolve(options.destDir ?? getProjectRoot());
25143
+ const destDir = path25.resolve(options.destDir ?? getProjectRoot());
26760
25144
  const occupied = hasSpecTree(destDir);
26761
25145
  const authored = hasAuthoredSpecs(destDir);
26762
25146
  if (authored && options.replaceExisting !== true) {
@@ -26787,249 +25171,30 @@ function importSpecTree(archive, options) {
26787
25171
  return result;
26788
25172
  }
26789
25173
  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;
25174
+ const modern = path25.join(rootDir, ".wai");
25175
+ if (fs16.existsSync(modern)) return modern;
25176
+ const legacy = path25.join(rootDir, ".wairon");
25177
+ if (fs16.existsSync(legacy)) return legacy;
26794
25178
  return null;
26795
25179
  }
26796
25180
  function timestampSlug() {
26797
25181
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
26798
25182
  }
26799
25183
 
26800
- // src/exporters/generate.ts
26801
- var path27 = __toESM(require("path"));
26802
-
26803
- // src/exporters/claude.ts
26804
- var path24 = __toESM(require("path"));
26805
- var MODEL_BY_TIER = {
26806
- small: "haiku",
26807
- standard: "sonnet",
26808
- large: "opus",
26809
- frontier: "fable"
26810
- };
26811
- var TOOLS_BY_CLASS = {
26812
- "read-only": ["Read", "Grep", "Glob"],
26813
- implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
26814
- orchestrate: ["Agent", "SendMessage", "TodoWrite"],
26815
- // `full` means "inherit everything" — expressed by omitting the field.
26816
- full: void 0
26817
- };
26818
- function toolsFor(budget) {
26819
- const base = TOOLS_BY_CLASS[budget.toolClass];
26820
- if (!base) return void 0;
26821
- if (budget.allowNestedDelegation && !base.includes("Agent")) {
26822
- return [...base, "Agent"];
26823
- }
26824
- if (!budget.allowNestedDelegation) {
26825
- return base.filter((t) => t !== "Agent");
26826
- }
26827
- return base;
26828
- }
26829
- function mcpServersFor(access) {
26830
- return access === "none" ? "[]" : void 0;
26831
- }
26832
- function yamlScalar(value) {
26833
- return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
26834
- }
26835
- var ClaudeExporter = class {
26836
- constructor(options = {}) {
26837
- this.options = options;
26838
- this.targetType = "claude";
26839
- }
26840
- outputPath(ctx) {
26841
- const { agent, target, projectRoot } = ctx;
26842
- const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
26843
- return path24.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26844
- }
26845
- export(ctx) {
26846
- const { agent, renderedInstructions, budget } = ctx;
26847
- const filePath = this.outputPath(ctx);
26848
- const frontmatter = [
26849
- `name: ${agent.name}`,
26850
- `description: ${yamlScalar(agent.description)}`
26851
- ];
26852
- if (budget && this.options.emitBudget) {
26853
- if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
26854
- if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
26855
- if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
26856
- const tools = toolsFor(budget);
26857
- if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
26858
- const servers = mcpServersFor(budget.mcp);
26859
- if (servers) frontmatter.push(`mcpServers: ${servers}`);
26860
- }
26861
- const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
26862
- const changed = writeFileIfChanged(filePath, content);
26863
- return { outputPath: filePath, content, unchanged: !changed };
26864
- }
26865
- };
26866
-
26867
- // src/exporters/custom.ts
26868
- var path25 = __toESM(require("path"));
26869
- var CustomExporter = class {
26870
- constructor() {
26871
- this.targetType = "custom";
26872
- }
26873
- outputPath(ctx) {
26874
- const { agent, target, projectRoot } = ctx;
26875
- if (!("outputDir" in target)) {
26876
- throw new Error("CustomExporter requires target.outputDir");
26877
- }
26878
- return path25.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
26879
- }
26880
- export(ctx) {
26881
- const { agent, target, renderedInstructions } = ctx;
26882
- const label = "label" in target ? target.label : "Custom";
26883
- const filePath = this.outputPath(ctx);
26884
- const content = [
26885
- "---",
26886
- `name: ${agent.name}`,
26887
- `description: ${agent.description}`,
26888
- `id: ${agent.id}`,
26889
- `target: ${label}`,
26890
- "---",
26891
- "",
26892
- renderedInstructions,
26893
- ""
26894
- ].join("\n");
26895
- const changed = writeFileIfChanged(filePath, content);
26896
- return { outputPath: filePath, content, unchanged: !changed };
26897
- }
26898
- };
26899
-
26900
- // src/exporters/gemini.ts
26901
- var path26 = __toESM(require("path"));
26902
- var GeminiExporter = class {
26903
- constructor() {
26904
- this.targetType = "gemini";
26905
- }
26906
- outputPath(ctx) {
26907
- const { agent, target, projectRoot } = ctx;
26908
- const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
26909
- return path26.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
26910
- }
26911
- export(ctx) {
26912
- const { agent, renderedInstructions } = ctx;
26913
- const filePath = this.outputPath(ctx);
26914
- const indentedInstructions = renderedInstructions.split("\n").map((line) => line.length > 0 ? ` ${line}` : "").join("\n");
26915
- const content = [
26916
- `name: ${yamlString(agent.name)}`,
26917
- `description: ${yamlString(agent.description)}`,
26918
- `system_prompt: |`,
26919
- indentedInstructions,
26920
- ""
26921
- ].join("\n");
26922
- const changed = writeFileIfChanged(filePath, content);
26923
- return { outputPath: filePath, content, unchanged: !changed };
26924
- }
26925
- };
26926
- function yamlString(value) {
26927
- if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
26928
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
26929
- }
26930
- return value;
26931
- }
26932
-
26933
- // src/exporters/registry.ts
26934
- var EXPORTERS = /* @__PURE__ */ new Map([
26935
- ["claude", new ClaudeExporter({ emitBudget: true })],
26936
- ["gemini", new GeminiExporter()],
26937
- ["agy", new GeminiExporter()],
26938
- ["cursor", new ClaudeExporter()],
26939
- ["copilot", new ClaudeExporter()],
26940
- ["codex", new ClaudeExporter()],
26941
- ["custom", new CustomExporter()]
26942
- ]);
26943
- function getExporter(target) {
26944
- const type = typeof target === "string" ? target : target.type;
26945
- const exporter = EXPORTERS.get(type);
26946
- if (!exporter) {
26947
- throw new WaironError(`No exporter registered for target type: "${type}"`);
26948
- }
26949
- return exporter;
26950
- }
26951
- function registerExporter(type, exporter) {
26952
- EXPORTERS.set(type, exporter);
26953
- }
26954
-
26955
- // src/exporters/base.ts
26956
- var WAIRON_MANAGED_MARKER = "wairon:managed";
26957
- var WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
26958
-
26959
- // src/exporters/generate.ts
26960
- function generateAgent(agent, projectConfig, options = {}) {
26961
- const projectRoot = options.projectRoot ?? getProjectRoot();
26962
- const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
26963
- const rendered = `${WAIRON_MANAGED_BANNER}
26964
- ${composeAgentBrief(agent.id).instructions}`;
26965
- const results = [];
26966
- const budget = resolveBudget(
26967
- deriveExecutionProfile(agent),
26968
- projectConfig.execution,
26969
- agent.id
26970
- );
26971
- for (const agentTarget of agent.targets) {
26972
- const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
26973
- if (!targetConfig) continue;
26974
- if (options.filterTargets) {
26975
- const type = "type" in targetConfig ? targetConfig.type : targetConfig;
26976
- if (!options.filterTargets.includes(type)) continue;
26977
- }
26978
- if (!options.dryRun) {
26979
- results.push(getExporter(targetConfig).export({
26980
- agent,
26981
- template,
26982
- renderedInstructions: rendered,
26983
- projectRoot,
26984
- target: targetConfig,
26985
- budget
26986
- }));
26987
- }
26988
- }
26989
- return { agent, results };
26990
- }
26991
- function generateAll(agents, projectConfig, options = {}) {
26992
- let pool = agents;
26993
- if (options.filterDomainIds && options.filterDomainIds.length > 0) {
26994
- const ids = new Set(options.filterDomainIds);
26995
- pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
26996
- }
26997
- return pool.map((agent) => generateAgent(agent, projectConfig, options));
26998
- }
26999
- function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProjectRoot()) {
27000
- const expected = /* @__PURE__ */ new Set();
27001
- for (const agent of agents) {
27002
- for (const agentTarget of agent.targets) {
27003
- const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
27004
- if (!targetConfig) continue;
27005
- const ctx = { agent, projectRoot, target: targetConfig };
27006
- expected.add(path27.resolve(getExporter(targetConfig).outputPath(ctx)));
27007
- }
27008
- }
27009
- return expected;
27010
- }
27011
- function resolveTargetConfig(agentTarget, projectConfig) {
27012
- const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
27013
- return projectConfig.targets.find((t) => {
27014
- if (typeof t === "string") return t === targetType;
27015
- return t.type === targetType;
27016
- });
27017
- }
27018
-
27019
- // src/core/stereotype-migration.ts
27020
- var DATA_FACADES = /* @__PURE__ */ new Set(["Repository", "Index", "Adapter"]);
27021
- function retireSpecialists(apply) {
27022
- const components = loadComponentSpecs();
27023
- const byId = new Map(components.map((c) => [c.id, c]));
27024
- const specialists = components.filter((c) => c.componentType === "Specialist" && !c.id.includes("::")).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
27025
- const specialistIds = new Set(specialists.map((s) => s.id));
27026
- const decided = /* @__PURE__ */ new Map();
27027
- const reasons = /* @__PURE__ */ new Map();
27028
- const fitOf = (id) => {
27029
- if (specialistIds.has(id)) {
27030
- const decision = decided.get(id);
27031
- if (decision === void 0) return "pending";
27032
- return decision === "unset" ? "neither" : decision;
25184
+ // src/core/stereotype-migration.ts
25185
+ var DATA_FACADES = /* @__PURE__ */ new Set(["Repository", "Index", "Adapter"]);
25186
+ function retireSpecialists(apply) {
25187
+ const components = loadComponentSpecs();
25188
+ const byId = new Map(components.map((c) => [c.id, c]));
25189
+ const specialists = components.filter((c) => c.componentType === "Specialist" && !c.id.includes("::")).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
25190
+ const specialistIds = new Set(specialists.map((s) => s.id));
25191
+ const decided = /* @__PURE__ */ new Map();
25192
+ const reasons = /* @__PURE__ */ new Map();
25193
+ const fitOf = (id) => {
25194
+ if (specialistIds.has(id)) {
25195
+ const decision = decided.get(id);
25196
+ if (decision === void 0) return "pending";
25197
+ return decision === "unset" ? "neither" : decision;
27033
25198
  }
27034
25199
  const dependency = byId.get(id);
27035
25200
  if (dependency?.componentType === "Orchestrator" && dependency.dependencyClass) return dependency.dependencyClass;
@@ -27149,130 +25314,610 @@ function repairForeignStepFields(apply) {
27149
25314
  }
27150
25315
 
27151
25316
  // src/core/approval.ts
27152
- var crypto4 = __toESM(require("crypto"));
27153
- var path28 = __toESM(require("path"));
25317
+ var crypto3 = __toESM(require("crypto"));
25318
+ var path26 = __toESM(require("path"));
25319
+
25320
+ // src/models/lock.ts
25321
+ function describeApprover(who) {
25322
+ const label = who.name ? `${who.name} (${who.id})` : who.id;
25323
+ return who.source === "hosted" ? `${label} [authenticated]` : label;
25324
+ }
25325
+
25326
+ // src/core/approval.ts
27154
25327
  function diffSize(d) {
27155
25328
  return d.added.length + d.changed.length + d.removed.length;
27156
25329
  }
27157
25330
  function digest(content) {
27158
25331
  const normalized = content.replace(/\r\n/g, "\n");
27159
- return crypto4.createHash("sha256").update(normalized, "utf8").digest("hex");
25332
+ return crypto3.createHash("sha256").update(normalized, "utf8").digest("hex");
27160
25333
  }
27161
25334
  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("/")}/`);
25335
+ const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path26.resolve(root, s.projectPath).split(path26.sep).join("/")}/`);
27163
25336
  const out = {};
27164
25337
  for (const [abs, content] of snapshotSpecFiles()) {
27165
- const normalized = path28.resolve(abs).split(path28.sep).join("/");
25338
+ const normalized = path26.resolve(abs).split(path26.sep).join("/");
27166
25339
  if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
27167
- out[path28.relative(root, abs).split(path28.sep).join("/")] = digest(content);
25340
+ out[path26.relative(root, abs).split(path26.sep).join("/")] = digest(content);
25341
+ }
25342
+ return out;
25343
+ }
25344
+ function captureApprovedSpecs(root = getProjectRoot(), scope) {
25345
+ const current2 = currentSpecDigests(root);
25346
+ if (!scope) return current2;
25347
+ const previous = readLockRecord()?.specs ?? {};
25348
+ const specs = { ...previous };
25349
+ for (const rel2 of Object.keys(previous)) {
25350
+ if (scope.paths.has(rel2) && current2[rel2] === void 0) delete specs[rel2];
25351
+ }
25352
+ for (const rel2 of scope.paths) {
25353
+ if (current2[rel2] !== void 0) specs[rel2] = current2[rel2];
25354
+ }
25355
+ return specs;
25356
+ }
25357
+ function diffAgainstApproval(root = getProjectRoot()) {
25358
+ const approved = approvedSpecs(root);
25359
+ if (!approved) return null;
25360
+ const current2 = currentSpecDigests(root);
25361
+ const added = [];
25362
+ const changed = [];
25363
+ const removed = [];
25364
+ const unchangedPaths = [];
25365
+ for (const [rel2, d] of Object.entries(current2)) {
25366
+ const before = approved[rel2];
25367
+ if (before === void 0) added.push(rel2);
25368
+ else if (before !== d) changed.push(rel2);
25369
+ else unchangedPaths.push(rel2);
25370
+ }
25371
+ for (const rel2 of Object.keys(approved)) {
25372
+ if (current2[rel2] === void 0) removed.push(rel2);
25373
+ }
25374
+ return {
25375
+ added: added.sort(),
25376
+ changed: changed.sort(),
25377
+ removed: removed.sort(),
25378
+ unchangedPaths: unchangedPaths.sort()
25379
+ };
25380
+ }
25381
+ function approvedSpecs(root) {
25382
+ return approvalRecord(root)?.specs ?? null;
25383
+ }
25384
+ function approvalRecord(root = getProjectRoot()) {
25385
+ return readLockRecordAt(root);
25386
+ }
25387
+ function settledSpecPaths(root = getProjectRoot()) {
25388
+ const diff = diffAgainstApproval(root);
25389
+ return diff ? new Set(diff.unchangedPaths) : null;
25390
+ }
25391
+ function pinOf(stateId) {
25392
+ return `${stateId.algorithm}:${stateId.digest}`;
25393
+ }
25394
+ function currentChildPins(mounts, root = getProjectRoot()) {
25395
+ const pins = {};
25396
+ for (const mount of mounts) {
25397
+ if (!mount.projectPath || mount.id.includes("::")) continue;
25398
+ const child = readLockRecordAt(path26.resolve(root, mount.projectPath));
25399
+ if (child) pins[mount.id] = pinOf(child.stateId);
25400
+ }
25401
+ return pins;
25402
+ }
25403
+ function movedChildren(mounts, root = getProjectRoot()) {
25404
+ const pinned = approvalRecord(root)?.children;
25405
+ if (!pinned) return [];
25406
+ const now = currentChildPins(mounts, root);
25407
+ const moved = [];
25408
+ for (const [id, was] of Object.entries(pinned)) {
25409
+ const current2 = now[id] ?? null;
25410
+ if (current2 !== was) moved.push({ id, pinned: was, now: current2 });
25411
+ }
25412
+ return moved;
25413
+ }
25414
+ function approvalVerdict() {
25415
+ const quiet = { text: "", drifted: false };
25416
+ try {
25417
+ const approval = approvalRecord();
25418
+ if (!approval) return quiet;
25419
+ const by = describeApprover(approval.lockedBy);
25420
+ const moved = movedChildren(loadSubsystemSpecs());
25421
+ const childNote = moved.length ? `
25422
+ ${moved.length} chained child project(s) moved since approval: ${moved.map((m) => m.id).join(", ")}.` : "";
25423
+ const diff = diffAgainstApproval();
25424
+ if (!diff) {
25425
+ return {
25426
+ text: `
25427
+ 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}
25428
+ `,
25429
+ drifted: moved.length > 0
25430
+ };
25431
+ }
25432
+ if (diffSize(diff) === 0) {
25433
+ return {
25434
+ text: `
25435
+ Approved: ${approval.lockedAt} by ${by} \u2014 no spec has changed since.${childNote}
25436
+ `,
25437
+ drifted: moved.length > 0
25438
+ };
25439
+ }
25440
+ const parts = [];
25441
+ if (diff.changed.length) parts.push(`${diff.changed.length} changed`);
25442
+ if (diff.added.length) parts.push(`${diff.added.length} added`);
25443
+ if (diff.removed.length) parts.push(`${diff.removed.length} removed`);
25444
+ const named = [...diff.changed, ...diff.added, ...diff.removed].slice(0, 5);
25445
+ const rest = diffSize(diff) - named.length;
25446
+ const n = diffSize(diff);
25447
+ const noun = `${n} spec${n === 1 ? "" : "s"}`;
25448
+ const headline = parts.length === 1 ? `${noun} ${parts[0].slice(String(diffSize(diff)).length + 1)} since approval` : `${noun} changed since approval (${parts.join(", ")})`;
25449
+ return {
25450
+ text: `
25451
+ ${headline} \u2014 approved ${approval.lockedAt} by ${by}:
25452
+ ` + named.map((p) => ` ${p}`).join("\n") + (rest > 0 ? `
25453
+ \u2026 and ${rest} more` : "") + childNote + "\n",
25454
+ drifted: true
25455
+ };
25456
+ } catch {
25457
+ return quiet;
25458
+ }
25459
+ }
25460
+
25461
+ // src/core/approver.ts
25462
+ var import_child_process = require("child_process");
25463
+ var os4 = __toESM(require("os"));
25464
+ function gitConfig(key) {
25465
+ try {
25466
+ const value = (0, import_child_process.execFileSync)("git", ["config", "--get", key], {
25467
+ encoding: "utf8",
25468
+ stdio: ["ignore", "pipe", "ignore"],
25469
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
25470
+ }).trim();
25471
+ return value || void 0;
25472
+ } catch {
25473
+ return void 0;
25474
+ }
25475
+ }
25476
+ function machineIdentity() {
25477
+ let user = "unknown";
25478
+ try {
25479
+ user = os4.userInfo().username || user;
25480
+ } catch {
25481
+ }
25482
+ let host = "";
25483
+ try {
25484
+ host = os4.hostname();
25485
+ } catch {
25486
+ }
25487
+ return { id: host ? `${user}@${host}` : user, source: "os" };
25488
+ }
25489
+ function localApprover() {
25490
+ const name = gitConfig("user.name");
25491
+ const email = gitConfig("user.email");
25492
+ if (name && email) return { id: `${name} <${email}>`, source: "git" };
25493
+ if (email) return { id: email, source: "git" };
25494
+ return machineIdentity();
25495
+ }
25496
+
25497
+ // src/utils/ai-guide.ts
25498
+ var fs17 = __toESM(require("fs"));
25499
+ var os5 = __toESM(require("os"));
25500
+ var path27 = __toESM(require("path"));
25501
+
25502
+ // src/core/stamp.ts
25503
+ function versionStamp() {
25504
+ return `<!-- wairon-version: ${WAIRON_VERSION} -->`;
25505
+ }
25506
+ var STAMP_RE = /<!--\s*wairon-version:\s*([^\s]+)\s*-->/;
25507
+ function readStampVersion(content) {
25508
+ const m = content.match(STAMP_RE);
25509
+ return m ? m[1] : null;
25510
+ }
25511
+
25512
+ // src/utils/ai-guide.ts
25513
+ var GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
25514
+ var GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
25515
+ var GLOBAL_GUIDE_BODY = `## wairon \u2014 Spec-Driven Development (optional)
25516
+
25517
+ If \`.wai/specs/\` exists, the wairon SDD workflow is active; otherwise ignore it. wairon does not orchestrate sessions \u2014 it equips yours.
25518
+
25519
+ ### In SDD Projects:
25520
+ - **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\`).
25521
+ - **Validation**: Conformance checks (stereotype rules, cycle checks, reference integrity) are run via the \`sdd_validate_tree\` MCP tool.
25522
+ - **Operating Rules**:
25523
+ 1. **Skills**: Use \`sdd-architect\` to design (and \`sdd-implement\`, \`sdd-narrative\`, \`sdd-auditor\`). Refer to project's local guide file for detailed constraints.
25524
+ 2. **MCP Tools Only**: Author/validate specs *only* via \`sdd_*\` tools (e.g. \`sdd_initialize_system\`, \`sdd_validate_tree\`).
25525
+ 3. **No CLI Exec**: Do not run the \`wairon\` CLI (human tool). Use MCP tools \`sdd_validate_tree\` and \`sdd_get_status\` instead.
25526
+ 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>\`).
25527
+ 5. **Design First**: Complete spec and pass \`sdd_validate_tree\` before writing code.
25528
+ 6. **Consistency**: Code must match L3 interfaces and L5 narratives exactly. If the spec is wrong, stop and update the spec.
25529
+ 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.`;
25530
+ var LOCAL_GUIDE_BODY = `## Wairon \u2014 Spec-Driven Development (you are operating inside it)
25531
+
25532
+ 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.
25533
+
25534
+ **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.**
25535
+
25536
+ **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.
25537
+
25538
+ ### How you operate
25539
+ - **To design/modify specs**: Use **\`sdd-architect\`** skill (in \`.claude/skills/\` or \`.gemini/skills/\`).
25540
+ - **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.
25541
+ - **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.
25542
+ - **Leading \`::\`**: Bypasses the local subsystem prefix to resolve absolute from the system root (e.g. \`::shared::error-type\`).
25543
+ - **\`super::\`**: Goes up one parent subsystem level (e.g. \`super::sibling_comp\`, \`super::super::parent_sibling\`).
25544
+ - **Do not run the \`wairon\` CLI**: Use \`sdd_validate_tree\` and \`sdd_get_status\` instead of CLI commands.
25545
+ - **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.
25546
+ - **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.
25547
+
25548
+ ### Rules (enforced by \`sdd_validate_tree\`)
25549
+ 1. **Design before code**: Complete spec and pass validator before writing source code.
25550
+ 2. **Human-in-the-loop**: Ask user approval for each spec layer before proceeding.
25551
+ 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.
25552
+ 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.
25553
+
25554
+ ### Component Vocabulary
25555
+ * **Blocks**: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer.
25556
+ * **Patterns**: Repository \u2014 the composable pattern that \`owns\` its member blocks: one Store with its Registry, Indexes and Queries, and optionally an Adapter.
25557
+ * **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.
25558
+ * Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
25559
+ function globalGuideFilePath(targetType) {
25560
+ if (targetType === "claude") return path27.join(process.env["CLAUDE_CONFIG_DIR"] || path27.join(os5.homedir(), ".claude"), "CLAUDE.md");
25561
+ if (targetType === "gemini") return path27.join(process.env["GEMINI_CONFIG_DIR"] || path27.join(os5.homedir(), ".gemini"), "GEMINI.md");
25562
+ return null;
25563
+ }
25564
+ function localGuideFilePath(projectRoot, targetType) {
25565
+ if (targetType === "claude") return path27.join(projectRoot, ".claude", "CLAUDE.md");
25566
+ if (targetType === "gemini" || targetType === "agy") return path27.join(projectRoot, ".gemini", "GEMINI.md");
25567
+ return null;
25568
+ }
25569
+ function injectGuide(filePath, scope) {
25570
+ const body = scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
25571
+ const section = `
25572
+
25573
+ ${GUIDE_MARKER_START}
25574
+ ${versionStamp()}
25575
+ ${body}
25576
+ ${GUIDE_MARKER_END}
25577
+ `;
25578
+ const existing = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8") : "";
25579
+ const stripped = stripGuideSection(existing);
25580
+ const newContent = stripped.trimEnd() + section;
25581
+ fs17.mkdirSync(path27.dirname(filePath), { recursive: true });
25582
+ fs17.writeFileSync(filePath, newContent, "utf-8");
25583
+ }
25584
+ function stripGuideSection(content) {
25585
+ const start = content.indexOf(GUIDE_MARKER_START);
25586
+ const end = content.indexOf(GUIDE_MARKER_END);
25587
+ if (start === -1 || end === -1) return content;
25588
+ return content.slice(0, start) + content.slice(end + GUIDE_MARKER_END.length);
25589
+ }
25590
+ function writeRootGuideDelegator(projectRoot, targetType) {
25591
+ if (targetType === "claude") {
25592
+ const filePath = path27.join(projectRoot, "CLAUDE.md");
25593
+ const content = `@.claude/CLAUDE.md
25594
+
25595
+ # Wairon SDD Project
25596
+
25597
+ This project uses the Wairon Spec-Driven Development (SDD) framework. The imported
25598
+ \`.claude/CLAUDE.md\` above is your complete operating guide \u2014 you already have the
25599
+ full context, so don't search the project to learn how wairon or SDD works.
25600
+
25601
+ To design or modify the system, invoke the **\`sdd-architect\`** skill
25602
+ (in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
25603
+ the \`wairon\` CLI is the human developer's tool, not yours.
25604
+ `;
25605
+ fs17.writeFileSync(filePath, content, "utf-8");
25606
+ } else if (targetType === "gemini" || targetType === "agy") {
25607
+ const filePath = path27.join(projectRoot, "GEMINI.md");
25608
+ const content = `# Wairon SDD Project
25609
+ ${GUIDE_MARKER_START}
25610
+ ${versionStamp()}
25611
+ ${LOCAL_GUIDE_BODY}
25612
+ ${GUIDE_MARKER_END}
25613
+ `;
25614
+ fs17.writeFileSync(filePath, content, "utf-8");
25615
+ } else if (targetType === "cursor") {
25616
+ const filePath = path27.join(projectRoot, ".cursorrules");
25617
+ const content = `# Wairon SDD Project
25618
+
25619
+ This project uses the Wairon Spec-Driven Development (SDD) framework.
25620
+
25621
+ Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
25622
+ `;
25623
+ fs17.writeFileSync(filePath, content, "utf-8");
25624
+ } else if (targetType === "copilot") {
25625
+ const filePath = path27.join(projectRoot, ".github", "copilot-instructions.md");
25626
+ fs17.mkdirSync(path27.dirname(filePath), { recursive: true });
25627
+ const content = `# Wairon SDD Project
25628
+
25629
+ This project uses the Wairon Spec-Driven Development (SDD) framework.
25630
+
25631
+ Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
25632
+ `;
25633
+ fs17.writeFileSync(filePath, content, "utf-8");
25634
+ } else if (targetType === "codex") {
25635
+ const filePath = path27.join(projectRoot, ".codexrules");
25636
+ const content = `# Wairon SDD Project
25637
+
25638
+ Refer to [.codex/agents/](.codex/agents/) for full instructions.
25639
+ `;
25640
+ fs17.writeFileSync(filePath, content, "utf-8");
27168
25641
  }
27169
- return out;
27170
25642
  }
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];
25643
+ var GUIDE_TARGETS = ["claude", "gemini", "agy", "cursor", "copilot", "codex"];
25644
+ function reinjectLocalGuides(projectRoot, targetTypes) {
25645
+ const written = [];
25646
+ for (const type of targetTypes) {
25647
+ if (!GUIDE_TARGETS.includes(type)) continue;
25648
+ const guidePath = localGuideFilePath(projectRoot, type);
25649
+ if (guidePath) {
25650
+ injectGuide(guidePath, "local");
25651
+ if (!written.includes(guidePath)) written.push(guidePath);
25652
+ }
25653
+ writeRootGuideDelegator(projectRoot, type);
27181
25654
  }
27182
- return specs;
25655
+ return written;
27183
25656
  }
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
- };
25657
+
25658
+ // src/core/context.ts
25659
+ function contextDir(...segments) {
25660
+ return aiDir("context", ...segments);
27207
25661
  }
27208
- function approvedSpecs(root) {
27209
- return approvalRecord(root)?.specs ?? null;
25662
+ var CONTEXT_PATHS = {
25663
+ dir: () => contextDir(),
25664
+ projectMd: () => contextDir("project.md"),
25665
+ architectureMd: () => contextDir("architecture.md"),
25666
+ domainsMd: () => contextDir("domains.md"),
25667
+ waironGuideMd: () => contextDir("wairon-guide.md")
25668
+ };
25669
+ function hasContext() {
25670
+ return pathExists(CONTEXT_PATHS.projectMd());
27210
25671
  }
27211
- function approvalRecord(root = getProjectRoot()) {
27212
- return readLockRecordAt(root);
25672
+ function readProjectContext() {
25673
+ return readFileOrNull(CONTEXT_PATHS.projectMd());
27213
25674
  }
27214
- function settledSpecPaths(root = getProjectRoot()) {
27215
- const diff = diffAgainstApproval(root);
27216
- return diff ? new Set(diff.unchangedPaths) : null;
25675
+ function readArchitectureContext() {
25676
+ return readFileOrNull(CONTEXT_PATHS.architectureMd());
27217
25677
  }
27218
- function pinOf(stateId) {
27219
- return `${stateId.algorithm}:${stateId.digest}`;
25678
+ function writeDomainsDoc(content) {
25679
+ return writeFileIfChanged(CONTEXT_PATHS.domainsMd(), content);
27220
25680
  }
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;
25681
+ function writeGuideDoc(content) {
25682
+ return writeFileIfChanged(CONTEXT_PATHS.waironGuideMd(), content);
27229
25683
  }
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 });
27238
- }
27239
- return moved;
25684
+ function derivedDocPaths() {
25685
+ return [CONTEXT_PATHS.waironGuideMd(), CONTEXT_PATHS.domainsMd()];
27240
25686
  }
27241
-
27242
- // src/core/approver.ts
27243
- var import_child_process = require("child_process");
27244
- var os5 = __toESM(require("os"));
27245
- function gitConfig(key) {
27246
- 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;
27253
- } catch {
27254
- return void 0;
25687
+ function renderDomainsDoc() {
25688
+ const domains = resolveDomains();
25689
+ const lines = [
25690
+ versionStamp(),
25691
+ `# Domains`,
25692
+ ``,
25693
+ `> Auto-generated by wairon. The human developer rebuilds this with \`wairon generate\`. `,
25694
+ ``
25695
+ ];
25696
+ if (domains.length === 0) {
25697
+ lines.push("_No domains yet. Define subsystems in the spec tree, or add free-standing domains with `wairon domains add`._");
25698
+ } else {
25699
+ lines.push(`**${domains.length} domain(s).**`);
25700
+ lines.push("");
25701
+ lines.push("| ID | Name | Source | Owned paths |");
25702
+ lines.push("|----|------|--------|-------------|");
25703
+ for (const d of domains) {
25704
+ const name = d.name ?? d.id;
25705
+ const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
25706
+ lines.push(`| \`${d.id}\` | ${name} | ${source} | \`${d.ownedPaths.join("`, `") || "\u2014"}\` |`);
25707
+ }
27255
25708
  }
25709
+ return lines.join("\n") + "\n";
27256
25710
  }
27257
- function machineIdentity() {
27258
- let user = "unknown";
25711
+ function renderWaironGuide() {
25712
+ const domains = resolveDomains();
25713
+ let projectName = "this project";
27259
25714
  try {
27260
- user = os5.userInfo().username || user;
25715
+ projectName = projectConfigRepository.load()?.name ?? projectName;
27261
25716
  } catch {
27262
25717
  }
27263
- let host = "";
25718
+ const projectCtx = readProjectContext();
25719
+ const archCtx = readArchitectureContext();
25720
+ const lines = [
25721
+ versionStamp(),
25722
+ `<!-- wairon-generated \u2014 do not edit directly; the human developer rebuilds this with \`wairon generate\` -->`,
25723
+ ``
25724
+ ];
25725
+ if (projectCtx) {
25726
+ lines.push(`# Project Context \u2014 ${projectName}`);
25727
+ lines.push("");
25728
+ lines.push(projectCtx.trim());
25729
+ lines.push("");
25730
+ lines.push("---");
25731
+ lines.push("");
25732
+ }
25733
+ if (archCtx) {
25734
+ lines.push("# Architecture");
25735
+ lines.push("");
25736
+ lines.push(archCtx.trim());
25737
+ lines.push("");
25738
+ lines.push("---");
25739
+ lines.push("");
25740
+ }
25741
+ lines.push(`# Domain Map (${domains.length} domain${domains.length !== 1 ? "s" : ""})`);
25742
+ lines.push("");
25743
+ if (domains.length === 0) {
25744
+ lines.push("_No domains yet._");
25745
+ } else {
25746
+ lines.push("| ID | Source | Name |");
25747
+ lines.push("|----|--------|------|");
25748
+ for (const d of domains) {
25749
+ const name = d.name ?? d.id;
25750
+ const source = d.boundTo ? `subsystem \`${d.boundTo}\`` : "free-standing";
25751
+ lines.push(`| \`${d.id}\` | ${source} | ${name} |`);
25752
+ }
25753
+ }
25754
+ lines.push("");
25755
+ lines.push("---");
25756
+ lines.push("");
25757
+ const mcpSettingsPath = require("path").join(process.cwd(), ".claude", "settings.json");
25758
+ let mcpInstalled = false;
27264
25759
  try {
27265
- host = os5.hostname();
25760
+ const s = JSON.parse(require("fs").readFileSync(mcpSettingsPath, "utf8"));
25761
+ mcpInstalled = !!s?.mcpServers?.wairon;
27266
25762
  } catch {
27267
25763
  }
27268
- return { id: host ? `${user}@${host}` : user, source: "os" };
25764
+ if (mcpInstalled) {
25765
+ lines.push("# wairon MCP Tools");
25766
+ lines.push("");
25767
+ lines.push("The **wairon MCP server** is active in this project. The tools are self-describing; call them directly:");
25768
+ lines.push("");
25769
+ 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`.");
25770
+ lines.push("- Reading & maintenance: `sdd_get_spec`, `sdd_update_spec`, `sdd_delete_spec`, `sdd_validate_tree`, `sdd_get_status`.");
25771
+ lines.push("- Topology: `listAgents`, `getAgent`, `listDomains`, `validateTopology`, `getProjectConfig`.");
25772
+ lines.push("");
25773
+ lines.push("Use these MCP tools to query and change project state \u2014 never the `wairon` CLI (that is the human developer's tool).");
25774
+ lines.push("");
25775
+ lines.push("---");
25776
+ lines.push("");
25777
+ }
25778
+ lines.push(GLOBAL_GUIDE_BODY);
25779
+ lines.push("");
25780
+ return lines.join("\n");
27269
25781
  }
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();
25782
+ function syncContextFiles() {
25783
+ const domainsContent = renderDomainsDoc();
25784
+ const guideContent = renderWaironGuide();
25785
+ const domainsUpdated = writeDomainsDoc(domainsContent);
25786
+ const guideUpdated = writeGuideDoc(guideContent);
25787
+ return { domainsUpdated, guideUpdated };
25788
+ }
25789
+
25790
+ // src/core/status.ts
25791
+ function getStatusReport(options = {}) {
25792
+ scanAllSpecs({ recursive: options.recursive ?? true });
25793
+ const system = loadSystemSpec();
25794
+ const loaderErrors = getLoaderIssues();
25795
+ if (loaderErrors.length > 0) {
25796
+ let errText = "Failed to parse specification files:\n";
25797
+ for (const issue2 of loaderErrors) {
25798
+ const prefix = issue2.specId ? `[${issue2.specId}] ` : "";
25799
+ errText += `${prefix}[${issue2.code}] ${issue2.message}
25800
+ `;
25801
+ }
25802
+ return errText;
25803
+ }
25804
+ if (!system) {
25805
+ return "L0 System specification (system.yaml) is missing.";
25806
+ }
25807
+ let subsystems = loadSubsystemSpecs();
25808
+ let components = loadComponentSpecs();
25809
+ let interfaces = loadInterfaceSpecs();
25810
+ let implementations = loadImplementationSpecs();
25811
+ if (options.subsystem) {
25812
+ subsystems = subsystems.filter((s) => s.id === options.subsystem || s.id.startsWith(`${options.subsystem}::`));
25813
+ components = components.filter((c) => c.subsystem === options.subsystem || c.subsystem.startsWith(`${options.subsystem}::`));
25814
+ interfaces = interfaces.filter((i) => {
25815
+ const c = components.find((comp) => comp.id === i.component);
25816
+ return c !== void 0;
25817
+ });
25818
+ implementations = implementations.filter((im) => {
25819
+ const inf = interfaces.find((i) => i.id === im.contract);
25820
+ return inf !== void 0;
25821
+ });
25822
+ }
25823
+ let output = "";
25824
+ const componentScores = /* @__PURE__ */ new Map();
25825
+ for (const comp of components) {
25826
+ let score = 20;
25827
+ const intf = interfaces.find((i) => i.component === comp.id);
25828
+ if (intf) {
25829
+ score += 30;
25830
+ }
25831
+ const impl = implementations.find((im) => intf && im.contract === intf.id);
25832
+ if (impl) {
25833
+ score += 30;
25834
+ const sourceFiles = implementationSourceFiles(impl);
25835
+ if (sourceFiles.length > 0 && sourceFiles.every((f) => pathExists(fromProjectRoot(f)))) {
25836
+ score += 20;
25837
+ }
25838
+ }
25839
+ const isDraft = comp.status === "draft" || comp.status === "design" || intf && (intf.status === "draft" || intf.status === "design") || impl && (impl.status === "draft" || impl.status === "design");
25840
+ if (isDraft) {
25841
+ score = Math.min(score, 50);
25842
+ }
25843
+ componentScores.set(comp.id, score);
25844
+ }
25845
+ const getSubsystemScore = (subId) => {
25846
+ const sub = subsystems.find((s) => s.id === subId);
25847
+ if (!sub) return 0;
25848
+ const subComps = components.filter((c) => c.subsystem === subId);
25849
+ if (subComps.length === 0) return 0;
25850
+ const totalScore = subComps.reduce((acc, c) => acc + (componentScores.get(c.id) ?? 0), 0);
25851
+ let avg = Math.round(totalScore / subComps.length);
25852
+ if (sub.status === "draft" || sub.status === "design") {
25853
+ avg = Math.min(avg, 50);
25854
+ }
25855
+ return avg;
25856
+ };
25857
+ const totalSubsystemsScore = subsystems.reduce((acc, s) => acc + getSubsystemScore(s.id), 0);
25858
+ const systemScore = subsystems.length > 0 ? Math.round(totalSubsystemsScore / subsystems.length) : 0;
25859
+ output += `\u25CF System: ${system.name} (${systemScore}% Complete)
25860
+ `;
25861
+ for (let i = 0; i < subsystems.length; i++) {
25862
+ const sub = subsystems[i];
25863
+ const isLastSub = i === subsystems.length - 1;
25864
+ const subPrefix = isLastSub ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
25865
+ const subIndent = isLastSub ? " " : "\u2502 ";
25866
+ const subScore = getSubsystemScore(sub.id);
25867
+ const subStatusStr = sub.status !== "complete" ? ` [${sub.status}]` : "";
25868
+ output += `${subPrefix}[Subsystem] ${sub.id}${subStatusStr} (${subScore}%)
25869
+ `;
25870
+ const subComps = components.filter((c) => c.subsystem === sub.id);
25871
+ for (let j = 0; j < subComps.length; j++) {
25872
+ const comp = subComps[j];
25873
+ const isLastComp = j === subComps.length - 1;
25874
+ const compPrefix = isLastComp ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
25875
+ const compIndent = isLastComp ? " " : "\u2502 ";
25876
+ const compScore = componentScores.get(comp.id) ?? 0;
25877
+ const compStatusStr = comp.status !== "complete" ? ` [${comp.status}]` : "";
25878
+ output += `${subIndent}${compPrefix}[Component: ${comp.componentType}] ${comp.id}${compStatusStr} (${compScore}%)
25879
+ `;
25880
+ const intf = interfaces.find((inf) => inf.component === comp.id);
25881
+ const impl = implementations.find((im) => intf && im.contract === intf.id);
25882
+ const intfPrefix = intf && impl ? "\u251C\u2500\u2500 " : "\u2514\u2500\u2500 ";
25883
+ if (intf) {
25884
+ const intfStatusStr = intf.status !== "complete" ? ` [${intf.status}]` : "";
25885
+ output += `${subIndent}${compIndent}${intfPrefix}Interface: ${intf.id}${intfStatusStr} (${intf.methods.length} methods)
25886
+ `;
25887
+ } else {
25888
+ output += `${subIndent}${compIndent}${intfPrefix}Interface: Missing (-30%)
25889
+ `;
25890
+ }
25891
+ if (impl) {
25892
+ const implStatusStr = impl.status !== "complete" ? ` [${impl.status}]` : "";
25893
+ const methodsWithOwnPath = impl.methods.filter((m) => m.sourcePath);
25894
+ let pathStr;
25895
+ if (impl.sourcePath) {
25896
+ pathStr = pathExists(fromProjectRoot(impl.sourcePath)) ? ` -> ${impl.sourcePath}` : ` -> ${impl.sourcePath} (File Missing!)`;
25897
+ } else if (methodsWithOwnPath.length > 0) {
25898
+ pathStr = "";
25899
+ } else {
25900
+ pathStr = " (No source path)";
25901
+ }
25902
+ output += `${subIndent}${compIndent}\u2514\u2500\u2500 Implementation: ${impl.id}${implStatusStr}${pathStr}
25903
+ `;
25904
+ const methodIndent = `${subIndent}${compIndent} `;
25905
+ for (let k = 0; k < methodsWithOwnPath.length; k++) {
25906
+ const method = methodsWithOwnPath[k];
25907
+ const isLastMethod = k === methodsWithOwnPath.length - 1;
25908
+ const methodPrefix = isLastMethod ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
25909
+ const methodPath = method.sourcePath;
25910
+ const fileMissing = !pathExists(fromProjectRoot(methodPath));
25911
+ output += `${methodIndent}${methodPrefix}method ${method.name} -> ${methodPath}${fileMissing ? " (File Missing!)" : ""}
25912
+ `;
25913
+ }
25914
+ } else {
25915
+ output += `${subIndent}${compIndent}\u2514\u2500\u2500 Implementation: Missing (-30%)
25916
+ `;
25917
+ }
25918
+ }
25919
+ }
25920
+ return output;
27276
25921
  }
27277
25922
 
27278
25923
  // src/core/index.ts
@@ -27348,6 +25993,18 @@ var logger = {
27348
25993
  }
27349
25994
  };
27350
25995
 
25996
+ // src/core/skills.ts
25997
+ var SKILL_NAMES = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
25998
+ function loadProjectConfig3() {
25999
+ return loadProjectConfig();
26000
+ }
26001
+ function activeTargetTypes2() {
26002
+ const config = loadProjectConfig3();
26003
+ if (!config) return [];
26004
+ return activeTargetTypes(config);
26005
+ }
26006
+ var RESOURCE_SKILL_IDS = [...SKILL_NAMES].sort();
26007
+
27351
26008
  // src/index.ts
27352
26009
  function loadProjectConfig4() {
27353
26010
  const config = loadProjectConfig();
@@ -27363,7 +26020,6 @@ function loadProjectConfig4() {
27363
26020
  AgentRecordSchema,
27364
26021
  AgentStatusSchema,
27365
26022
  AgentTemplateSchema,
27366
- AssertionSelectorSchema,
27367
26023
  BACKEND_COMMANDS,
27368
26024
  BUILTIN_PROFILES,
27369
26025
  BUILTIN_TYPES,
@@ -27371,8 +26027,6 @@ function loadProjectConfig4() {
27371
26027
  BuiltinTargetConfigSchema,
27372
26028
  BuiltinTargetSchema,
27373
26029
  BundleNotFoundError,
27374
- COMPONENT_AUTH_SOURCE,
27375
- CONTEXT_PATHS,
27376
26030
  CarriedDebtKindSchema,
27377
26031
  CarriedDebtSchema,
27378
26032
  CarriedFindingSchema,
@@ -27389,7 +26043,6 @@ function loadProjectConfig4() {
27389
26043
  CustomTargetSchema,
27390
26044
  DEFAULT_TARGET_DIRS,
27391
26045
  DatabaseSpecSchema,
27392
- DeclarativePackSchema,
27393
26046
  DependencyClassSchema,
27394
26047
  DesignDepthSchema,
27395
26048
  DiagramConfigSchema,
@@ -27405,7 +26058,6 @@ function loadProjectConfig4() {
27405
26058
  ExternalLinkTypeSchema,
27406
26059
  FindingDeclarationSchema,
27407
26060
  GITHUB_REPO,
27408
- GLOBAL_PACKS_DEFAULT,
27409
26061
  GeminiExporter,
27410
26062
  GroupSpecSchema,
27411
26063
  GuaranteeSchema,
@@ -27413,7 +26065,6 @@ function loadProjectConfig4() {
27413
26065
  ImplementationSpecSchema,
27414
26066
  InterfaceSpecSchema,
27415
26067
  InvariantSchema,
27416
- LanguagePackDefSchema,
27417
26068
  LifecycleEntrypointSchema,
27418
26069
  LintAllowSchema,
27419
26070
  LintConfigSchema,
@@ -27427,21 +26078,15 @@ function loadProjectConfig4() {
27427
26078
  NarrativeStepSchema,
27428
26079
  NarrativeStepTypeSchema,
27429
26080
  OutputTargetSchema,
27430
- PACK_DIR_ENTRIES,
27431
26081
  PATTERN_TYPES,
27432
26082
  PROJECT_KINDS,
27433
- PackAssertionSchema,
27434
- PackInstructionBlockSchema,
27435
26083
  PackSelectionSchema,
27436
- PackSkillSchema,
27437
26084
  ParallelBranchSchema,
27438
26085
  PathsConfigSchema,
27439
- PatternDefSchema,
27440
26086
  PatternRefSchema,
27441
26087
  PortalAuthSchema,
27442
26088
  PortalAuthSchemeSchema,
27443
26089
  PortalTypeSchema,
27444
- ProfileDefSchema,
27445
26090
  ProfileSelectionSubjectSchema,
27446
26091
  ProjectConfigSchema,
27447
26092
  ProjectNotInitializedError,
@@ -27460,10 +26105,8 @@ function loadProjectConfig4() {
27460
26105
  STEP_TYPE_FIELDS,
27461
26106
  SUPPORTED_ALIASES,
27462
26107
  SURFACE_AUDIENCES,
27463
- SkillResourceNotFoundError,
27464
26108
  SpecIdSchema,
27465
26109
  SpecStatusSchema,
27466
- SpecWorkspace,
27467
26110
  SubsystemSpecSchema,
27468
26111
  SurfaceAudienceSchema,
27469
26112
  SurfaceContractEntrySchema,
@@ -27483,9 +26126,6 @@ function loadProjectConfig4() {
27483
26126
  TypeKindSchema,
27484
26127
  TypeMethodSchema,
27485
26128
  TypeSpecSchema,
27486
- UNVERSIONED,
27487
- UnknownAgentError,
27488
- VariantDefSchema,
27489
26129
  WAIRON_MANAGED_BANNER,
27490
26130
  WAIRON_MANAGED_MARKER,
27491
26131
  WAIRON_VERSION,
@@ -27496,44 +26136,28 @@ function loadProjectConfig4() {
27496
26136
  aiDirAt,
27497
26137
  aiPathsAt,
27498
26138
  ambiguityMessage,
27499
- applySpecStatus,
27500
26139
  approvalRecord,
27501
- assertContainedProjectPath,
26140
+ approvalVerdict,
27502
26141
  assertProjectInitialized,
27503
- assertionFullCode,
27504
- audienceRank,
27505
26142
  backendCommand,
27506
- backfillChainedSubprojectConfigs,
27507
26143
  buildCanvasDataModel,
27508
- buildGraphModel,
27509
26144
  buildProjectGraph,
27510
26145
  buildRuleContext,
27511
- buildServerInstructions,
27512
- buildTreeArchive,
27513
26146
  callSitesOf,
27514
26147
  captureApprovedSpecs,
27515
- checkSkillFreshness,
27516
- clearLoaderIssues,
27517
26148
  cognitiveScore,
27518
- collectPromotableSpecs,
27519
- commitStagedTree,
27520
26149
  complexityLevel,
27521
26150
  composeAgentBrief,
27522
26151
  composeRuleSequence,
27523
- composeVariantGuidance,
27524
- computeGateStateId,
27525
- computePackDigest,
27526
26152
  computeStateId,
27527
26153
  computeStateIdAt,
27528
26154
  conceptNoun,
27529
26155
  consumedContractInputs,
27530
- contextDir,
27531
26156
  createAgentRecord,
27532
26157
  createChainedSubsystem,
27533
26158
  createEmptyRegistry,
27534
26159
  createEmptyTopologyConfig,
27535
26160
  createProjectConfig,
27536
- createStagingDir,
27537
26161
  currentChildPins,
27538
26162
  declaredPackNames,
27539
26163
  declaredProfileIds,
@@ -27543,129 +26167,82 @@ function loadProjectConfig4() {
27543
26167
  defaultPackSelections,
27544
26168
  defaultTargetConfig,
27545
26169
  deleteComponentSpec,
27546
- deleteGroupSpec,
27547
26170
  deleteImplementationSpec,
27548
26171
  deleteInterfaceSpec,
27549
26172
  deleteSubsystemSpec,
27550
26173
  deleteTypeSpec,
27551
26174
  deregisterPackRef,
27552
26175
  deriveExecutionProfile,
27553
- describeApprover,
26176
+ derivedDocPaths,
27554
26177
  detectDomainCandidates,
27555
- diagnoseProjectPacks,
27556
26178
  diagramSetIndex,
27557
26179
  diffAgainstApproval,
27558
26180
  diffSize,
27559
- discardStagingDir,
27560
26181
  discoverPacks,
27561
26182
  dryRunSerializeSpecs,
27562
26183
  effectiveDetail,
27563
26184
  emptyExtensions,
27564
26185
  ensureDir,
27565
26186
  ensureProjectInitialized,
27566
- exportSddSkills,
27567
26187
  exportSpecTree,
27568
- exportSurface,
27569
26188
  externalizeSubsystem,
27570
- extractTreeArchive,
27571
26189
  extractTypeIdentifiers,
27572
26190
  factsFor,
27573
26191
  fieldTypeRefs,
27574
26192
  fieldTypesOf,
27575
- findChainingParent,
27576
- findChainingSubprojectsMissingConfig,
27577
- findLegacySpecFiles,
27578
26193
  findProjectRoot,
27579
26194
  findSystemRoot,
27580
- findTestsReferencing,
27581
- fromOpenApi,
27582
26195
  fromProjectRoot,
27583
26196
  generateAgent,
27584
26197
  generateAll,
27585
26198
  generateComponentDiagram,
27586
26199
  generateDiagramSet,
27587
26200
  generateSequenceDiagram,
27588
- getComponentPath,
27589
26201
  getExporter,
27590
- getGroupPath,
27591
- getImplementationPath,
27592
- getInterfacePath,
27593
- getLoaderIssues,
27594
26202
  getProjectRoot,
27595
26203
  getProjectRootOverride,
27596
26204
  getRequestParentReach,
27597
26205
  getRequestProjectRoot,
27598
- getSnapshot,
27599
- getSubprojectPrefix,
27600
- getSubsystemPath,
27601
- getTypePath,
26206
+ getStatusReport,
27602
26207
  globalGuideFilePath,
27603
26208
  globalPacksDir,
27604
- globalPacksEnabled,
27605
26209
  globalTemplatesDir,
27606
- globalVariantsDir,
27607
- hasArchitectureContext,
27608
- hasAuthoredSpecs,
27609
26210
  hasContext,
27610
26211
  hasFunctionBody,
27611
- hasSpecTree,
27612
26212
  headNoun,
27613
26213
  holdsState,
27614
26214
  implementationSourceFiles,
27615
26215
  importBindingOf,
27616
26216
  importSpecTree,
27617
- importSurface,
27618
- ineffectiveDeltaPaths,
27619
26217
  injectGuide,
27620
- inspectChainedRoots,
27621
- inspectTreeArchive,
27622
26218
  installPackFromDirectory,
27623
26219
  interfaceGenericParameters,
27624
26220
  internalizeSubsystem,
27625
- invalidateSpecCache,
27626
26221
  isDraftSubsystem,
27627
26222
  isLogic,
27628
- isOpenApiDocument,
27629
26223
  isPattern,
27630
26224
  isProjectInitialized,
27631
26225
  isProvidedBy,
27632
26226
  isRetired,
27633
- listChainedRoots,
27634
26227
  listDirectChainedSubprojects,
27635
- listExternalInterfaces,
27636
26228
  listFiles,
27637
26229
  listFilesRecursive,
27638
26230
  listInstalledPacks,
27639
- listMountSnapshots,
27640
- listProjectVariants,
27641
- listResources,
27642
- listRules,
27643
- listSkillNames,
27644
- listSkillResources,
27645
- listSnapshots,
27646
- listTemplateIds,
27647
- loadAgentOverride,
27648
26231
  loadComponentSpec,
27649
26232
  loadComponentSpecs,
27650
26233
  loadExtensionPacks,
27651
26234
  loadExtensions,
27652
- loadGroupSpec,
27653
- loadGroupSpecs,
27654
26235
  loadImplementationSpec,
27655
26236
  loadImplementationSpecs,
27656
26237
  loadInterfaceSpec,
27657
26238
  loadInterfaceSpecs,
27658
- loadMountSurfaceSnapshots,
27659
26239
  loadProjectConfig,
27660
26240
  loadProjectExtensions,
27661
- loadProjectVariants,
27662
26241
  loadRegistry,
27663
26242
  loadSpecGraph,
27664
26243
  loadSubsystemSpec,
27665
26244
  loadSubsystemSpecs,
27666
- loadSurfaceSnapshots,
27667
26245
  loadSystemSpec,
27668
- loadTemplate,
27669
26246
  loadTopologyConfig,
27670
26247
  loadTypeSpec,
27671
26248
  loadTypeSpecs,
@@ -27683,53 +26260,30 @@ function loadProjectConfig4() {
27683
26260
  moveSubsystemProject,
27684
26261
  movedChildren,
27685
26262
  narrativeStepForeignFields,
27686
- normalizeApprover,
27687
- normalizeComponentLayout,
27688
- packDirEntry,
27689
- packEntryLabel,
27690
- packEntryRef,
27691
26263
  packStoreDir,
27692
26264
  parseDeclaredCall,
27693
- parseTemplate,
27694
26265
  parseYaml,
27695
26266
  passesIntentFloor,
27696
26267
  pathExists,
27697
26268
  pathKey,
27698
- pinFamilySurfaces,
27699
- pinInstalledPacksAsSelections,
27700
- projectChildSurface,
27701
26269
  projectConfigExists,
27702
- projectOwnSurface,
27703
- projectSubsystemSurface,
27704
26270
  provisionProject,
27705
26271
  qualifiedTypeId,
27706
- readArchitectureContext,
27707
26272
  readFileOrNull,
27708
26273
  readJsonFile,
27709
26274
  readLockRecord,
27710
- readLockRecordAt,
27711
26275
  readLockState,
27712
- readManifest,
27713
- readProjectContext,
27714
- readResource,
27715
- readSkillResource,
27716
26276
  readStampVersion,
27717
26277
  readYamlFile,
27718
- rebaseProjectVariants,
27719
- rebaseReference,
27720
26278
  recordProfileSelection,
27721
26279
  registerExporter,
27722
26280
  registerPackRef,
27723
26281
  reinjectLocalGuides,
27724
26282
  removeDomain,
27725
26283
  removePackSelection,
27726
- removeSnapshot,
27727
26284
  renameComponent,
27728
26285
  renameMethod,
27729
26286
  renderDiagram,
27730
- renderDomainsDoc,
27731
- renderTemplateInstructions,
27732
- renderWaironGuide,
27733
26287
  repairForeignStepFields,
27734
26288
  resolveAgentTopology,
27735
26289
  resolveBudget,
@@ -27738,47 +26292,31 @@ function loadProjectConfig4() {
27738
26292
  resolveExpectedOutputPaths,
27739
26293
  resolveImport,
27740
26294
  resolveInstalledPack,
27741
- resolvePackRef,
27742
26295
  resolveSubprojectForNamespace,
27743
- resolveVariantGuidance,
27744
- restoreSpecFiles,
27745
26296
  retireSpecialists,
27746
- rewriteSpecRefs,
27747
26297
  runWithProjectBinding,
27748
26298
  runWithProjectRoot,
27749
26299
  sameContract,
27750
26300
  saveComponentSpec,
27751
- saveGroupSpec,
27752
26301
  saveImplementationSpec,
27753
26302
  saveInterfaceSpec,
27754
- saveSnapshot,
27755
26303
  saveSubsystemSpec,
27756
26304
  saveSystemSpec,
27757
26305
  saveTopologyConfig,
27758
26306
  saveTypeSpec,
27759
- scanAllSpecs,
27760
26307
  serializeYaml,
27761
26308
  setExecutionTier,
27762
26309
  setLogLevel,
27763
26310
  setProjectRoot,
27764
26311
  setProjectType,
27765
26312
  settledSpecPaths,
27766
- skillExtendErrors,
27767
- skillsDirForTarget,
27768
- snapshotSpecFiles,
27769
- specChanges,
27770
- specKind,
27771
26313
  specPathsInScope,
27772
26314
  splitNamespace,
27773
- stateIdEquals,
27774
- stateIdString,
27775
26315
  stepConfigVerdict,
27776
26316
  stepFieldsFor,
27777
26317
  stepGraph,
27778
26318
  syncContextFiles,
27779
26319
  toMarkdown,
27780
- toOpenApi,
27781
- toOpenApiSet,
27782
26320
  typeBindingOf,
27783
26321
  typeGenericParameters,
27784
26322
  typeMatchesRef,
@@ -27786,18 +26324,11 @@ function loadProjectConfig4() {
27786
26324
  uninstallPack,
27787
26325
  updateSpec,
27788
26326
  upsertPackSelection,
27789
- validateAsComplete,
27790
- validateComponentCandidate,
27791
- validateProjectConfig,
27792
- validateRegistry,
27793
26327
  validateSddTree,
27794
- workspaceFor,
27795
- writeArchitectureContext,
27796
26328
  writeFile,
27797
26329
  writeFileIfChanged,
27798
26330
  writeJsonFile,
27799
26331
  writeLockRecord,
27800
- writeProjectContext,
27801
26332
  writeRootGuideDelegator,
27802
26333
  writeYamlFile
27803
26334
  });