@canonical/pragma-cli 0.35.0 → 0.37.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 (295) hide show
  1. package/README.md +2 -2
  2. package/bundled-skills/add-standard/SKILL.md +338 -0
  3. package/bundled-skills/adoption-a1-styles/SKILL.md +269 -0
  4. package/bundled-skills/adoption-a2-components/SKILL.md +291 -0
  5. package/bundled-skills/adoption-a3-forms/SKILL.md +260 -0
  6. package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +406 -0
  7. package/bundled-skills/anatomy-author/SKILL.md +1226 -0
  8. package/bundled-skills/design-auditor/SKILL.md +455 -0
  9. package/bundled-skills/implement-component/SKILL.md +333 -0
  10. package/bundled-skills/specify-component/SKILL.md +331 -0
  11. package/bundled-skills/specify-pattern/SKILL.md +292 -0
  12. package/dist/package.json +24 -20
  13. package/dist/pragma.conf.js +266 -34
  14. package/dist/pragma.conf.js.map +1 -1
  15. package/dist/src/bin.js +1 -1
  16. package/dist/src/bin.js.map +1 -1
  17. package/dist/src/capabilities/capabilities/hints.js +1 -1
  18. package/dist/src/capabilities/capabilities/hints.js.map +1 -1
  19. package/dist/src/capabilities/colophon/colophon.render.js +1 -1
  20. package/dist/src/capabilities/colophon/colophon.render.js.map +1 -1
  21. package/dist/src/capabilities/create/create.verb.js +2 -1
  22. package/dist/src/capabilities/create/create.verb.js.map +1 -1
  23. package/dist/src/capabilities/create/createSurface.generated.js +23 -1
  24. package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
  25. package/dist/src/capabilities/create/mount.js +4 -3
  26. package/dist/src/capabilities/create/mount.js.map +1 -1
  27. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +11 -6
  28. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -1
  29. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +60 -4
  30. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -1
  31. package/dist/src/capabilities/doctor/checks/checkShellCompletions.js +8 -8
  32. package/dist/src/capabilities/doctor/checks/checkShellCompletions.js.map +1 -1
  33. package/dist/src/capabilities/doctor/checks/harnessInventory.js +195 -0
  34. package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -0
  35. package/dist/src/capabilities/doctor/checks/index.js +6 -6
  36. package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js +38 -0
  37. package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
  38. package/dist/src/capabilities/doctor/checks/targetHealth.js +194 -50
  39. package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
  40. package/dist/src/capabilities/doctor/doctor.render.js +43 -64
  41. package/dist/src/capabilities/doctor/doctor.render.js.map +1 -1
  42. package/dist/src/capabilities/doctor/doctor.verb.js +6 -2
  43. package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -1
  44. package/dist/src/capabilities/doctor/runChecks.js +14 -11
  45. package/dist/src/capabilities/doctor/runChecks.js.map +1 -1
  46. package/dist/src/capabilities/graph/query.render.js +2 -2
  47. package/dist/src/capabilities/graph/query.render.js.map +1 -1
  48. package/dist/src/capabilities/info/collectInfo.js +8 -2
  49. package/dist/src/capabilities/info/collectInfo.js.map +1 -1
  50. package/dist/src/capabilities/info/info.render.js +6 -2
  51. package/dist/src/capabilities/info/info.render.js.map +1 -1
  52. package/dist/src/capabilities/prompt/prompt.render.js +2 -2
  53. package/dist/src/capabilities/prompt/prompt.render.js.map +1 -1
  54. package/dist/src/capabilities/setup/buildPlan.js +43 -39
  55. package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
  56. package/dist/src/capabilities/setup/mode.js +2 -2
  57. package/dist/src/capabilities/setup/operations/index.js +4 -4
  58. package/dist/src/capabilities/setup/operations/index.js.map +1 -1
  59. package/dist/src/capabilities/setup/operations/setupCompletions.js +6 -2
  60. package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
  61. package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
  62. package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
  63. package/dist/src/capabilities/setup/operations/setupGenerator.js +156 -58
  64. package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
  65. package/dist/src/capabilities/setup/operations/setupLsp.js +136 -38
  66. package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
  67. package/dist/src/capabilities/setup/operations/setupMcp.js +101 -52
  68. package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
  69. package/dist/src/capabilities/setup/operations/setupSkills.js +329 -49
  70. package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
  71. package/dist/src/capabilities/setup/plan.js.map +1 -1
  72. package/dist/src/capabilities/setup/plan.render.js +144 -66
  73. package/dist/src/capabilities/setup/plan.render.js.map +1 -1
  74. package/dist/src/capabilities/setup/setup.render.js +1 -1
  75. package/dist/src/capabilities/setup/setup.verb.js +165 -63
  76. package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
  77. package/dist/src/capabilities/setup/targets.js +122 -51
  78. package/dist/src/capabilities/setup/targets.js.map +1 -1
  79. package/dist/src/capabilities/shared/index.js +7 -6
  80. package/dist/src/capabilities/shared/index.js.map +1 -1
  81. package/dist/src/capabilities/shared/packageManager.js +300 -54
  82. package/dist/src/capabilities/shared/packageManager.js.map +1 -1
  83. package/dist/src/capabilities/skill/discover.js +97 -11
  84. package/dist/src/capabilities/skill/discover.js.map +1 -1
  85. package/dist/src/capabilities/skill/render.js +2 -2
  86. package/dist/src/capabilities/skill/render.js.map +1 -1
  87. package/dist/src/capabilities/sources/installSkills.js +145 -3
  88. package/dist/src/capabilities/sources/installSkills.js.map +1 -1
  89. package/dist/src/capabilities/sources/runUpdate.js +68 -2
  90. package/dist/src/capabilities/sources/runUpdate.js.map +1 -1
  91. package/dist/src/capabilities/sources/update.verb.js +3 -3
  92. package/dist/src/capabilities/sources/update.verb.js.map +1 -1
  93. package/dist/src/capabilities/upgrade/runUpgrade.js +43 -7
  94. package/dist/src/capabilities/upgrade/runUpgrade.js.map +1 -1
  95. package/dist/src/capabilities/upgrade/upgrade.render.js +10 -2
  96. package/dist/src/capabilities/upgrade/upgrade.render.js.map +1 -1
  97. package/dist/src/constants.js +13 -2
  98. package/dist/src/constants.js.map +1 -1
  99. package/dist/src/kernel/index.js +11 -2
  100. package/dist/src/kernel/index.js.map +1 -1
  101. package/dist/src/kernel/interactivity.js +68 -0
  102. package/dist/src/kernel/interactivity.js.map +1 -0
  103. package/dist/src/kernel/packs/renderPack.js +3 -3
  104. package/dist/src/kernel/packs/renderPack.js.map +1 -1
  105. package/dist/src/kernel/packs/resolveEntity.js +63 -12
  106. package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
  107. package/dist/src/kernel/packs/runBodies.js +57 -4
  108. package/dist/src/kernel/packs/runBodies.js.map +1 -1
  109. package/dist/src/kernel/packs/schema.js +54 -2
  110. package/dist/src/kernel/packs/schema.js.map +1 -1
  111. package/dist/src/kernel/packs/sparql/applyFilters.js +104 -5
  112. package/dist/src/kernel/packs/sparql/applyFilters.js.map +1 -1
  113. package/dist/src/kernel/packs/sparql/buildLookupQuery.js +310 -43
  114. package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
  115. package/dist/src/kernel/packs/types.js.map +1 -1
  116. package/dist/src/kernel/project/cli/buildProgram.js +1 -1
  117. package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
  118. package/dist/src/kernel/project/cli/dispatch.js +46 -24
  119. package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
  120. package/dist/src/kernel/project/cli/globalFlags.js +4 -1
  121. package/dist/src/kernel/project/cli/globalFlags.js.map +1 -1
  122. package/dist/src/kernel/project/cli/helpFormat.js +1 -2
  123. package/dist/src/kernel/project/cli/helpFormat.js.map +1 -1
  124. package/dist/src/kernel/project/cli/rootHelp.js +42 -9
  125. package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
  126. package/dist/src/kernel/project/mcp/registerVerb.js +16 -1
  127. package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
  128. package/dist/src/kernel/render/renderers.js +1 -1
  129. package/dist/src/kernel/render/style.js +29 -9
  130. package/dist/src/kernel/render/style.js.map +1 -1
  131. package/dist/src/kernel/render/vocabulary.js +174 -0
  132. package/dist/src/kernel/render/vocabulary.js.map +1 -0
  133. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +2 -3
  134. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
  135. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
  136. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
  137. package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
  138. package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
  139. package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
  140. package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
  141. package/dist/src/kernel/runtime/graphpack/read.js +14 -9
  142. package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
  143. package/dist/src/kernel/runtime/loadSession.js +3 -1
  144. package/dist/src/kernel/runtime/loadSession.js.map +1 -1
  145. package/dist/src/kernel/runtime/probe.js +1 -1
  146. package/dist/src/kernel/runtime/probe.js.map +1 -1
  147. package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
  148. package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
  149. package/dist/src/kernel/runtime/refs/resolve.js +9 -3
  150. package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
  151. package/dist/src/kernel/spec/emitReference.js +1 -1
  152. package/dist/src/kernel/spec/emitReference.js.map +1 -1
  153. package/package.json +24 -20
  154. package/pragma.conf.ts +272 -34
  155. package/src/bin.ts +8 -1
  156. package/src/capabilities/block.parity.test.ts +25 -11
  157. package/src/capabilities/block.shipped.exec.test.ts +282 -0
  158. package/src/capabilities/block.tierRank.exec.test.ts +300 -0
  159. package/src/capabilities/capabilities/hints.ts +1 -1
  160. package/src/capabilities/colophon/colophon.render.ts +1 -2
  161. package/src/capabilities/colophon/colophon.test.ts +2 -2
  162. package/src/capabilities/config/collectConfigShow.test.ts +1 -0
  163. package/src/capabilities/create/byteEquality.test.ts +28 -1
  164. package/src/capabilities/create/create.test.ts +1 -0
  165. package/src/capabilities/create/create.verb.ts +2 -1
  166. package/src/capabilities/create/createGrammar.test.ts +5 -2
  167. package/src/capabilities/create/createSurface.generated.ts +23 -1
  168. package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
  169. package/src/capabilities/create/mount.ts +3 -3
  170. package/src/capabilities/distribution.parity.test.ts +4 -0
  171. package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
  172. package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
  173. package/src/capabilities/doctor/checks/checkPackageRefs.ts +69 -4
  174. package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +6 -4
  175. package/src/capabilities/doctor/checks/checkShellCompletions.ts +8 -8
  176. package/src/capabilities/doctor/checks/harnessInventory.test.ts +219 -0
  177. package/src/capabilities/doctor/checks/harnessInventory.ts +298 -0
  178. package/src/capabilities/doctor/checks/index.ts +6 -6
  179. package/src/capabilities/doctor/checks/isSupportedNodeVersion.test.ts +111 -0
  180. package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
  181. package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
  182. package/src/capabilities/doctor/checks/targetHealth.ts +229 -59
  183. package/src/capabilities/doctor/doctor.render.test.ts +108 -32
  184. package/src/capabilities/doctor/doctor.render.ts +56 -80
  185. package/src/capabilities/doctor/doctor.test.ts +247 -35
  186. package/src/capabilities/doctor/doctor.verb.ts +7 -2
  187. package/src/capabilities/doctor/runChecks.ts +14 -11
  188. package/src/capabilities/doctor/types.ts +15 -24
  189. package/src/capabilities/emptyRecovery.test.ts +10 -2
  190. package/src/capabilities/graph/query.render.ts +2 -2
  191. package/src/capabilities/info/collectInfo.ts +8 -1
  192. package/src/capabilities/info/info.render.ts +6 -2
  193. package/src/capabilities/info/info.test.ts +37 -1
  194. package/src/capabilities/info/types.ts +10 -2
  195. package/src/capabilities/lazy.test.ts +26 -2
  196. package/src/capabilities/listLookup.shipped.exec.test.ts +340 -0
  197. package/src/capabilities/prompt/prompt.render.ts +2 -2
  198. package/src/capabilities/renderVocabularySync.test.ts +82 -0
  199. package/src/capabilities/resources/resources.test.ts +38 -2
  200. package/src/capabilities/scopeTypeSync.test.ts +29 -15
  201. package/src/capabilities/setup/buildPlan.ts +45 -41
  202. package/src/capabilities/setup/index.ts +1 -1
  203. package/src/capabilities/setup/mode.ts +2 -2
  204. package/src/capabilities/setup/operations/index.ts +6 -1
  205. package/src/capabilities/setup/operations/setupCompletions.ts +9 -2
  206. package/src/capabilities/setup/operations/setupConfig.ts +7 -2
  207. package/src/capabilities/setup/operations/setupGenerator.ts +227 -84
  208. package/src/capabilities/setup/operations/setupLsp.ts +203 -38
  209. package/src/capabilities/setup/operations/setupMcp.ts +139 -62
  210. package/src/capabilities/setup/operations/setupSkills.ts +399 -60
  211. package/src/capabilities/setup/plan.render.ts +171 -76
  212. package/src/capabilities/setup/plan.ts +17 -12
  213. package/src/capabilities/setup/setup.mcp.correctness.test.ts +9 -9
  214. package/src/capabilities/setup/setup.render.test.ts +50 -36
  215. package/src/capabilities/setup/setup.render.ts +1 -1
  216. package/src/capabilities/setup/setup.test.ts +1126 -50
  217. package/src/capabilities/setup/setup.verb.ts +174 -68
  218. package/src/capabilities/setup/targets.ts +138 -60
  219. package/src/capabilities/setup/types.ts +10 -18
  220. package/src/capabilities/shared/index.ts +18 -6
  221. package/src/capabilities/shared/packageManager.test.ts +421 -6
  222. package/src/capabilities/shared/packageManager.ts +394 -59
  223. package/src/capabilities/skill/bundledSkills.test.ts +347 -0
  224. package/src/capabilities/skill/discover.ts +100 -11
  225. package/src/capabilities/skill/render.ts +2 -2
  226. package/src/capabilities/skill/skill.test.ts +17 -4
  227. package/src/capabilities/sources/installSkills.ts +181 -3
  228. package/src/capabilities/sources/runUpdate.ts +78 -2
  229. package/src/capabilities/sources/sources.test.ts +228 -0
  230. package/src/capabilities/sources/update.verb.ts +3 -3
  231. package/src/capabilities/surface.test.ts +14 -6
  232. package/src/capabilities/upgrade/runUpgrade.ts +45 -6
  233. package/src/capabilities/upgrade/types.ts +10 -2
  234. package/src/capabilities/upgrade/upgrade.render.ts +9 -2
  235. package/src/capabilities/upgrade/upgrade.test.ts +72 -0
  236. package/src/constants.ts +14 -1
  237. package/src/identity.test.ts +18 -5
  238. package/src/kernel/completion/entitySource.test.ts +15 -2
  239. package/src/kernel/completion/safety.test.ts +16 -9
  240. package/src/kernel/config/defaults.test.ts +19 -3
  241. package/src/kernel/config/readConfig.test.ts +1 -1
  242. package/src/kernel/index.ts +11 -2
  243. package/src/kernel/interactivity.test.ts +76 -0
  244. package/src/kernel/interactivity.ts +69 -0
  245. package/src/kernel/packs/compile.test.ts +92 -0
  246. package/src/kernel/packs/renderPack.ts +3 -3
  247. package/src/kernel/packs/resolveEntity.test.ts +75 -14
  248. package/src/kernel/packs/resolveEntity.ts +88 -24
  249. package/src/kernel/packs/runBodies.ts +84 -19
  250. package/src/kernel/packs/schema.ts +60 -4
  251. package/src/kernel/packs/sparql/applyFilters.ts +125 -4
  252. package/src/kernel/packs/sparql/buildLookupQuery.test.ts +290 -0
  253. package/src/kernel/packs/sparql/buildLookupQuery.ts +327 -45
  254. package/src/kernel/packs/toolDescription.test.ts +35 -1
  255. package/src/kernel/packs/types.ts +125 -2
  256. package/src/kernel/project/cli/buildProgram.test.ts +73 -2
  257. package/src/kernel/project/cli/buildProgram.ts +8 -1
  258. package/src/kernel/project/cli/dispatch.test.ts +5 -4
  259. package/src/kernel/project/cli/dispatch.ts +48 -25
  260. package/src/kernel/project/cli/globalFlags.ts +4 -1
  261. package/src/kernel/project/cli/helpFormat.ts +1 -2
  262. package/src/kernel/project/cli/rootHelp.ts +44 -8
  263. package/src/kernel/project/mcp/registerVerb.ts +20 -1
  264. package/src/kernel/render/prefixes.test.ts +2 -0
  265. package/src/kernel/render/renderers.ts +1 -1
  266. package/src/kernel/render/style.ts +32 -9
  267. package/src/kernel/render/vocabulary.ts +276 -0
  268. package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +2 -3
  269. package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
  270. package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
  271. package/src/kernel/runtime/graphpack/embedded.ts +14 -6
  272. package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
  273. package/src/kernel/runtime/graphpack/read.ts +14 -12
  274. package/src/kernel/runtime/loadSession.ts +3 -1
  275. package/src/kernel/runtime/probe.ts +1 -1
  276. package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
  277. package/src/kernel/runtime/refs/parseRef.ts +25 -1
  278. package/src/kernel/runtime/refs/resolve.ts +9 -3
  279. package/src/kernel/runtime/types.ts +17 -0
  280. package/src/kernel/spec/emitReference.ts +1 -1
  281. package/src/kernel/spec/types.ts +35 -6
  282. package/src/testing/PARITY_GAPS.ts +9 -3
  283. package/src/testing/behavioral/docExamples.test.ts +4 -2
  284. package/src/testing/behavioral/errorMatrix.mcp.test.ts +110 -7
  285. package/src/testing/behavioral/journeys.firstInstall.test.ts +7 -2
  286. package/src/testing/behavioral/journeys.packageStories.test.ts +6 -3
  287. package/src/testing/eval/__snapshots__/eval.test.ts.snap +26 -1
  288. package/src/testing/eval/cases/readNouns.ts +245 -9
  289. package/src/testing/fixtures/blockGraph.ts +28 -13
  290. package/src/testing/fixtures/graph/canonical.ts +95 -12
  291. package/src/testing/helpers/runCli.test.ts +44 -0
  292. package/src/testing/helpers/runCli.ts +27 -3
  293. package/dist/src/capabilities/shared/bands.js +0 -16
  294. package/dist/src/capabilities/shared/bands.js.map +0 -1
  295. package/src/capabilities/shared/bands.ts +0 -16
@@ -10,11 +10,11 @@
10
10
  * Every selected target is a visible row here, including the ones that skip.
11
11
  */
12
12
  import { defaultSelected, } from "./plan.js";
13
- import { supportsBand, TARGETS, } from "./targets.js";
13
+ import { supportsScope, TARGETS, } from "./targets.js";
14
14
  /** The failure a row's detection ended in, or `undefined` when it settled. */
15
15
  export const detectionFailure = (row) => row.failure;
16
- /** The bands a `--scope` selection runs, global before project. */
17
- export const bandsForScope = (scope) => scope === "both" ? ["global", "project"] : [scope];
16
+ /** The scopes a `--scope` selection runs, global before project. */
17
+ export const scopesForSelection = (scope) => scope === "both" ? ["global", "project"] : [scope];
18
18
  /**
19
19
  * The two named roots. The global root is the user's home directory (rendered
20
20
  * `~`), the project root is the directory the invocation resolves against.
@@ -30,7 +30,7 @@ export async function resolveRoots(rt) {
30
30
  /** The cause a rejected detection carries, as one line of copy. */
31
31
  const messageOf = (reason) => reason instanceof Error ? reason.message : String(reason);
32
32
  /**
33
- * Detect every requested target in every band the scope runs.
33
+ * Detect every requested target in every scope the scope runs.
34
34
  *
35
35
  * Detections are started together and SETTLED INDEPENDENTLY: they are
36
36
  * independent reads, and a run-all that probed five targets serially paid for
@@ -40,53 +40,57 @@ const messageOf = (reason) => reason instanceof Error ? reason.message : String(
40
40
  * unreadable config, a permission-denied directory — takes only its own row
41
41
  * down. Awaiting them as one `Promise.all` meant the first rejection prevented
42
42
  * a run from being built at all: none of the other targets ran, and doctor
43
- * rendered no banded rows whatsoever. The failed row carries its cause and is
43
+ * rendered no scoped rows whatsoever. The failed row carries its cause and is
44
44
  * reported as a row, which is the same shape a failed COMPOSE already has.
45
45
  *
46
46
  * @param rt - The per-invocation runtime.
47
47
  * @param ids - The targets to plan (all five for the run-all).
48
- * @param scope - The resolved band selection.
49
- * @returns One entry per (target, band) the scope actually runs.
48
+ * @param scope - The resolved scope selection.
49
+ * @returns One entry per (target, scope) the scope actually runs.
50
50
  * @note Impure — every target's `detect` reads the real filesystem.
51
51
  */
52
52
  export async function detectTargets(rt, ids, scope) {
53
53
  const wanted = TARGETS.filter((target) => ids.includes(target.id));
54
- const pairs = bandsForScope(scope).flatMap((band) => wanted
55
- .filter((target) => supportsBand(target, band))
54
+ const pairs = scopesForSelection(scope).flatMap((scope) => wanted
55
+ .filter((target) => supportsScope(target, scope))
56
56
  .map((target) => ({
57
57
  target,
58
- band,
58
+ scope,
59
59
  })));
60
- const settled = await Promise.allSettled(pairs.map(({ target, band }) => target.detect(rt, band)));
61
- return pairs.map(({ target, band }, index) => {
60
+ const settled = await Promise.allSettled(pairs.map(({ target, scope }) => target.detect(rt, scope)));
61
+ return pairs.map(({ target, scope }, index) => {
62
62
  const outcome = settled[index];
63
63
  if (outcome.status === "fulfilled") {
64
- return { target, band, detection: outcome.value };
64
+ return { target, scope, detection: outcome.value };
65
65
  }
66
66
  return {
67
67
  target,
68
- band,
68
+ scope,
69
69
  detection: undefined,
70
70
  failure: messageOf(outcome.reason),
71
71
  };
72
72
  });
73
73
  }
74
74
  /**
75
- * The dim row a target gets when the SELECTED band cannot hold it — `setup
76
- * --local` still shows `completions`, saying why it is not in this run. A band
77
- * merely filters the run-all: the user asked for a band, not for that target, so
75
+ * The dim row a target gets when the SELECTED scope cannot hold it — `setup
76
+ * --local` still shows `completions`, saying why it is not in this run. A scope
77
+ * merely filters the run-all: the user asked for a scope, not for that target, so
78
78
  * nothing errors, but nothing is silently absent either. (Asking for the
79
- * impossible band on the SUB-VERB is a different thing entirely — a typed
79
+ * impossible scope on the SUB-VERB is a different thing entirely — a typed
80
80
  * contradiction, and a usage error.)
81
+ *
82
+ * The reason names the flag that WOULD reach the target, so the row is not a
83
+ * dead end: a reader who wanted `completions` under `--local` is told in the
84
+ * same line that `--global` is where it lives.
81
85
  */
82
- const outOfBandRow = (target, band) => ({
86
+ const outOfScopeRow = (target, scope) => ({
83
87
  target: target.id,
84
- band,
88
+ scope,
85
89
  action: "skip",
86
- detail: "not in this band",
87
- reason: band === "project"
88
- ? "user-level only — it has no project band"
89
- : "project-level only — it has no global band",
90
+ detail: "not part of this scope",
91
+ reason: scope === "project"
92
+ ? "this one is global only — run it with `--global`"
93
+ : "this one is per-project only — run it with `--local`",
90
94
  selected: false,
91
95
  });
92
96
  /**
@@ -96,9 +100,9 @@ const outOfBandRow = (target, band) => ({
96
100
  * into a `failed` outcome, so the run exits non-zero naming this target rather
97
101
  * than reporting a clean sweep over the targets that did settle.
98
102
  */
99
- const failedDetectionRow = (target, band, failure) => ({
103
+ const failedDetectionRow = (target, scope, failure) => ({
100
104
  target: target.id,
101
- band,
105
+ scope,
102
106
  action: "skip",
103
107
  detail: "detection did not complete",
104
108
  reason: failure,
@@ -117,44 +121,44 @@ const failedDetectionRow = (target, band, failure) => ({
117
121
  */
118
122
  export function draftFor(hit, roots, removal) {
119
123
  return removal
120
- ? hit.target.removalPlan(hit.detection, hit.band, roots)
121
- : hit.target.plan(hit.detection, hit.band, roots);
124
+ ? hit.target.removalPlan(hit.detection, hit.scope, roots)
125
+ : hit.target.plan(hit.detection, hit.scope, roots);
122
126
  }
123
127
  /**
124
128
  * Project detections into plan rows.
125
129
  *
126
- * @param scope - The resolved band selection (named in the header).
130
+ * @param selection - The resolved scope selection (named in the header).
127
131
  * @param roots - The two named roots every path renders relative to.
128
- * @param detected - The detections, in table order per band.
129
- * @param ids - The targets that were REQUESTED, so an out-of-band one still
132
+ * @param detected - The detections, in table order per scope.
133
+ * @param ids - The targets that were REQUESTED, so an out-of-scope one still
130
134
  * gets a visible row.
131
135
  * @param removal - Build the removal plan (`--undo`) instead of the forward one.
132
136
  * @returns The plan.
133
137
  */
134
- export function buildPlan(scope, roots, detected, ids, removal = false) {
138
+ export function buildPlan(selection, roots, detected, ids, removal = false) {
135
139
  const rows = [];
136
- for (const band of bandsForScope(scope)) {
140
+ for (const scope of scopesForSelection(selection)) {
137
141
  for (const target of TARGETS) {
138
142
  if (!ids.includes(target.id))
139
143
  continue;
140
- const hit = detected.find((d) => d.target.id === target.id && d.band === band);
144
+ const hit = detected.find((d) => d.target.id === target.id && d.scope === scope);
141
145
  if (hit === undefined) {
142
- // Only worth a line when the target has no row in ANY selected band —
146
+ // Only worth a line when the target has no row in ANY selected scope —
143
147
  // under `--scope both` a global-only target already appears above.
144
148
  const elsewhere = detected.some((d) => d.target.id === target.id);
145
149
  if (!elsewhere)
146
- rows.push(outOfBandRow(target, band));
150
+ rows.push(outOfScopeRow(target, scope));
147
151
  continue;
148
152
  }
149
153
  const failure = detectionFailure(hit);
150
154
  if (failure !== undefined) {
151
- rows.push(failedDetectionRow(target, band, failure));
155
+ rows.push(failedDetectionRow(target, scope, failure));
152
156
  continue;
153
157
  }
154
158
  const draft = draftFor(hit, roots, removal);
155
159
  rows.push({
156
160
  target: target.id,
157
- band,
161
+ scope,
158
162
  action: draft.action,
159
163
  detail: draft.detail,
160
164
  ...(draft.reason === undefined ? {} : { reason: draft.reason }),
@@ -163,6 +167,6 @@ export function buildPlan(scope, roots, detected, ids, removal = false) {
163
167
  });
164
168
  }
165
169
  }
166
- return { scope, roots, rows };
170
+ return { scope: selection, roots, rows };
167
171
  }
168
172
  //# sourceMappingURL=buildPlan.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildPlan.js","sourceRoot":"","sources":["../../../../src/capabilities/setup/buildPlan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildPlan.js","sourceRoot":"","sources":["../../../../src/capabilities/setup/buildPlan.ts"],"names":[],"mappings":"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"}
@@ -20,8 +20,8 @@
20
20
  * who forgot `--yes` reads the hint on the very output they are capturing.
21
21
  *
22
22
  * An MCP tool call is programmatic consent: `transport === "mcp"` resolves as if
23
- * `--yes` were passed. The band default applies there too — the tool writes the
24
- * global band unless told otherwise.
23
+ * `--yes` were passed. The scope default applies there too — the tool writes the
24
+ * global scope unless told otherwise.
25
25
  */
26
26
  /**
27
27
  * Lift the decision inputs off a runtime. A tool call over MCP counts as `yes`.
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * The detection types are part of the surface, not an implementation leak: a
15
15
  * detection is the value passed from the read half to the compose half and on
16
- * to the plan rows, so `doctor`'s banded checks name the same records `setup`
16
+ * to the plan rows, so `doctor`'s scoped checks name the same records `setup`
17
17
  * acts on. The presentation helpers travel with them for the same reason — a
18
18
  * skip reason or an uninstall remedy is derived from one detection, and
19
19
  * deriving it twice is how the two surfaces start disagreeing about the same
@@ -33,7 +33,7 @@
33
33
  export { composeCompletions, composeCompletionsRemoval, detectCompletions, } from "./setupCompletions.js";
34
34
  export { composeConfigFile, composeConfigRemoval, detectConfigFile, } from "./setupConfig.js";
35
35
  export { buildSetupRun } from "./setupGenerator.js";
36
- export { composeLsp, composeLspRemoval, detectLsp, LSP_SKIP_REMEDY, lspEditorNames, lspSkipReason, lspUninstallRemedy, } from "./setupLsp.js";
37
- export { composeMcp, composeMcpRemoval, detectMcp, mcpGroupState, ownedMcpGroups, selectedGroups, } from "./setupMcp.js";
38
- export { composeSkills, composeSkillsRemoval, detectSkills, ownedSkillLinks, skillsSkipReason, } from "./setupSkills.js";
36
+ export { composeLsp, composeLspRemoval, detectLsp, LSP_SKIP_REMEDY, lspEditorNames, lspSkipReason, lspUninstallRemedy, ownedLspEditors, } from "./setupLsp.js";
37
+ export { composeMcp, composeMcpRemoval, detectMcp, mcpGroupState, mcpWriteState, ownedMcpGroups, selectedGroups, } from "./setupMcp.js";
38
+ export { composeSkills, composeSkillsRemoval, detectSkills, ownedSkillLinks, skillsSkipReason, skillsSkipRemedy, staleSkillLinks, withinRoot, } from "./setupSkills.js";
39
39
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,aAAa,EACb,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,eAAe,EACf,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,UAAU,GACX,MAAM,kBAAkB,CAAC"}
@@ -149,12 +149,16 @@ export function composeCompletions(d) {
149
149
  * machine that never installed one reverses zero steps and says so.
150
150
  *
151
151
  * @param d - The detection gathered up front.
152
+ * @param undoKey - Correlation key stamped on the reversal(s), echoed on
153
+ * their undo outcomes so the caller can read results back per row.
152
154
  * @returns A Task whose undo deletes the installed script.
153
155
  */
154
- export function composeCompletionsRemoval(d) {
156
+ export function composeCompletionsRemoval(d, undoKey) {
155
157
  if (d.path === null || d.script === null || d.state === "absent") {
156
158
  return sequence_([]);
157
159
  }
158
- return sequence_([writeFile(d.path, d.script, { undo: deleteFile(d.path) })]);
160
+ return sequence_([
161
+ writeFile(d.path, d.script, { undo: deleteFile(d.path), undoKey }),
162
+ ]);
159
163
  }
160
164
  //# sourceMappingURL=setupCompletions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setupCompletions.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupCompletions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setupCompletions.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupCompletions.ts"],"names":[],"mappings":"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"}
@@ -87,13 +87,15 @@ export function composeConfigFile(d) {
87
87
  * delete as its `undo`, which is what the undo interpreter executes.
88
88
  *
89
89
  * @param d - The detection gathered up front.
90
+ * @param undoKey - Correlation key stamped on the reversal(s), echoed on
91
+ * their undo outcomes so the caller can read results back per row.
90
92
  * @returns A Task whose undo removes a seed-only config, or an empty Task.
91
93
  */
92
- export function composeConfigRemoval(d) {
94
+ export function composeConfigRemoval(d, undoKey) {
93
95
  if (!d.exists || !d.isSeed)
94
96
  return sequence_([]);
95
97
  return sequence_([
96
- writeFile(d.path, SEED_CONFIG, { undo: deleteFile(d.path) }),
98
+ writeFile(d.path, SEED_CONFIG, { undo: deleteFile(d.path), undoKey }),
97
99
  ]);
98
100
  }
99
101
  /** The line a removal prints when the file carries the user's own settings. */
@@ -1 +1 @@
1
- {"version":3,"file":"setupConfig.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,IAAI,EACJ,KAAK,EACL,SAAS,EAET,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,mEAAmE;AACnE,wEAAwE;AACxE,2EAA2E;AAC3E,wEAAwE;AACxE,8BAA8B;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAclC,4EAA4E;AAC5E,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,OAAO,CACL,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CACjC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAkB;IAClD,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;QACf,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;QAC5B,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAkB;IACrD,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC;QACf,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAc,EAAE,CAC5D,IAAI,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC"}
1
+ {"version":3,"file":"setupConfig.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,IAAI,EACJ,KAAK,EACL,SAAS,EAET,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,mEAAmE;AACnE,wEAAwE;AACxE,2EAA2E;AAC3E,wEAAwE;AACxE,8BAA8B;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAclC,4EAA4E;AAC5E,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,OAAO,CACL,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CACjC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAkB;IAClD,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;QACf,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;QAC5B,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,CAAkB,EAClB,OAAgB;IAEhB,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC;QACf,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAc,EAAE,CAC5D,IAAI,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC"}
@@ -5,7 +5,7 @@
5
5
  * gate, live progress, colours, and the shared cancel fixes by construction.
6
6
  *
7
7
  * The shape mirrors `create`: detection runs FOR REAL up front (once per
8
- * target/band, in `detectTargets`), then a PURE `generate` composes only the
8
+ * target/scope, in `detectTargets`), then a PURE `generate` composes only the
9
9
  * effects for the SELECTED rows. `generate` must stay re-interpretable —
10
10
  * `execute` invokes it more than once (the confirm-gate preview and the build) —
11
11
  * so it is composed from combinators and does no reads of its own.
@@ -36,8 +36,8 @@ const CHILD_ANSWER = {
36
36
  mcp: MCP_FILES_ANSWER,
37
37
  lsp: LSP_EDITORS_ANSWER,
38
38
  };
39
- /** A row's identity in an answer bag: band-qualified, so `both` stays unambiguous. */
40
- const rowKey = (band, target) => `${band}:${target}`;
39
+ /** A row's identity in an answer bag: scope-qualified, so `both` stays unambiguous. */
40
+ const rowKey = (scope, target) => `${scope}:${target}`;
41
41
  /**
42
42
  * Where a failed row's error lands during interpretation.
43
43
  *
@@ -87,11 +87,28 @@ const rowPragmaError = (error) => error.cause instanceof PragmaError
87
87
  * throw bypasses the trampoline's recovery frames — which is why the row bodies
88
88
  * raise via `checkExecOk`/`failPragma`, never a bare throw. Interruption bypasses
89
89
  * recovery by interpreter invariant, so Ctrl-C still stops the whole run.
90
+ *
91
+ * Each row is also BRACKETED with {@link RowEvent}s — `start` as its body is
92
+ * entered, `done`/`failed` as it settles — emitted from the continuations,
93
+ * which run at interpretation time. Like the sink writes beside them, the
94
+ * emits capture nothing IN the task: the composition stays pure and
95
+ * re-interpretable, and each drive simply narrates itself as it runs.
90
96
  */
91
- const runRowsIsolated = (sink, rows) => flatMap(pure(undefined), () => {
97
+ const runRowsIsolated = (sink, rows, emit) => flatMap(pure(undefined), () => {
92
98
  sink.clear();
93
- return sequence_(rows.map(({ key, task }) => recover(task, (error) => flatMap(warn(`The ${key.split(":")[1]} step did not complete — continuing with the remaining targets.`), () => {
99
+ return sequence_(rows.map(({ key, label, doneLabel, task }) => recover(flatMap(pure(undefined), () => {
100
+ emit({ key, label, status: "start" });
101
+ return flatMap(task, () => {
102
+ emit({ key, label: doneLabel, status: "done" });
103
+ return pure(undefined);
104
+ });
105
+ }), (error) => flatMap(warn(`The ${key.split(":")[1]} step did not complete — continuing with the remaining targets.`), () => {
94
106
  sink.record(key, error);
107
+ emit({
108
+ key,
109
+ label: `${label} — ${rowPragmaError(error).message}`,
110
+ status: "failed",
111
+ });
95
112
  return pure(undefined);
96
113
  }))));
97
114
  });
@@ -116,7 +133,7 @@ const buildRowsPrompt = (plan) => {
116
133
  .filter((row) => row.action !== "skip")
117
134
  .map((row) => ({
118
135
  label: `${row.target} — ${row.detail}${row.action === "none" ? " (already configured)" : ""}`,
119
- value: rowKey(row.band, row.target),
136
+ value: rowKey(row.scope, row.target),
120
137
  }));
121
138
  return {
122
139
  name: ROWS_ANSWER,
@@ -125,23 +142,26 @@ const buildRowsPrompt = (plan) => {
125
142
  choices,
126
143
  default: plan.rows
127
144
  .filter((row) => row.selected)
128
- .map((row) => rowKey(row.band, row.target)),
145
+ .map((row) => rowKey(row.scope, row.target)),
129
146
  };
130
147
  };
131
- /** The opt-in "customize which files" gate — defaults to false. */
132
- const buildCustomizePrompt = (when) => ({
133
- name: "customize",
134
- type: "confirm",
135
- message: `Customize which files ${BIN_NAME} configures?`,
136
- default: false,
137
- when,
138
- });
139
148
  /**
140
149
  * The per-file MCP multiselect — one row per deduplicated config file, across
141
- * every band the run covers. An already-current file is DEFAULT-DESELECTED; a
142
- * file that is absent or drifted stays selected. Retained unchanged from the
143
- * landed opt-in narrowing: it is row-level CHILD selection, which is exactly
144
- * what the plan's child rows are.
150
+ * every scope the run covers. An already-current file is DEFAULT-DESELECTED; a
151
+ * file that is absent or drifted stays selected. It is row-level CHILD
152
+ * selection, which is exactly what the plan's child rows are.
153
+ *
154
+ * It used to sit behind a meta-question — "Customize which files pragma
155
+ * configures?", answered no by default. That gate was read in exactly ONE place
156
+ * in the repo (this prompt's `when`) and nowhere else: not by `generate`, not by
157
+ * `applied`, not by any plan, recap, renderer or JSON projection. Answering no
158
+ * meant the child prompt was never asked, its key was absent from the answer
159
+ * bag, `readList` returned `undefined`, and the compose bodies read that as
160
+ * "all" — so everything detected was configured anyway. A meta-question in front
161
+ * of a direct question is one more thing to answer and no more control; the
162
+ * choices below already carry the detected state per child (`— unchanged`,
163
+ * `— add`, `— update`), which is the answer the meta-question was standing in
164
+ * front of.
145
165
  */
146
166
  const buildChildPrompt = (plan, target, message, when) => {
147
167
  const children = childrenOf(plan, target);
@@ -159,7 +179,7 @@ const buildChildPrompt = (plan, target, message, when) => {
159
179
  .map((child) => child.key),
160
180
  };
161
181
  };
162
- /** Every child row a target contributes, across the bands in the plan. */
182
+ /** Every child row a target contributes, across the scopes in the plan. */
163
183
  const childrenOf = (plan, target) => plan.rows
164
184
  .filter((row) => row.target === target)
165
185
  .flatMap((row) => row.children ?? []);
@@ -167,7 +187,7 @@ const childrenOf = (plan, target) => plan.rows
167
187
  const isChosen = (row, chosen) => row.action !== "skip" &&
168
188
  (chosen === undefined
169
189
  ? row.selected
170
- : chosen.includes(rowKey(row.band, row.target)));
190
+ : chosen.includes(rowKey(row.scope, row.target)));
171
191
  /**
172
192
  * What a row DID, as a past-tense word. The row's detail says what and where;
173
193
  * the note says what happened to it, so a progress line and a recap line read
@@ -211,7 +231,7 @@ function childNote(row, kept) {
211
231
  *
212
232
  * @param rt - The per-invocation runtime.
213
233
  * @param mode - The entry point: the run-all, or one target.
214
- * @param scope - The resolved band selection.
234
+ * @param scope - The resolved scope selection.
215
235
  * @param removal - Compose the removal (`--undo`) instead of the install.
216
236
  * @returns The plan, the generator, and the answers-to-plan projection.
217
237
  * @note Impure — runs every selected target's real detection.
@@ -233,22 +253,41 @@ export async function buildSetupRun(rt, mode, scope, removal = false) {
233
253
  ["mcp", "Configure MCP for which files?"],
234
254
  ["lsp", "Install the extension into which editors?"],
235
255
  ].filter(([target]) => !removal && childrenOf(plan, target).length > 1);
236
- if (narrowable.length > 0) {
237
- const anyChosen = (answers) => {
256
+ for (const [target, message] of narrowable) {
257
+ // Asked whenever the row it narrows is in the run — one direct question,
258
+ // no meta-question in front of it. Removing a prompt cannot break the
259
+ // non-interactive paths: `autoPrompt`/`mcpPrompt` return each question's
260
+ // default, so a smaller prompt list means a smaller answer bag, and the
261
+ // compose bodies already read an absent child answer as "all". (The
262
+ // asymmetry is the reason this direction is safe: ADDING a defaultless
263
+ // prompt would hard-fail with MISSING_REQUIRED_ANSWER.)
264
+ const rowChosen = (answers) => {
238
265
  const chosen = readList(answers, ROWS_ANSWER);
239
- return narrowable.some(([target]) => plan.rows.some((row) => row.target === target && isChosen(row, chosen)));
266
+ return plan.rows.some((row) => row.target === target && isChosen(row, chosen));
240
267
  };
241
- prompts.push(buildCustomizePrompt(anyChosen));
242
- for (const [target, message] of narrowable) {
243
- const rowChosen = (answers) => {
244
- const chosen = readList(answers, ROWS_ANSWER);
245
- return plan.rows.some((row) => row.target === target && isChosen(row, chosen));
246
- };
247
- prompts.push(buildChildPrompt(plan, target, message, (answers) => answers.customize === true && rowChosen(answers)));
248
- }
268
+ prompts.push(buildChildPrompt(plan, target, message, rowChosen));
249
269
  }
250
270
  /** The detection behind a row, for composing and for re-reading its draft. */
251
- const detectionFor = (row) => detected.find((d) => d.target.id === row.target && d.band === row.band);
271
+ const detectionFor = (row) => detected.find((d) => d.target.id === row.target && d.scope === row.scope);
272
+ /**
273
+ * The success note a row's completion carries — ONE derivation for the
274
+ * recap's outcome and the live row event's `done` label, so the sentence a
275
+ * watcher saw land is the sentence the recap repeats. A removal never
276
+ * borrows the forward child summary: its children are the files the entry is
277
+ * being taken OUT of, and counting them as `1 updated` described the
278
+ * opposite of what the run had just done.
279
+ */
280
+ const noteFor = (row, answers) => {
281
+ if (removal)
282
+ return ACTION_NOTES[row.action];
283
+ const childKey = CHILD_ANSWER[row.target];
284
+ const kept = childKey === undefined ? undefined : readList(answers, childKey);
285
+ return childNote(row, kept) ?? ACTION_NOTES[row.action];
286
+ };
287
+ /** The live row listener, when a wizard is watching. See {@link SetupRun}. */
288
+ let rowListener;
289
+ /** The id column width — the recap's own rule, so the columns agree. */
290
+ const idWidth = Math.max(...plan.rows.map((row) => row.target.length));
252
291
  const generator = {
253
292
  meta: buildMeta(rt, mode === "all" ? `${BIN_NAME} setup` : `${BIN_NAME} setup ${mode}`),
254
293
  prompts,
@@ -264,12 +303,28 @@ export async function buildSetupRun(rt, mode, scope, removal = false) {
264
303
  // MCP file paths to every other target's compose.
265
304
  const key = CHILD_ANSWER[row.target];
266
305
  const children = key === undefined ? undefined : readList(answers, key);
306
+ // A removal stamps the row's identity on every reversal it composes:
307
+ // `--undo` executes those reversals in a LATER phase (the undo
308
+ // interpreter's), whose outcomes come back correlated by this key —
309
+ // see `appliedUndo`.
267
310
  const task = removal
268
- ? hit.target.composeRemoval(hit.detection)
311
+ ? hit.target.composeRemoval(hit.detection, rowKey(row.scope, row.target))
269
312
  : hit.target.compose(hit.detection, children);
270
- return [{ key: rowKey(row.band, row.target), task }];
313
+ // The row's progress sentence — the `target detail — note` shape
314
+ // `renderProgressLine` prints — so the live view and the recap say the
315
+ // same thing about the same row.
316
+ const label = `${row.target.padEnd(idWidth)} ${row.detail}`;
317
+ const note = noteFor(row, answers);
318
+ return [
319
+ {
320
+ key: rowKey(row.scope, row.target),
321
+ label,
322
+ doneLabel: note === undefined ? label : `${label} — ${note}`,
323
+ task,
324
+ },
325
+ ];
271
326
  });
272
- return runRowsIsolated(sink, tasks);
327
+ return runRowsIsolated(sink, tasks, (event) => rowListener?.(event));
273
328
  },
274
329
  };
275
330
  /** The outcome one row ended in, read off the sink and its own draft. */
@@ -294,11 +349,20 @@ export async function buildSetupRun(rt, mode, scope, removal = false) {
294
349
  // outcome at all left a converged re-run with a plan-shaped output that
295
350
  // claimed nothing had run — while the row still rendered a bare green ✓.
296
351
  // Convergence is a real result: one quiet line per row, zero writes.
297
- if (row.action === "none")
298
- return { status: "noop", note: "unchanged" };
352
+ //
353
+ // On a REMOVAL the same state is `kept`, not `noop`: the run owned
354
+ // nothing here and deliberately left the machine's state standing (the
355
+ // config the user edited, the editor with no extension copy). That is
356
+ // standing aside, which the vocabulary marks inert (○), where `noop`'s
357
+ // green ✓ would claim removal work that never existed.
358
+ if (row.action === "none") {
359
+ return removal
360
+ ? { status: "kept" }
361
+ : { status: "noop", note: "unchanged" };
362
+ }
299
363
  if (!isChosen(row, chosen))
300
364
  return undefined;
301
- const error = sink.get(rowKey(row.band, row.target));
365
+ const error = sink.get(rowKey(row.scope, row.target));
302
366
  if (error !== undefined) {
303
367
  const pragma = rowPragmaError(error);
304
368
  return {
@@ -311,32 +375,66 @@ export async function buildSetupRun(rt, mode, scope, removal = false) {
311
375
  }
312
376
  if (!isActionable(row.action))
313
377
  return { status: "noop" };
314
- // A removal never borrows the forward child summary: its children are the
315
- // files the entry is being taken OUT of, and counting them as "1 updated"
316
- // described the opposite of what the run had just done.
317
- const childKey = CHILD_ANSWER[row.target];
318
- const kept = childKey === undefined ? undefined : readList(answers, childKey);
319
- const note = removal
320
- ? ACTION_NOTES[row.action]
321
- : (childNote(row, kept) ?? ACTION_NOTES[row.action]);
378
+ const note = noteFor(row, answers);
322
379
  return {
323
380
  status: removal ? "removed" : "done",
324
381
  ...(note === undefined ? {} : { note }),
325
382
  };
326
383
  };
384
+ /** The one answers→plan projection both `applied` faces share. */
385
+ const project = (answers) => {
386
+ const chosen = readList(answers, ROWS_ANSWER);
387
+ return withRows(plan, plan.rows.map((row) => {
388
+ const outcome = outcomeFor(row, chosen, answers);
389
+ return {
390
+ ...row,
391
+ selected: isChosen(row, chosen),
392
+ ...(outcome === undefined ? {} : { outcome }),
393
+ };
394
+ }));
395
+ };
327
396
  return {
328
397
  plan,
329
398
  generator,
330
- applied: (answers) => {
331
- const chosen = readList(answers, ROWS_ANSWER);
332
- return withRows(plan, plan.rows.map((row) => {
333
- const outcome = outcomeFor(row, chosen, answers);
334
- return {
335
- ...row,
336
- selected: isChosen(row, chosen),
337
- ...(outcome === undefined ? {} : { outcome }),
338
- };
339
- }));
399
+ setRowListener: (listener) => {
400
+ rowListener = listener;
401
+ },
402
+ applied: project,
403
+ appliedUndo: (outcomes) => {
404
+ // The undo path's sink fill. The forward run's recover frames write the
405
+ // sink WHILE the task is interpreted; a real `--undo` interprets the
406
+ // task only as the mocked collection walk, so the executed reversals'
407
+ // outcomes land here instead — same sink, same reader (`outcomeFor`),
408
+ // other direction. The first failure per row wins: it is the earliest
409
+ // cause, and the row's note should name it, not the knock-on.
410
+ sink.clear();
411
+ for (const outcome of outcomes) {
412
+ if (outcome.status !== "failed" || outcome.key === undefined)
413
+ continue;
414
+ if (sink.get(outcome.key) !== undefined)
415
+ continue;
416
+ sink.record(outcome.key, outcome.error);
417
+ }
418
+ // A row that owed reversals and heard back from NONE of them cannot
419
+ // report `removed` — nothing proved anything happened. Structurally
420
+ // every actionable removal row composes at least one keyed reversal,
421
+ // so this is a guard against a future target breaking that invariant,
422
+ // not a path any current target takes.
423
+ const reported = new Set(outcomes.flatMap((o) => (o.key === undefined ? [] : [o.key])));
424
+ for (const row of plan.rows) {
425
+ const id = rowKey(row.scope, row.target);
426
+ if (!isActionable(row.action) || !row.selected)
427
+ continue;
428
+ if (reported.has(id) || sink.get(id) !== undefined)
429
+ continue;
430
+ sink.record(id, {
431
+ code: "UNSUPPORTED",
432
+ message: "no reversal was executed for this target",
433
+ });
434
+ }
435
+ // No answers: `--undo` asks nothing, so every row falls back to its
436
+ // own default selection — exactly the set `generate` composed from.
437
+ return project({});
340
438
  },
341
439
  };
342
440
  }