agents-inc 0.158.0 → 0.160.0

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.
Files changed (149) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/{chunk-P6OKOH62.js → chunk-4APXK7ZY.js} +2 -2
  3. package/dist/{chunk-QNAMXQKF.js → chunk-4VVKVOOP.js} +2 -2
  4. package/dist/{chunk-DAUY2SB3.js → chunk-5K33RJ7Z.js} +70 -25
  5. package/dist/chunk-5K33RJ7Z.js.map +1 -0
  6. package/dist/{chunk-G6G2FT2G.js → chunk-5KB4I5J7.js} +2 -5
  7. package/dist/chunk-5KB4I5J7.js.map +1 -0
  8. package/dist/{chunk-2PN4QXON.js → chunk-6CP3CLDE.js} +5 -10
  9. package/dist/chunk-6CP3CLDE.js.map +1 -0
  10. package/dist/{chunk-TUXXBEBB.js → chunk-7JQPIMKD.js} +3 -3
  11. package/dist/{chunk-KUZBMEWR.js → chunk-AU5FS3QK.js} +3 -3
  12. package/dist/{chunk-WMVOJY6V.js → chunk-C5P7RUDR.js} +4 -4
  13. package/dist/{chunk-H4CL23HG.js → chunk-CICB4AKA.js} +3 -3
  14. package/dist/{chunk-KVVXINCJ.js → chunk-CWQLRKWB.js} +3 -3
  15. package/dist/{chunk-L4FHSOL5.js → chunk-DEWI5HDF.js} +5 -5
  16. package/dist/{chunk-JG3B47P3.js → chunk-EPBUWEW4.js} +8 -8
  17. package/dist/{chunk-EEAX7E2X.js → chunk-GWPKIXBM.js} +2 -2
  18. package/dist/{chunk-DP6YQFVO.js → chunk-IJ7GWQUR.js} +5 -5
  19. package/dist/{chunk-TZRXWFF5.js → chunk-ITEJARWI.js} +3 -3
  20. package/dist/{chunk-TPQ5M3BW.js → chunk-IWUFZ6NR.js} +3 -3
  21. package/dist/{chunk-PNRLBPGS.js → chunk-J7Q5VYR7.js} +12 -12
  22. package/dist/{chunk-4ABNXKAR.js → chunk-JQDN7KAZ.js} +2 -2
  23. package/dist/{chunk-Q7CAE5NN.js → chunk-K6MQV6SK.js} +3 -3
  24. package/dist/{chunk-54QLV3OH.js → chunk-KCN5N3PB.js} +34 -6
  25. package/dist/chunk-KCN5N3PB.js.map +1 -0
  26. package/dist/{chunk-X52QUV4U.js → chunk-LJ6V54NR.js} +5 -5
  27. package/dist/{chunk-H25VRR2T.js → chunk-LX7UXZBN.js} +6 -6
  28. package/dist/{chunk-VZRO7RYT.js → chunk-OI2H6M5I.js} +1 -103
  29. package/dist/chunk-OI2H6M5I.js.map +1 -0
  30. package/dist/{chunk-VTIDLRNA.js → chunk-OJIQOVWB.js} +2 -2
  31. package/dist/{chunk-OQB2CKBT.js → chunk-OJR3ASZI.js} +7 -7
  32. package/dist/{chunk-3PJLLBUS.js → chunk-OUG6TCQ4.js} +220 -345
  33. package/dist/chunk-OUG6TCQ4.js.map +1 -0
  34. package/dist/{chunk-WCZNQECQ.js → chunk-PEHYVSJG.js} +2 -2
  35. package/dist/{chunk-6DBE562W.js → chunk-PIUCYRLP.js} +5 -15
  36. package/dist/chunk-PIUCYRLP.js.map +1 -0
  37. package/dist/{chunk-PZNXBORZ.js → chunk-PWPKZNCV.js} +4 -4
  38. package/dist/{chunk-SJ4T5YLG.js → chunk-Q2HB5SWU.js} +5 -5
  39. package/dist/{chunk-H2DHTJKW.js → chunk-RJ3JYZJ7.js} +9 -9
  40. package/dist/chunk-RJ3JYZJ7.js.map +1 -0
  41. package/dist/{chunk-DZD25NHW.js → chunk-SITF5EZM.js} +2 -2
  42. package/dist/{chunk-IK6YOXZH.js → chunk-SLB2SFTX.js} +4 -28
  43. package/dist/chunk-SLB2SFTX.js.map +1 -0
  44. package/dist/{chunk-LKI3ENGQ.js → chunk-VH6P7UGF.js} +4 -4
  45. package/dist/{chunk-3Q2N7CSY.js → chunk-VI4X5DN5.js} +6 -6
  46. package/dist/{chunk-YXI3BTQQ.js → chunk-X5PLVOJS.js} +2 -2
  47. package/dist/{chunk-XNYHMRVJ.js → chunk-XDNGMXOZ.js} +4 -4
  48. package/dist/{chunk-3NBXQSW2.js → chunk-XSULY25W.js} +6 -6
  49. package/dist/{chunk-7Z4N4JWQ.js → chunk-XX657S4U.js} +1 -103
  50. package/dist/chunk-XX657S4U.js.map +1 -0
  51. package/dist/{chunk-4DMFK67G.js → chunk-YKRPWZ3G.js} +2 -2
  52. package/dist/commands/build/marketplace.js +8 -8
  53. package/dist/commands/build/plugins.js +8 -8
  54. package/dist/commands/compile.js +11 -11
  55. package/dist/commands/doctor.js +13 -13
  56. package/dist/commands/doctor.js.map +1 -1
  57. package/dist/commands/edit.js +59 -68
  58. package/dist/commands/edit.js.map +1 -1
  59. package/dist/commands/eject.js +11 -11
  60. package/dist/commands/init.js +41 -37
  61. package/dist/commands/list.js +9 -9
  62. package/dist/commands/new/marketplace.js +8 -9
  63. package/dist/commands/new/marketplace.js.map +1 -1
  64. package/dist/commands/search.js +11 -11
  65. package/dist/commands/share.js +100 -16
  66. package/dist/commands/share.js.map +1 -1
  67. package/dist/commands/uninstall.js +12 -12
  68. package/dist/commands/update.js +7 -7
  69. package/dist/components/common/removal-plan-confirm.js +2 -2
  70. package/dist/components/common/select-list.js +2 -2
  71. package/dist/components/wizard/category-grid.js +4 -4
  72. package/dist/components/wizard/checkbox-grid.js +4 -4
  73. package/dist/components/wizard/domain-selection.js +10 -10
  74. package/dist/components/wizard/run-wizard-session.js +27 -27
  75. package/dist/components/wizard/scroll-affordance.js +2 -2
  76. package/dist/components/wizard/skill-agent-summary.js +6 -6
  77. package/dist/components/wizard/source-grid.js +5 -5
  78. package/dist/components/wizard/stack-selection.js +8 -8
  79. package/dist/components/wizard/step-agents.js +9 -9
  80. package/dist/components/wizard/step-build.js +8 -8
  81. package/dist/components/wizard/step-confirm.js +10 -10
  82. package/dist/components/wizard/step-sources.js +9 -9
  83. package/dist/components/wizard/step-stack.js +9 -9
  84. package/dist/components/wizard/summary-panel.js +9 -9
  85. package/dist/components/wizard/toast.js +2 -2
  86. package/dist/components/wizard/wizard-layout.js +13 -13
  87. package/dist/components/wizard/wizard-tabs.js +2 -2
  88. package/dist/components/wizard/wizard.js +26 -26
  89. package/dist/config-exports.js +1 -1
  90. package/dist/hooks/init.js +37 -37
  91. package/dist/load-agent-defs-KWHG7P7G.js +13 -0
  92. package/dist/recompile-project-agents-5FTDDHX7.js +17 -0
  93. package/dist/{source-loader-CO2FZ3OO.js → source-loader-CDYH2NIM.js} +5 -5
  94. package/dist/src/agents/_templates/methodologies/anti-over-engineering.liquid +14 -0
  95. package/dist/src/agents/_templates/methodologies/context-management.liquid +7 -154
  96. package/dist/src/agents/_templates/methodologies/investigation-requirements.liquid +12 -0
  97. package/dist/src/agents/_templates/methodologies/success-criteria.liquid +10 -0
  98. package/dist/stores/wizard-store.js +5 -5
  99. package/package.json +1 -1
  100. package/src/agents/_templates/methodologies/anti-over-engineering.liquid +14 -0
  101. package/src/agents/_templates/methodologies/context-management.liquid +7 -154
  102. package/src/agents/_templates/methodologies/investigation-requirements.liquid +12 -0
  103. package/src/agents/_templates/methodologies/success-criteria.liquid +10 -0
  104. package/src/schemas/project-source-config.schema.json +0 -3
  105. package/dist/chunk-2PN4QXON.js.map +0 -1
  106. package/dist/chunk-3PJLLBUS.js.map +0 -1
  107. package/dist/chunk-54QLV3OH.js.map +0 -1
  108. package/dist/chunk-6DBE562W.js.map +0 -1
  109. package/dist/chunk-7Z4N4JWQ.js.map +0 -1
  110. package/dist/chunk-DAUY2SB3.js.map +0 -1
  111. package/dist/chunk-G6G2FT2G.js.map +0 -1
  112. package/dist/chunk-H2DHTJKW.js.map +0 -1
  113. package/dist/chunk-IK6YOXZH.js.map +0 -1
  114. package/dist/chunk-VZRO7RYT.js.map +0 -1
  115. package/dist/load-agent-defs-2VYAV5GL.js +0 -13
  116. package/dist/recompile-project-agents-NG5DCPHJ.js +0 -17
  117. /package/dist/{chunk-P6OKOH62.js.map → chunk-4APXK7ZY.js.map} +0 -0
  118. /package/dist/{chunk-QNAMXQKF.js.map → chunk-4VVKVOOP.js.map} +0 -0
  119. /package/dist/{chunk-TUXXBEBB.js.map → chunk-7JQPIMKD.js.map} +0 -0
  120. /package/dist/{chunk-KUZBMEWR.js.map → chunk-AU5FS3QK.js.map} +0 -0
  121. /package/dist/{chunk-WMVOJY6V.js.map → chunk-C5P7RUDR.js.map} +0 -0
  122. /package/dist/{chunk-H4CL23HG.js.map → chunk-CICB4AKA.js.map} +0 -0
  123. /package/dist/{chunk-KVVXINCJ.js.map → chunk-CWQLRKWB.js.map} +0 -0
  124. /package/dist/{chunk-L4FHSOL5.js.map → chunk-DEWI5HDF.js.map} +0 -0
  125. /package/dist/{chunk-JG3B47P3.js.map → chunk-EPBUWEW4.js.map} +0 -0
  126. /package/dist/{chunk-EEAX7E2X.js.map → chunk-GWPKIXBM.js.map} +0 -0
  127. /package/dist/{chunk-DP6YQFVO.js.map → chunk-IJ7GWQUR.js.map} +0 -0
  128. /package/dist/{chunk-TZRXWFF5.js.map → chunk-ITEJARWI.js.map} +0 -0
  129. /package/dist/{chunk-TPQ5M3BW.js.map → chunk-IWUFZ6NR.js.map} +0 -0
  130. /package/dist/{chunk-PNRLBPGS.js.map → chunk-J7Q5VYR7.js.map} +0 -0
  131. /package/dist/{chunk-4ABNXKAR.js.map → chunk-JQDN7KAZ.js.map} +0 -0
  132. /package/dist/{chunk-Q7CAE5NN.js.map → chunk-K6MQV6SK.js.map} +0 -0
  133. /package/dist/{chunk-X52QUV4U.js.map → chunk-LJ6V54NR.js.map} +0 -0
  134. /package/dist/{chunk-H25VRR2T.js.map → chunk-LX7UXZBN.js.map} +0 -0
  135. /package/dist/{chunk-VTIDLRNA.js.map → chunk-OJIQOVWB.js.map} +0 -0
  136. /package/dist/{chunk-OQB2CKBT.js.map → chunk-OJR3ASZI.js.map} +0 -0
  137. /package/dist/{chunk-WCZNQECQ.js.map → chunk-PEHYVSJG.js.map} +0 -0
  138. /package/dist/{chunk-PZNXBORZ.js.map → chunk-PWPKZNCV.js.map} +0 -0
  139. /package/dist/{chunk-SJ4T5YLG.js.map → chunk-Q2HB5SWU.js.map} +0 -0
  140. /package/dist/{chunk-DZD25NHW.js.map → chunk-SITF5EZM.js.map} +0 -0
  141. /package/dist/{chunk-LKI3ENGQ.js.map → chunk-VH6P7UGF.js.map} +0 -0
  142. /package/dist/{chunk-3Q2N7CSY.js.map → chunk-VI4X5DN5.js.map} +0 -0
  143. /package/dist/{chunk-YXI3BTQQ.js.map → chunk-X5PLVOJS.js.map} +0 -0
  144. /package/dist/{chunk-XNYHMRVJ.js.map → chunk-XDNGMXOZ.js.map} +0 -0
  145. /package/dist/{chunk-3NBXQSW2.js.map → chunk-XSULY25W.js.map} +0 -0
  146. /package/dist/{chunk-4DMFK67G.js.map → chunk-YKRPWZ3G.js.map} +0 -0
  147. /package/dist/{load-agent-defs-2VYAV5GL.js.map → load-agent-defs-KWHG7P7G.js.map} +0 -0
  148. /package/dist/{recompile-project-agents-NG5DCPHJ.js.map → recompile-project-agents-5FTDDHX7.js.map} +0 -0
  149. /package/dist/{source-loader-CO2FZ3OO.js.map → source-loader-CDYH2NIM.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/edit.tsx","../../src/cli/lib/seed/seed-apply.ts","../../src/cli/utils/open-url.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\n\nimport chalk from \"chalk\";\nimport { Flags } from \"@oclif/core\";\nimport { render } from \"../components/render.js\";\n\nimport { difference, indexBy, partition } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { runWizardSession } from \"../components/wizard/run-wizard-session.js\";\nimport {\n CLI_INVOKE_COMMAND,\n CLI_COLORS,\n EDIT_PROJECT_SETUP_FLAG,\n EJECT_SOURCE,\n editorConfigUrl,\n formatSourceDisplayName,\n} from \"../consts.js\";\nimport {\n detectProject,\n loadSource,\n copyLocalSkills,\n uninstallPluginSkills,\n loadAgentDefs,\n type AgentDefs,\n writeProjectConfig,\n type ConfigWriteResult,\n compileAgentsAllScopes,\n discoverInstalledSkills,\n removeCompiledAgents,\n type RemoveCompiledAgentsOptions,\n} from \"../lib/operations/index.js\";\nimport { Spinner } from \"../components/common/spinner.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n type EjectCopyResult,\n type Installation,\n detectMigrations,\n ejectCopyFailureError,\n executeMigration,\n isHomeDirectory,\n installBaseDir,\n resolveInstallPaths,\n INSTALL_MODE_DESCRIPTIONS,\n} from \"../lib/installation/index.js\";\nimport {\n applyMigratedGlobalSources,\n mutateGlobal,\n normalizeProjectPath,\n} from \"../lib/config-gate/index.js\";\nimport { matrix, getSkillById, getSkillDisplayName } from \"../lib/matrix/matrix-provider\";\nimport { type AuthoritativeScope, loadProjectConfigFromDir } from \"../lib/configuration/index.js\";\nimport {\n activeAgentNames,\n activeAgentScopeMap,\n isActiveAt,\n} from \"../lib/configuration/scope-predicates.js\";\nimport type { SourceLoadResult } from \"../lib/loading/index.js\";\nimport {\n discoverAllPluginSkills,\n buildMarketplacePluginRef,\n toClaudePluginScope,\n} from \"../lib/plugins/index.js\";\nimport {\n deleteLocalSkill,\n migrateLocalSkillScope,\n unresolvedSkillRemovalReasons,\n} from \"../lib/skills/index.js\";\nimport type {\n SkillId,\n SkillConfig,\n AgentName,\n AgentScopeConfig,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillScope,\n} from \"../types/index.js\";\nimport {\n seedPayloadForInstallation,\n skillsAuthoredHere,\n} from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport { fetchSeedConfig } from \"../lib/seed/fetch-seed.js\";\nimport {\n registerExternalSkills,\n writeExternalSkills,\n type ExternalSkillInstall,\n} from \"../lib/seed/external-skills.js\";\nimport { seedToWizardResult, type SeedMapping } from \"../lib/seed/seed-to-wizard.js\";\nimport { reconcileSharedConfig, type KeptFromRoundTrip } from \"../lib/seed/seed-apply.js\";\nimport {\n RemovalPlanConfirm,\n type RemovalPlanSection,\n} from \"../components/common/removal-plan-confirm.js\";\nimport { promptConfirm } from \"../components/common/prompt-confirm.js\";\nimport { claudePluginInstall, claudePluginUninstall } from \"../utils/exec.js\";\nimport { openUrl } from \"../utils/open-url.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport {\n INCOMPLETE_WORK_RECOVERY,\n ERROR_MESSAGES,\n INFO_MESSAGES,\n SHARED_CONFIG_APPLY,\n SHARED_CONFIG_ONE_DIRECTION,\n STATUS_MESSAGES,\n agentsNotCompiled,\n authoredHereKept,\n carriedSkillsWritten,\n globallyInstalledRemoved,\n localSkillsCopied,\n recompileSummary,\n sharedConfigDestinations,\n sharedConfigNeedsTerminal,\n skippedUnknownAgents,\n skippedUnknownSkills,\n unplaceableKept,\n} from \"../utils/messages.js\";\nimport { formatScopeTag } from \"../lib/wizard/index.js\";\nimport { typedKeys } from \"../utils/typed-object.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/** A scope transition (`from` → `to`) for a re-scoped skill or agent. */\ntype ScopeChange = { from: SkillScope; to: SkillScope };\n\n/**\n * The noun `edit`'s recompile summary counts in. `edit` recompiles every scope this\n * context owns in one pass, so it has no scope word to qualify with — `compile`,\n * which runs one scope at a time, does.\n */\nconst RECOMPILE_SUBJECT = \"agents\";\n\n/**\n * Dual-scope add/remove: the project half of a [P][G] pair was toggled while the\n * global half persists. Reported as a project-scope addition/removal; a\n * scope-change arrow line would falsely claim the global install moved.\n */\nfunction formatDualScopeTransition(displayName: string, to: SkillScope): string {\n const isAdd = to === \"project\";\n const prefix = isAdd ? \"+\" : \"-\";\n const color = isAdd ? CLI_COLORS.SUCCESS : CLI_COLORS.ERROR;\n return chalk.hex(color)(` ${prefix} ${displayName} [P]`);\n}\n\n/**\n * One re-scoped skill's line. A dual-scope toggle is the transition above rather than a\n * migration; a genuine `[G] → [P]` reads as an addition because the skill arrives in this\n * project, and every other direction is the amber `~` a move is written with.\n */\nfunction formatSkillScopeChangeLine(\n skillId: SkillId,\n change: ScopeChange,\n dualScopeSkillTransitions: ReadonlySet<SkillId>,\n): string {\n const displayName = getSkillDisplayName(skillId);\n if (dualScopeSkillTransitions.has(skillId)) {\n return formatDualScopeTransition(displayName, change.to);\n }\n\n const isGlobalToProject = change.from === \"global\" && change.to === \"project\";\n const prefix = isGlobalToProject ? \"+\" : \"~\";\n const color = isGlobalToProject ? CLI_COLORS.SUCCESS : CLI_COLORS.WARNING;\n return (\n chalk.hex(color)(` ${prefix} ${displayName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change))\n );\n}\n\n/**\n * The agent mirror of the line above, with two differences preserved from how this summary has\n * always read: there is no `[G] → [P]`-reads-as-addition arm — an agent that moves is a move —\n * and only the dual-scope arm carries the `(agent)` suffix, since a `~` line names no skill it\n * could be confused with.\n */\nfunction formatAgentScopeChangeLine(\n agentName: AgentName,\n change: ScopeChange,\n dualScopeAgentTransitions: ReadonlySet<AgentName>,\n): string {\n const agentSuffix = chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\");\n if (dualScopeAgentTransitions.has(agentName)) {\n return formatDualScopeTransition(agentName, change.to) + agentSuffix;\n }\n\n return (\n chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change))\n );\n}\n\n/** The ` ([P] → [G])` half both lines above end with, in the tags the wizard writes scopes as. */\nfunction scopeArrow(change: ScopeChange): string {\n return ` (${formatScopeTag(change.from)} \\u2192 ${formatScopeTag(change.to)})`;\n}\n\n/**\n * The name this session's catalogue answers to — what a marketplace-dropped entry's removal\n * reason says the skill is not present in. The resolved marketplace where there is one,\n * otherwise the source string itself, which is what an installation pointed at a source that\n * never carried the skill has to be named by.\n */\nfunction loadedSourceLabel(sourceResult: SourceLoadResult): string {\n return sourceResult.marketplace ?? sourceResult.sourceConfig.source;\n}\n\n/** @internal Re-exported for testing — the transform itself lives inside the gate. */\nexport { applyMigratedGlobalSources };\n\ntype EditContext = {\n installation: Installation;\n projectConfig: ProjectConfig | null;\n /** The detected installation's root — where this run READS its saved skills from. */\n projectDir: string;\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n currentSkillIds: SkillId[];\n};\n\n/**\n * The one directory an `edit` run acts on, and everything every layer needs to know about it.\n *\n * Six layers used to answer \"am I editing the global installation?\" for themselves, three of\n * them off the working directory, and they disagreed the moment the command was started\n * outside an install. Passing this value instead of a bare path is what makes them one\n * answer: a layer that wants a different one has to reach past the parameter it was handed.\n */\ntype EditRoot = {\n /** Where this run writes, registers plugins and compiles into. */\n dir: string;\n /**\n * True when {@link EditRoot.dir} IS the global installation, so there is no project scope to\n * offer.\n */\n isGlobal: boolean;\n /**\n * True when this run must materialise {@link EditRoot.dir} as a project even with nothing to\n * change.\n */\n isProjectSetup: boolean;\n};\n\n/**\n * Which installation this run is editing, decided once.\n *\n * `edit` names no directory. It edits the installation `detectProject` found, and that\n * installation's root is the only root that HAS a config to edit — so it is the only root\n * this run may write to. Reading the working directory instead made a project out of\n * whichever directory the command was started in: over a global-only install the wizard\n * offered the project/global scope toggle for a project that did not exist, and saving\n * wrote a `.claude-src/` pair into an unrelated checkout.\n *\n * `--project-setup` is an instance of that rule rather than an exception to it. It means the\n * user ran `cc init` HERE, which declares this directory the installation being set up, so\n * the config this run writes is what makes the claim true. At the home root there is nothing\n * to set up and both spellings name the same directory anyway, which is why the flag alone\n * picks the root and the resolved criterion decides whether anything is materialised.\n */\nfunction resolveEditRoot(\n installation: Installation,\n cwd: string,\n setupRequested: boolean,\n): EditRoot {\n const dir = setupRequested ? cwd : installation.projectDir;\n const isGlobal = isHomeDirectory(dir);\n return { dir, isGlobal, isProjectSetup: setupRequested && !isGlobal };\n}\n\n/**\n * What this run is about to apply, and which producer said so.\n *\n * The two produce the same `WizardResultV2` and are applied by the same sequence — that is what\n * stops `edit` growing a second copy of its own pipeline. They differ in what has to happen\n * between the diff and the first mutation: a wizard result was authored keystroke by keystroke\n * and needs no permission, while a shared configuration arrived whole and destroys whatever it\n * left out, so its removals are shown and confirmed there.\n */\ntype EditSelection =\n | { producer: \"wizard\"; result: WizardResultV2 }\n | {\n producer: \"shared\";\n result: WizardResultV2;\n /** Statements naming what this run may not remove — rendered in the confirm. */\n kept: string[];\n /** Skills the configuration carries rather than names, written once it is approved. */\n carried: ExternalSkillInstall[];\n };\n\n/** What a shared apply is confirmed against: one heading, the lists, and the prose under them. */\ntype SharedConfigPlan = {\n heading: string;\n sections: RemovalPlanSection[];\n statements: string[];\n};\n\n/** A removal set's two lists, whichever scope the entries in it were installed at. */\ntype RemovedEntries = { skills: SkillId[]; agents: AgentName[] };\n\n/** The removal set split by the scope each entry was actually installed at. */\ntype RemovalsByScope = { here: RemovedEntries; global: RemovedEntries };\n\n/** The entries this run is applying over, which is where a removal's scope is read from. */\ntype InstalledEntries = Pick<ProjectConfig, \"skills\" | \"agents\">;\n\n/**\n * The plan INSIDE the global installation: the ordinary one, and deliberately nothing more.\n *\n * The person ran this at their home directory. The location IS the global scope, they chose it,\n * and that global is inherited by every project is what global means — so a second\n * acknowledgement restates a fact the directory already states, and a gate that fires everywhere\n * is one nobody is still reading by the time it matters.\n */\nfunction globalScopePlan(changes: ConfigChanges, kept: string[]): SharedConfigPlan {\n const sections = removalSections(changes.removedSkills, changes.removedAgents);\n return { heading: planHeading(sections), sections, statements: kept };\n}\n\n/**\n * The plan INSIDE a project, where a removal can reach past the directory it was asked for in.\n *\n * A global install is one installation every registered project reads, so removing one here\n * changes projects the person confirming is not looking at. Those entries get their own section\n * and a statement counting and naming the projects the yes changes; everything else reads as it\n * always has. The split is on the entries' own scope rather than on wording, so the two confirms\n * stay two branches — one gate firing everywhere and explaining itself differently is how a gate\n * drifts into firing wrongly.\n */\nfunction projectScopePlan(\n changes: ConfigChanges,\n kept: string[],\n installed: InstalledEntries,\n otherProjects: string[],\n): SharedConfigPlan {\n const { here, global } = splitRemovalsByScope(changes, installed);\n const sections = [\n ...removalSections(here.skills, here.agents),\n ...globalRemovalSections(global.skills, global.agents),\n ];\n\n return {\n heading: planHeading(sections),\n sections,\n statements: [...globalReachStatement(global, otherProjects), ...kept],\n };\n}\n\n/** Which removals leave this project only, and which leave the machine. */\nfunction splitRemovalsByScope(\n changes: ConfigChanges,\n installed: InstalledEntries,\n): RemovalsByScope {\n const isGlobalSkill = (id: SkillId): boolean =>\n installed.skills.some((skill) => skill.id === id && isActiveAt(skill, \"global\"));\n const isGlobalAgent = (name: AgentName): boolean =>\n installed.agents.some((agent) => agent.name === name && isActiveAt(agent, \"global\"));\n\n const [globalSkills, projectSkills] = partition(changes.removedSkills, isGlobalSkill);\n const [globalAgents, projectAgents] = partition(changes.removedAgents, isGlobalAgent);\n\n return {\n here: { skills: projectSkills, agents: projectAgents },\n global: { skills: globalSkills, agents: globalAgents },\n };\n}\n\n/** The removals a shared configuration makes here, grouped as the plan prints them. */\nfunction removalSections(skills: SkillId[], agents: AgentName[]): RemovalPlanSection[] {\n return [\n { label: SHARED_CONFIG_APPLY.SKILLS_HEADING, items: skills.map(skillLabel) },\n { label: SHARED_CONFIG_APPLY.AGENTS_HEADING, items: [...agents] },\n ].filter((section) => section.items.length > 0);\n}\n\n/** The same lists for entries that live at global scope, under headings that say so. */\nfunction globalRemovalSections(skills: SkillId[], agents: AgentName[]): RemovalPlanSection[] {\n return [\n { label: SHARED_CONFIG_APPLY.GLOBAL_SKILLS_HEADING, items: skills.map(skillLabel) },\n { label: SHARED_CONFIG_APPLY.GLOBAL_AGENTS_HEADING, items: [...agents] },\n ].filter((section) => section.items.length > 0);\n}\n\n/** Who else a global removal lands on — printed only when there is one to land. */\nfunction globalReachStatement(global: RemovedEntries, otherProjects: string[]): string[] {\n if (global.skills.length === 0 && global.agents.length === 0) return [];\n return [globallyInstalledRemoved(otherProjects)];\n}\n\n/**\n * The plan's opening line. A heading is a promise about the lines beneath it, so one promising\n * removals over an empty list would be a lie — a configuration that only adds says so instead,\n * and is still confirmed, because it is still applied whole.\n */\nfunction planHeading(sections: RemovalPlanSection[]): string {\n if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;\n return SHARED_CONFIG_APPLY.PREVIEW_HEADING;\n}\n\n/** How a removal reads in the plan: the name the user picked it by, with the id behind it. */\nfunction skillLabel(skillId: SkillId): string {\n const displayName = getSkillDisplayName(skillId);\n return displayName === skillId ? skillId : `${displayName} (${skillId})`;\n}\n\n/**\n * The plan's kept half, one statement per reason.\n *\n * Both reasons are disclosed rather than acted on, which is the point: no configuration ever\n * carried a skill written here, and an id this catalogue cannot place is one this run had an\n * instruction about and could not honour — so an apply that silently left them behind would\n * recreate exactly the defect the destructive ruling exists to kill, nobody able to tell why an\n * agent still carries a skill they never picked.\n */\nfunction keptStatements(kept: KeptFromRoundTrip): string[] {\n return [...authorshipStatement(kept), ...catalogueStatement(kept)];\n}\n\n/** The ownership half, whose remedy is the wizard rather than another configuration. */\nfunction authorshipStatement(kept: KeptFromRoundTrip): string[] {\n if (kept.authoredSkillIds.length === 0) return [];\n return [authoredHereKept(kept.authoredSkillIds)];\n}\n\n/** The catalogue's own limit, whose remedy is the catalogue rather than anything installed. */\nfunction catalogueStatement(kept: KeptFromRoundTrip): string[] {\n if (kept.unplaceableSkillIds.length === 0) return [];\n return [unplaceableKept(kept.unplaceableSkillIds)];\n}\n\n/**\n * How much of what it can see a run owns — the word the merger takes, and the same word the\n * global config the project write commits is resolved under.\n *\n * At the home root, everything: the session loaded the whole global config, so an absent entry\n * was deselected. In a project the WIZARD owns only what the project owns, because the store\n * refuses to deselect a live global entry at all — an inherited row absent from its result is\n * one it never offered, not one anybody dropped. A CONFIRMED shared configuration is the other\n * case and the reason this is not simply `editRoot.isGlobal`: it states a whole roster, the plan\n * above named every global removal and every project that reaches, and somebody answered yes.\n */\nfunction applyAuthority(\n producer: EditSelection[\"producer\"],\n editRoot: EditRoot,\n): AuthoritativeScope {\n if (editRoot.isGlobal) return \"all\";\n return producer === \"shared\" ? \"all\" : \"owned\";\n}\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static examples = [\n {\n description: \"Open the edit wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Open this installation in the editor instead of the wizard\",\n command: \"<%= config.bin %> <%= command.id %> --ui\",\n },\n {\n description: \"Apply a configuration built in the editor, by its id\",\n command: \"<%= config.bin %> <%= command.id %> --from <id>\",\n },\n ];\n\n static flags = {\n ui: Flags.boolean({\n description: \"Edit this installation in the browser at agentsinc.sh instead of the wizard\",\n default: false,\n }),\n from: Flags.string({\n description:\n \"Apply a configuration shared from agentsinc.sh by its id, removing whatever it leaves out\",\n helpValue: \"<id>\",\n }),\n [EDIT_PROJECT_SETUP_FLAG]: Flags.boolean({\n description: \"Internal: this run continues an `init` project setup\",\n default: false,\n hidden: true,\n }),\n };\n\n /**\n * The command in two statements: do the work, then answer for it.\n *\n * `applyEdit` owns every path through the edit and returns however it likes; the exit code is\n * decided once, here, after the last of them. Deciding it inside `applyEdit` would mean\n * deciding it at each of that method's three endings, and an ending added later would inherit\n * the exit-0 default silently — which is the defect this pair exists to close.\n */\n async run(): Promise<void> {\n await this.applyEdit();\n this.exitIfWorkIncomplete();\n }\n\n private async applyEdit(): Promise<void> {\n const { flags } = await this.parse(Edit);\n const cwd = process.cwd();\n\n // Before anything renders: a config that cannot be read is recreated, not edited, and\n // refusing here is what keeps the refusal clean — past this point the wizard has already\n // copied skills and installed plugins by the time a config read fails.\n await this.ensureConfigReadable(cwd);\n\n if (flags.ui && flags.from !== undefined) {\n this.error(SHARED_CONFIG_ONE_DIRECTION, { exit: EXIT_CODES.ERROR });\n }\n\n // The browser is the other editor, so it replaces the wizard rather than preceding it —\n // above the source load, which exists to fill screens this run will never paint.\n if (flags.ui) return this.openInEditor(cwd);\n\n // The inbound half is destructive, so it is confirmed — and a confirm nobody can answer must\n // never become a yes. Refusing here, above the fetch and above the catalogue load, is what\n // keeps a run that cannot finish from spending either.\n const payload =\n flags.from === undefined ? null : await this.fetchSharedConfigOrFail(flags.from);\n\n const context = await this.loadContextUnderSpinner();\n\n // Which installation this run is editing, resolved once and read by every layer below.\n const editRoot = resolveEditRoot(context.installation, cwd, flags[EDIT_PROJECT_SETUP_FLAG]);\n\n // Still before anything renders, one layer below the config itself: an entry whose skill\n // IS installed and whose metadata.yaml describes it no longer would otherwise be dropped\n // from config.ts on the way out, over a file this refusal asks to be repaired instead.\n await this.ensureSavedSkillsReadable(\n context.projectConfig?.skills ?? [],\n context.sourceResult.matrix,\n context.projectDir,\n );\n\n const selection = payload\n ? await this.selectionFromSharedConfig(payload, context, editRoot)\n : await this.selectionFromWizard(context, editRoot);\n if (!selection) this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n\n const { result } = selection;\n this.reportValidationErrors(result.validation);\n\n // Filter excluded entries ONCE — downstream methods receive only active entries\n const activeNewSkills = result.skills.filter((s) => !s.excluded);\n const activeNewAgents = result.agentConfigs.filter((a) => !a.excluded);\n const activeOldSkills = (context.projectConfig?.skills ?? []).filter((s) => !s.excluded);\n const activeOldAgents = (context.projectConfig?.agents ?? []).filter((a) => !a.excluded);\n\n const filteredResult: WizardResultV2 = {\n ...result,\n skills: activeNewSkills,\n agentConfigs: activeNewAgents,\n };\n const filteredOldConfig: ProjectConfig | null = context.projectConfig\n ? { ...context.projectConfig, skills: activeOldSkills, agents: activeOldAgents }\n : null;\n\n const changes = detectConfigChanges(filteredOldConfig, filteredResult, {\n newSkills: result.skills,\n oldSkills: context.projectConfig?.skills ?? [],\n newAgents: result.agentConfigs,\n oldAgents: context.projectConfig?.agents ?? [],\n });\n // The gate, at the one point where the removals are known and none has been made: after the\n // diff, above every mutation, and above the no-change return — a configuration that carries\n // its own skills still has bytes to land when the roster is unchanged.\n if (selection.producer === \"shared\") {\n await this.confirmSharedConfigOrCancel(\n changes,\n selection.kept,\n { skills: activeOldSkills, agents: activeOldAgents },\n editRoot,\n );\n await this.writeCarriedSkills(selection.carried);\n }\n\n // One word for both halves of the write, decided once from what was actually confirmed: the\n // merger reads it for the config ROW, and the gate reads it for the global config a project\n // write commits. Deriving it twice is how the row and the disk come to disagree.\n const authority = applyAuthority(selection.producer, editRoot);\n\n if (!hasAnyChanges(changes)) {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(\"No changes made.\"));\n // `cc init` inside a project means \"set this project up\", so the project must be\n // materialised — `<project>/.claude-src/config.ts` + `config-types.ts` written and the\n // path registered in the global `projects[]` — even when the wizard produced no roster\n // change. At the home root there is no project to set up: the global install is what the\n // dashboard was shown for, so a no-change pass there stays an inspection, as does every\n // bare `cc edit`.\n if (!editRoot.isProjectSetup) return;\n await this.writeConfigAndCompile(result, context, editRoot, authority);\n this.logCompletionSummary(changes);\n return;\n }\n\n const removalReasons = await unresolvedSkillRemovalReasons(\n result.unresolvableSkillIds,\n activeOldSkills,\n context.projectDir,\n loadedSourceLabel(context.sourceResult),\n );\n this.logChangeSummary(\n changes,\n filteredResult.skills,\n filteredOldConfig?.skills ?? [],\n removalReasons,\n );\n const migratedSkillIds = await this.applyMigrations(\n changes,\n filteredResult,\n activeOldSkills,\n context,\n editRoot,\n );\n await this.recordGlobalSourceMigrations(\n migratedSkillIds,\n filteredResult.skills,\n editRoot,\n context,\n );\n await this.applyScopeChanges(changes, filteredResult, context, editRoot);\n await this.applySourceChanges(changes, activeOldSkills, editRoot, migratedSkillIds);\n await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, editRoot);\n await this.copyNewLocalSkills(changes, filteredResult, context, editRoot);\n await this.removeDeletedLocalSkills(changes, activeOldSkills, editRoot);\n await this.writeConfigAndCompile(result, context, editRoot, authority);\n await this.cleanupStaleAgentFiles(changes, activeOldAgents, editRoot);\n this.logCompletionSummary(changes);\n }\n\n /** The interactive producer: open the wizard on what is installed, return what was chosen. */\n private async selectionFromWizard(\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<EditSelection | null> {\n const result = await this.runEditWizard(context, editRoot);\n if (!result) return null;\n\n return { producer: \"wizard\", result };\n }\n\n /**\n * The `--from <id>` producer: fetch, seat what the configuration carries, decode, and put back\n * what this run has no authority to remove.\n *\n * Everything a shared configuration says is a statement about the whole roster, so the apply\n * that follows is destructive — the project is made to MATCH it. Two exceptions come back into\n * the result: a skill written here, which the producer drops on the way out because\n * `forkedFrom` says the CLI never wrote it, and an id the configuration NAMES that this\n * catalogue cannot place, because a destructive apply removes on intent and never on its own\n * inability. Both are disclosed in the confirm rather than silently excused.\n *\n * A globally installed entry is NOT one of them. It is removable from here, and what its scope\n * changes is who the removal reaches — which the confirm names, rather than this putting the\n * entry back and calling the reach impossible.\n */\n private async selectionFromSharedConfig(\n payload: SeedPayload,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<EditSelection> {\n const { matrix: sourceMatrix } = context.sourceResult;\n // Before the decode, because a skill the payload CARRIES answers to no catalogue: unseated,\n // its id is skipped like any other unknown one and its content is never read.\n const carried = this.registerExternalSkillsOrFail(payload, sourceMatrix, editRoot.dir);\n const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(\n payload,\n sourceMatrix,\n );\n\n // The first moment this can be asked, and above everything this run would say or do: an\n // all-global configuration is exactly what a global installation is for, so only the decode\n // says whether THIS one has anywhere to be written here. `init --from` asks it at the same\n // point of the same value, and a run about to be refused must not first narrate its skips.\n this.refuseProjectScopedContentAtHome(result, editRoot.dir);\n\n if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));\n if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));\n\n const reconciled = reconcileSharedConfig({\n decoded: result,\n installed: context.projectConfig,\n authoredHere: await this.readAuthoredHere(context.projectConfig, editRoot.dir),\n // The ids the decode above could not place. They are the skips just reported, read as\n // what STAYS rather than as what did not arrive: the payload named them, so their absence\n // from the decode is this catalogue's limit and not an instruction to delete anything.\n unplaceable: new Set(skippedSkillIds),\n });\n\n return {\n producer: \"shared\",\n result: reconciled.result,\n kept: keptStatements(reconciled.kept),\n carried,\n };\n }\n\n /**\n * Which installed skills the round trip does not own, asked of the disk exactly as the\n * producing half asks it.\n *\n * Best-effort by nature and never fatal: the question is only ever asked to PROTECT a skill,\n * so a directory that cannot be read protects nothing and must not fail an apply. The\n * consequence of an unanswered question is that the entry is treated as the CLI's own, which\n * is what every other command already assumes about it.\n */\n private async readAuthoredHere(\n projectConfig: ProjectConfig | null,\n editRoot: string,\n ): Promise<Set<SkillId>> {\n if (!projectConfig) return new Set();\n\n try {\n return await skillsAuthoredHere(projectConfig, editRoot);\n } catch (error) {\n this.warn(`Could not tell which skills were written here: ${getErrorMessage(error)}`);\n return new Set();\n }\n }\n\n /**\n * The id, fetched — or the run refused before it is.\n *\n * The terminal question is answered first because nothing in the payload can change its\n * answer: an apply that cannot be confirmed is over before the store is asked, and a refusal\n * that had already spent a round trip would be describing work it never intended to do.\n */\n private async fetchSharedConfigOrFail(id: string): Promise<SeedPayload> {\n if (!process.stdin.isTTY) {\n this.error(sharedConfigNeedsTerminal(id), { exit: EXIT_CODES.ERROR });\n }\n\n this.log(`Fetching configuration ${id}...`);\n const fetched = await fetchSeedConfig(id);\n if (!fetched.ok) {\n this.error(fetched.error, { exit: EXIT_CODES.ERROR });\n }\n\n return fetched.payload;\n }\n\n /**\n * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).\n * That is a failure of this command, reported with this command's exit code rather than left to\n * surface as an unhandled throw.\n */\n private decodeSeedOrFail(payload: SeedPayload, sourceMatrix: MergedSkillsMatrix): SeedMapping {\n try {\n return seedToWizardResult(payload, sourceMatrix);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Seats the catalogue entries the payload carries with it, or refuses the run. The refusal is\n * `registerExternalSkills`' own — a carried skill asked for as a plugin, which no marketplace\n * serves — reported with this command's exit code for the same reason the decode's is.\n */\n private registerExternalSkillsOrFail(\n payload: SeedPayload,\n sourceMatrix: MergedSkillsMatrix,\n projectDir: string,\n ): ExternalSkillInstall[] {\n try {\n return registerExternalSkills(payload, sourceMatrix, projectDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /** Writes the skills the configuration brought with it, and says which they were. */\n private async writeCarriedSkills(carried: ExternalSkillInstall[]): Promise<void> {\n if (carried.length === 0) return;\n\n await writeExternalSkills(carried);\n this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));\n }\n\n /**\n * Shows what applying this configuration takes away, and stops the run unless a person says\n * yes.\n *\n * The plan is built from the SAME `ConfigChanges` the apply below acts on, so what is approved\n * and what is removed are one value read twice. Its kept half is the other side of the same\n * honesty: nothing is refused over an entry this run cannot remove, and nothing is silent\n * about one either.\n *\n * WHICH plan is built is decided here and only here, on the directory the run was started in.\n * Inside the global installation the scope was chosen and is obvious, so the ordinary confirm\n * is the whole of the gate; inside a project a global removal reaches projects nobody here is\n * looking at, so it is shown apart and the reach is named.\n */\n private async confirmSharedConfigOrCancel(\n changes: ConfigChanges,\n kept: string[],\n installed: InstalledEntries,\n editRoot: EditRoot,\n ): Promise<void> {\n const plan = editRoot.isGlobal\n ? globalScopePlan(changes, kept)\n : projectScopePlan(\n changes,\n kept,\n installed,\n await this.otherRegisteredProjects(editRoot.dir),\n );\n\n const outcome = await promptConfirm(({ onConfirm, onCancel }) => (\n <RemovalPlanConfirm\n heading={plan.heading}\n sections={plan.sections}\n statements={plan.statements}\n message={SHARED_CONFIG_APPLY.CONFIRM}\n onConfirm={onConfirm}\n onCancel={onCancel}\n />\n ));\n if (outcome === \"confirmed\") return;\n\n this.log(\"\\nEdit cancelled\");\n this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n }\n\n /**\n * Every registered project but this one — the blast radius a global removal actually has.\n *\n * Read from the GLOBAL config rather than from `context.projectConfig`: `projects[]` is the\n * registry the fan-out itself walks, and a project's own config never carries it, so taking\n * the list from anywhere else would let the confirm name a set the propagation does not.\n *\n * Best-effort by nature. The list exists to be DISCLOSED, so a home directory that cannot be\n * read leaves the disclosure counting nobody rather than failing an apply — and the statement\n * it produces then is the one that says no other project is registered.\n */\n private async otherRegisteredProjects(editRoot: string): Promise<string[]> {\n try {\n const global = await loadProjectConfigFromDir(os.homedir());\n const here = normalizeProjectPath(editRoot);\n return (global?.config.projects ?? []).filter((projectDir) => projectDir !== here);\n } catch (error) {\n this.warn(`Could not tell which projects share this install: ${getErrorMessage(error)}`);\n return [];\n }\n }\n\n /**\n * The outbound half of the editor round trip: this installation, minted as a configuration\n * the editor opens, and handed to a browser.\n *\n * It is the same mint `share` performs — same reader, same mapping, same refusals, through\n * `seedPayloadForInstallation` — because an id is the whole of what either command produces\n * and two spellings of \"the installation in this directory\" would mint two different ids for\n * one project. What differs is only the ending: `share` reports the id, this opens it.\n *\n * Nothing on disk is touched. A configuration is read, not rewritten, so a run that changed\n * anything here would be editing the project on the way to offering to edit it.\n */\n private async openInEditor(projectDir: string): Promise<void> {\n const prepared = await seedPayloadForInstallation(projectDir);\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.log(`Opening ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n const published = await publishSeedConfig(prepared.payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n await this.handToBrowser(published.id);\n }\n\n /**\n * The link, printed first and opened second.\n *\n * Printed first because it is the only part of this that works everywhere: over a pipe, in CI\n * and on a machine with no desktop session there is no browser to be anybody's, and a link\n * nobody can copy is the whole loss. Opening one is the convenience on top, so a failure to\n * open is a warning beside a link that still works rather than a failed command.\n *\n * `process.stdin.isTTY` is the same question `init`'s dashboard asks before it offers a\n * prompt — is there a person here — because that is exactly what \"whose browser is this\"\n * means.\n */\n private async handToBrowser(id: string): Promise<void> {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n\n if (!process.stdin.isTTY) return;\n\n const opened = await openUrl(editorConfigUrl(id));\n if (!opened.ok) this.warn(opened.error);\n }\n\n /**\n * The load below, behind a spinner that comes down whichever way the await ends.\n *\n * The cleanup is a `finally` because all three of `loadContext`'s refusals are raised\n * while this spinner is mounted, and oclif would otherwise paint its error under an Ink\n * tree still repainting over it. Never a `catch`: the throw reaches oclif untouched, or\n * both the error rendering and the pinned exit codes change with it.\n */\n private async loadContextUnderSpinner(): Promise<EditContext> {\n const { unmount, clear: clearSpinner } = render(\n <Spinner label={STATUS_MESSAGES.LOADING_SKILLS} />,\n );\n try {\n return await this.loadContext();\n } finally {\n clearSpinner();\n unmount();\n }\n }\n\n private async loadContext(): Promise<EditContext> {\n const detected = await detectProject();\n if (!detected) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n const { installation, config: projectConfig } = detected;\n\n // The detected installation's own root, which is what this run READS: the source it stored,\n // and the plugins registered against it. Every WRITE goes to `EditRoot.dir` instead, and the\n // two are the same directory unless `--project-setup` is promoting this one to a project.\n const projectDir = installation.projectDir;\n\n let sourceResult: SourceLoadResult;\n let startupMessages: StartupMessage[] = [];\n try {\n // No source is named here: `edit` reads the one the installation stored.\n const loaded = await loadSource({ projectDir, captureStartupMessages: true });\n sourceResult = loaded.sourceResult;\n startupMessages = loaded.startupMessages;\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n startupMessages.push({\n level: \"info\",\n text: `Loaded ${Object.keys(matrix.skills).length} skills (${sourceInfo})`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n let currentSkillIds: SkillId[];\n try {\n const discoveredSkills = await discoverAllPluginSkills(projectDir);\n const pluginSkillIds = typedKeys(discoveredSkills);\n\n // Merge plugin-discovered skills with config skills (catches local skills and\n // global-scoped plugins that discoverAllPluginSkills doesn't find).\n // Exclude skills marked as excluded — they should not appear as selected in the build step.\n // They are still preserved in skillConfigs via installedSkillConfigs for info panel/confirm step.\n const excludedConfigIds = new Set(\n projectConfig?.skills.filter((s) => s.excluded).map((s) => s.id) ?? [],\n );\n const configSkillIds =\n projectConfig?.skills.filter((s) => !s.excluded).map((s) => s.id) ?? [];\n const filteredPluginSkillIds = pluginSkillIds.filter((id) => !excludedConfigIds.has(id));\n const mergedIds = new Set<SkillId>([...filteredPluginSkillIds, ...configSkillIds]);\n currentSkillIds = [...mergedIds];\n\n startupMessages.push({\n level: \"info\",\n text: `Found ${currentSkillIds.length} installed skills`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n return {\n installation,\n projectConfig,\n projectDir,\n sourceResult,\n startupMessages,\n currentSkillIds,\n };\n }\n\n private async runEditWizard(\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<WizardResultV2 | null> {\n const { projectConfig, currentSkillIds } = context;\n const selectedAgents = projectConfig?.agents && activeAgentNames(projectConfig.agents);\n\n return runWizardSession({\n hydrate: {\n initialStep: \"build\",\n ...(projectConfig?.selectedDomains !== undefined && {\n initialDomains: projectConfig.selectedDomains,\n }),\n ...(selectedAgents !== undefined && { initialAgents: selectedAgents }),\n installedSkillIds: currentSkillIds,\n ...(projectConfig?.skills !== undefined && { installedSkillConfigs: projectConfig.skills }),\n ...(projectConfig?.agents !== undefined && { installedAgentConfigs: projectConfig.agents }),\n isEditingFromGlobalScope: editRoot.isGlobal,\n },\n props: {\n version: this.config.version,\n initialAgents: selectedAgents,\n installedSkillIds: currentSkillIds,\n startupMessages: context.startupMessages,\n },\n onCancel: () => this.log(\"\\nEdit cancelled\"),\n clearTerminal: () => this.clearTerminal(),\n });\n }\n\n /**\n * Records, in the GLOBAL config, the install-mode migrations this run already performed\n * under `$HOME`.\n *\n * A project-context edit otherwise never writes global config (commit 403df46, \"never\n * modify global config from project-level operations\"), and `authoritativeScope: \"owned\"`\n * enforces that for the roster — an inherited global-active entry is read-only, so\n * `mergeGlobalConfigs` preserves it verbatim. That protection is correct for selection and\n * scope, but `executeMigration` resolves each skill's paths from ITS OWN scope: switching a\n * global-scoped skill's source has already copied it under `$HOME` (or deleted it) and\n * added/removed its user-scope plugin registration by the time the config is written.\n * Leaving the global config alone there protects nothing — it only makes the recorded\n * source contradict the filesystem and the plugin registry.\n *\n * So authority follows the work actually performed, and no further: only ids\n * `executeMigration` acted on this run are rewritten, and only their `origin` field. Global\n * entries this session merely displayed, re-scoped or deselected are untouched, as are\n * `marketplace`, `stack`, `agents` and every other registered project's view of them.\n *\n * Driving a global-scope migration from a project directory is NOT a supported flow, and this\n * method is no longer the thing that permits it. The wizard now refuses it at source: the two\n * bulk install-mode keys are withdrawn, and `setInstallMode` ignores a project-context call\n * against a global slot the hydration snapshot owns — the same authority the Sources grid\n * already enforced by rendering that row inert. What still reaches here is the residue that\n * authority leaves legitimate: a mode change committed on the project half of a `[P][G]` pair\n * and then carried to global scope by a P->G collapse (`s`) in the same session. The entry is\n * the project's own to configure at the moment it is configured, and global at the moment it\n * is written — so the migration is real, and the global config must record it.\n *\n * Runs BEFORE `writeConfigAndCompile`, so the global config written here is the one\n * the wizard write reloads, keeps (existing wins in `mergeGlobalConfigs`) and inlines\n * into the project config — both files then tell the same story. That second write\n * classifies as a no-op against what this one left on disk, so the fan-out below\n * happens once.\n *\n * The migrated `origin` decides the reference form a compiled agent emits, so every\n * OTHER registered project's config and agents are stale until this write fans out —\n * which is why it goes through the gate rather than straight to the file.\n */\n private async recordGlobalSourceMigrations(\n migratedSkillIds: Set<SkillId>,\n newSkills: SkillConfig[],\n editRoot: EditRoot,\n context: EditContext,\n ): Promise<void> {\n // A global-context edit writes the whole global config from the wizard result already.\n if (editRoot.isGlobal) return;\n\n const migratedSources = new Map(\n newSkills\n .filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, \"global\"))\n .map((s) => [s.id, s.origin] as const),\n );\n if (migratedSources.size === 0) return;\n\n try {\n const report = await mutateGlobal(\n { kind: \"migrate-skill-sources\", sources: migratedSources },\n {\n // The deps contract in config-gate/deps.ts declares\n // `() => Promise<MergedSkillsMatrix>`; this caller happens to have its\n // matrix in hand already.\n // eslint-disable-next-line @typescript-eslint/require-await -- deps contract\n loadMatrix: async () => context.sourceResult.matrix,\n loadAgents: async () => (await loadAgentDefs()).agents,\n },\n );\n this.reportPropagatedRecompile(report);\n } catch (error) {\n // The migration itself already happened — the skill has been copied under $HOME or had\n // its user-scope registration moved. Only the record of it failed, so the disk and the\n // global config now describe different installations and nothing downstream will notice.\n this.reportIncompleteWork(\n `Could not record global origin change: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private logChangeSummary(\n changes: ConfigChanges,\n newSkills: SkillConfig[],\n oldSkills: SkillConfig[],\n removalReasons: ReadonlyMap<SkillId, string>,\n ): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n dualScopeSkillTransitions,\n dualScopeAgentTransitions,\n } = changes;\n\n this.log(`\\n${chalk.hex(CLI_COLORS.WHITE).bold(\"Changes:\")}`);\n for (const skillId of addedSkills) {\n const scope = newSkills.find((s) => s.id === skillId)?.scope;\n const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : \"\";\n this.log(\n chalk.hex(CLI_COLORS.SUCCESS)(` + ${getSkillById(skillId).displayName}${scopeLabel}`),\n );\n }\n for (const skillId of removedSkills) {\n const scope = oldSkills.find((s) => s.id === skillId)?.scope;\n const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : \"\";\n const reason = removalReasons.get(skillId);\n this.log(\n chalk.hex(CLI_COLORS.ERROR)(` - ${getSkillDisplayName(skillId)}${scopeLabel}`) +\n (reason ? chalk.hex(CLI_COLORS.NEUTRAL)(` (${reason})`) : \"\"),\n );\n }\n for (const agentName of addedAgents) {\n this.log(\n chalk.hex(CLI_COLORS.SUCCESS)(` + ${agentName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\"),\n );\n }\n for (const agentName of removedAgents) {\n this.log(\n chalk.hex(CLI_COLORS.ERROR)(` - ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\"),\n );\n }\n for (const [skillId, change] of sourceChanges) {\n const displayName = getSkillDisplayName(skillId);\n const fromLabel = formatSourceDisplayName(change.from);\n const toLabel = formatSourceDisplayName(change.to);\n this.log(\n chalk.hex(CLI_COLORS.WARNING)(` ~ ${displayName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(` (${fromLabel} \\u2192 ${toLabel})`),\n );\n }\n for (const [skillId, change] of scopeChanges) {\n this.log(formatSkillScopeChangeLine(skillId, change, dualScopeSkillTransitions));\n }\n for (const [agentName, change] of agentScopeChanges) {\n this.log(formatAgentScopeChangeLine(agentName, change, dualScopeAgentTransitions));\n }\n this.log(\"\");\n }\n\n private async applyMigrations(\n _changes: ConfigChanges,\n filteredResult: WizardResultV2,\n activeOldSkills: SkillConfig[],\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<Set<SkillId>> {\n const migrationPlan = detectMigrations(activeOldSkills, filteredResult.skills);\n const migratedSkillIds = new Set([\n ...migrationPlan.toEject.map((m) => m.id),\n ...migrationPlan.toPlugin.map((m) => m.id),\n ]);\n if (migratedSkillIds.size === 0) return migratedSkillIds;\n\n if (migrationPlan.toEject.length > 0) {\n this.logModeSwitch(migrationPlan.toEject.length, INSTALL_MODE_DESCRIPTIONS.eject);\n }\n if (migrationPlan.toPlugin.length > 0) {\n this.logModeSwitch(migrationPlan.toPlugin.length, INSTALL_MODE_DESCRIPTIONS.plugin);\n // Installing a plugin needs the marketplace REGISTERED and up to date with the\n // Claude CLI — the same precondition `applyPluginChanges` and `applyScopeChanges`\n // establish. Without it `claude plugin install` rejects every ref against a stale\n // local copy. Runs before `executeMigration` so an unresolvable marketplace exits\n // while the ejected working copies are still intact. Eject-side plugin uninstalls\n // are diagnostic-only, so only plugin-install work demands this.\n await this.requireMarketplaceOrExit(context.sourceResult, \"migrate skills to plugin mode\");\n // The install itself happens inside `executeMigration`, which deletes each skill's\n // working copy the moment that skill's plugin is registered — so the banner is\n // announced here and the outcome reported below, through the same surface `init`\n // and the newly-added-skill path narrate an install with.\n this.announcePluginInstall();\n }\n\n const migrationResult = await executeMigration(\n migrationPlan,\n editRoot.dir,\n context.sourceResult,\n );\n\n for (const warning of migrationResult.warnings) {\n this.warn(warning);\n }\n\n // Reports what was copied and hard-errors on any failure, for the reason the plugin\n // direction does below: a skill whose local copy could not be written must not reach\n // `recordGlobalSourceMigrations` or `writeConfigAndCompile`, either of which would\n // persist `origin: \"eject\"` for a skill that has no copy on disk.\n if (migrationPlan.toEject.length > 0) {\n this.reportEjectCopies(migrationResult.ejectCopies);\n }\n\n // Reports what was installed and hard-errors on any failure: a migration whose\n // plugin could not be installed must not reach `recordGlobalSourceMigrations` or\n // `writeConfigAndCompile`, either of which would persist a marketplace `origin`\n // for a skill with no plugin registration.\n if (migrationPlan.toPlugin.length > 0) {\n this.reportPluginInstalls(migrationResult.pluginInstalls);\n }\n\n return migratedSkillIds;\n }\n\n /**\n * What the plugin→eject half copied, what it could not, and the refusal to continue past\n * a failure.\n *\n * The shape of `BaseCommand.reportPluginInstalls`, deliberately: the two directions of one\n * mode switch owe the user the same account, and the eject half having no structured\n * failure at all is what let a config record `origin: \"eject\"` for a skill whose copy was\n * refused. It stays private because `edit` is the only command that migrates a mode —\n * `init` installs, and has no old state to move.\n *\n * The count line is the same one `copyNewLocalSkills` prints, and names no destination:\n * the migration splits its copies between the project and $HOME by each skill's own scope,\n * so one directory would misname the other half.\n */\n private reportEjectCopies(result: EjectCopyResult): void {\n for (const item of result.failed) {\n this.warn(`Failed to copy ${item.id} for eject: ${item.error}`);\n }\n if (result.failed.length > 0) {\n this.error(ejectCopyFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });\n }\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));\n }\n\n /** Names what this run is switching, in the words `init` describes an install mode with. */\n private logModeSwitch(count: number, modeDescription: string): void {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));\n }\n\n private async applyScopeChanges(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { scopeChanges } = changes;\n\n // Handle scope migrations (P->G or G->P) for eject-mode skills\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = filteredResult.skills.find((s) => s.id === skillId);\n if (skillConfig?.origin === EJECT_SOURCE) {\n await migrateLocalSkillScope(skillId, change.from, editRoot.dir);\n }\n }\n\n // Plugin scope migrations require a marketplace.\n // Compute eligible migrations first; only resolve/demand marketplace when there are any.\n const hasPluginScopeChanges = [...scopeChanges.keys()].some((skillId) => {\n const skillConfig = filteredResult.skills.find((s) => s.id === skillId);\n return skillConfig && skillConfig.origin !== EJECT_SOURCE;\n });\n if (!hasPluginScopeChanges) return;\n\n const marketplace = await this.requireMarketplaceOrExit(\n context.sourceResult,\n \"migrate plugin skill scopes\",\n );\n\n const pluginScopeResult = await migratePluginSkillScopes(\n scopeChanges,\n filteredResult.skills,\n marketplace,\n editRoot.dir,\n );\n // A scope migration INSTALLS the plugin at its new scope, so a failure here is not the\n // diagnostic an uninstall failure is: the skill is registered at neither scope while the\n // config is about to record the new one.\n for (const item of pluginScopeResult.failed) {\n this.reportIncompleteWork(\n `Failed to migrate plugin scope for ${item.id}: ${item.error}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private async applySourceChanges(\n changes: ConfigChanges,\n activeOldSkills: SkillConfig[],\n editRoot: EditRoot,\n migratedSkillIds: Set<SkillId>,\n ): Promise<void> {\n const { sourceChanges } = changes;\n\n // Handle remaining non-migration source changes (e.g., marketplace A -> marketplace B)\n for (const [skillId, change] of sourceChanges) {\n // Skip skills already handled by mode migration\n if (migratedSkillIds.has(skillId)) {\n continue;\n }\n if (change.from === EJECT_SOURCE) {\n const oldSkill = activeOldSkills.find((s) => s.id === skillId);\n const deleteDir = installBaseDir(editRoot.dir, oldSkill?.scope);\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n }\n\n private async applyPluginChanges(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n activeOldSkills: SkillConfig[],\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { addedSkills, removedSkills } = changes;\n\n // Compute plugin-intent lists per-skill (ungated) — per-skill `origin` drives install mode.\n const addedPluginSkills = filteredResult.skills.filter(\n (s) => addedSkills.includes(s.id) && s.origin !== EJECT_SOURCE,\n );\n const removedPluginSkills = removedSkills.filter(\n (id) => activeOldSkills.find((s) => s.id === id)?.origin !== EJECT_SOURCE,\n );\n\n if (addedPluginSkills.length === 0 && removedPluginSkills.length === 0) return;\n\n const marketplace = await this.requireMarketplaceOrExit(\n context.sourceResult,\n \"install or uninstall plugin skills\",\n );\n\n if (addedPluginSkills.length > 0) {\n await this.installPluginSkillsReported(\n addedPluginSkills,\n marketplace,\n editRoot.dir,\n context.sourceResult.matrix,\n );\n }\n\n if (removedPluginSkills.length > 0) {\n const uninstallResult = await uninstallPluginSkills(\n removedPluginSkills,\n activeOldSkills,\n marketplace,\n editRoot.dir,\n );\n if (uninstallResult.uninstalled.length > 0) {\n this.log(\n chalk.hex(CLI_COLORS.NEUTRAL)(`Removed ${uninstallResult.uninstalled.length} plugin(s)`),\n );\n }\n for (const item of uninstallResult.failed) {\n this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);\n }\n }\n }\n\n private async copyNewLocalSkills(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { addedSkills } = changes;\n\n // Copy newly added local-source skills to .claude/skills/ (split by scope)\n const addedLocalSkills = filteredResult.skills.filter(\n (s) => addedSkills.includes(s.id) && s.origin === EJECT_SOURCE,\n );\n\n if (addedLocalSkills.length > 0) {\n const copyResult = await copyLocalSkills(\n addedLocalSkills,\n editRoot.dir,\n context.sourceResult,\n );\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(copyResult.totalCopied)));\n }\n }\n\n private async removeDeletedLocalSkills(\n changes: ConfigChanges,\n activeOldSkills: SkillConfig[],\n editRoot: EditRoot,\n ): Promise<void> {\n const { removedSkills } = changes;\n\n // A fully-deselected eject-mode skill is a genuine uninstall — its copied directory under\n // .claude/skills/<id>/ must be removed from the scope it was installed at. Plugin\n // removals are handled by applyPluginChanges; source-change (eject->marketplace) deletions by\n // applySourceChanges. deleteLocalSkill is a no-op when the directory is absent.\n for (const skillId of removedSkills) {\n const oldSkill = activeOldSkills.find((s) => s.id === skillId);\n if (oldSkill?.origin !== EJECT_SOURCE) continue;\n\n const deleteDir = installBaseDir(editRoot.dir, oldSkill.scope);\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n authority: AuthoritativeScope,\n ): Promise<void> {\n // Load agent definitions — needed for both config-types.ts and recompilation\n let agentDefsResult: AgentDefs;\n try {\n agentDefsResult = await loadAgentDefs();\n } catch (error) {\n this.handleError(error);\n }\n\n // Persist wizard result to config.ts and config-types.ts (split by scope when in project context)\n //\n // A failed write is fatal, not a warning. Every mutation this run made — plugin\n // registrations, ejected copies, deleted working copies — has already landed on disk,\n // and config.ts is the only record of what they were for. Continuing past it into the\n // agent recompile left the registry, the config and `.claude/agents/` mutually\n // inconsistent and still reported success, which is the same silent-substitution defect\n // the plugin install path refuses.\n let configResult: ConfigWriteResult;\n try {\n configResult = await writeProjectConfig({\n wizardResult: result,\n sourceResult: context.sourceResult,\n projectDir: editRoot.dir,\n agentDefs: agentDefsResult,\n // A full `cc edit` pass is authoritative over the roster it owns, so deselected entries\n // are removed rather than union-preserved. `applyAuthority` decides\n // how much that is from the producer and the directory, and hands the same word to the\n // merger and to the global config the project branch of the gate commits.\n authoritativeScope: authority,\n });\n } catch (error) {\n this.error(`Could not update config: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n this.reportUnassignedSkills(configResult.config);\n\n try {\n const agentScopeMap = activeAgentScopeMap(result.agentConfigs);\n const { allSkills } = await discoverInstalledSkills(editRoot.dir);\n const compilationResult = await compileAgentsAllScopes({\n projectDir: editRoot.dir,\n sourcePath: agentDefsResult.sourcePath,\n skills: allSkills,\n agentScopeMap,\n });\n\n const { compiled, rewritten, failed, warnings } = compilationResult;\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n RECOMPILE_SUBJECT,\n );\n\n if (failed.length > 0) {\n this.log(\n chalk.hex(CLI_COLORS.NEUTRAL)(summary) +\n chalk.hex(CLI_COLORS.WARNING)(` (${failed.length} failed)`),\n );\n for (const warning of warnings) {\n this.warn(warning);\n }\n // Recorded off `failed` rather than off the warnings just printed: `warnings` also\n // carries entries that are not failures — a scope with nothing to compile contributes\n // one on every project-context run — and the ending must not file those as work owed.\n this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);\n } else if (compiled.length > 0) {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(summary));\n } else {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE));\n }\n } catch (error) {\n // The config write above has already landed, and the recompile is the last step — so\n // there is nothing left to abort into. What is wrong is the silence: `.claude/agents/`\n // now describes the roster this edit replaced, and the run used to report success over it.\n this.reportIncompleteWork(\n `Agent recompilation failed: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.RECOMPILE,\n );\n this.log(`You can manually recompile with '${CLI_INVOKE_COMMAND} compile'.`);\n }\n\n this.reportPropagatedRecompile(configResult.propagation);\n }\n\n private async cleanupStaleAgentFiles(\n changes: ConfigChanges,\n oldAgents: AgentScopeConfig[],\n editRoot: EditRoot,\n ): Promise<void> {\n for (const removal of planStaleAgentRemovals(changes, oldAgents, editRoot.dir)) {\n const { failed } = await removeCompiledAgents(removal);\n\n // A compiled sub-agent this project no longer configures is still a sub-agent Claude Code\n // loads, so a removal that did not happen is a roster the edit did not actually change.\n for (const { name, error } of failed) {\n const agentPath = path.join(removal.agentsDir, `${name}.md`);\n this.reportIncompleteWork(\n `Could not remove agent file ${agentPath}: ${error}`,\n INCOMPLETE_WORK_RECOVERY.DELETE_AGENT_FILE,\n );\n }\n }\n }\n\n private logCompletionSummary(_changes: ConfigChanges): void {\n // A run with work owed ends on the account below instead \\u2014 a tick over a partial apply is\n // the claim being withdrawn here, not an extra line beside it.\n if (this.hasIncompleteWork) return;\n\n this.log(`\\n${chalk.hex(CLI_COLORS.SUCCESS)(\"\\u2713 Done\")}\\n`);\n }\n}\n\n/** @internal Exported for testing */\nexport type ConfigChanges = {\n addedSkills: SkillId[];\n removedSkills: SkillId[];\n addedAgents: AgentName[];\n removedAgents: AgentName[];\n sourceChanges: Map<SkillId, { from: string; to: string }>;\n scopeChanges: Map<SkillId, ScopeChange>;\n agentScopeChanges: Map<AgentName, ScopeChange>;\n /**\n * Skill ids whose `scopeChanges` entry is a dual-scope add/remove — the project\n * half of a `[P][G]` pair was toggled while the global half persists — NOT a true\n * single-entry migration. The disk-side scope work still flows through\n * `scopeChanges`; this set only steers the completion-summary display so a\n * dual-scope addition is not misreported as a `[G] → [P]` migration.\n */\n dualScopeSkillTransitions: Set<SkillId>;\n /** Agent equivalent of `dualScopeSkillTransitions`. */\n dualScopeAgentTransitions: Set<AgentName>;\n};\n\n/** Full (tombstone-inclusive) entry lists used to classify dual-scope transitions. */\ntype FullScopeEntries = {\n newSkills: SkillConfig[];\n oldSkills: SkillConfig[];\n newAgents: AgentScopeConfig[];\n oldAgents: AgentScopeConfig[];\n};\n\n/**\n * @internal Exported for testing\n *\n * `oldConfig` / `wizardResult` carry the ACTIVE (tombstone-filtered) entries used\n * for add/remove/source/scope diffing. `fullEntries`, when provided, carries the\n * unfiltered lists (including excluded tombstones) used ONLY to tell a genuine\n * scope migration apart from a dual-scope add/remove. When omitted, every scope\n * change is treated as a migration (the pre-dual-scope behaviour).\n */\nexport function detectConfigChanges(\n oldConfig: ProjectConfig | null,\n wizardResult: WizardResultV2,\n fullEntries?: FullScopeEntries,\n): ConfigChanges {\n const oldSkillIds = oldConfig?.skills.map((s) => s.id) ?? [];\n const newSkillIds = wizardResult.skills.map((s) => s.id);\n const oldAgentNames = oldConfig?.agents.map((a) => a.name) ?? [];\n const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);\n\n const oldSkillsById = indexBy(oldConfig?.skills ?? [], (s) => s.id);\n const oldAgentsByName = indexBy(oldConfig?.agents ?? [], (a) => a.name);\n\n const scopeChanges = detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.scope,\n );\n const agentScopeChanges = detectPropertyChanges(\n wizardResult.agentConfigs,\n oldAgentsByName,\n (a) => a.name,\n (a) => a.scope,\n );\n\n return {\n addedSkills: difference(newSkillIds, oldSkillIds),\n removedSkills: difference(oldSkillIds, newSkillIds),\n addedAgents: difference(newAgentNames, oldAgentNames),\n removedAgents: difference(oldAgentNames, newAgentNames),\n sourceChanges: detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.origin,\n ),\n scopeChanges,\n agentScopeChanges,\n dualScopeSkillTransitions: detectDualScopeTransitions(\n scopeChanges,\n fullEntries?.newSkills ?? [],\n fullEntries?.oldSkills ?? [],\n (s) => s.id,\n ),\n dualScopeAgentTransitions: detectDualScopeTransitions(\n agentScopeChanges,\n fullEntries?.newAgents ?? [],\n fullEntries?.oldAgents ?? [],\n (a) => a.name,\n ),\n };\n}\n\nfunction detectPropertyChanges<T, K extends string, V>(\n newItems: T[],\n oldByKey: Record<string, T>,\n getKey: (item: T) => K,\n getValue: (item: T) => V,\n): Map<K, { from: V; to: V }> {\n const changes = new Map<K, { from: V; to: V }>();\n for (const item of newItems) {\n const key = getKey(item);\n const old = oldByKey[key];\n if (old && getValue(old) !== getValue(item)) {\n changes.set(key, { from: getValue(old), to: getValue(item) });\n }\n }\n return changes;\n}\n\n/**\n * A scope change is a dual-scope transition (not a migration) when the canonical\n * dual-scope tombstone — an excluded global entry — sits alongside it:\n * - G→P add: the NEW state keeps a global tombstone, so the global install\n * survives and the project half was merely added.\n * - P→G remove: the OLD state held a global tombstone, so the pair was already\n * dual-scope and the project half was merely removed.\n * Either way the item occupied both scopes, so `[X] → [Y]` would misdescribe it.\n */\nfunction detectDualScopeTransitions<\n K extends string,\n T extends { scope: SkillScope; excluded?: boolean },\n>(scopeChanges: Map<K, ScopeChange>, fullNew: T[], fullOld: T[], getKey: (item: T) => K): Set<K> {\n const hasGlobalTombstone = (items: T[], key: K): boolean =>\n items.some((item) => getKey(item) === key && item.scope === \"global\" && item.excluded === true);\n\n const result = new Set<K>();\n for (const [key, change] of scopeChanges) {\n if (change.from === \"global\" && change.to === \"project\" && hasGlobalTombstone(fullNew, key)) {\n result.add(key);\n } else if (\n change.from === \"project\" &&\n change.to === \"global\" &&\n hasGlobalTombstone(fullOld, key)\n ) {\n result.add(key);\n }\n }\n return result;\n}\n\ntype StaleAgent = { name: AgentName; scope: SkillScope };\n\n/** Every scope a stale compiled agent can be sitting at. */\nconst STALE_AGENT_SCOPES = [\"project\", \"global\"] as const satisfies readonly SkillScope[];\n\n/** The scope a deselected agent was installed at, for one absent from the old roster. */\nconst UNRECORDED_AGENT_SCOPE: SkillScope = \"project\";\n\nfunction installedScope(name: AgentName, oldAgents: AgentScopeConfig[]): SkillScope {\n return oldAgents.find((agent) => agent.name === name)?.scope ?? UNRECORDED_AGENT_SCOPE;\n}\n\n/**\n * The compiled files an edit leaves stale, one removal per scope directory that\n * holds any: the project copy a P→G move superseded, plus every deselected agent\n * at the scope it was installed at.\n *\n * G→P moves are absent deliberately — that direction is an override, so the global\n * installation stays untouched and the project copy shadows it. A scope with\n * nothing to remove is absent too: only a directory this edit actually removed\n * from is a directory this edit may tidy.\n */\nfunction planStaleAgentRemovals(\n changes: ConfigChanges,\n oldAgents: AgentScopeConfig[],\n editRoot: string,\n): RemoveCompiledAgentsOptions[] {\n const supersededByGlobal = [...changes.agentScopeChanges]\n .filter(([, change]) => change.from !== \"global\")\n .map(([name]): StaleAgent => ({ name, scope: \"project\" }));\n\n const deselected = changes.removedAgents.map((name): StaleAgent => ({\n name,\n scope: installedScope(name, oldAgents),\n }));\n\n const stale = [...supersededByGlobal, ...deselected];\n const removalAtScope = (scope: SkillScope): RemoveCompiledAgentsOptions => ({\n agentsDir: resolveInstallPaths(editRoot, scope).agentsDir,\n agents: stale.filter((agent) => agent.scope === scope).map((agent) => agent.name),\n });\n\n return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);\n}\n\nfunction hasAnyChanges(changes: ConfigChanges): boolean {\n return (\n changes.addedSkills.length > 0 ||\n changes.removedSkills.length > 0 ||\n changes.addedAgents.length > 0 ||\n changes.removedAgents.length > 0 ||\n changes.sourceChanges.size > 0 ||\n changes.scopeChanges.size > 0 ||\n changes.agentScopeChanges.size > 0\n );\n}\n\n/** @internal Exported for testing */\nexport type PluginScopeMigrationResult = {\n migrated: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\n/** @internal Exported for testing */\nexport async function migratePluginSkillScopes(\n scopeChanges: Map<SkillId, ScopeChange>,\n skills: Pick<SkillConfig, \"id\" | \"origin\">[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginScopeMigrationResult> {\n const migrated: SkillId[] = [];\n const failed: PluginScopeMigrationResult[\"failed\"] = [];\n\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = skills.find((s) => s.id === skillId);\n if (!skillConfig || skillConfig.origin === EJECT_SOURCE) {\n continue;\n }\n\n const newPluginScope = toClaudePluginScope(change.to);\n const pluginRef = buildMarketplacePluginRef(skillId, marketplace);\n\n try {\n // global→project: keep the global registration, just add project scope.\n // The global plugin must remain for other projects.\n // project→global: uninstall the project-scope registration, install global.\n if (change.from === \"project\") {\n await claudePluginUninstall(pluginRef, \"project\", projectDir);\n }\n await claudePluginInstall(pluginRef, newPluginScope, projectDir);\n migrated.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { migrated, failed };\n}\n","import { getCategoryDomain, matrix } from \"../matrix/matrix-provider.js\";\nimport { orderDomains } from \"../wizard/domain-order.js\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object.js\";\n\nimport type { WizardResultV2 } from \"../../components/wizard/wizard.js\";\nimport type { AgentName } from \"../../types/agents.js\";\nimport type { ProjectConfig, SkillConfig } from \"../../types/config.js\";\nimport type { Category, Domain } from \"../../types/matrix.js\";\nimport type { SkillAssignment, SkillId } from \"../../types/skills.js\";\nimport type { StackAgentConfig } from \"../../types/stacks.js\";\n\n/**\n * What applying a shared configuration here is not allowed to take away, split by the reason —\n * because the reasons have different remedies and only the user knows which they meant.\n */\nexport type KeptFromRoundTrip = {\n /** Written here rather than installed, so no shared configuration ever carried them. */\n authoredSkillIds: SkillId[];\n /** Named by the configuration and unplaceable by this catalogue, so nothing here applied. */\n unplaceableSkillIds: SkillId[];\n};\n\nexport type ReconciledSharedConfig = {\n /** The decoded payload with everything above put back into it. */\n result: WizardResultV2;\n kept: KeptFromRoundTrip;\n};\n\nexport type ReconcileOptions = {\n /** The payload as `seedToWizardResult` decoded it. */\n decoded: WizardResultV2;\n /** This directory's installation — its own config, or the global one it inherits. */\n installed: ProjectConfig | null;\n /** Ids outside the round trip, from `skillsAuthoredHere` — one definition, both halves. */\n authoredHere: ReadonlySet<SkillId>;\n /**\n * Ids the payload NAMED that the decode could not place — `SeedMapping.skippedSkillIds`,\n * which is why they are ids off the wire rather than `SkillId`s of this catalogue.\n *\n * Stated by the caller rather than recomputed here: the decode already answered it, and a\n * second derivation could disagree with the skips the same run reported.\n */\n unplaceable: ReadonlySet<string>;\n};\n\nconst NOTHING_KEPT: KeptFromRoundTrip = {\n authoredSkillIds: [],\n unplaceableSkillIds: [],\n};\n\n/**\n * Puts back what this run may not remove, so the destructive apply removes only what it may.\n *\n * `edit --from` makes the project MATCH the payload: a skill the previous configuration\n * installed and this one omits is removed. Two kinds of installed entry are outside that\n * authority, and each is outside it for its own reason.\n *\n * A skill written here, because `forkedFrom` decides ownership and the producer drops a\n * directory carrying none: the payload never named it, so reading its absence as an instruction\n * to delete it would be this command inventing an instruction nobody gave. And an id the payload\n * DID name that this catalogue could not place, because there the instruction exists and the run\n * failed to carry it out — a destructive command removes on intent, never on its own inability.\n *\n * SCOPE IS NOT ONE OF THEM, and this module therefore takes no authority word. A globally\n * installed entry is removable through `edit --from` from a project as well as from the home\n * directory: the removal is shown, a project run additionally names every other project it\n * reaches, and the user answers. What is protected here is only what a removal may never be\n * INFERRED from, and an entry's scope infers nothing — it decides who else a removal touches,\n * which is the confirm's subject rather than this one's.\n *\n * Both are put back into the RESULT rather than excused at the writer, and that is the whole\n * point of this module. `authoritativeScope` decides whether the merger preserves a config row;\n * it does not protect the files, because the removal DIFF is what drives the plugin uninstall\n * and the `deleteLocalSkill` call. An entry left in the removal set is deleted from disk\n * whatever the merger later does with its row.\n *\n * What comes back with an entry matters as much as the entry. A kept skill with no stack row is\n * installed and loaded by no sub-agent; a kept skill whose domain fell off `selectedDomains` is\n * hidden from the next wizard, deselected by not being shown, and deleted by the run after this\n * one — a removal this one promised not to make.\n */\nexport function reconcileSharedConfig(options: ReconcileOptions): ReconciledSharedConfig {\n const { decoded, installed } = options;\n if (!installed) return { result: decoded, kept: NOTHING_KEPT };\n\n const keptSkills = skillsToKeep(options, installed);\n if (keptSkills.length === 0) return { result: decoded, kept: NOTHING_KEPT };\n\n return {\n result: withKeptEntries(decoded, installed, keptSkills),\n kept: describeKept(options, keptSkills),\n };\n}\n\n/**\n * The installed skills this run has to leave alone: absent from what the payload placed here,\n * and immune to removal by authorship, or because this catalogue could not place the id the\n * payload named.\n *\n * A tombstone is neither. It is a statement about something that is NOT installed here, so\n * there are no files to protect and nothing to tell the user is staying.\n */\nfunction skillsToKeep(options: ReconcileOptions, installed: ProjectConfig): SkillConfig[] {\n const named = new Set(options.decoded.skills.map((skill) => skill.id));\n\n return installed.skills.filter(\n (skill) => !skill.excluded && !named.has(skill.id) && mayNotRemove(skill, options),\n );\n}\n\n/** Whether either reason covers this entry — the question the split below refines. */\nfunction mayNotRemove(skill: SkillConfig, options: ReconcileOptions): boolean {\n return options.authoredHere.has(skill.id) || options.unplaceable.has(skill.id);\n}\n\ntype KeptReason = \"authored\" | \"unplaceable\";\n\nfunction describeKept(options: ReconcileOptions, keptSkills: SkillConfig[]): KeptFromRoundTrip {\n const idsKeptFor = (reason: KeptReason): SkillId[] =>\n keptSkills.filter((skill) => reasonKept(skill, options) === reason).map((skill) => skill.id);\n\n return {\n authoredSkillIds: idsKeptFor(\"authored\"),\n unplaceableSkillIds: idsKeptFor(\"unplaceable\"),\n };\n}\n\n/**\n * Which of the two an entry is disclosed as, where both are true — judged from the more\n * permanent claim to the less, because each statement carries its own remedy and only the one\n * that is true of the whole entry is worth naming.\n *\n * A skill nobody installed cannot be removed by any shared configuration from anywhere. An id\n * this catalogue cannot place is inert only for as long as this installation reads this\n * catalogue, so `update` is a real way out of it and nothing is a way out of the other.\n */\nfunction reasonKept(skill: SkillConfig, options: ReconcileOptions): KeptReason {\n return options.authoredHere.has(skill.id) ? \"authored\" : \"unplaceable\";\n}\n\n/** The payload, plus the entries it was never entitled to speak about. */\nfunction withKeptEntries(\n decoded: WizardResultV2,\n installed: ProjectConfig,\n keptSkills: SkillConfig[],\n): WizardResultV2 {\n return {\n ...decoded,\n skills: [...decoded.skills, ...keptSkills],\n selectedDomains: withKeptDomains(decoded.selectedDomains, keptSkills),\n ...(decoded.assignedStack !== undefined && {\n assignedStack: withKeptStackRows(decoded.assignedStack, installed.stack, {\n keptSkillIds: new Set(keptSkills.map((skill) => skill.id)),\n survivingAgents: new Set(decoded.selectedAgents),\n }),\n }),\n };\n}\n\n/** The domains the payload chose, plus the ones its kept entries still need a tab for. */\nfunction withKeptDomains(selected: Domain[], keptSkills: SkillConfig[]): Domain[] {\n const keptDomains = keptSkills.flatMap((skill) => domainOfSkill(skill.id) ?? []);\n const missing = keptDomains.filter((domain) => !selected.includes(domain));\n if (missing.length === 0) return selected;\n\n return orderDomains([...selected, ...new Set(missing)]);\n}\n\n/**\n * A kept skill's domain, where this catalogue knows the skill. Optional by nature rather than by\n * caution: a config entry the loaded source cannot resolve has no category to place, and\n * `edit`'s own unresolvable-entry path is what speaks about those.\n */\nfunction domainOfSkill(skillId: SkillId): Domain | undefined {\n const category = matrix.skills[skillId]?.category;\n return category === undefined ? undefined : getCategoryDomain(category);\n}\n\ntype KeptRowFilter = {\n keptSkillIds: ReadonlySet<SkillId>;\n survivingAgents: ReadonlySet<AgentName>;\n};\n\n/**\n * The installed stack rows a kept skill needs, folded into the payload's own.\n *\n * `assignedStack` REPLACES the ownership-derived stack rather than merging with it, so a row\n * this reconcile does not carry is a row nothing downstream re-derives. A kept skill is kept\n * because the payload never spoke about it, and a row naming it is the same silence one layer\n * down — so the row the installation already had is the only statement there is about it.\n *\n * A row under a sub-agent this configuration removes is dropped with it. That sub-agent IS this\n * run's to remove, and a stack row naming one no configuration installs is what `compile` warns\n * about and leaves out of the agents it writes.\n */\nfunction withKeptStackRows(\n assigned: Partial<Record<AgentName, StackAgentConfig>>,\n installedStack: Partial<Record<AgentName, StackAgentConfig>> | undefined,\n filter: KeptRowFilter,\n): Partial<Record<AgentName, StackAgentConfig>> {\n if (!installedStack) return assigned;\n\n const carried = { ...assigned };\n for (const [agent, agentStack] of typedEntries<AgentName, StackAgentConfig>(installedStack)) {\n if (!filter.survivingAgents.has(agent)) continue;\n\n const rows = keptRowsFor(agentStack, filter.keptSkillIds);\n if (typedKeys(rows).length === 0) continue;\n\n carried[agent] = { ...carried[agent], ...rows };\n }\n return carried;\n}\n\n/** One sub-agent's rows that a kept skill accounts for, category by category. */\nfunction keptRowsFor(\n agentStack: StackAgentConfig,\n keptSkillIds: ReadonlySet<SkillId>,\n): StackAgentConfig {\n const rows: StackAgentConfig = {};\n for (const [category, assignments] of typedEntries<Category, SkillAssignment[]>(agentStack)) {\n const carried = assignments.filter((assignment) => keptSkillIds.has(assignment.id));\n if (carried.length > 0) rows[category] = carried;\n }\n return rows;\n}\n","import { execCommand } from \"./exec.js\";\nimport { getErrorMessage } from \"./errors.js\";\n\n/** The shell-out one platform answers \"open this with whatever handles it\" with. */\nexport type OpenerCommand = { command: string; args: string[] };\n\n/**\n * Never a throw. A machine with no browser, no desktop session or no opener at all is a\n * legitimate place to run this CLI, so failing to open a link is something to say rather than\n * something to fail on — the same posture the seed boundaries take, and for the same reason:\n * the link is already printed by the time this runs, so nothing is lost by it not working.\n */\nexport type OpenUrlResult = { ok: true } | { ok: false; error: string };\n\n/**\n * The command a platform opens a link with.\n *\n * There is no dependency for this. All three are one-line shell-outs to something the operating\n * system already ships, and a package for it would be a fourth thing to keep current for no\n * behaviour this does not have.\n *\n * Windows goes through `cmd` because `start` is a shell builtin rather than a program, and the\n * empty string after it is its TITLE argument: without one, `start` reads the first quoted\n * argument it is given as the window title and opens nothing.\n */\nexport function browserOpenerCommand(platform: NodeJS.Platform, url: string): OpenerCommand {\n if (platform === \"darwin\") return { command: \"open\", args: [url] };\n if (platform === \"win32\") return { command: \"cmd\", args: [\"/c\", \"start\", \"\", url] };\n return { command: \"xdg-open\", args: [url] };\n}\n\nfunction openerRefusedMessage(command: string, exitCode: number): string {\n return `Could not open your browser — '${command}' exited ${exitCode}.`;\n}\n\nfunction openerUnavailableMessage(command: string, reason: string): string {\n return `Could not open your browser — '${command}' could not be run: ${reason}`;\n}\n\n/**\n * Hands a link to whatever this platform opens links with.\n *\n * The URL travels as its own argument rather than inside a command line: `execCommand` spawns\n * without a shell, so the argument vector is the whole of the injection guard — there is no\n * string for a link to break out of.\n */\nexport async function openUrl(url: string): Promise<OpenUrlResult> {\n const { command, args } = browserOpenerCommand(process.platform, url);\n\n try {\n const result = await execCommand(command, args);\n if (result.exitCode !== 0) {\n return { ok: false, error: openerRefusedMessage(command, result.exitCode) };\n }\n return { ok: true };\n } catch (error) {\n return { ok: false, error: openerUnavailableMessage(command, getErrorMessage(error)) };\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/edit.tsx","../../src/cli/lib/seed/seed-apply.ts"],"sourcesContent":["import os from \"os\";\nimport path from \"path\";\n\nimport chalk from \"chalk\";\nimport { Flags } from \"@oclif/core\";\nimport { render } from \"../components/render.js\";\n\nimport { difference, indexBy, partition } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { runWizardSession } from \"../components/wizard/run-wizard-session.js\";\nimport {\n CLI_INVOKE_COMMAND,\n CLI_COLORS,\n EDIT_PROJECT_SETUP_FLAG,\n EJECT_SOURCE,\n editorConfigUrl,\n formatSourceDisplayName,\n} from \"../consts.js\";\nimport {\n detectProject,\n loadSource,\n copyLocalSkills,\n uninstallPluginSkills,\n loadAgentDefs,\n type AgentDefs,\n writeProjectConfig,\n type ConfigWriteResult,\n compileAgentsAllScopes,\n discoverInstalledSkills,\n removeCompiledAgents,\n type RemoveCompiledAgentsOptions,\n} from \"../lib/operations/index.js\";\nimport { Spinner } from \"../components/common/spinner.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n type EjectCopyResult,\n type Installation,\n detectMigrations,\n ejectCopyFailureError,\n executeMigration,\n isHomeDirectory,\n installBaseDir,\n resolveInstallPaths,\n INSTALL_MODE_DESCRIPTIONS,\n} from \"../lib/installation/index.js\";\nimport {\n applyMigratedGlobalSources,\n mutateGlobal,\n normalizeProjectPath,\n} from \"../lib/config-gate/index.js\";\nimport { matrix, getSkillById, getSkillDisplayName } from \"../lib/matrix/matrix-provider\";\nimport { type AuthoritativeScope, loadProjectConfigFromDir } from \"../lib/configuration/index.js\";\nimport {\n activeAgentNames,\n activeAgentScopeMap,\n isActiveAt,\n} from \"../lib/configuration/scope-predicates.js\";\nimport type { SourceLoadResult } from \"../lib/loading/index.js\";\nimport {\n discoverAllPluginSkills,\n buildMarketplacePluginRef,\n toClaudePluginScope,\n} from \"../lib/plugins/index.js\";\nimport {\n deleteLocalSkill,\n migrateLocalSkillScope,\n unresolvedSkillRemovalReasons,\n} from \"../lib/skills/index.js\";\nimport type {\n SkillId,\n SkillConfig,\n AgentName,\n AgentScopeConfig,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillScope,\n} from \"../types/index.js\";\nimport {\n seedPayloadForInstallation,\n skillsAuthoredHere,\n} from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport { fetchSeedConfig } from \"../lib/seed/fetch-seed.js\";\nimport {\n registerExternalSkills,\n writeExternalSkills,\n type ExternalSkillInstall,\n} from \"../lib/seed/external-skills.js\";\nimport { seedToWizardResult, type SeedMapping } from \"../lib/seed/seed-to-wizard.js\";\nimport { reconcileSharedConfig, type KeptFromRoundTrip } from \"../lib/seed/seed-apply.js\";\nimport {\n RemovalPlanConfirm,\n type RemovalPlanSection,\n} from \"../components/common/removal-plan-confirm.js\";\nimport { promptConfirm } from \"../components/common/prompt-confirm.js\";\nimport { claudePluginInstall, claudePluginUninstall } from \"../utils/exec.js\";\nimport { openUrl } from \"../utils/open-url.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport {\n INCOMPLETE_WORK_RECOVERY,\n ERROR_MESSAGES,\n INFO_MESSAGES,\n SHARED_CONFIG_APPLY,\n STATUS_MESSAGES,\n agentsNotCompiled,\n authoredHereKept,\n carriedSkillsWritten,\n globallyInstalledRemoved,\n localSkillsCopied,\n recompileSummary,\n sharedConfigDestinations,\n sharedConfigNeedsTerminal,\n skippedUnknownAgents,\n skippedUnknownSkills,\n unplaceableKept,\n} from \"../utils/messages.js\";\nimport { formatScopeTag } from \"../lib/wizard/index.js\";\nimport { typedKeys } from \"../utils/typed-object.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/** A scope transition (`from` → `to`) for a re-scoped skill or agent. */\ntype ScopeChange = { from: SkillScope; to: SkillScope };\n\n/**\n * The noun `edit`'s recompile summary counts in. `edit` recompiles every scope this\n * context owns in one pass, so it has no scope word to qualify with — `compile`,\n * which runs one scope at a time, does.\n */\nconst RECOMPILE_SUBJECT = \"agents\";\n\n/**\n * Dual-scope add/remove: the project half of a [P][G] pair was toggled while the\n * global half persists. Reported as a project-scope addition/removal; a\n * scope-change arrow line would falsely claim the global install moved.\n */\nfunction formatDualScopeTransition(displayName: string, to: SkillScope): string {\n const isAdd = to === \"project\";\n const prefix = isAdd ? \"+\" : \"-\";\n const color = isAdd ? CLI_COLORS.SUCCESS : CLI_COLORS.ERROR;\n return chalk.hex(color)(` ${prefix} ${displayName} [P]`);\n}\n\n/**\n * One re-scoped skill's line. A dual-scope toggle is the transition above rather than a\n * migration; a genuine `[G] → [P]` reads as an addition because the skill arrives in this\n * project, and every other direction is the amber `~` a move is written with.\n */\nfunction formatSkillScopeChangeLine(\n skillId: SkillId,\n change: ScopeChange,\n dualScopeSkillTransitions: ReadonlySet<SkillId>,\n): string {\n const displayName = getSkillDisplayName(skillId);\n if (dualScopeSkillTransitions.has(skillId)) {\n return formatDualScopeTransition(displayName, change.to);\n }\n\n const isGlobalToProject = change.from === \"global\" && change.to === \"project\";\n const prefix = isGlobalToProject ? \"+\" : \"~\";\n const color = isGlobalToProject ? CLI_COLORS.SUCCESS : CLI_COLORS.WARNING;\n return (\n chalk.hex(color)(` ${prefix} ${displayName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change))\n );\n}\n\n/**\n * The agent mirror of the line above, with two differences preserved from how this summary has\n * always read: there is no `[G] → [P]`-reads-as-addition arm — an agent that moves is a move —\n * and only the dual-scope arm carries the `(agent)` suffix, since a `~` line names no skill it\n * could be confused with.\n */\nfunction formatAgentScopeChangeLine(\n agentName: AgentName,\n change: ScopeChange,\n dualScopeAgentTransitions: ReadonlySet<AgentName>,\n): string {\n const agentSuffix = chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\");\n if (dualScopeAgentTransitions.has(agentName)) {\n return formatDualScopeTransition(agentName, change.to) + agentSuffix;\n }\n\n return (\n chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change))\n );\n}\n\n/** The ` ([P] → [G])` half both lines above end with, in the tags the wizard writes scopes as. */\nfunction scopeArrow(change: ScopeChange): string {\n return ` (${formatScopeTag(change.from)} \\u2192 ${formatScopeTag(change.to)})`;\n}\n\n/**\n * The name this session's catalogue answers to — what a marketplace-dropped entry's removal\n * reason says the skill is not present in. The resolved marketplace where there is one,\n * otherwise the source string itself, which is what an installation pointed at a source that\n * never carried the skill has to be named by.\n */\nfunction loadedSourceLabel(sourceResult: SourceLoadResult): string {\n return sourceResult.marketplace ?? sourceResult.sourceConfig.source;\n}\n\n/** @internal Re-exported for testing — the transform itself lives inside the gate. */\nexport { applyMigratedGlobalSources };\n\ntype EditContext = {\n installation: Installation;\n projectConfig: ProjectConfig | null;\n /** The detected installation's root — where this run READS its saved skills from. */\n projectDir: string;\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n currentSkillIds: SkillId[];\n};\n\n/**\n * The one directory an `edit` run acts on, and everything every layer needs to know about it.\n *\n * Six layers used to answer \"am I editing the global installation?\" for themselves, three of\n * them off the working directory, and they disagreed the moment the command was started\n * outside an install. Passing this value instead of a bare path is what makes them one\n * answer: a layer that wants a different one has to reach past the parameter it was handed.\n */\ntype EditRoot = {\n /** Where this run writes, registers plugins and compiles into. */\n dir: string;\n /**\n * True when {@link EditRoot.dir} IS the global installation, so there is no project scope to\n * offer.\n */\n isGlobal: boolean;\n /**\n * True when this run must materialise {@link EditRoot.dir} as a project even with nothing to\n * change.\n */\n isProjectSetup: boolean;\n};\n\n/**\n * Which installation this run is editing, decided once.\n *\n * `edit` names no directory. It edits the installation `detectProject` found, and that\n * installation's root is the only root that HAS a config to edit — so it is the only root\n * this run may write to. Reading the working directory instead made a project out of\n * whichever directory the command was started in: over a global-only install the wizard\n * offered the project/global scope toggle for a project that did not exist, and saving\n * wrote a `.claude-src/` pair into an unrelated checkout.\n *\n * `--project-setup` is an instance of that rule rather than an exception to it. It means the\n * user ran `cc init` HERE, which declares this directory the installation being set up, so\n * the config this run writes is what makes the claim true. At the home root there is nothing\n * to set up and both spellings name the same directory anyway, which is why the flag alone\n * picks the root and the resolved criterion decides whether anything is materialised.\n */\nfunction resolveEditRoot(\n installation: Installation,\n cwd: string,\n setupRequested: boolean,\n): EditRoot {\n const dir = setupRequested ? cwd : installation.projectDir;\n const isGlobal = isHomeDirectory(dir);\n return { dir, isGlobal, isProjectSetup: setupRequested && !isGlobal };\n}\n\n/**\n * What this run is about to apply, and which producer said so.\n *\n * The two produce the same `WizardResultV2` and are applied by the same sequence — that is what\n * stops `edit` growing a second copy of its own pipeline. They differ in what has to happen\n * between the diff and the first mutation: a wizard result was authored keystroke by keystroke\n * and needs no permission, while a shared configuration arrived whole and destroys whatever it\n * left out, so its removals are shown and confirmed there.\n */\ntype EditSelection =\n | { producer: \"wizard\"; result: WizardResultV2 }\n | {\n producer: \"shared\";\n result: WizardResultV2;\n /** Statements naming what this run may not remove — rendered in the confirm. */\n kept: string[];\n /** Skills the configuration carries rather than names, written once it is approved. */\n carried: ExternalSkillInstall[];\n };\n\n/** What a shared apply is confirmed against: one heading, the lists, and the prose under them. */\ntype SharedConfigPlan = {\n heading: string;\n sections: RemovalPlanSection[];\n statements: string[];\n};\n\n/** A removal set's two lists, whichever scope the entries in it were installed at. */\ntype RemovedEntries = { skills: SkillId[]; agents: AgentName[] };\n\n/** The removal set split by the scope each entry was actually installed at. */\ntype RemovalsByScope = { here: RemovedEntries; global: RemovedEntries };\n\n/** The entries this run is applying over, which is where a removal's scope is read from. */\ntype InstalledEntries = Pick<ProjectConfig, \"skills\" | \"agents\">;\n\n/**\n * The plan INSIDE the global installation: the ordinary one, and deliberately nothing more.\n *\n * The person ran this at their home directory. The location IS the global scope, they chose it,\n * and that global is inherited by every project is what global means — so a second\n * acknowledgement restates a fact the directory already states, and a gate that fires everywhere\n * is one nobody is still reading by the time it matters.\n */\nfunction globalScopePlan(changes: ConfigChanges, kept: string[]): SharedConfigPlan {\n const sections = removalSections(changes.removedSkills, changes.removedAgents);\n return { heading: planHeading(sections), sections, statements: kept };\n}\n\n/**\n * The plan INSIDE a project, where a removal can reach past the directory it was asked for in.\n *\n * A global install is one installation every registered project reads, so removing one here\n * changes projects the person confirming is not looking at. Those entries get their own section\n * and a statement counting and naming the projects the yes changes; everything else reads as it\n * always has. The split is on the entries' own scope rather than on wording, so the two confirms\n * stay two branches — one gate firing everywhere and explaining itself differently is how a gate\n * drifts into firing wrongly.\n */\nfunction projectScopePlan(\n changes: ConfigChanges,\n kept: string[],\n installed: InstalledEntries,\n otherProjects: string[],\n): SharedConfigPlan {\n const { here, global } = splitRemovalsByScope(changes, installed);\n const sections = [\n ...removalSections(here.skills, here.agents),\n ...globalRemovalSections(global.skills, global.agents),\n ];\n\n return {\n heading: planHeading(sections),\n sections,\n statements: [...globalReachStatement(global, otherProjects), ...kept],\n };\n}\n\n/** Which removals leave this project only, and which leave the machine. */\nfunction splitRemovalsByScope(\n changes: ConfigChanges,\n installed: InstalledEntries,\n): RemovalsByScope {\n const isGlobalSkill = (id: SkillId): boolean =>\n installed.skills.some((skill) => skill.id === id && isActiveAt(skill, \"global\"));\n const isGlobalAgent = (name: AgentName): boolean =>\n installed.agents.some((agent) => agent.name === name && isActiveAt(agent, \"global\"));\n\n const [globalSkills, projectSkills] = partition(changes.removedSkills, isGlobalSkill);\n const [globalAgents, projectAgents] = partition(changes.removedAgents, isGlobalAgent);\n\n return {\n here: { skills: projectSkills, agents: projectAgents },\n global: { skills: globalSkills, agents: globalAgents },\n };\n}\n\n/** The removals a shared configuration makes here, grouped as the plan prints them. */\nfunction removalSections(skills: SkillId[], agents: AgentName[]): RemovalPlanSection[] {\n return [\n { label: SHARED_CONFIG_APPLY.SKILLS_HEADING, items: skills.map(skillLabel) },\n { label: SHARED_CONFIG_APPLY.AGENTS_HEADING, items: [...agents] },\n ].filter((section) => section.items.length > 0);\n}\n\n/** The same lists for entries that live at global scope, under headings that say so. */\nfunction globalRemovalSections(skills: SkillId[], agents: AgentName[]): RemovalPlanSection[] {\n return [\n { label: SHARED_CONFIG_APPLY.GLOBAL_SKILLS_HEADING, items: skills.map(skillLabel) },\n { label: SHARED_CONFIG_APPLY.GLOBAL_AGENTS_HEADING, items: [...agents] },\n ].filter((section) => section.items.length > 0);\n}\n\n/** Who else a global removal lands on — printed only when there is one to land. */\nfunction globalReachStatement(global: RemovedEntries, otherProjects: string[]): string[] {\n if (global.skills.length === 0 && global.agents.length === 0) return [];\n return [globallyInstalledRemoved(otherProjects)];\n}\n\n/**\n * The plan's opening line. A heading is a promise about the lines beneath it, so one promising\n * removals over an empty list would be a lie — a configuration that only adds says so instead,\n * and is still confirmed, because it is still applied whole.\n */\nfunction planHeading(sections: RemovalPlanSection[]): string {\n if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;\n return SHARED_CONFIG_APPLY.PREVIEW_HEADING;\n}\n\n/** How a removal reads in the plan: the name the user picked it by, with the id behind it. */\nfunction skillLabel(skillId: SkillId): string {\n const displayName = getSkillDisplayName(skillId);\n return displayName === skillId ? skillId : `${displayName} (${skillId})`;\n}\n\n/**\n * The plan's kept half, one statement per reason.\n *\n * Both reasons are disclosed rather than acted on, which is the point: no configuration ever\n * carried a skill written here, and an id this catalogue cannot place is one this run had an\n * instruction about and could not honour — so an apply that silently left them behind would\n * recreate exactly the defect the destructive ruling exists to kill, nobody able to tell why an\n * agent still carries a skill they never picked.\n */\nfunction keptStatements(kept: KeptFromRoundTrip): string[] {\n return [...authorshipStatement(kept), ...catalogueStatement(kept)];\n}\n\n/** The ownership half, whose remedy is the wizard rather than another configuration. */\nfunction authorshipStatement(kept: KeptFromRoundTrip): string[] {\n if (kept.authoredSkillIds.length === 0) return [];\n return [authoredHereKept(kept.authoredSkillIds)];\n}\n\n/** The catalogue's own limit, whose remedy is the catalogue rather than anything installed. */\nfunction catalogueStatement(kept: KeptFromRoundTrip): string[] {\n if (kept.unplaceableSkillIds.length === 0) return [];\n return [unplaceableKept(kept.unplaceableSkillIds)];\n}\n\n/**\n * How much of what it can see a run owns — the word the merger takes, and the same word the\n * global config the project write commits is resolved under.\n *\n * At the home root, everything: the session loaded the whole global config, so an absent entry\n * was deselected. In a project the WIZARD owns only what the project owns, because the store\n * refuses to deselect a live global entry at all — an inherited row absent from its result is\n * one it never offered, not one anybody dropped. A CONFIRMED shared configuration is the other\n * case and the reason this is not simply `editRoot.isGlobal`: it states a whole roster, the plan\n * above named every global removal and every project that reaches, and somebody answered yes.\n */\nfunction applyAuthority(\n producer: EditSelection[\"producer\"],\n editRoot: EditRoot,\n): AuthoritativeScope {\n if (editRoot.isGlobal) return \"all\";\n return producer === \"shared\" ? \"all\" : \"owned\";\n}\n\nexport default class Edit extends BaseCommand {\n static summary = \"Edit skills in the plugin\";\n static description = \"Modify the currently installed skills via interactive wizard\";\n\n static examples = [\n {\n description: \"Open the edit wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Open this installation in the editor instead of the wizard\",\n command: \"<%= config.bin %> <%= command.id %> --ui\",\n },\n {\n description: \"Apply a configuration built in the editor, by its id\",\n command: \"<%= config.bin %> <%= command.id %> --from <id>\",\n },\n ];\n\n static flags = {\n ui: Flags.boolean({\n description:\n \"Open agentsinc.sh instead of the wizard — the id --from names, or this installation\",\n default: false,\n }),\n from: Flags.string({\n description:\n \"Apply a configuration shared from agentsinc.sh by its id, removing whatever it leaves out\",\n helpValue: \"<id>\",\n }),\n [EDIT_PROJECT_SETUP_FLAG]: Flags.boolean({\n description: \"Internal: this run continues an `init` project setup\",\n default: false,\n hidden: true,\n }),\n };\n\n /**\n * The command in two statements: do the work, then answer for it.\n *\n * `applyEdit` owns every path through the edit and returns however it likes; the exit code is\n * decided once, here, after the last of them. Deciding it inside `applyEdit` would mean\n * deciding it at each of that method's three endings, and an ending added later would inherit\n * the exit-0 default silently — which is the defect this pair exists to close.\n */\n async run(): Promise<void> {\n await this.applyEdit();\n this.exitIfWorkIncomplete();\n }\n\n private async applyEdit(): Promise<void> {\n const { flags } = await this.parse(Edit);\n const cwd = process.cwd();\n\n // ABOVE `ensureConfigReadable`, and above `edit`'s own requirement that something be installed\n // here at all. Opening an id somebody shared reads no local state — no config, no catalogue,\n // no marketplace — so a directory's condition cannot decide whether you may look at it, and\n // the id already IS a stored configuration so nothing is minted either. That exemption is the\n // owner's ruling of 2026-08-24 rather than an oversight, and `edit-ui-from.e2e.test.ts` is\n // what says so: `edit` refuses an empty directory on every other path.\n if (flags.ui && flags.from !== undefined) return this.openSharedInEditor(flags.from);\n\n // Before anything renders: a config that cannot be read is recreated, not edited, and\n // refusing here is what keeps the refusal clean — past this point the wizard has already\n // copied skills and installed plugins by the time a config read fails.\n await this.ensureConfigReadable(cwd);\n\n // The browser is the other editor, so it replaces the wizard rather than preceding it —\n // above the source load, which exists to fill screens this run will never paint.\n if (flags.ui) return this.openInEditor(cwd);\n\n // The inbound half is destructive, so it is confirmed — and a confirm nobody can answer must\n // never become a yes. Refusing here, above the fetch and above the catalogue load, is what\n // keeps a run that cannot finish from spending either.\n const payload =\n flags.from === undefined ? null : await this.fetchSharedConfigOrFail(flags.from);\n\n const context = await this.loadContextUnderSpinner();\n\n // Which installation this run is editing, resolved once and read by every layer below.\n const editRoot = resolveEditRoot(context.installation, cwd, flags[EDIT_PROJECT_SETUP_FLAG]);\n\n // Still before anything renders, one layer below the config itself: an entry whose skill\n // IS installed and whose metadata.yaml describes it no longer would otherwise be dropped\n // from config.ts on the way out, over a file this refusal asks to be repaired instead.\n await this.ensureSavedSkillsReadable(\n context.projectConfig?.skills ?? [],\n context.sourceResult.matrix,\n context.projectDir,\n );\n\n const selection = payload\n ? await this.selectionFromSharedConfig(payload, context, editRoot)\n : await this.selectionFromWizard(context, editRoot);\n if (!selection) this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n\n const { result } = selection;\n this.reportValidationErrors(result.validation);\n\n // Filter excluded entries ONCE — downstream methods receive only active entries\n const activeNewSkills = result.skills.filter((s) => !s.excluded);\n const activeNewAgents = result.agentConfigs.filter((a) => !a.excluded);\n const activeOldSkills = (context.projectConfig?.skills ?? []).filter((s) => !s.excluded);\n const activeOldAgents = (context.projectConfig?.agents ?? []).filter((a) => !a.excluded);\n\n const filteredResult: WizardResultV2 = {\n ...result,\n skills: activeNewSkills,\n agentConfigs: activeNewAgents,\n };\n const filteredOldConfig: ProjectConfig | null = context.projectConfig\n ? { ...context.projectConfig, skills: activeOldSkills, agents: activeOldAgents }\n : null;\n\n const changes = detectConfigChanges(filteredOldConfig, filteredResult, {\n newSkills: result.skills,\n oldSkills: context.projectConfig?.skills ?? [],\n newAgents: result.agentConfigs,\n oldAgents: context.projectConfig?.agents ?? [],\n });\n // The gate, at the one point where the removals are known and none has been made: after the\n // diff, above every mutation, and above the no-change return — a configuration that carries\n // its own skills still has bytes to land when the roster is unchanged.\n if (selection.producer === \"shared\") {\n await this.confirmSharedConfigOrCancel(\n changes,\n selection.kept,\n { skills: activeOldSkills, agents: activeOldAgents },\n editRoot,\n );\n await this.writeCarriedSkills(selection.carried);\n }\n\n // One word for both halves of the write, decided once from what was actually confirmed: the\n // merger reads it for the config ROW, and the gate reads it for the global config a project\n // write commits. Deriving it twice is how the row and the disk come to disagree.\n const authority = applyAuthority(selection.producer, editRoot);\n\n if (!hasAnyChanges(changes)) {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(\"No changes made.\"));\n // `cc init` inside a project means \"set this project up\", so the project must be\n // materialised — `<project>/.claude-src/config.ts` + `config-types.ts` written and the\n // path registered in the global `projects[]` — even when the wizard produced no roster\n // change. At the home root there is no project to set up: the global install is what the\n // dashboard was shown for, so a no-change pass there stays an inspection, as does every\n // bare `cc edit`.\n if (!editRoot.isProjectSetup) return;\n await this.writeConfigAndCompile(result, context, editRoot, authority);\n this.logCompletionSummary(changes);\n return;\n }\n\n const removalReasons = await unresolvedSkillRemovalReasons(\n result.unresolvableSkillIds,\n activeOldSkills,\n context.projectDir,\n loadedSourceLabel(context.sourceResult),\n );\n this.logChangeSummary(\n changes,\n filteredResult.skills,\n filteredOldConfig?.skills ?? [],\n removalReasons,\n );\n const migratedSkillIds = await this.applyMigrations(\n changes,\n filteredResult,\n activeOldSkills,\n context,\n editRoot,\n );\n await this.recordGlobalSourceMigrations(\n migratedSkillIds,\n filteredResult.skills,\n editRoot,\n context,\n );\n await this.applyScopeChanges(changes, filteredResult, context, editRoot);\n await this.applySourceChanges(changes, activeOldSkills, editRoot, migratedSkillIds);\n await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, editRoot);\n await this.copyNewLocalSkills(changes, filteredResult, context, editRoot);\n await this.removeDeletedLocalSkills(changes, activeOldSkills, editRoot);\n await this.writeConfigAndCompile(result, context, editRoot, authority);\n await this.cleanupStaleAgentFiles(changes, activeOldAgents, editRoot);\n this.logCompletionSummary(changes);\n }\n\n /** The interactive producer: open the wizard on what is installed, return what was chosen. */\n private async selectionFromWizard(\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<EditSelection | null> {\n const result = await this.runEditWizard(context, editRoot);\n if (!result) return null;\n\n return { producer: \"wizard\", result };\n }\n\n /**\n * The `--from <id>` producer: fetch, seat what the configuration carries, decode, and put back\n * what this run has no authority to remove.\n *\n * Everything a shared configuration says is a statement about the whole roster, so the apply\n * that follows is destructive — the project is made to MATCH it. Two exceptions come back into\n * the result: a skill written here, which the producer drops on the way out because\n * `forkedFrom` says the CLI never wrote it, and an id the configuration NAMES that this\n * catalogue cannot place, because a destructive apply removes on intent and never on its own\n * inability. Both are disclosed in the confirm rather than silently excused.\n *\n * A globally installed entry is NOT one of them. It is removable from here, and what its scope\n * changes is who the removal reaches — which the confirm names, rather than this putting the\n * entry back and calling the reach impossible.\n */\n private async selectionFromSharedConfig(\n payload: SeedPayload,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<EditSelection> {\n const { matrix: sourceMatrix } = context.sourceResult;\n // Before the decode, because a skill the payload CARRIES answers to no catalogue: unseated,\n // its id is skipped like any other unknown one and its content is never read.\n const carried = this.registerExternalSkillsOrFail(payload, sourceMatrix, editRoot.dir);\n const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(\n payload,\n sourceMatrix,\n );\n\n // The first moment this can be asked, and above everything this run would say or do: an\n // all-global configuration is exactly what a global installation is for, so only the decode\n // says whether THIS one has anywhere to be written here. `init --from` asks it at the same\n // point of the same value, and a run about to be refused must not first narrate its skips.\n this.refuseProjectScopedContentAtHome(result, editRoot.dir);\n\n if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));\n if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));\n\n const reconciled = reconcileSharedConfig({\n decoded: result,\n installed: context.projectConfig,\n authoredHere: await this.readAuthoredHere(context.projectConfig, editRoot.dir),\n // The ids the decode above could not place. They are the skips just reported, read as\n // what STAYS rather than as what did not arrive: the payload named them, so their absence\n // from the decode is this catalogue's limit and not an instruction to delete anything.\n unplaceable: new Set(skippedSkillIds),\n });\n\n return {\n producer: \"shared\",\n result: reconciled.result,\n kept: keptStatements(reconciled.kept),\n carried,\n };\n }\n\n /**\n * Which installed skills the round trip does not own, asked of the disk exactly as the\n * producing half asks it.\n *\n * Best-effort by nature and never fatal: the question is only ever asked to PROTECT a skill,\n * so a directory that cannot be read protects nothing and must not fail an apply. The\n * consequence of an unanswered question is that the entry is treated as the CLI's own, which\n * is what every other command already assumes about it.\n */\n private async readAuthoredHere(\n projectConfig: ProjectConfig | null,\n editRoot: string,\n ): Promise<Set<SkillId>> {\n if (!projectConfig) return new Set();\n\n try {\n return await skillsAuthoredHere(projectConfig, editRoot);\n } catch (error) {\n this.warn(`Could not tell which skills were written here: ${getErrorMessage(error)}`);\n return new Set();\n }\n }\n\n /**\n * The id, fetched — or the run refused before it is.\n *\n * The terminal question is answered first because nothing in the payload can change its\n * answer: an apply that cannot be confirmed is over before the store is asked, and a refusal\n * that had already spent a round trip would be describing work it never intended to do.\n */\n private async fetchSharedConfigOrFail(id: string): Promise<SeedPayload> {\n if (!process.stdin.isTTY) {\n this.error(sharedConfigNeedsTerminal(id), { exit: EXIT_CODES.ERROR });\n }\n\n this.log(`Fetching configuration ${id}...`);\n const fetched = await fetchSeedConfig(id);\n if (!fetched.ok) {\n this.error(fetched.error, { exit: EXIT_CODES.ERROR });\n }\n\n return fetched.payload;\n }\n\n /**\n * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).\n * That is a failure of this command, reported with this command's exit code rather than left to\n * surface as an unhandled throw.\n */\n private decodeSeedOrFail(payload: SeedPayload, sourceMatrix: MergedSkillsMatrix): SeedMapping {\n try {\n return seedToWizardResult(payload, sourceMatrix);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Seats the catalogue entries the payload carries with it, or refuses the run. The refusal is\n * `registerExternalSkills`' own — a carried skill asked for as a plugin, which no marketplace\n * serves — reported with this command's exit code for the same reason the decode's is.\n */\n private registerExternalSkillsOrFail(\n payload: SeedPayload,\n sourceMatrix: MergedSkillsMatrix,\n projectDir: string,\n ): ExternalSkillInstall[] {\n try {\n return registerExternalSkills(payload, sourceMatrix, projectDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /** Writes the skills the configuration brought with it, and says which they were. */\n private async writeCarriedSkills(carried: ExternalSkillInstall[]): Promise<void> {\n if (carried.length === 0) return;\n\n await writeExternalSkills(carried);\n this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));\n }\n\n /**\n * Shows what applying this configuration takes away, and stops the run unless a person says\n * yes.\n *\n * The plan is built from the SAME `ConfigChanges` the apply below acts on, so what is approved\n * and what is removed are one value read twice. Its kept half is the other side of the same\n * honesty: nothing is refused over an entry this run cannot remove, and nothing is silent\n * about one either.\n *\n * WHICH plan is built is decided here and only here, on the directory the run was started in.\n * Inside the global installation the scope was chosen and is obvious, so the ordinary confirm\n * is the whole of the gate; inside a project a global removal reaches projects nobody here is\n * looking at, so it is shown apart and the reach is named.\n */\n private async confirmSharedConfigOrCancel(\n changes: ConfigChanges,\n kept: string[],\n installed: InstalledEntries,\n editRoot: EditRoot,\n ): Promise<void> {\n const plan = editRoot.isGlobal\n ? globalScopePlan(changes, kept)\n : projectScopePlan(\n changes,\n kept,\n installed,\n await this.otherRegisteredProjects(editRoot.dir),\n );\n\n const outcome = await promptConfirm(({ onConfirm, onCancel }) => (\n <RemovalPlanConfirm\n heading={plan.heading}\n sections={plan.sections}\n statements={plan.statements}\n message={SHARED_CONFIG_APPLY.CONFIRM}\n onConfirm={onConfirm}\n onCancel={onCancel}\n />\n ));\n if (outcome === \"confirmed\") return;\n\n this.log(\"\\nEdit cancelled\");\n this.error(\"Cancelled\", { exit: EXIT_CODES.CANCELLED });\n }\n\n /**\n * Every registered project but this one — the blast radius a global removal actually has.\n *\n * Read from the GLOBAL config rather than from `context.projectConfig`: `projects[]` is the\n * registry the fan-out itself walks, and a project's own config never carries it, so taking\n * the list from anywhere else would let the confirm name a set the propagation does not.\n *\n * Best-effort by nature. The list exists to be DISCLOSED, so a home directory that cannot be\n * read leaves the disclosure counting nobody rather than failing an apply — and the statement\n * it produces then is the one that says no other project is registered.\n */\n private async otherRegisteredProjects(editRoot: string): Promise<string[]> {\n try {\n const global = await loadProjectConfigFromDir(os.homedir());\n const here = normalizeProjectPath(editRoot);\n return (global?.config.projects ?? []).filter((projectDir) => projectDir !== here);\n } catch (error) {\n this.warn(`Could not tell which projects share this install: ${getErrorMessage(error)}`);\n return [];\n }\n }\n\n /**\n * The outbound half of the editor round trip: this installation, minted as a configuration\n * the editor opens, and handed to a browser.\n *\n * It is the same mint `share` performs — same reader, same mapping, same refusals, through\n * `seedPayloadForInstallation` — because an id is the whole of what either command produces\n * and two spellings of \"the installation in this directory\" would mint two different ids for\n * one project. What differs is only the ending: `share` reports the id, this opens it.\n *\n * Nothing on disk is touched. A configuration is read, not rewritten, so a run that changed\n * anything here would be editing the project on the way to offering to edit it.\n */\n /**\n * An id somebody shared, opened rather than applied.\n *\n * The counterpart of `openInEditor` above and deliberately not a variant of it: that one MINTS,\n * because an installation is not yet a configuration the store holds. An id already is one, so\n * there is nothing to publish, nothing to read off disk, and no way for this to fail except the\n * browser refusing to launch — which is a warning beside a link that still works.\n *\n * `--from` without `--ui` remains the destructive apply. Looking and applying are the two\n * things a recipient can do with an id, and this is the one that changes nothing.\n */\n private async openSharedInEditor(id: string): Promise<void> {\n const url = editorConfigUrl(id);\n\n this.log(`Open it at ${url}`);\n this.log(`To apply it here instead, run '${CLI_INVOKE_COMMAND} edit --from ${id}'.`);\n\n if (!process.stdin.isTTY) return;\n\n const opened = await openUrl(url);\n if (!opened.ok) this.warn(opened.error);\n }\n\n private async openInEditor(projectDir: string): Promise<void> {\n const prepared = await seedPayloadForInstallation(projectDir);\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.log(`Opening ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n const published = await publishSeedConfig(prepared.payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n await this.handToBrowser(published.id);\n }\n\n /**\n * The link, printed first and opened second.\n *\n * Printed first because it is the only part of this that works everywhere: over a pipe, in CI\n * and on a machine with no desktop session there is no browser to be anybody's, and a link\n * nobody can copy is the whole loss. Opening one is the convenience on top, so a failure to\n * open is a warning beside a link that still works rather than a failed command.\n *\n * `process.stdin.isTTY` is the same question `init`'s dashboard asks before it offers a\n * prompt — is there a person here — because that is exactly what \"whose browser is this\"\n * means.\n */\n private async handToBrowser(id: string): Promise<void> {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n\n if (!process.stdin.isTTY) return;\n\n const opened = await openUrl(editorConfigUrl(id));\n if (!opened.ok) this.warn(opened.error);\n }\n\n /**\n * The load below, behind a spinner that comes down whichever way the await ends.\n *\n * The cleanup is a `finally` because all three of `loadContext`'s refusals are raised\n * while this spinner is mounted, and oclif would otherwise paint its error under an Ink\n * tree still repainting over it. Never a `catch`: the throw reaches oclif untouched, or\n * both the error rendering and the pinned exit codes change with it.\n */\n private async loadContextUnderSpinner(): Promise<EditContext> {\n const { unmount, clear: clearSpinner } = render(\n <Spinner label={STATUS_MESSAGES.LOADING_SKILLS} />,\n );\n try {\n return await this.loadContext();\n } finally {\n clearSpinner();\n unmount();\n }\n }\n\n private async loadContext(): Promise<EditContext> {\n const detected = await detectProject();\n if (!detected) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n const { installation, config: projectConfig } = detected;\n\n // The detected installation's own root, which is what this run READS: the source it stored,\n // and the plugins registered against it. Every WRITE goes to `EditRoot.dir` instead, and the\n // two are the same directory unless `--project-setup` is promoting this one to a project.\n const projectDir = installation.projectDir;\n\n let sourceResult: SourceLoadResult;\n let startupMessages: StartupMessage[] = [];\n try {\n // No source is named here: `edit` reads the one the installation stored.\n const loaded = await loadSource({ projectDir, captureStartupMessages: true });\n sourceResult = loaded.sourceResult;\n startupMessages = loaded.startupMessages;\n\n const sourceInfo = sourceResult.isLocal ? \"local\" : sourceResult.sourceConfig.sourceOrigin;\n startupMessages.push({\n level: \"info\",\n text: `Loaded ${Object.keys(matrix.skills).length} skills (${sourceInfo})`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n let currentSkillIds: SkillId[];\n try {\n const discoveredSkills = await discoverAllPluginSkills(projectDir);\n const pluginSkillIds = typedKeys(discoveredSkills);\n\n // Merge plugin-discovered skills with config skills (catches local skills and\n // global-scoped plugins that discoverAllPluginSkills doesn't find).\n // Exclude skills marked as excluded — they should not appear as selected in the build step.\n // They are still preserved in skillConfigs via installedSkillConfigs for info panel/confirm step.\n const excludedConfigIds = new Set(\n projectConfig?.skills.filter((s) => s.excluded).map((s) => s.id) ?? [],\n );\n const configSkillIds =\n projectConfig?.skills.filter((s) => !s.excluded).map((s) => s.id) ?? [];\n const filteredPluginSkillIds = pluginSkillIds.filter((id) => !excludedConfigIds.has(id));\n const mergedIds = new Set<SkillId>([...filteredPluginSkillIds, ...configSkillIds]);\n currentSkillIds = [...mergedIds];\n\n startupMessages.push({\n level: \"info\",\n text: `Found ${currentSkillIds.length} installed skills`,\n });\n } catch (error) {\n this.handleError(error);\n }\n\n return {\n installation,\n projectConfig,\n projectDir,\n sourceResult,\n startupMessages,\n currentSkillIds,\n };\n }\n\n private async runEditWizard(\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<WizardResultV2 | null> {\n const { projectConfig, currentSkillIds } = context;\n const selectedAgents = projectConfig?.agents && activeAgentNames(projectConfig.agents);\n\n return runWizardSession({\n hydrate: {\n initialStep: \"build\",\n ...(projectConfig?.selectedDomains !== undefined && {\n initialDomains: projectConfig.selectedDomains,\n }),\n ...(selectedAgents !== undefined && { initialAgents: selectedAgents }),\n installedSkillIds: currentSkillIds,\n ...(projectConfig?.skills !== undefined && { installedSkillConfigs: projectConfig.skills }),\n ...(projectConfig?.agents !== undefined && { installedAgentConfigs: projectConfig.agents }),\n isEditingFromGlobalScope: editRoot.isGlobal,\n },\n props: {\n version: this.config.version,\n initialAgents: selectedAgents,\n installedSkillIds: currentSkillIds,\n startupMessages: context.startupMessages,\n },\n onCancel: () => this.log(\"\\nEdit cancelled\"),\n clearTerminal: () => this.clearTerminal(),\n });\n }\n\n /**\n * Records, in the GLOBAL config, the install-mode migrations this run already performed\n * under `$HOME`.\n *\n * A project-context edit otherwise never writes global config (commit 403df46, \"never\n * modify global config from project-level operations\"), and `authoritativeScope: \"owned\"`\n * enforces that for the roster — an inherited global-active entry is read-only, so\n * `mergeGlobalConfigs` preserves it verbatim. That protection is correct for selection and\n * scope, but `executeMigration` resolves each skill's paths from ITS OWN scope: switching a\n * global-scoped skill's source has already copied it under `$HOME` (or deleted it) and\n * added/removed its user-scope plugin registration by the time the config is written.\n * Leaving the global config alone there protects nothing — it only makes the recorded\n * source contradict the filesystem and the plugin registry.\n *\n * So authority follows the work actually performed, and no further: only ids\n * `executeMigration` acted on this run are rewritten, and only their `origin` field. Global\n * entries this session merely displayed, re-scoped or deselected are untouched, as are\n * `marketplace`, `stack`, `agents` and every other registered project's view of them.\n *\n * Driving a global-scope migration from a project directory is NOT a supported flow, and this\n * method is no longer the thing that permits it. The wizard now refuses it at source: the two\n * bulk install-mode keys are withdrawn, and `setInstallMode` ignores a project-context call\n * against a global slot the hydration snapshot owns — the same authority the Sources grid\n * already enforced by rendering that row inert. What still reaches here is the residue that\n * authority leaves legitimate: a mode change committed on the project half of a `[P][G]` pair\n * and then carried to global scope by a P->G collapse (`s`) in the same session. The entry is\n * the project's own to configure at the moment it is configured, and global at the moment it\n * is written — so the migration is real, and the global config must record it.\n *\n * Runs BEFORE `writeConfigAndCompile`, so the global config written here is the one\n * the wizard write reloads, keeps (existing wins in `mergeGlobalConfigs`) and inlines\n * into the project config — both files then tell the same story. That second write\n * classifies as a no-op against what this one left on disk, so the fan-out below\n * happens once.\n *\n * The migrated `origin` decides the reference form a compiled agent emits, so every\n * OTHER registered project's config and agents are stale until this write fans out —\n * which is why it goes through the gate rather than straight to the file.\n */\n private async recordGlobalSourceMigrations(\n migratedSkillIds: Set<SkillId>,\n newSkills: SkillConfig[],\n editRoot: EditRoot,\n context: EditContext,\n ): Promise<void> {\n // A global-context edit writes the whole global config from the wizard result already.\n if (editRoot.isGlobal) return;\n\n const migratedSources = new Map(\n newSkills\n .filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, \"global\"))\n .map((s) => [s.id, s.origin] as const),\n );\n if (migratedSources.size === 0) return;\n\n try {\n const report = await mutateGlobal(\n { kind: \"migrate-skill-sources\", sources: migratedSources },\n {\n // The deps contract in config-gate/deps.ts declares\n // `() => Promise<MergedSkillsMatrix>`; this caller happens to have its\n // matrix in hand already.\n // eslint-disable-next-line @typescript-eslint/require-await -- deps contract\n loadMatrix: async () => context.sourceResult.matrix,\n loadAgents: async () => (await loadAgentDefs()).agents,\n },\n );\n this.reportPropagatedRecompile(report);\n } catch (error) {\n // The migration itself already happened — the skill has been copied under $HOME or had\n // its user-scope registration moved. Only the record of it failed, so the disk and the\n // global config now describe different installations and nothing downstream will notice.\n this.reportIncompleteWork(\n `Could not record global origin change: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private logChangeSummary(\n changes: ConfigChanges,\n newSkills: SkillConfig[],\n oldSkills: SkillConfig[],\n removalReasons: ReadonlyMap<SkillId, string>,\n ): void {\n const {\n addedSkills,\n removedSkills,\n addedAgents,\n removedAgents,\n sourceChanges,\n scopeChanges,\n agentScopeChanges,\n dualScopeSkillTransitions,\n dualScopeAgentTransitions,\n } = changes;\n\n this.log(`\\n${chalk.hex(CLI_COLORS.WHITE).bold(\"Changes:\")}`);\n for (const skillId of addedSkills) {\n const scope = newSkills.find((s) => s.id === skillId)?.scope;\n const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : \"\";\n this.log(\n chalk.hex(CLI_COLORS.SUCCESS)(` + ${getSkillById(skillId).displayName}${scopeLabel}`),\n );\n }\n for (const skillId of removedSkills) {\n const scope = oldSkills.find((s) => s.id === skillId)?.scope;\n const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : \"\";\n const reason = removalReasons.get(skillId);\n this.log(\n chalk.hex(CLI_COLORS.ERROR)(` - ${getSkillDisplayName(skillId)}${scopeLabel}`) +\n (reason ? chalk.hex(CLI_COLORS.NEUTRAL)(` (${reason})`) : \"\"),\n );\n }\n for (const agentName of addedAgents) {\n this.log(\n chalk.hex(CLI_COLORS.SUCCESS)(` + ${agentName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\"),\n );\n }\n for (const agentName of removedAgents) {\n this.log(\n chalk.hex(CLI_COLORS.ERROR)(` - ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(\" (agent)\"),\n );\n }\n for (const [skillId, change] of sourceChanges) {\n const displayName = getSkillDisplayName(skillId);\n const fromLabel = formatSourceDisplayName(change.from);\n const toLabel = formatSourceDisplayName(change.to);\n this.log(\n chalk.hex(CLI_COLORS.WARNING)(` ~ ${displayName}`) +\n chalk.hex(CLI_COLORS.NEUTRAL)(` (${fromLabel} \\u2192 ${toLabel})`),\n );\n }\n for (const [skillId, change] of scopeChanges) {\n this.log(formatSkillScopeChangeLine(skillId, change, dualScopeSkillTransitions));\n }\n for (const [agentName, change] of agentScopeChanges) {\n this.log(formatAgentScopeChangeLine(agentName, change, dualScopeAgentTransitions));\n }\n this.log(\"\");\n }\n\n private async applyMigrations(\n _changes: ConfigChanges,\n filteredResult: WizardResultV2,\n activeOldSkills: SkillConfig[],\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<Set<SkillId>> {\n const migrationPlan = detectMigrations(activeOldSkills, filteredResult.skills);\n const migratedSkillIds = new Set([\n ...migrationPlan.toEject.map((m) => m.id),\n ...migrationPlan.toPlugin.map((m) => m.id),\n ]);\n if (migratedSkillIds.size === 0) return migratedSkillIds;\n\n if (migrationPlan.toEject.length > 0) {\n this.logModeSwitch(migrationPlan.toEject.length, INSTALL_MODE_DESCRIPTIONS.eject);\n }\n if (migrationPlan.toPlugin.length > 0) {\n this.logModeSwitch(migrationPlan.toPlugin.length, INSTALL_MODE_DESCRIPTIONS.plugin);\n // Installing a plugin needs the marketplace REGISTERED and up to date with the\n // Claude CLI — the same precondition `applyPluginChanges` and `applyScopeChanges`\n // establish. Without it `claude plugin install` rejects every ref against a stale\n // local copy. Runs before `executeMigration` so an unresolvable marketplace exits\n // while the ejected working copies are still intact. Eject-side plugin uninstalls\n // are diagnostic-only, so only plugin-install work demands this.\n await this.requireMarketplaceOrExit(context.sourceResult, \"migrate skills to plugin mode\");\n // The install itself happens inside `executeMigration`, which deletes each skill's\n // working copy the moment that skill's plugin is registered — so the banner is\n // announced here and the outcome reported below, through the same surface `init`\n // and the newly-added-skill path narrate an install with.\n this.announcePluginInstall();\n }\n\n const migrationResult = await executeMigration(\n migrationPlan,\n editRoot.dir,\n context.sourceResult,\n );\n\n for (const warning of migrationResult.warnings) {\n this.warn(warning);\n }\n\n // Reports what was copied and hard-errors on any failure, for the reason the plugin\n // direction does below: a skill whose local copy could not be written must not reach\n // `recordGlobalSourceMigrations` or `writeConfigAndCompile`, either of which would\n // persist `origin: \"eject\"` for a skill that has no copy on disk.\n if (migrationPlan.toEject.length > 0) {\n this.reportEjectCopies(migrationResult.ejectCopies);\n }\n\n // Reports what was installed and hard-errors on any failure: a migration whose\n // plugin could not be installed must not reach `recordGlobalSourceMigrations` or\n // `writeConfigAndCompile`, either of which would persist a marketplace `origin`\n // for a skill with no plugin registration.\n if (migrationPlan.toPlugin.length > 0) {\n this.reportPluginInstalls(migrationResult.pluginInstalls);\n }\n\n return migratedSkillIds;\n }\n\n /**\n * What the plugin→eject half copied, what it could not, and the refusal to continue past\n * a failure.\n *\n * The shape of `BaseCommand.reportPluginInstalls`, deliberately: the two directions of one\n * mode switch owe the user the same account, and the eject half having no structured\n * failure at all is what let a config record `origin: \"eject\"` for a skill whose copy was\n * refused. It stays private because `edit` is the only command that migrates a mode —\n * `init` installs, and has no old state to move.\n *\n * The count line is the same one `copyNewLocalSkills` prints, and names no destination:\n * the migration splits its copies between the project and $HOME by each skill's own scope,\n * so one directory would misname the other half.\n */\n private reportEjectCopies(result: EjectCopyResult): void {\n for (const item of result.failed) {\n this.warn(`Failed to copy ${item.id} for eject: ${item.error}`);\n }\n if (result.failed.length > 0) {\n this.error(ejectCopyFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });\n }\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));\n }\n\n /** Names what this run is switching, in the words `init` describes an install mode with. */\n private logModeSwitch(count: number, modeDescription: string): void {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));\n }\n\n private async applyScopeChanges(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { scopeChanges } = changes;\n\n // Handle scope migrations (P->G or G->P) for eject-mode skills\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = filteredResult.skills.find((s) => s.id === skillId);\n if (skillConfig?.origin === EJECT_SOURCE) {\n await migrateLocalSkillScope(skillId, change.from, editRoot.dir);\n }\n }\n\n // Plugin scope migrations require a marketplace.\n // Compute eligible migrations first; only resolve/demand marketplace when there are any.\n const hasPluginScopeChanges = [...scopeChanges.keys()].some((skillId) => {\n const skillConfig = filteredResult.skills.find((s) => s.id === skillId);\n return skillConfig && skillConfig.origin !== EJECT_SOURCE;\n });\n if (!hasPluginScopeChanges) return;\n\n const marketplace = await this.requireMarketplaceOrExit(\n context.sourceResult,\n \"migrate plugin skill scopes\",\n );\n\n const pluginScopeResult = await migratePluginSkillScopes(\n scopeChanges,\n filteredResult.skills,\n marketplace,\n editRoot.dir,\n );\n // A scope migration INSTALLS the plugin at its new scope, so a failure here is not the\n // diagnostic an uninstall failure is: the skill is registered at neither scope while the\n // config is about to record the new one.\n for (const item of pluginScopeResult.failed) {\n this.reportIncompleteWork(\n `Failed to migrate plugin scope for ${item.id}: ${item.error}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private async applySourceChanges(\n changes: ConfigChanges,\n activeOldSkills: SkillConfig[],\n editRoot: EditRoot,\n migratedSkillIds: Set<SkillId>,\n ): Promise<void> {\n const { sourceChanges } = changes;\n\n // Handle remaining non-migration source changes (e.g., marketplace A -> marketplace B)\n for (const [skillId, change] of sourceChanges) {\n // Skip skills already handled by mode migration\n if (migratedSkillIds.has(skillId)) {\n continue;\n }\n if (change.from === EJECT_SOURCE) {\n const oldSkill = activeOldSkills.find((s) => s.id === skillId);\n const deleteDir = installBaseDir(editRoot.dir, oldSkill?.scope);\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n }\n\n private async applyPluginChanges(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n activeOldSkills: SkillConfig[],\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { addedSkills, removedSkills } = changes;\n\n // Compute plugin-intent lists per-skill (ungated) — per-skill `origin` drives install mode.\n const addedPluginSkills = filteredResult.skills.filter(\n (s) => addedSkills.includes(s.id) && s.origin !== EJECT_SOURCE,\n );\n const removedPluginSkills = removedSkills.filter(\n (id) => activeOldSkills.find((s) => s.id === id)?.origin !== EJECT_SOURCE,\n );\n\n if (addedPluginSkills.length === 0 && removedPluginSkills.length === 0) return;\n\n const marketplace = await this.requireMarketplaceOrExit(\n context.sourceResult,\n \"install or uninstall plugin skills\",\n );\n\n if (addedPluginSkills.length > 0) {\n await this.installPluginSkillsReported(\n addedPluginSkills,\n marketplace,\n editRoot.dir,\n context.sourceResult.matrix,\n );\n }\n\n if (removedPluginSkills.length > 0) {\n const uninstallResult = await uninstallPluginSkills(\n removedPluginSkills,\n activeOldSkills,\n marketplace,\n editRoot.dir,\n );\n if (uninstallResult.uninstalled.length > 0) {\n this.log(\n chalk.hex(CLI_COLORS.NEUTRAL)(`Removed ${uninstallResult.uninstalled.length} plugin(s)`),\n );\n }\n for (const item of uninstallResult.failed) {\n this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);\n }\n }\n }\n\n private async copyNewLocalSkills(\n changes: ConfigChanges,\n filteredResult: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n ): Promise<void> {\n const { addedSkills } = changes;\n\n // Copy newly added local-source skills to .claude/skills/ (split by scope)\n const addedLocalSkills = filteredResult.skills.filter(\n (s) => addedSkills.includes(s.id) && s.origin === EJECT_SOURCE,\n );\n\n if (addedLocalSkills.length > 0) {\n const copyResult = await copyLocalSkills(\n addedLocalSkills,\n editRoot.dir,\n context.sourceResult,\n );\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(copyResult.totalCopied)));\n }\n }\n\n private async removeDeletedLocalSkills(\n changes: ConfigChanges,\n activeOldSkills: SkillConfig[],\n editRoot: EditRoot,\n ): Promise<void> {\n const { removedSkills } = changes;\n\n // A fully-deselected eject-mode skill is a genuine uninstall — its copied directory under\n // .claude/skills/<id>/ must be removed from the scope it was installed at. Plugin\n // removals are handled by applyPluginChanges; source-change (eject->marketplace) deletions by\n // applySourceChanges. deleteLocalSkill is a no-op when the directory is absent.\n for (const skillId of removedSkills) {\n const oldSkill = activeOldSkills.find((s) => s.id === skillId);\n if (oldSkill?.origin !== EJECT_SOURCE) continue;\n\n const deleteDir = installBaseDir(editRoot.dir, oldSkill.scope);\n await deleteLocalSkill(deleteDir, skillId);\n }\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n context: EditContext,\n editRoot: EditRoot,\n authority: AuthoritativeScope,\n ): Promise<void> {\n // Load agent definitions — needed for both config-types.ts and recompilation\n let agentDefsResult: AgentDefs;\n try {\n agentDefsResult = await loadAgentDefs();\n } catch (error) {\n this.handleError(error);\n }\n\n // Persist wizard result to config.ts and config-types.ts (split by scope when in project context)\n //\n // A failed write is fatal, not a warning. Every mutation this run made — plugin\n // registrations, ejected copies, deleted working copies — has already landed on disk,\n // and config.ts is the only record of what they were for. Continuing past it into the\n // agent recompile left the registry, the config and `.claude/agents/` mutually\n // inconsistent and still reported success, which is the same silent-substitution defect\n // the plugin install path refuses.\n let configResult: ConfigWriteResult;\n try {\n configResult = await writeProjectConfig({\n wizardResult: result,\n sourceResult: context.sourceResult,\n projectDir: editRoot.dir,\n agentDefs: agentDefsResult,\n // A full `cc edit` pass is authoritative over the roster it owns, so deselected entries\n // are removed rather than union-preserved. `applyAuthority` decides\n // how much that is from the producer and the directory, and hands the same word to the\n // merger and to the global config the project branch of the gate commits.\n authoritativeScope: authority,\n });\n } catch (error) {\n this.error(`Could not update config: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n this.reportUnassignedSkills(configResult.config);\n\n try {\n const agentScopeMap = activeAgentScopeMap(result.agentConfigs);\n const { allSkills } = await discoverInstalledSkills(editRoot.dir);\n const compilationResult = await compileAgentsAllScopes({\n projectDir: editRoot.dir,\n sourcePath: agentDefsResult.sourcePath,\n skills: allSkills,\n agentScopeMap,\n });\n\n const { compiled, rewritten, failed, warnings } = compilationResult;\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n RECOMPILE_SUBJECT,\n );\n\n if (failed.length > 0) {\n this.log(\n chalk.hex(CLI_COLORS.NEUTRAL)(summary) +\n chalk.hex(CLI_COLORS.WARNING)(` (${failed.length} failed)`),\n );\n for (const warning of warnings) {\n this.warn(warning);\n }\n // Recorded off `failed` rather than off the warnings just printed: `warnings` also\n // carries entries that are not failures — a scope with nothing to compile contributes\n // one on every project-context run — and the ending must not file those as work owed.\n this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);\n } else if (compiled.length > 0) {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(summary));\n } else {\n this.log(chalk.hex(CLI_COLORS.NEUTRAL)(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE));\n }\n } catch (error) {\n // The config write above has already landed, and the recompile is the last step — so\n // there is nothing left to abort into. What is wrong is the silence: `.claude/agents/`\n // now describes the roster this edit replaced, and the run used to report success over it.\n this.reportIncompleteWork(\n `Agent recompilation failed: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.RECOMPILE,\n );\n this.log(`You can manually recompile with '${CLI_INVOKE_COMMAND} compile'.`);\n }\n\n this.reportPropagatedRecompile(configResult.propagation);\n }\n\n private async cleanupStaleAgentFiles(\n changes: ConfigChanges,\n oldAgents: AgentScopeConfig[],\n editRoot: EditRoot,\n ): Promise<void> {\n for (const removal of planStaleAgentRemovals(changes, oldAgents, editRoot.dir)) {\n const { failed } = await removeCompiledAgents(removal);\n\n // A compiled sub-agent this project no longer configures is still a sub-agent Claude Code\n // loads, so a removal that did not happen is a roster the edit did not actually change.\n for (const { name, error } of failed) {\n const agentPath = path.join(removal.agentsDir, `${name}.md`);\n this.reportIncompleteWork(\n `Could not remove agent file ${agentPath}: ${error}`,\n INCOMPLETE_WORK_RECOVERY.DELETE_AGENT_FILE,\n );\n }\n }\n }\n\n private logCompletionSummary(_changes: ConfigChanges): void {\n // A run with work owed ends on the account below instead \\u2014 a tick over a partial apply is\n // the claim being withdrawn here, not an extra line beside it.\n if (this.hasIncompleteWork) return;\n\n this.log(`\\n${chalk.hex(CLI_COLORS.SUCCESS)(\"\\u2713 Done\")}\\n`);\n }\n}\n\n/** @internal Exported for testing */\nexport type ConfigChanges = {\n addedSkills: SkillId[];\n removedSkills: SkillId[];\n addedAgents: AgentName[];\n removedAgents: AgentName[];\n sourceChanges: Map<SkillId, { from: string; to: string }>;\n scopeChanges: Map<SkillId, ScopeChange>;\n agentScopeChanges: Map<AgentName, ScopeChange>;\n /**\n * Skill ids whose `scopeChanges` entry is a dual-scope add/remove — the project\n * half of a `[P][G]` pair was toggled while the global half persists — NOT a true\n * single-entry migration. The disk-side scope work still flows through\n * `scopeChanges`; this set only steers the completion-summary display so a\n * dual-scope addition is not misreported as a `[G] → [P]` migration.\n */\n dualScopeSkillTransitions: Set<SkillId>;\n /** Agent equivalent of `dualScopeSkillTransitions`. */\n dualScopeAgentTransitions: Set<AgentName>;\n};\n\n/** Full (tombstone-inclusive) entry lists used to classify dual-scope transitions. */\ntype FullScopeEntries = {\n newSkills: SkillConfig[];\n oldSkills: SkillConfig[];\n newAgents: AgentScopeConfig[];\n oldAgents: AgentScopeConfig[];\n};\n\n/**\n * @internal Exported for testing\n *\n * `oldConfig` / `wizardResult` carry the ACTIVE (tombstone-filtered) entries used\n * for add/remove/source/scope diffing. `fullEntries`, when provided, carries the\n * unfiltered lists (including excluded tombstones) used ONLY to tell a genuine\n * scope migration apart from a dual-scope add/remove. When omitted, every scope\n * change is treated as a migration (the pre-dual-scope behaviour).\n */\nexport function detectConfigChanges(\n oldConfig: ProjectConfig | null,\n wizardResult: WizardResultV2,\n fullEntries?: FullScopeEntries,\n): ConfigChanges {\n const oldSkillIds = oldConfig?.skills.map((s) => s.id) ?? [];\n const newSkillIds = wizardResult.skills.map((s) => s.id);\n const oldAgentNames = oldConfig?.agents.map((a) => a.name) ?? [];\n const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);\n\n const oldSkillsById = indexBy(oldConfig?.skills ?? [], (s) => s.id);\n const oldAgentsByName = indexBy(oldConfig?.agents ?? [], (a) => a.name);\n\n const scopeChanges = detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.scope,\n );\n const agentScopeChanges = detectPropertyChanges(\n wizardResult.agentConfigs,\n oldAgentsByName,\n (a) => a.name,\n (a) => a.scope,\n );\n\n return {\n addedSkills: difference(newSkillIds, oldSkillIds),\n removedSkills: difference(oldSkillIds, newSkillIds),\n addedAgents: difference(newAgentNames, oldAgentNames),\n removedAgents: difference(oldAgentNames, newAgentNames),\n sourceChanges: detectPropertyChanges(\n wizardResult.skills,\n oldSkillsById,\n (s) => s.id,\n (s) => s.origin,\n ),\n scopeChanges,\n agentScopeChanges,\n dualScopeSkillTransitions: detectDualScopeTransitions(\n scopeChanges,\n fullEntries?.newSkills ?? [],\n fullEntries?.oldSkills ?? [],\n (s) => s.id,\n ),\n dualScopeAgentTransitions: detectDualScopeTransitions(\n agentScopeChanges,\n fullEntries?.newAgents ?? [],\n fullEntries?.oldAgents ?? [],\n (a) => a.name,\n ),\n };\n}\n\nfunction detectPropertyChanges<T, K extends string, V>(\n newItems: T[],\n oldByKey: Record<string, T>,\n getKey: (item: T) => K,\n getValue: (item: T) => V,\n): Map<K, { from: V; to: V }> {\n const changes = new Map<K, { from: V; to: V }>();\n for (const item of newItems) {\n const key = getKey(item);\n const old = oldByKey[key];\n if (old && getValue(old) !== getValue(item)) {\n changes.set(key, { from: getValue(old), to: getValue(item) });\n }\n }\n return changes;\n}\n\n/**\n * A scope change is a dual-scope transition (not a migration) when the canonical\n * dual-scope tombstone — an excluded global entry — sits alongside it:\n * - G→P add: the NEW state keeps a global tombstone, so the global install\n * survives and the project half was merely added.\n * - P→G remove: the OLD state held a global tombstone, so the pair was already\n * dual-scope and the project half was merely removed.\n * Either way the item occupied both scopes, so `[X] → [Y]` would misdescribe it.\n */\nfunction detectDualScopeTransitions<\n K extends string,\n T extends { scope: SkillScope; excluded?: boolean },\n>(scopeChanges: Map<K, ScopeChange>, fullNew: T[], fullOld: T[], getKey: (item: T) => K): Set<K> {\n const hasGlobalTombstone = (items: T[], key: K): boolean =>\n items.some((item) => getKey(item) === key && item.scope === \"global\" && item.excluded === true);\n\n const result = new Set<K>();\n for (const [key, change] of scopeChanges) {\n if (change.from === \"global\" && change.to === \"project\" && hasGlobalTombstone(fullNew, key)) {\n result.add(key);\n } else if (\n change.from === \"project\" &&\n change.to === \"global\" &&\n hasGlobalTombstone(fullOld, key)\n ) {\n result.add(key);\n }\n }\n return result;\n}\n\ntype StaleAgent = { name: AgentName; scope: SkillScope };\n\n/** Every scope a stale compiled agent can be sitting at. */\nconst STALE_AGENT_SCOPES = [\"project\", \"global\"] as const satisfies readonly SkillScope[];\n\n/** The scope a deselected agent was installed at, for one absent from the old roster. */\nconst UNRECORDED_AGENT_SCOPE: SkillScope = \"project\";\n\nfunction installedScope(name: AgentName, oldAgents: AgentScopeConfig[]): SkillScope {\n return oldAgents.find((agent) => agent.name === name)?.scope ?? UNRECORDED_AGENT_SCOPE;\n}\n\n/**\n * The compiled files an edit leaves stale, one removal per scope directory that\n * holds any: the project copy a P→G move superseded, plus every deselected agent\n * at the scope it was installed at.\n *\n * G→P moves are absent deliberately — that direction is an override, so the global\n * installation stays untouched and the project copy shadows it. A scope with\n * nothing to remove is absent too: only a directory this edit actually removed\n * from is a directory this edit may tidy.\n */\nfunction planStaleAgentRemovals(\n changes: ConfigChanges,\n oldAgents: AgentScopeConfig[],\n editRoot: string,\n): RemoveCompiledAgentsOptions[] {\n const supersededByGlobal = [...changes.agentScopeChanges]\n .filter(([, change]) => change.from !== \"global\")\n .map(([name]): StaleAgent => ({ name, scope: \"project\" }));\n\n const deselected = changes.removedAgents.map((name): StaleAgent => ({\n name,\n scope: installedScope(name, oldAgents),\n }));\n\n const stale = [...supersededByGlobal, ...deselected];\n const removalAtScope = (scope: SkillScope): RemoveCompiledAgentsOptions => ({\n agentsDir: resolveInstallPaths(editRoot, scope).agentsDir,\n agents: stale.filter((agent) => agent.scope === scope).map((agent) => agent.name),\n });\n\n return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);\n}\n\nfunction hasAnyChanges(changes: ConfigChanges): boolean {\n return (\n changes.addedSkills.length > 0 ||\n changes.removedSkills.length > 0 ||\n changes.addedAgents.length > 0 ||\n changes.removedAgents.length > 0 ||\n changes.sourceChanges.size > 0 ||\n changes.scopeChanges.size > 0 ||\n changes.agentScopeChanges.size > 0\n );\n}\n\n/** @internal Exported for testing */\nexport type PluginScopeMigrationResult = {\n migrated: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\n/** @internal Exported for testing */\nexport async function migratePluginSkillScopes(\n scopeChanges: Map<SkillId, ScopeChange>,\n skills: Pick<SkillConfig, \"id\" | \"origin\">[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginScopeMigrationResult> {\n const migrated: SkillId[] = [];\n const failed: PluginScopeMigrationResult[\"failed\"] = [];\n\n for (const [skillId, change] of scopeChanges) {\n const skillConfig = skills.find((s) => s.id === skillId);\n if (!skillConfig || skillConfig.origin === EJECT_SOURCE) {\n continue;\n }\n\n const newPluginScope = toClaudePluginScope(change.to);\n const pluginRef = buildMarketplacePluginRef(skillId, marketplace);\n\n try {\n // global→project: keep the global registration, just add project scope.\n // The global plugin must remain for other projects.\n // project→global: uninstall the project-scope registration, install global.\n if (change.from === \"project\") {\n await claudePluginUninstall(pluginRef, \"project\", projectDir);\n }\n await claudePluginInstall(pluginRef, newPluginScope, projectDir);\n migrated.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { migrated, failed };\n}\n","import { getCategoryDomain, matrix } from \"../matrix/matrix-provider.js\";\nimport { orderDomains } from \"../wizard/domain-order.js\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object.js\";\n\nimport type { WizardResultV2 } from \"../../components/wizard/wizard.js\";\nimport type { AgentName } from \"../../types/agents.js\";\nimport type { ProjectConfig, SkillConfig } from \"../../types/config.js\";\nimport type { Category, Domain } from \"../../types/matrix.js\";\nimport type { SkillAssignment, SkillId } from \"../../types/skills.js\";\nimport type { StackAgentConfig } from \"../../types/stacks.js\";\n\n/**\n * What applying a shared configuration here is not allowed to take away, split by the reason —\n * because the reasons have different remedies and only the user knows which they meant.\n */\nexport type KeptFromRoundTrip = {\n /** Written here rather than installed, so no shared configuration ever carried them. */\n authoredSkillIds: SkillId[];\n /** Named by the configuration and unplaceable by this catalogue, so nothing here applied. */\n unplaceableSkillIds: SkillId[];\n};\n\nexport type ReconciledSharedConfig = {\n /** The decoded payload with everything above put back into it. */\n result: WizardResultV2;\n kept: KeptFromRoundTrip;\n};\n\nexport type ReconcileOptions = {\n /** The payload as `seedToWizardResult` decoded it. */\n decoded: WizardResultV2;\n /** This directory's installation — its own config, or the global one it inherits. */\n installed: ProjectConfig | null;\n /** Ids outside the round trip, from `skillsAuthoredHere` — one definition, both halves. */\n authoredHere: ReadonlySet<SkillId>;\n /**\n * Ids the payload NAMED that the decode could not place — `SeedMapping.skippedSkillIds`,\n * which is why they are ids off the wire rather than `SkillId`s of this catalogue.\n *\n * Stated by the caller rather than recomputed here: the decode already answered it, and a\n * second derivation could disagree with the skips the same run reported.\n */\n unplaceable: ReadonlySet<string>;\n};\n\nconst NOTHING_KEPT: KeptFromRoundTrip = {\n authoredSkillIds: [],\n unplaceableSkillIds: [],\n};\n\n/**\n * Puts back what this run may not remove, so the destructive apply removes only what it may.\n *\n * `edit --from` makes the project MATCH the payload: a skill the previous configuration\n * installed and this one omits is removed. Two kinds of installed entry are outside that\n * authority, and each is outside it for its own reason.\n *\n * A skill written here, because `forkedFrom` decides ownership and the producer drops a\n * directory carrying none: the payload never named it, so reading its absence as an instruction\n * to delete it would be this command inventing an instruction nobody gave. And an id the payload\n * DID name that this catalogue could not place, because there the instruction exists and the run\n * failed to carry it out — a destructive command removes on intent, never on its own inability.\n *\n * SCOPE IS NOT ONE OF THEM, and this module therefore takes no authority word. A globally\n * installed entry is removable through `edit --from` from a project as well as from the home\n * directory: the removal is shown, a project run additionally names every other project it\n * reaches, and the user answers. What is protected here is only what a removal may never be\n * INFERRED from, and an entry's scope infers nothing — it decides who else a removal touches,\n * which is the confirm's subject rather than this one's.\n *\n * Both are put back into the RESULT rather than excused at the writer, and that is the whole\n * point of this module. `authoritativeScope` decides whether the merger preserves a config row;\n * it does not protect the files, because the removal DIFF is what drives the plugin uninstall\n * and the `deleteLocalSkill` call. An entry left in the removal set is deleted from disk\n * whatever the merger later does with its row.\n *\n * What comes back with an entry matters as much as the entry. A kept skill with no stack row is\n * installed and loaded by no sub-agent; a kept skill whose domain fell off `selectedDomains` is\n * hidden from the next wizard, deselected by not being shown, and deleted by the run after this\n * one — a removal this one promised not to make.\n */\nexport function reconcileSharedConfig(options: ReconcileOptions): ReconciledSharedConfig {\n const { decoded, installed } = options;\n if (!installed) return { result: decoded, kept: NOTHING_KEPT };\n\n const keptSkills = skillsToKeep(options, installed);\n if (keptSkills.length === 0) return { result: decoded, kept: NOTHING_KEPT };\n\n return {\n result: withKeptEntries(decoded, installed, keptSkills),\n kept: describeKept(options, keptSkills),\n };\n}\n\n/**\n * The installed skills this run has to leave alone: absent from what the payload placed here,\n * and immune to removal by authorship, or because this catalogue could not place the id the\n * payload named.\n *\n * A tombstone is neither. It is a statement about something that is NOT installed here, so\n * there are no files to protect and nothing to tell the user is staying.\n */\nfunction skillsToKeep(options: ReconcileOptions, installed: ProjectConfig): SkillConfig[] {\n const named = new Set(options.decoded.skills.map((skill) => skill.id));\n\n return installed.skills.filter(\n (skill) => !skill.excluded && !named.has(skill.id) && mayNotRemove(skill, options),\n );\n}\n\n/** Whether either reason covers this entry — the question the split below refines. */\nfunction mayNotRemove(skill: SkillConfig, options: ReconcileOptions): boolean {\n return options.authoredHere.has(skill.id) || options.unplaceable.has(skill.id);\n}\n\ntype KeptReason = \"authored\" | \"unplaceable\";\n\nfunction describeKept(options: ReconcileOptions, keptSkills: SkillConfig[]): KeptFromRoundTrip {\n const idsKeptFor = (reason: KeptReason): SkillId[] =>\n keptSkills.filter((skill) => reasonKept(skill, options) === reason).map((skill) => skill.id);\n\n return {\n authoredSkillIds: idsKeptFor(\"authored\"),\n unplaceableSkillIds: idsKeptFor(\"unplaceable\"),\n };\n}\n\n/**\n * Which of the two an entry is disclosed as, where both are true — judged from the more\n * permanent claim to the less, because each statement carries its own remedy and only the one\n * that is true of the whole entry is worth naming.\n *\n * A skill nobody installed cannot be removed by any shared configuration from anywhere. An id\n * this catalogue cannot place is inert only for as long as this installation reads this\n * catalogue, so `update` is a real way out of it and nothing is a way out of the other.\n */\nfunction reasonKept(skill: SkillConfig, options: ReconcileOptions): KeptReason {\n return options.authoredHere.has(skill.id) ? \"authored\" : \"unplaceable\";\n}\n\n/** The payload, plus the entries it was never entitled to speak about. */\nfunction withKeptEntries(\n decoded: WizardResultV2,\n installed: ProjectConfig,\n keptSkills: SkillConfig[],\n): WizardResultV2 {\n return {\n ...decoded,\n skills: [...decoded.skills, ...keptSkills],\n selectedDomains: withKeptDomains(decoded.selectedDomains, keptSkills),\n ...(decoded.assignedStack !== undefined && {\n assignedStack: withKeptStackRows(decoded.assignedStack, installed.stack, {\n keptSkillIds: new Set(keptSkills.map((skill) => skill.id)),\n survivingAgents: new Set(decoded.selectedAgents),\n }),\n }),\n };\n}\n\n/** The domains the payload chose, plus the ones its kept entries still need a tab for. */\nfunction withKeptDomains(selected: Domain[], keptSkills: SkillConfig[]): Domain[] {\n const keptDomains = keptSkills.flatMap((skill) => domainOfSkill(skill.id) ?? []);\n const missing = keptDomains.filter((domain) => !selected.includes(domain));\n if (missing.length === 0) return selected;\n\n return orderDomains([...selected, ...new Set(missing)]);\n}\n\n/**\n * A kept skill's domain, where this catalogue knows the skill. Optional by nature rather than by\n * caution: a config entry the loaded source cannot resolve has no category to place, and\n * `edit`'s own unresolvable-entry path is what speaks about those.\n */\nfunction domainOfSkill(skillId: SkillId): Domain | undefined {\n const category = matrix.skills[skillId]?.category;\n return category === undefined ? undefined : getCategoryDomain(category);\n}\n\ntype KeptRowFilter = {\n keptSkillIds: ReadonlySet<SkillId>;\n survivingAgents: ReadonlySet<AgentName>;\n};\n\n/**\n * The installed stack rows a kept skill needs, folded into the payload's own.\n *\n * `assignedStack` REPLACES the ownership-derived stack rather than merging with it, so a row\n * this reconcile does not carry is a row nothing downstream re-derives. A kept skill is kept\n * because the payload never spoke about it, and a row naming it is the same silence one layer\n * down — so the row the installation already had is the only statement there is about it.\n *\n * A row under a sub-agent this configuration removes is dropped with it. That sub-agent IS this\n * run's to remove, and a stack row naming one no configuration installs is what `compile` warns\n * about and leaves out of the agents it writes.\n */\nfunction withKeptStackRows(\n assigned: Partial<Record<AgentName, StackAgentConfig>>,\n installedStack: Partial<Record<AgentName, StackAgentConfig>> | undefined,\n filter: KeptRowFilter,\n): Partial<Record<AgentName, StackAgentConfig>> {\n if (!installedStack) return assigned;\n\n const carried = { ...assigned };\n for (const [agent, agentStack] of typedEntries<AgentName, StackAgentConfig>(installedStack)) {\n if (!filter.survivingAgents.has(agent)) continue;\n\n const rows = keptRowsFor(agentStack, filter.keptSkillIds);\n if (typedKeys(rows).length === 0) continue;\n\n carried[agent] = { ...carried[agent], ...rows };\n }\n return carried;\n}\n\n/** One sub-agent's rows that a kept skill accounts for, category by category. */\nfunction keptRowsFor(\n agentStack: StackAgentConfig,\n keptSkillIds: ReadonlySet<SkillId>,\n): StackAgentConfig {\n const rows: StackAgentConfig = {};\n for (const [category, assignments] of typedEntries<Category, SkillAssignment[]>(agentStack)) {\n const carried = assignments.filter((assignment) => keptSkillIds.has(assignment.id));\n if (carried.length > 0) rows[category] = carried;\n }\n return rows;\n}\n"],"mappings":"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","names":[]}
@@ -5,16 +5,16 @@ import {
5
5
  loadSource,
6
6
  mutateGlobal,
7
7
  writeProjectPartial
8
- } from "../chunk-H2DHTJKW.js";
9
- import "../chunk-H25VRR2T.js";
10
- import "../chunk-H4CL23HG.js";
11
- import "../chunk-WMVOJY6V.js";
8
+ } from "../chunk-RJ3JYZJ7.js";
9
+ import "../chunk-LX7UXZBN.js";
10
+ import "../chunk-CICB4AKA.js";
11
+ import "../chunk-C5P7RUDR.js";
12
12
  import {
13
13
  BaseCommand,
14
14
  EXIT_CODES
15
- } from "../chunk-X52QUV4U.js";
16
- import "../chunk-TPQ5M3BW.js";
17
- import "../chunk-QNAMXQKF.js";
15
+ } from "../chunk-LJ6V54NR.js";
16
+ import "../chunk-IWUFZ6NR.js";
17
+ import "../chunk-4VVKVOOP.js";
18
18
  import {
19
19
  INCOMPLETE_WORK_RECOVERY,
20
20
  INFO_MESSAGES,
@@ -29,19 +29,19 @@ import {
29
29
  listDirectories,
30
30
  loadProjectSourceConfig,
31
31
  resolveSource
32
- } from "../chunk-3PJLLBUS.js";
32
+ } from "../chunk-OUG6TCQ4.js";
33
33
  import {
34
34
  matrix,
35
35
  typedKeys
36
- } from "../chunk-7Z4N4JWQ.js";
36
+ } from "../chunk-XX657S4U.js";
37
37
  import {
38
38
  CLAUDE_SRC_DIR,
39
39
  DIRS,
40
40
  LOCAL_SKILLS_PATH,
41
41
  PROJECT_ROOT,
42
42
  STANDARD_FILES
43
- } from "../chunk-G6G2FT2G.js";
44
- import "../chunk-VZRO7RYT.js";
43
+ } from "../chunk-5KB4I5J7.js";
44
+ import "../chunk-OI2H6M5I.js";
45
45
 
46
46
  // src/cli/commands/eject.ts
47
47
  import { Args, Flags } from "@oclif/core";