@ybotok/loam 0.2.0-alpha.5 → 0.2.0-alpha.7

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 (303) hide show
  1. package/CHANGELOG.md +1063 -0
  2. package/MIGRATING-from-OpenSpec.md +7 -4
  3. package/QUICKSTART.md +8 -3
  4. package/README.md +13 -7
  5. package/ROADMAP.md +285 -11
  6. package/SCHEMA.md +566 -45
  7. package/WORKFLOW.md +23 -10
  8. package/dist/commands/adopt/render.js +47 -8
  9. package/dist/commands/adopt/render.js.map +1 -1
  10. package/dist/commands/archive/plan/landscape.js +45 -1
  11. package/dist/commands/archive/plan/landscape.js.map +1 -1
  12. package/dist/commands/archive/plan/model/extending.js +85 -0
  13. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  14. package/dist/commands/archive/run.js +53 -23
  15. package/dist/commands/archive/run.js.map +1 -1
  16. package/dist/commands/context/print.js +11 -1
  17. package/dist/commands/context/print.js.map +1 -1
  18. package/dist/commands/doctor.js +46 -0
  19. package/dist/commands/doctor.js.map +1 -1
  20. package/dist/commands/explore.js +12 -2
  21. package/dist/commands/explore.js.map +1 -1
  22. package/dist/commands/list/views.js +5 -1
  23. package/dist/commands/list/views.js.map +1 -1
  24. package/dist/commands/seed/commit.js +34 -1
  25. package/dist/commands/seed/commit.js.map +1 -1
  26. package/dist/commands/seed/plan.js +158 -13
  27. package/dist/commands/seed/plan.js.map +1 -1
  28. package/dist/commands/seed/seed.js +7 -2
  29. package/dist/commands/seed/seed.js.map +1 -1
  30. package/dist/commands/show/feature.js +2 -1
  31. package/dist/commands/show/feature.js.map +1 -1
  32. package/dist/commands/show/marks.js +3 -5
  33. package/dist/commands/show/marks.js.map +1 -1
  34. package/dist/commands/show/service.js +39 -18
  35. package/dist/commands/show/service.js.map +1 -1
  36. package/dist/commands/subsystem/edit.js +4 -2
  37. package/dist/commands/subsystem/edit.js.map +1 -1
  38. package/dist/commands/subsystem/move.js +55 -17
  39. package/dist/commands/subsystem/move.js.map +1 -1
  40. package/dist/commands/subsystem/sync.js +238 -87
  41. package/dist/commands/subsystem/sync.js.map +1 -1
  42. package/dist/commands/subsystem/txn/exclude.js +132 -0
  43. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  44. package/dist/commands/subsystem/txn/report.js +174 -0
  45. package/dist/commands/subsystem/txn/report.js.map +1 -0
  46. package/dist/commands/subsystem/txn/txn.js +126 -22
  47. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  48. package/dist/commands/subsystem/txn/views.js +159 -19
  49. package/dist/commands/subsystem/txn/views.js.map +1 -1
  50. package/dist/commands/validate/arch-coverage.js +16 -9
  51. package/dist/commands/validate/arch-coverage.js.map +1 -1
  52. package/dist/commands/validate/checks/fleet-shape.js +30 -77
  53. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  54. package/dist/commands/validate/checks/health-deps.js +9 -6
  55. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  56. package/dist/commands/validate/checks/vocabulary.js +4 -19
  57. package/dist/commands/validate/checks/vocabulary.js.map +1 -1
  58. package/dist/commands/validate/feature.js +1 -1
  59. package/dist/commands/validate/feature.js.map +1 -1
  60. package/dist/commands/validate/fleet/census.js +37 -13
  61. package/dist/commands/validate/fleet/census.js.map +1 -1
  62. package/dist/commands/validate/fleet/landscape.js +131 -120
  63. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  64. package/dist/commands/validate/fleet/load.js +66 -0
  65. package/dist/commands/validate/fleet/load.js.map +1 -1
  66. package/dist/commands/validate/fleet/map/attest.js +102 -0
  67. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  68. package/dist/commands/validate/fleet/map/bindings.js +109 -0
  69. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  70. package/dist/commands/validate/fleet/map/consumers.js +219 -0
  71. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  72. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  73. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  74. package/dist/commands/validate/fleet/map/usecases.js +56 -0
  75. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  76. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  77. package/dist/commands/validate/fleet/usecases/steps.js +49 -17
  78. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -1
  79. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  80. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  81. package/dist/commands/validate/fleet/views/ids.js +45 -15
  82. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  83. package/dist/commands/validate/fleet/views/projects.js +258 -70
  84. package/dist/commands/validate/fleet/views/projects.js.map +1 -1
  85. package/dist/commands/validate/fleet/views/root-documents.js +99 -0
  86. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  87. package/dist/commands/validate/fleet/views/stale.js +32 -15
  88. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  89. package/dist/commands/validate/service/model/diverged.js +226 -0
  90. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  91. package/dist/commands/validate/service/model/grade.js +163 -0
  92. package/dist/commands/validate/service/model/grade.js.map +1 -0
  93. package/dist/commands/validate/service/service.js +110 -34
  94. package/dist/commands/validate/service/service.js.map +1 -1
  95. package/dist/commands/validate/service/specs.js +39 -5
  96. package/dist/commands/validate/service/specs.js.map +1 -1
  97. package/dist/commands/validate/service/spine.js +41 -3
  98. package/dist/commands/validate/service/spine.js.map +1 -1
  99. package/dist/commands/validate/service/usecases/tags.js +113 -0
  100. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  101. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  102. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  103. package/dist/commands/validate/validate.js +10 -24
  104. package/dist/commands/validate/validate.js.map +1 -1
  105. package/dist/core/agent/agents-md/artifacts.js +1 -0
  106. package/dist/core/agent/agents-md/artifacts.js.map +1 -1
  107. package/dist/core/agent/agents-md/command-map.js +19 -5
  108. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  109. package/dist/core/agent/agents-md/cycle.js +24 -9
  110. package/dist/core/agent/agents-md/cycle.js.map +1 -1
  111. package/dist/core/agent/agents-md/map/lenses/context.js +4 -3
  112. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  113. package/dist/core/agent/agents-md/map/subsystem.js +70 -17
  114. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  115. package/dist/core/agent/agents-md/map/usecases.js +45 -3
  116. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  117. package/dist/core/agent/agents-md/refusals.js +5 -3
  118. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  119. package/dist/core/agent/agents-md.js +26 -7
  120. package/dist/core/agent/agents-md.js.map +1 -1
  121. package/dist/core/agent/support/report.js +39 -5
  122. package/dist/core/agent/support/report.js.map +1 -1
  123. package/dist/core/agent/workflows/adopt.js +123 -14
  124. package/dist/core/agent/workflows/adopt.js.map +1 -1
  125. package/dist/core/agent/workflows/check.js +34 -20
  126. package/dist/core/agent/workflows/check.js.map +1 -1
  127. package/dist/core/agent/workflows/closing.js +3 -1
  128. package/dist/core/agent/workflows/closing.js.map +1 -1
  129. package/dist/core/agent/workflows/reference/spine.js +12 -6
  130. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  131. package/dist/core/brief/brief.js +88 -19
  132. package/dist/core/brief/brief.js.map +1 -1
  133. package/dist/core/brief/checks.js +133 -7
  134. package/dist/core/brief/checks.js.map +1 -1
  135. package/dist/core/brief/landscape.js +212 -129
  136. package/dist/core/brief/landscape.js.map +1 -1
  137. package/dist/core/brief/map/extend.js +81 -0
  138. package/dist/core/brief/map/extend.js.map +1 -0
  139. package/dist/core/brief/map/owed.js +284 -0
  140. package/dist/core/brief/map/owed.js.map +1 -0
  141. package/dist/core/brief/targets.js +94 -29
  142. package/dist/core/brief/targets.js.map +1 -1
  143. package/dist/core/brief/unchecked.js +13 -3
  144. package/dist/core/brief/unchecked.js.map +1 -1
  145. package/dist/core/c4/likec4.js +23 -1
  146. package/dist/core/c4/likec4.js.map +1 -1
  147. package/dist/core/c4/parsed/deployment.js +5 -3
  148. package/dist/core/c4/parsed/deployment.js.map +1 -1
  149. package/dist/core/c4/parsed/view-ids.js +39 -1
  150. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  151. package/dist/core/c4/prefetch/fleet.js +142 -0
  152. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  153. package/dist/core/c4/project/architecture.js +77 -7
  154. package/dist/core/c4/project/architecture.js.map +1 -1
  155. package/dist/core/c4/project/batch.js +140 -0
  156. package/dist/core/c4/project/batch.js.map +1 -0
  157. package/dist/core/c4/project/documents.js +12 -6
  158. package/dist/core/c4/project/documents.js.map +1 -1
  159. package/dist/core/c4/project/load.js +85 -42
  160. package/dist/core/c4/project/load.js.map +1 -1
  161. package/dist/core/c4/project/staged.js +53 -15
  162. package/dist/core/c4/project/staged.js.map +1 -1
  163. package/dist/core/c4/resolve/attested.js +0 -0
  164. package/dist/core/c4/resolve/attested.js.map +1 -0
  165. package/dist/core/c4/resolve/service.js +8 -17
  166. package/dist/core/c4/resolve/service.js.map +1 -1
  167. package/dist/core/c4/resolve/steps.js +18 -0
  168. package/dist/core/c4/resolve/steps.js.map +1 -1
  169. package/dist/core/c4/root-project/exclude.js +352 -0
  170. package/dist/core/c4/root-project/exclude.js.map +1 -0
  171. package/dist/core/c4/service-model/documents.js +47 -0
  172. package/dist/core/c4/service-model/documents.js.map +1 -0
  173. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  174. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  175. package/dist/core/c4/service-model/load.js +165 -0
  176. package/dist/core/c4/service-model/load.js.map +1 -0
  177. package/dist/core/c4/service-model/renderer.js +128 -0
  178. package/dist/core/c4/service-model/renderer.js.map +1 -0
  179. package/dist/core/c4/service-model/shape.js +126 -0
  180. package/dist/core/c4/service-model/shape.js.map +1 -0
  181. package/dist/core/c4/service-model/slice.js +188 -0
  182. package/dist/core/c4/service-model/slice.js.map +1 -0
  183. package/dist/core/c4/source-scan.js +26 -0
  184. package/dist/core/c4/source-scan.js.map +1 -1
  185. package/dist/core/c4/splice/authored-source.js +60 -13
  186. package/dist/core/c4/splice/authored-source.js.map +1 -1
  187. package/dist/core/c4/splice/contract.js.map +1 -1
  188. package/dist/core/c4/splice/identity/declared.js +87 -0
  189. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  190. package/dist/core/c4/splice/identity/edges.js +17 -0
  191. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  192. package/dist/core/c4/splice/identity/existing.js +80 -0
  193. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  194. package/dist/core/c4/splice/identity/interior.js +80 -0
  195. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  196. package/dist/core/c4/splice/identity/owner.js +50 -0
  197. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  198. package/dist/core/c4/splice/landscape-merge.js +154 -100
  199. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  200. package/dist/core/c4/splice/model/merge.js +140 -0
  201. package/dist/core/c4/splice/model/merge.js.map +1 -0
  202. package/dist/core/c4/splice/placement.js +14 -4
  203. package/dist/core/c4/splice/placement.js.map +1 -1
  204. package/dist/core/c4/workspace.js +2 -1
  205. package/dist/core/c4/workspace.js.map +1 -1
  206. package/dist/core/coherence/coherence.js +7 -0
  207. package/dist/core/coherence/coherence.js.map +1 -1
  208. package/dist/core/delta/delta.js +9 -0
  209. package/dist/core/delta/delta.js.map +1 -1
  210. package/dist/core/deployment/delta.js +16 -10
  211. package/dist/core/deployment/delta.js.map +1 -1
  212. package/dist/core/diff/base-state.js +21 -5
  213. package/dist/core/diff/base-state.js.map +1 -1
  214. package/dist/core/diff/victims.js +10 -1
  215. package/dist/core/diff/victims.js.map +1 -1
  216. package/dist/core/docs.js +29 -24
  217. package/dist/core/docs.js.map +1 -1
  218. package/dist/core/doctor/config.js +7 -3
  219. package/dist/core/doctor/config.js.map +1 -1
  220. package/dist/core/doctor/doctor.js +36 -8
  221. package/dist/core/doctor/doctor.js.map +1 -1
  222. package/dist/core/doctor/report.js.map +1 -1
  223. package/dist/core/doctor/reports/scan.js +242 -0
  224. package/dist/core/doctor/reports/scan.js.map +1 -0
  225. package/dist/core/explain/refusals.js +1 -1
  226. package/dist/core/explain/refusals.js.map +1 -1
  227. package/dist/core/explore/explore.js +44 -9
  228. package/dist/core/explore/explore.js.map +1 -1
  229. package/dist/core/fleet-context.js +47 -0
  230. package/dist/core/fleet-context.js.map +1 -1
  231. package/dist/core/gate/checks.js +5 -1
  232. package/dist/core/gate/checks.js.map +1 -1
  233. package/dist/core/gate/partners.js +65 -26
  234. package/dist/core/gate/partners.js.map +1 -1
  235. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  236. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  237. package/dist/core/pack/living.js +47 -13
  238. package/dist/core/pack/living.js.map +1 -1
  239. package/dist/core/pack/pack.js +9 -6
  240. package/dist/core/pack/pack.js.map +1 -1
  241. package/dist/core/projection/arch-slice.js +2 -2
  242. package/dist/core/projection/arch-slice.js.map +1 -1
  243. package/dist/core/repo/paths.js +45 -38
  244. package/dist/core/repo/paths.js.map +1 -1
  245. package/dist/core/repo/tree/render/body.js +45 -6
  246. package/dist/core/repo/tree/render/body.js.map +1 -1
  247. package/dist/core/repo/tree/render/projects.js +93 -35
  248. package/dist/core/repo/tree/render/projects.js.map +1 -1
  249. package/dist/core/repo/tree/render/service/header.js +125 -0
  250. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  251. package/dist/core/repo/tree/render/service/peers.js +28 -0
  252. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  253. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  254. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  255. package/dist/core/repo/tree/render/service/views.js +78 -0
  256. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  257. package/dist/core/repo/tree/render/stale.js +20 -4
  258. package/dist/core/repo/tree/render/stale.js.map +1 -1
  259. package/dist/core/repo/tree/render/views.js +149 -32
  260. package/dist/core/repo/tree/render/views.js.map +1 -1
  261. package/dist/core/repo/tree/walk.js +45 -2
  262. package/dist/core/repo/tree/walk.js.map +1 -1
  263. package/dist/core/scaffold/landscape.js +219 -9
  264. package/dist/core/scaffold/landscape.js.map +1 -1
  265. package/dist/core/staging/writes.js.map +1 -1
  266. package/dist/core/usecases/delta/claims.js +1 -0
  267. package/dist/core/usecases/delta/claims.js.map +1 -1
  268. package/dist/core/usecases/delta/overlay.js +4 -0
  269. package/dist/core/usecases/delta/overlay.js.map +1 -1
  270. package/dist/core/usecases/fleet.js +18 -6
  271. package/dist/core/usecases/fleet.js.map +1 -1
  272. package/dist/core/usecases/operations.js +7 -0
  273. package/dist/core/usecases/operations.js.map +1 -1
  274. package/dist/core/usecases/service/exclude.js +119 -0
  275. package/dist/core/usecases/service/exclude.js.map +1 -0
  276. package/dist/core/usecases/service/flows.js +161 -0
  277. package/dist/core/usecases/service/flows.js.map +1 -0
  278. package/dist/core/verify/checklist.js +42 -10
  279. package/dist/core/verify/checklist.js.map +1 -1
  280. package/dist/core/vocabulary/issue.js.map +1 -1
  281. package/dist/core/vocabulary/maturity.js +51 -1
  282. package/dist/core/vocabulary/maturity.js.map +1 -1
  283. package/examples/README.md +30 -8
  284. package/examples/docs/architecture/landscape.likec4 +47 -0
  285. package/examples/docs/architecture/services.likec4 +70 -0
  286. package/examples/docs/architecture/subsystems.likec4 +3 -0
  287. package/examples/docs/architecture/usecases/order-notification.likec4 +5 -2
  288. package/examples/docs/likec4.config.json +0 -1
  289. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  290. package/examples/docs/services/order-service/arch.spec.md +13 -6
  291. package/examples/docs/services/order-service/model.likec4 +58 -70
  292. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  293. package/examples/docs/services/payment-service/model.likec4 +38 -39
  294. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  295. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  296. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  297. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  298. package/package.json +1 -1
  299. package/examples/docs/services/checkout-web/likec4.config.json +0 -4
  300. package/examples/docs/services/order-service/likec4.config.json +0 -4
  301. package/examples/docs/services/payment-service/likec4.config.json +0 -4
  302. package/examples/docs/services/platform/identity-service/likec4.config.json +0 -4
  303. package/examples/docs/services/platform/notification-service/likec4.config.json +0 -4
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/commands/subsystem/edit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two verbs that create and remove GROUPS: `subsystem new` and\n * `subsystem rm`. Both commit the marker AND the regenerated views file in\n * one journaled transaction, because a marker without its view (or a view\n * outliving its marker) is exactly the `subsystem.views-stale` state the\n * generated file's contract refuses to leave behind.\n *\n * `rm` refuses a subsystem with members — services, child subsystems, or any\n * stray non-dot entry beside the marker the tree does not already count —\n * naming each once, as what it is (`subsystem-not-empty`):\n * a destructive command never picks targets the caller did not name, and a\n * directory emptied of its marker but not of its contents would re-enter the\n * walk as a phantom service.\n */\nimport { existsSync } from \"node:fs\";\nimport { readdir, rmdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { stringify } from \"yaml\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseSubsystemName } from \"../../core/kernel/ids/subsystem.js\";\nimport { emitJson, fail, repoPath } from \"../../core/envelope/json.js\";\nimport { servicesDir, subsystemPathUnder } from \"../../core/repo/paths.js\";\nimport { findInTree, nearestTreeNames, servicesUnder, subsystemsUnder } from \"../../core/repo/tree/find.js\";\nimport { entryIs } from \"../../core/repo/tree/fs.js\";\nimport { SUBSYSTEM_MARKER } from \"../../core/repo/tree/marker.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { planWrite } from \"../../core/staging/writes.js\";\nimport { commitWindow, reportViews, type SubsystemTxn } from \"./txn/txn.js\";\nimport type { SubsystemOptions } from \"./subsystem.js\";\n\n/** `subsystem new <name> [--under <parent>] [--title …] [--description …] [--owner …]` */\nexport async function runNew(\n docsDir: DocsDir,\n name: string,\n opts: SubsystemOptions,\n json: boolean,\n): Promise<void> {\n const parsed = parseSubsystemName(name, \"subsystem name\");\n if (!parsed.ok) {\n fail(json, \"invalid-option\", parsed.problem);\n return;\n }\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n // The flat namespace: one name, one meaning, at any depth — a `new` that\n // collides with ANY service or subsystem would be the exact state\n // `subsystem.name-collision` refuses after the fact.\n const taken = findInTree(tree, name);\n if (taken !== null) {\n const where = taken.kind === \"service\" ? taken.service.dir : taken.subsystem.dir;\n fail(\n json,\n \"already-exists\",\n `'${name}' is already a ${taken.kind} (${repoPath(docsDir, where)}) — ` +\n `service ids and subsystem names share one flat namespace, unique at any depth. Pick another name.`,\n );\n return null;\n }\n let parentDir = servicesDir(docsDir);\n let parentPath: string[] = [];\n if (opts.under !== undefined) {\n const parent = findInTree(tree, opts.under);\n if (parent === null) {\n const close = nearestTreeNames(opts.under, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${opts.under}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (parent.kind === \"service\") {\n fail(json, \"invalid-option\", `--under names the service '${opts.under}' — a service never contains subsystems.`);\n return null;\n }\n parentDir = parent.subsystem.dir;\n parentPath = parent.subsystem.path;\n }\n const dir = subsystemPathUnder(parentDir, parsed.name);\n // The flat-namespace check above compares exact strings; the FILESYSTEM\n // may not. On a case-folding volume (macOS APFS by default) `Billing`\n // and an existing `services/billing` are one directory, so the marker\n // write below would land subsystem.yaml INSIDE the live service — the\n // exact marker-beside-artifacts state `subsystem.marker-misplaced`\n // refuses after the fact, created by a blessed command. A plain file of\n // the same name reaches here too (files at the root are not walked). So\n // the disk is probed directly and anything already there refuses closed.\n if (existsSync(dir)) {\n fail(\n json,\n \"already-exists\",\n `${repoPath(docsDir, dir)} already exists on disk — the tree resolves no entry by that exact name, ` +\n `so either this filesystem folds case (the directory answers to another spelling of the name) ` +\n `or something non-loam created it. Pick another name, or move what is there first. Nothing was created.`,\n );\n return null;\n }\n const meta = {\n ...(opts.title === undefined ? {} : { title: opts.title }),\n ...(opts.description === undefined ? {} : { description: opts.description }),\n ...(opts.owner === undefined ? {} : { owner: opts.owner }),\n };\n // An empty file is a valid marker — presence classifies, content is metadata.\n const marker = Object.keys(meta).length === 0 ? \"\" : stringify(meta);\n const after: FleetTree = {\n ...tree,\n subsystems: [...tree.subsystems, { name, path: [...parentPath, name], dir, meta }],\n };\n return {\n target: name,\n writes: [planWrite(join(dir, SUBSYSTEM_MARKER), marker)],\n tree: after,\n // A lost exclusive-create race on the marker IS the name being taken.\n racedCode: \"already-exists\",\n what: \"created\",\n report: (views, recovered) => {\n if (json) {\n emitJson({\n command: \"subsystem\",\n created: name,\n path: repoPath(docsDir, dir),\n views,\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`created ${repoPath(docsDir, dir)}/ (${SUBSYSTEM_MARKER} written)${reportViews(views)}`);\n },\n };\n });\n}\n\n/** `subsystem rm <name>` — refuses anything but an empty group. */\nexport async function runRm(docsDir: DocsDir, name: string, json: boolean): Promise<void> {\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const hit = findInTree(tree, name);\n if (hit === null) {\n const close = nearestTreeNames(name, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${name}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(\n json,\n \"invalid-option\",\n `'${name}' is a service, not a subsystem — loam does not delete services (\\`git rm -r ${repoPath(docsDir, hit.service.dir)}\\` does, and version control keeps the record).`,\n );\n return null;\n }\n const sub = hit.subsystem;\n const services = servicesUnder(tree, sub).map((s) => s.id);\n const children = subsystemsUnder(tree, sub).map((s) => s.name);\n // Stray entries beside the marker count as members too: after the marker\n // is gone the directory would re-enter the walk as an empty \"service\" the\n // moment anything keeps rmdir from removing it. But only entries the tree\n // has NOT already counted — a member service or child subsystem is also a\n // readdir entry here, and listing it a second time as \"file X\" made the\n // count wrong and the same name appear under two kinds. What remains is\n // discriminated by what it is (`entryIs`, the walk's own symlink-aware\n // question): a file, or a directory the tree does not claim (an unmarked\n // group, already its own `subsystem.unmarked` finding).\n const counted = new Set<string>([\n ...servicesUnder(tree, sub).filter((s) => s.subsystem.length === sub.path.length).map((s) => s.id as string),\n ...subsystemsUnder(tree, sub).filter((c) => c.path.length === sub.path.length + 1).map((c) => c.name),\n ]);\n const strays = (await readdir(sub.dir, { withFileTypes: true }))\n .filter((e) => !e.name.startsWith(\".\") && e.name !== SUBSYSTEM_MARKER && !counted.has(e.name))\n .map((e) => `${entryIs(sub.dir, e, \"dir\") ? \"directory\" : \"file\"} ${e.name}`);\n const members = [\n ...services.map((s) => `service ${s}`),\n ...children.map((c) => `subsystem ${c}`),\n ...strays,\n ];\n if (members.length > 0) {\n fail(\n json,\n \"subsystem-not-empty\",\n `'${name}' still holds ${members.length} member(s): ${members.join(\", \")}. ` +\n \"`loam subsystem move <name>... --into <sub|.>` moves them out; a destructive command never picks targets you did not name.\",\n );\n return null;\n }\n const after: FleetTree = { ...tree, subsystems: tree.subsystems.filter((s) => s !== sub) };\n return {\n target: name,\n writes: [{ path: join(sub.dir, SUBSYSTEM_MARKER), content: null }],\n tree: after,\n what: \"removed\",\n report: async (views, recovered) => {\n // The directory itself, after the transaction: the marker is gone, the\n // group was verifiably empty, and an empty marker-less directory would\n // read as an unfiled service. Dotfile litter (.DS_Store) can still\n // defeat rmdir — reported, not swallowed.\n let directoryRemoved = true;\n try {\n await rmdir(sub.dir);\n } catch {\n directoryRemoved = !existsSync(sub.dir);\n }\n if (json) {\n emitJson({\n command: \"subsystem\",\n removed: name,\n path: repoPath(docsDir, sub.dir),\n directoryRemoved,\n views,\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`removed subsystem '${name}' (${repoPath(docsDir, sub.dir)}/)${reportViews(views)}`);\n if (!directoryRemoved) {\n console.log(\n `note: the directory itself could not be removed (something non-loam is still inside) — ` +\n `until it is deleted by hand it will list as an empty unfiled service.`,\n );\n }\n },\n };\n });\n}\n"]}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/commands/subsystem/edit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two verbs that create and remove GROUPS: `subsystem new` and\n * `subsystem rm`. Both commit the marker AND the regenerated views file in\n * one journaled transaction, because a marker without its view (or a view\n * outliving its marker) is exactly the `subsystem.views-stale` state the\n * generated file's contract refuses to leave behind.\n *\n * `rm` refuses a subsystem with members — services, child subsystems, or any\n * stray non-dot entry beside the marker the tree does not already count —\n * naming each once, as what it is (`subsystem-not-empty`):\n * a destructive command never picks targets the caller did not name, and a\n * directory emptied of its marker but not of its contents would re-enter the\n * walk as a phantom service.\n */\nimport { existsSync } from \"node:fs\";\nimport { readdir, rmdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { stringify } from \"yaml\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseSubsystemName } from \"../../core/kernel/ids/subsystem.js\";\nimport { emitJson, fail, repoPath } from \"../../core/envelope/json.js\";\nimport { servicesDir, subsystemPathUnder } from \"../../core/repo/paths.js\";\nimport { findInTree, nearestTreeNames, servicesUnder, subsystemsUnder } from \"../../core/repo/tree/find.js\";\nimport { entryIs } from \"../../core/repo/tree/fs.js\";\nimport { SUBSYSTEM_MARKER } from \"../../core/repo/tree/marker.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { planWrite } from \"../../core/staging/writes.js\";\nimport { commitWindow, reportViews, type SubsystemTxn } from \"./txn/txn.js\";\nimport type { SubsystemOptions } from \"./subsystem.js\";\n\n/** `subsystem new <name> [--under <parent>] [--title …] [--description …] [--owner …]` */\nexport async function runNew(\n docsDir: DocsDir,\n name: string,\n opts: SubsystemOptions,\n json: boolean,\n): Promise<void> {\n const parsed = parseSubsystemName(name, \"subsystem name\");\n if (!parsed.ok) {\n fail(json, \"invalid-option\", parsed.problem);\n return;\n }\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n // The flat namespace: one name, one meaning, at any depth — a `new` that\n // collides with ANY service or subsystem would be the exact state\n // `subsystem.name-collision` refuses after the fact.\n const taken = findInTree(tree, name);\n if (taken !== null) {\n const where = taken.kind === \"service\" ? taken.service.dir : taken.subsystem.dir;\n fail(\n json,\n \"already-exists\",\n `'${name}' is already a ${taken.kind} (${repoPath(docsDir, where)}) — ` +\n `service ids and subsystem names share one flat namespace, unique at any depth. Pick another name.`,\n );\n return null;\n }\n let parentDir = servicesDir(docsDir);\n let parentPath: string[] = [];\n if (opts.under !== undefined) {\n const parent = findInTree(tree, opts.under);\n if (parent === null) {\n const close = nearestTreeNames(opts.under, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${opts.under}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (parent.kind === \"service\") {\n fail(json, \"invalid-option\", `--under names the service '${opts.under}' — a service never contains subsystems.`);\n return null;\n }\n parentDir = parent.subsystem.dir;\n parentPath = parent.subsystem.path;\n }\n const dir = subsystemPathUnder(parentDir, parsed.name);\n // The flat-namespace check above compares exact strings; the FILESYSTEM\n // may not. On a case-folding volume (macOS APFS by default) `Billing`\n // and an existing `services/billing` are one directory, so the marker\n // write below would land subsystem.yaml INSIDE the live service — the\n // exact marker-beside-artifacts state `subsystem.marker-misplaced`\n // refuses after the fact, created by a blessed command. A plain file of\n // the same name reaches here too (files at the root are not walked). So\n // the disk is probed directly and anything already there refuses closed.\n if (existsSync(dir)) {\n fail(\n json,\n \"already-exists\",\n `${repoPath(docsDir, dir)} already exists on disk — the tree resolves no entry by that exact name, ` +\n `so either this filesystem folds case (the directory answers to another spelling of the name) ` +\n `or something non-loam created it. Pick another name, or move what is there first. Nothing was created.`,\n );\n return null;\n }\n const meta = {\n ...(opts.title === undefined ? {} : { title: opts.title }),\n ...(opts.description === undefined ? {} : { description: opts.description }),\n ...(opts.owner === undefined ? {} : { owner: opts.owner }),\n };\n // An empty file is a valid marker — presence classifies, content is metadata.\n const marker = Object.keys(meta).length === 0 ? \"\" : stringify(meta);\n const after: FleetTree = {\n ...tree,\n subsystems: [...tree.subsystems, { name, path: [...parentPath, name], dir, meta }],\n };\n return {\n target: name,\n writes: [planWrite(join(dir, SUBSYSTEM_MARKER), marker)],\n tree: after,\n // A lost exclusive-create race on the marker IS the name being taken.\n racedCode: \"already-exists\",\n what: \"created\",\n report: (views, recovered) => {\n if (json) {\n emitJson({\n command: \"subsystem\",\n created: name,\n path: repoPath(docsDir, dir),\n views: views.subsystems,\n serviceViews: views.services,\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`created ${repoPath(docsDir, dir)}/ (${SUBSYSTEM_MARKER} written)${reportViews(views)}`);\n },\n };\n });\n}\n\n/** `subsystem rm <name>` — refuses anything but an empty group. */\nexport async function runRm(docsDir: DocsDir, name: string, json: boolean): Promise<void> {\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const hit = findInTree(tree, name);\n if (hit === null) {\n const close = nearestTreeNames(name, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${name}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(\n json,\n \"invalid-option\",\n `'${name}' is a service, not a subsystem — loam does not delete services (\\`git rm -r ${repoPath(docsDir, hit.service.dir)}\\` does, and version control keeps the record).`,\n );\n return null;\n }\n const sub = hit.subsystem;\n const services = servicesUnder(tree, sub).map((s) => s.id);\n const children = subsystemsUnder(tree, sub).map((s) => s.name);\n // Stray entries beside the marker count as members too: after the marker\n // is gone the directory would re-enter the walk as an empty \"service\" the\n // moment anything keeps rmdir from removing it. But only entries the tree\n // has NOT already counted — a member service or child subsystem is also a\n // readdir entry here, and listing it a second time as \"file X\" made the\n // count wrong and the same name appear under two kinds. What remains is\n // discriminated by what it is (`entryIs`, the walk's own symlink-aware\n // question): a file, or a directory the tree does not claim (an unmarked\n // group, already its own `subsystem.unmarked` finding).\n const counted = new Set<string>([\n ...servicesUnder(tree, sub).filter((s) => s.subsystem.length === sub.path.length).map((s) => s.id as string),\n ...subsystemsUnder(tree, sub).filter((c) => c.path.length === sub.path.length + 1).map((c) => c.name),\n ]);\n const strays = (await readdir(sub.dir, { withFileTypes: true }))\n .filter((e) => !e.name.startsWith(\".\") && e.name !== SUBSYSTEM_MARKER && !counted.has(e.name))\n .map((e) => `${entryIs(sub.dir, e, \"dir\") ? \"directory\" : \"file\"} ${e.name}`);\n const members = [\n ...services.map((s) => `service ${s}`),\n ...children.map((c) => `subsystem ${c}`),\n ...strays,\n ];\n if (members.length > 0) {\n fail(\n json,\n \"subsystem-not-empty\",\n `'${name}' still holds ${members.length} member(s): ${members.join(\", \")}. ` +\n \"`loam subsystem move <name>... --into <sub|.>` moves them out; a destructive command never picks targets you did not name.\",\n );\n return null;\n }\n const after: FleetTree = { ...tree, subsystems: tree.subsystems.filter((s) => s !== sub) };\n return {\n target: name,\n writes: [{ path: join(sub.dir, SUBSYSTEM_MARKER), content: null }],\n tree: after,\n what: \"removed\",\n report: async (views, recovered) => {\n // The directory itself, after the transaction: the marker is gone, the\n // group was verifiably empty, and an empty marker-less directory would\n // read as an unfiled service. Dotfile litter (.DS_Store) can still\n // defeat rmdir — reported, not swallowed.\n let directoryRemoved = true;\n try {\n await rmdir(sub.dir);\n } catch {\n directoryRemoved = !existsSync(sub.dir);\n }\n if (json) {\n emitJson({\n command: \"subsystem\",\n removed: name,\n path: repoPath(docsDir, sub.dir),\n directoryRemoved,\n views: views.subsystems,\n serviceViews: views.services,\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`removed subsystem '${name}' (${repoPath(docsDir, sub.dir)}/)${reportViews(views)}`);\n if (!directoryRemoved) {\n console.log(\n `note: the directory itself could not be removed (something non-loam is still inside) — ` +\n `until it is deleted by hand it will list as an empty unfiled service.`,\n );\n }\n },\n };\n });\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `subsystem move` and `subsystem rename` — ONE transaction over N directory
3
- * renames plus the generated views file, the first real consumer of the
3
+ * renames plus BOTH generated views files, the first real consumer of the
4
4
  * journaled txn's moves half (`core/staging/txn/`). The planning lives in
5
5
  * this module; the commit window itself is `./txn/txn.ts`, shared with
6
6
  * `new` and `rm`.
@@ -9,7 +9,7 @@
9
9
  * uncommitted changes under a directory being moved — and only on positive
10
10
  * evidence: where git will not say, the move proceeds. After a landed move
11
11
  * loam performs the roadmap's one blessed git write, a best-effort `git add`
12
- * of the rename pairs and the regenerated views file, so git records the
12
+ * of the rename pairs and of BOTH regenerated views files, so git records the
13
13
  * renames as renames and `subsystem history` stays answerable once the user
14
14
  * commits. Nothing is ever committed.
15
15
  */
@@ -20,7 +20,7 @@ import { parseSubsystemName } from "../../core/kernel/ids/subsystem.js";
20
20
  import { isRecord } from "../../core/kernel/records.js";
21
21
  import { emitJson, fail, repoPath } from "../../core/envelope/json.js";
22
22
  import { gitDirtyPaths, gitStageRenames } from "../../core/provenance/gitq/moves.js";
23
- import { servicesDir, subsystemPathUnder, subsystemViewsPath } from "../../core/repo/paths.js";
23
+ import { servicesDir, serviceViewsPath, subsystemPathUnder, subsystemViewsPath } from "../../core/repo/paths.js";
24
24
  import { listFeatures } from "../../core/repo/repo.js";
25
25
  import { findInTree, nearestTreeNames, treeNames, withinSubsystem } from "../../core/repo/tree/find.js";
26
26
  import { SNAPSHOT_COMPAT_VERSION, SNAPSHOT_MANIFEST, snapshotDir } from "../../core/staging/snapshot.js";
@@ -87,7 +87,7 @@ export async function runMove(docsDir, names, into, json) {
87
87
  failedCode: "move-failed",
88
88
  what: "moved",
89
89
  report: async (views, recovered) => {
90
- await stageInGit(docsDir, renames);
90
+ await stageInGit(docsDir, renames, views);
91
91
  const rows = moved.map((m, i) => ({
92
92
  name: m.name,
93
93
  kind: m.kind,
@@ -99,7 +99,8 @@ export async function runMove(docsDir, names, into, json) {
99
99
  command: "subsystem",
100
100
  into,
101
101
  moved: rows,
102
- views,
102
+ views: views.subsystems,
103
+ serviceViews: views.services,
103
104
  ...(notices.length === 0 ? {} : { warnings: notices }),
104
105
  ...(recovered === null ? {} : { recovered }),
105
106
  });
@@ -151,14 +152,15 @@ export async function runRename(docsDir, names, json) {
151
152
  failedCode: "move-failed",
152
153
  what: "renamed",
153
154
  report: async (views, recovered) => {
154
- await stageInGit(docsDir, [rename]);
155
+ await stageInGit(docsDir, [rename], views);
155
156
  if (json) {
156
157
  emitJson({
157
158
  command: "subsystem",
158
159
  renamed: from,
159
160
  to,
160
161
  path: repoPath(docsDir, rename.to),
161
- views,
162
+ views: views.subsystems,
163
+ serviceViews: views.services,
162
164
  ...(notices.length === 0 ? {} : { warnings: notices }),
163
165
  ...(recovered === null ? {} : { recovered }),
164
166
  });
@@ -209,17 +211,53 @@ async function refuseUncommitted(docsDir, dirs, json) {
209
211
  }
210
212
  /**
211
213
  * Stage the move's whole delta, silently: the rename pairs (both ends — the
212
- * delete side and the add side) AND the regenerated views file. The views
213
- * file rides along for the same reason the transaction writes it in the same
214
- * commit: a user whose next `git commit` captured the renames without it
215
- * would commit a tree `validate --all` fails (`subsystem.views-stale`) — the
216
- * exact "failing between two commits" state the roadmap forbids.
214
+ * delete side and the add side) AND BOTH regenerated views files. They ride
215
+ * along for the same reason the transaction writes them in the same commit: a
216
+ * user whose next `git commit` captured the renames without them would commit
217
+ * a tree `validate --all` fails (`subsystem.views-stale`) — the exact "failing
218
+ * between two commits" state the roadmap forbids.
219
+ *
220
+ * A generated file that is neither ON DISK nor REMOVED BY THIS COMMIT is left
221
+ * out of the pathspec, and that is a correctness rule rather than tidiness:
222
+ * `gitStageRenames` runs one `git add -A -- <paths>`, and a pathspec matching
223
+ * neither the worktree nor the index makes git refuse the WHOLE invocation
224
+ * (silently — that write is failure-silent by contract) — so naming an absent
225
+ * `architecture/services.likec4` (a fleet whose map draws no service renders
226
+ * none) would take the other paths out of the index with it.
227
+ *
228
+ * THE `removed` ARM IS WHY `existsSync` ALONE IS NOT THE FILTER. A move can be
229
+ * the commit that DELETES a generated file rather than rewriting it: a
230
+ * committed `architecture/subsystems.likec4` standing over a tree that no
231
+ * longer marks any subsystem (the marker went in an earlier commit) must not
232
+ * exist, so the window renders null and the transaction removes it — and by the
233
+ * time this runs the file is gone from disk. Measured 2026-09-07 on exactly that
234
+ * fixture: under a disk-only filter the path never reached the pathspec, git
235
+ * reported the deletion as ` D` (unstaged) while both rename ends went in as
236
+ * `R `, and the user's next `git commit` captured the renames plus a generated
237
+ * file the tree no longer licenses — `subsystem.views-stale` on a commit loam
238
+ * itself produced, the exact state the paragraph above says this staging exists
239
+ * to prevent. A path this commit deleted is still in the INDEX, so it matches
240
+ * the pathspec and `-A` stages the deletion; the commit window's own
241
+ * `ViewsActions` is what says which file that was, so no second guess about disk
242
+ * is needed.
243
+ *
244
+ * TWO INVOCATIONS, not one, and the split is what makes the `removed` arm safe
245
+ * to add: a generated file that was never committed and is deleted here is in
246
+ * neither the worktree nor the index, and folded into one pathspec it would take
247
+ * the renames down with it — the failure this function's first rule exists to
248
+ * refuse. Staging in two calls costs one extra best-effort spawn and cannot
249
+ * cost the renames. git records a rename from the index state at commit time,
250
+ * never from which `git add` put the two ends there.
217
251
  */
218
- async function stageInGit(docsDir, renames) {
219
- await gitStageRenames(docsDir, [
220
- ...renames.flatMap((r) => [repoPath(docsDir, r.from), repoPath(docsDir, r.to)]),
221
- repoPath(docsDir, subsystemViewsPath(docsDir)),
222
- ]);
252
+ async function stageInGit(docsDir, renames, views) {
253
+ await gitStageRenames(docsDir, renames.flatMap((r) => [repoPath(docsDir, r.from), repoPath(docsDir, r.to)]));
254
+ const generated = [
255
+ [subsystemViewsPath(docsDir), views.subsystems],
256
+ [serviceViewsPath(docsDir), views.services],
257
+ ];
258
+ await gitStageRenames(docsDir, generated
259
+ .filter(([path, action]) => action === "removed" || existsSync(path))
260
+ .map(([path]) => repoPath(docsDir, path)));
223
261
  }
224
262
  /**
225
263
  * Which archived features hold a VERSION-2 snapshot addressing a path under
@@ -1 +1 @@
1
- {"version":3,"file":"move.js","sourceRoot":"","sources":["../../../src/commands/subsystem/move.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `subsystem move` and `subsystem rename` — ONE transaction over N directory\n * renames plus the generated views file, the first real consumer of the\n * journaled txn's moves half (`core/staging/txn/`). The planning lives in\n * this module; the commit window itself is `./txn/txn.ts`, shared with\n * `new` and `rm`.\n *\n * The ONLY move-specific refusal is `move-uncommitted` — git reports\n * uncommitted changes under a directory being moved — and only on positive\n * evidence: where git will not say, the move proceeds. After a landed move\n * loam performs the roadmap's one blessed git write, a best-effort `git add`\n * of the rename pairs and the regenerated views file, so git records the\n * renames as renames and `subsystem history` stays answerable once the user\n * commits. Nothing is ever committed.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join, sep } from \"node:path\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseSubsystemName } from \"../../core/kernel/ids/subsystem.js\";\nimport { isRecord } from \"../../core/kernel/records.js\";\nimport { emitJson, fail, repoPath } from \"../../core/envelope/json.js\";\nimport { gitDirtyPaths, gitStageRenames } from \"../../core/provenance/gitq/moves.js\";\nimport type { FeatureEntry } from \"../../core/repo/entries.js\";\nimport { servicesDir, subsystemPathUnder, subsystemViewsPath } from \"../../core/repo/paths.js\";\nimport { listFeatures } from \"../../core/repo/repo.js\";\nimport { findInTree, nearestTreeNames, treeNames, withinSubsystem } from \"../../core/repo/tree/find.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { SNAPSHOT_COMPAT_VERSION, SNAPSHOT_MANIFEST, snapshotDir } from \"../../core/staging/snapshot.js\";\nimport { commitWindow, reportViews, type SubsystemTxn } from \"./txn/txn.js\";\nimport { movedTree } from \"./txn/views.js\";\n\n/** What one name resolved to for a move: where it is, and where it goes. */\ninterface Moved {\n name: string;\n kind: \"service\" | \"subsystem\";\n dir: string;\n /** Path of the CONTAINING directory, as names from services/ down. */\n parent: string[];\n}\n\n/** `subsystem move <name>... --into <sub|.>` — services and whole subtrees alike. */\nexport async function runMove(docsDir: DocsDir, names: string[], into: string, json: boolean): Promise<void> {\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const seen = new Set<string>();\n for (const name of names) {\n if (seen.has(name)) {\n fail(json, \"invalid-option\", `'${name}' is named twice — each service or subsystem moves once.`);\n return null;\n }\n seen.add(name);\n }\n const target = resolveTarget(tree, into, { docsDir, json });\n if (target === null) return null;\n const moved: Moved[] = [];\n for (const name of names) {\n const hit = findInTree(tree, name);\n if (hit === null) {\n const close = nearestTreeNames(name, treeNames(tree));\n fail(\n json,\n \"unknown-target\",\n `No service or subsystem '${name}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n moved.push(\n hit.kind === \"service\"\n ? { name, kind: \"service\", dir: hit.service.dir, parent: hit.service.subsystem }\n : { name, kind: \"subsystem\", dir: hit.subsystem.dir, parent: hit.subsystem.path.slice(0, -1) },\n );\n }\n for (const m of moved) {\n if (m.kind === \"subsystem\" && withinSubsystem([...m.parent, m.name], target.path)) {\n fail(json, \"invalid-option\", `'${m.name}' cannot move into itself or its own subtree.`);\n return null;\n }\n if (m.parent.join(\"/\") === target.path.join(\"/\")) {\n fail(json, \"invalid-option\", `'${m.name}' is already directly in ${into === \".\" ? \"the services/ root\" : `'${into}'`} — nothing to move.`);\n return null;\n }\n const inside = moved.find(\n (other) => other.kind === \"subsystem\" && other !== m && (m.dir + sep).startsWith(other.dir + sep),\n );\n if (inside !== undefined) {\n fail(json, \"invalid-option\", `'${m.name}' sits inside '${inside.name}', which is also being moved — name only the subtree root.`);\n return null;\n }\n if (existsSync(join(target.dir, m.name))) {\n // Unreachable in a healthy flat namespace; a tree already carrying\n // name collisions can produce it, and refusing beats stacking a\n // second directory of the same name.\n fail(json, \"already-exists\", `${repoPath(docsDir, join(target.dir, m.name))} already exists — fix the name collision first.`);\n return null;\n }\n }\n if (await refuseUncommitted(docsDir, moved.map((m) => m.dir), json)) return null;\n const notices = await v2SnapshotNotices(docsDir, moved.map((m) => m.dir));\n const renames = moved.map((m) => ({ from: m.dir, to: join(target.dir, m.name) }));\n return {\n target: names.join(\", \"),\n writes: [],\n tree: movedTree(tree, renames, servicesDir(docsDir)),\n moves: renames,\n failedCode: \"move-failed\",\n what: \"moved\",\n report: async (views, recovered) => {\n await stageInGit(docsDir, renames);\n const rows = moved.map((m, i) => ({\n name: m.name,\n kind: m.kind,\n from: repoPath(docsDir, renames[i]!.from),\n to: repoPath(docsDir, renames[i]!.to),\n }));\n if (json) {\n emitJson({\n command: \"subsystem\",\n into,\n moved: rows,\n views,\n ...(notices.length === 0 ? {} : { warnings: notices }),\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n for (const row of rows) console.log(`moved ${row.from} -> ${row.to}`);\n for (const n of notices) console.log(`note: ${n}`);\n console.log(`Renames staged where git answers; nothing committed${reportViews(views)}.`);\n },\n };\n });\n}\n\n/** `subsystem rename <old> <new>` — one rename through the same transaction. */\nexport async function runRename(docsDir: DocsDir, names: [string, string], json: boolean): Promise<void> {\n const [from, to] = names;\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const hit = findInTree(tree, from);\n if (hit === null) {\n const close = nearestTreeNames(from, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${from}' in the tree.` + (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \"\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(\n json,\n \"invalid-option\",\n `'${from}' is a service — a service's id IS its identity (loam.json, frontmatter, feature specs all join on it), so loam never renames one.`,\n );\n return null;\n }\n const parsed = parseSubsystemName(to, \"subsystem name\");\n if (!parsed.ok) {\n fail(json, \"invalid-option\", parsed.problem);\n return null;\n }\n const taken = findInTree(tree, to);\n if (taken !== null) {\n const where = taken.kind === \"service\" ? taken.service.dir : taken.subsystem.dir;\n fail(json, \"already-exists\", `'${to}' is already a ${taken.kind} (${repoPath(docsDir, where)}) — the namespace is flat at any depth.`);\n return null;\n }\n if (await refuseUncommitted(docsDir, [hit.subsystem.dir], json)) return null;\n const notices = await v2SnapshotNotices(docsDir, [hit.subsystem.dir]);\n const rename = { from: hit.subsystem.dir, to: subsystemPathUnder(dirname(hit.subsystem.dir), parsed.name) };\n return {\n target: `${from} -> ${to}`,\n writes: [],\n tree: movedTree(tree, [rename], servicesDir(docsDir)),\n moves: [rename],\n failedCode: \"move-failed\",\n what: \"renamed\",\n report: async (views, recovered) => {\n await stageInGit(docsDir, [rename]);\n if (json) {\n emitJson({\n command: \"subsystem\",\n renamed: from,\n to,\n path: repoPath(docsDir, rename.to),\n views,\n ...(notices.length === 0 ? {} : { warnings: notices }),\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`renamed subsystem '${from}' -> '${to}' (${repoPath(docsDir, rename.to)}/)${reportViews(views)}`);\n for (const n of notices) console.log(`note: ${n}`);\n },\n };\n });\n}\n\n/** Where `--into` points: the services/ root for `.`, an existing subsystem otherwise. */\nfunction resolveTarget(tree: FleetTree, into: string, at: { docsDir: DocsDir; json: boolean }): { dir: string; path: string[] } | null {\n if (into === \".\") return { dir: servicesDir(at.docsDir), path: [] };\n const hit = findInTree(tree, into);\n if (hit === null) {\n const close = nearestTreeNames(into, tree.subsystems.map((s) => s.name));\n fail(\n at.json,\n \"unknown-target\",\n `No subsystem '${into}' to move into.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `--into .` unfiles; `loam subsystem new` creates.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(at.json, \"invalid-option\", `--into names the service '${into}' — a service never contains other services.`);\n return null;\n }\n return { dir: hit.subsystem.dir, path: hit.subsystem.path };\n}\n\n/**\n * The one move-specific refusal, on positive evidence only: git names\n * uncommitted work under a directory about to be renamed. Null (git will not\n * say) proceeds — a fleet that does not use git must not be refused over it.\n */\nasync function refuseUncommitted(docsDir: DocsDir, dirs: string[], json: boolean): Promise<boolean> {\n const dirty = await gitDirtyPaths(docsDir, dirs.map((d) => repoPath(docsDir, d)));\n if (dirty === null || dirty.length === 0) return false;\n fail(\n json,\n \"move-uncommitted\",\n // \"or untracked\", and `git stash -u` by name: the check fires on ANY\n // porcelain entry, untracked files included, and plain `git stash` does\n // not stash those — advice that said \"stash\" sent the user in a loop,\n // refused again with the same sentence after doing what it asked.\n `git reports ${dirty.length} uncommitted or untracked path(s) under the directory(ies) being moved: ${dirty.join(\", \")}. ` +\n \"Renaming now would sweep them into a move nobody reviewed — commit them, `git stash -u`, or remove them, then re-run. \" +\n \"Nothing was moved.\",\n );\n return true;\n}\n\n/**\n * Stage the move's whole delta, silently: the rename pairs (both ends — the\n * delete side and the add side) AND the regenerated views file. The views\n * file rides along for the same reason the transaction writes it in the same\n * commit: a user whose next `git commit` captured the renames without it\n * would commit a tree `validate --all` fails (`subsystem.views-stale`) — the\n * exact \"failing between two commits\" state the roadmap forbids.\n */\nasync function stageInGit(docsDir: DocsDir, renames: { from: string; to: string }[]): Promise<void> {\n await gitStageRenames(docsDir, [\n ...renames.flatMap((r) => [repoPath(docsDir, r.from), repoPath(docsDir, r.to)]),\n repoPath(docsDir, subsystemViewsPath(docsDir)),\n ]);\n}\n\n/**\n * Which archived features hold a VERSION-2 snapshot addressing a path under\n * one of these directories — the notice, never a refusal, a move prints\n * before it proceeds. A version-2 manifest predates the tree and records\n * literal `services/<id>/…` paths, so after this move an `unarchive --force`\n * of that feature restores into the OLD path, resurrecting the pre-move\n * directory beside the moved one (two claimants, `subsystem.name-collision`\n * — loud, but avoidable by being told now). Version-3 manifests key rows by\n * service id and follow the enumeration, so they are not named. Every\n * failure to read reads as \"nothing to warn about\": a warning needs positive\n * evidence exactly as the move's one refusal does.\n */\nasync function v2SnapshotNotices(docsDir: DocsDir, dirs: string[]): Promise<string[]> {\n const rels = dirs.map((d) => repoPath(docsDir, d));\n const notices: string[] = [];\n let features: FeatureEntry[];\n try {\n features = await listFeatures(docsDir, { includeArchived: true });\n } catch {\n return notices;\n }\n for (const f of features.filter((entry) => entry.archived)) {\n let manifest: unknown;\n try {\n manifest = JSON.parse(await readFile(join(snapshotDir(f.dir), SNAPSHOT_MANIFEST), \"utf8\"));\n } catch {\n continue;\n }\n if (!isRecord(manifest) || manifest.version !== SNAPSHOT_COMPAT_VERSION || !Array.isArray(manifest.files)) continue;\n const addressed = rels.filter((rel) =>\n (manifest.files as unknown[]).some(\n (row) => isRecord(row) && typeof row.path === \"string\" && row.path.startsWith(`${rel}/`),\n ),\n );\n if (addressed.length > 0) {\n notices.push(\n `${f.id}'s archived snapshot is version 2 and addresses ${addressed.join(\", \")} by literal path — ` +\n `\\`loam unarchive ${f.id} --force\\` after this move would restore into the old location, ` +\n `resurrecting the pre-move directory beside the moved one.`,\n );\n }\n }\n return notices;\n}\n"]}
1
+ {"version":3,"file":"move.js","sourceRoot":"","sources":["../../../src/commands/subsystem/move.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `subsystem move` and `subsystem rename` — ONE transaction over N directory\n * renames plus BOTH generated views files, the first real consumer of the\n * journaled txn's moves half (`core/staging/txn/`). The planning lives in\n * this module; the commit window itself is `./txn/txn.ts`, shared with\n * `new` and `rm`.\n *\n * The ONLY move-specific refusal is `move-uncommitted` — git reports\n * uncommitted changes under a directory being moved — and only on positive\n * evidence: where git will not say, the move proceeds. After a landed move\n * loam performs the roadmap's one blessed git write, a best-effort `git add`\n * of the rename pairs and of BOTH regenerated views files, so git records the\n * renames as renames and `subsystem history` stays answerable once the user\n * commits. Nothing is ever committed.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join, sep } from \"node:path\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseSubsystemName } from \"../../core/kernel/ids/subsystem.js\";\nimport { isRecord } from \"../../core/kernel/records.js\";\nimport { emitJson, fail, repoPath } from \"../../core/envelope/json.js\";\nimport { gitDirtyPaths, gitStageRenames } from \"../../core/provenance/gitq/moves.js\";\nimport type { FeatureEntry } from \"../../core/repo/entries.js\";\nimport { servicesDir, serviceViewsPath, subsystemPathUnder, subsystemViewsPath } from \"../../core/repo/paths.js\";\nimport { listFeatures } from \"../../core/repo/repo.js\";\nimport { findInTree, nearestTreeNames, treeNames, withinSubsystem } from \"../../core/repo/tree/find.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { SNAPSHOT_COMPAT_VERSION, SNAPSHOT_MANIFEST, snapshotDir } from \"../../core/staging/snapshot.js\";\nimport { commitWindow, reportViews, type SubsystemTxn, type ViewsActions } from \"./txn/txn.js\";\nimport { movedTree } from \"./txn/views.js\";\n\n/** What one name resolved to for a move: where it is, and where it goes. */\ninterface Moved {\n name: string;\n kind: \"service\" | \"subsystem\";\n dir: string;\n /** Path of the CONTAINING directory, as names from services/ down. */\n parent: string[];\n}\n\n/** `subsystem move <name>... --into <sub|.>` — services and whole subtrees alike. */\nexport async function runMove(docsDir: DocsDir, names: string[], into: string, json: boolean): Promise<void> {\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const seen = new Set<string>();\n for (const name of names) {\n if (seen.has(name)) {\n fail(json, \"invalid-option\", `'${name}' is named twice — each service or subsystem moves once.`);\n return null;\n }\n seen.add(name);\n }\n const target = resolveTarget(tree, into, { docsDir, json });\n if (target === null) return null;\n const moved: Moved[] = [];\n for (const name of names) {\n const hit = findInTree(tree, name);\n if (hit === null) {\n const close = nearestTreeNames(name, treeNames(tree));\n fail(\n json,\n \"unknown-target\",\n `No service or subsystem '${name}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n moved.push(\n hit.kind === \"service\"\n ? { name, kind: \"service\", dir: hit.service.dir, parent: hit.service.subsystem }\n : { name, kind: \"subsystem\", dir: hit.subsystem.dir, parent: hit.subsystem.path.slice(0, -1) },\n );\n }\n for (const m of moved) {\n if (m.kind === \"subsystem\" && withinSubsystem([...m.parent, m.name], target.path)) {\n fail(json, \"invalid-option\", `'${m.name}' cannot move into itself or its own subtree.`);\n return null;\n }\n if (m.parent.join(\"/\") === target.path.join(\"/\")) {\n fail(json, \"invalid-option\", `'${m.name}' is already directly in ${into === \".\" ? \"the services/ root\" : `'${into}'`} — nothing to move.`);\n return null;\n }\n const inside = moved.find(\n (other) => other.kind === \"subsystem\" && other !== m && (m.dir + sep).startsWith(other.dir + sep),\n );\n if (inside !== undefined) {\n fail(json, \"invalid-option\", `'${m.name}' sits inside '${inside.name}', which is also being moved — name only the subtree root.`);\n return null;\n }\n if (existsSync(join(target.dir, m.name))) {\n // Unreachable in a healthy flat namespace; a tree already carrying\n // name collisions can produce it, and refusing beats stacking a\n // second directory of the same name.\n fail(json, \"already-exists\", `${repoPath(docsDir, join(target.dir, m.name))} already exists — fix the name collision first.`);\n return null;\n }\n }\n if (await refuseUncommitted(docsDir, moved.map((m) => m.dir), json)) return null;\n const notices = await v2SnapshotNotices(docsDir, moved.map((m) => m.dir));\n const renames = moved.map((m) => ({ from: m.dir, to: join(target.dir, m.name) }));\n return {\n target: names.join(\", \"),\n writes: [],\n tree: movedTree(tree, renames, servicesDir(docsDir)),\n moves: renames,\n failedCode: \"move-failed\",\n what: \"moved\",\n report: async (views, recovered) => {\n await stageInGit(docsDir, renames, views);\n const rows = moved.map((m, i) => ({\n name: m.name,\n kind: m.kind,\n from: repoPath(docsDir, renames[i]!.from),\n to: repoPath(docsDir, renames[i]!.to),\n }));\n if (json) {\n emitJson({\n command: \"subsystem\",\n into,\n moved: rows,\n views: views.subsystems,\n serviceViews: views.services,\n ...(notices.length === 0 ? {} : { warnings: notices }),\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n for (const row of rows) console.log(`moved ${row.from} -> ${row.to}`);\n for (const n of notices) console.log(`note: ${n}`);\n console.log(`Renames staged where git answers; nothing committed${reportViews(views)}.`);\n },\n };\n });\n}\n\n/** `subsystem rename <old> <new>` — one rename through the same transaction. */\nexport async function runRename(docsDir: DocsDir, names: [string, string], json: boolean): Promise<void> {\n const [from, to] = names;\n await commitWindow(docsDir, json, async (tree): Promise<SubsystemTxn | null> => {\n const hit = findInTree(tree, from);\n if (hit === null) {\n const close = nearestTreeNames(from, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${from}' in the tree.` + (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \"\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(\n json,\n \"invalid-option\",\n `'${from}' is a service — a service's id IS its identity (loam.json, frontmatter, feature specs all join on it), so loam never renames one.`,\n );\n return null;\n }\n const parsed = parseSubsystemName(to, \"subsystem name\");\n if (!parsed.ok) {\n fail(json, \"invalid-option\", parsed.problem);\n return null;\n }\n const taken = findInTree(tree, to);\n if (taken !== null) {\n const where = taken.kind === \"service\" ? taken.service.dir : taken.subsystem.dir;\n fail(json, \"already-exists\", `'${to}' is already a ${taken.kind} (${repoPath(docsDir, where)}) — the namespace is flat at any depth.`);\n return null;\n }\n if (await refuseUncommitted(docsDir, [hit.subsystem.dir], json)) return null;\n const notices = await v2SnapshotNotices(docsDir, [hit.subsystem.dir]);\n const rename = { from: hit.subsystem.dir, to: subsystemPathUnder(dirname(hit.subsystem.dir), parsed.name) };\n return {\n target: `${from} -> ${to}`,\n writes: [],\n tree: movedTree(tree, [rename], servicesDir(docsDir)),\n moves: [rename],\n failedCode: \"move-failed\",\n what: \"renamed\",\n report: async (views, recovered) => {\n await stageInGit(docsDir, [rename], views);\n if (json) {\n emitJson({\n command: \"subsystem\",\n renamed: from,\n to,\n path: repoPath(docsDir, rename.to),\n views: views.subsystems,\n serviceViews: views.services,\n ...(notices.length === 0 ? {} : { warnings: notices }),\n ...(recovered === null ? {} : { recovered }),\n });\n return;\n }\n console.log(`renamed subsystem '${from}' -> '${to}' (${repoPath(docsDir, rename.to)}/)${reportViews(views)}`);\n for (const n of notices) console.log(`note: ${n}`);\n },\n };\n });\n}\n\n/** Where `--into` points: the services/ root for `.`, an existing subsystem otherwise. */\nfunction resolveTarget(tree: FleetTree, into: string, at: { docsDir: DocsDir; json: boolean }): { dir: string; path: string[] } | null {\n if (into === \".\") return { dir: servicesDir(at.docsDir), path: [] };\n const hit = findInTree(tree, into);\n if (hit === null) {\n const close = nearestTreeNames(into, tree.subsystems.map((s) => s.name));\n fail(\n at.json,\n \"unknown-target\",\n `No subsystem '${into}' to move into.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `--into .` unfiles; `loam subsystem new` creates.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(at.json, \"invalid-option\", `--into names the service '${into}' — a service never contains other services.`);\n return null;\n }\n return { dir: hit.subsystem.dir, path: hit.subsystem.path };\n}\n\n/**\n * The one move-specific refusal, on positive evidence only: git names\n * uncommitted work under a directory about to be renamed. Null (git will not\n * say) proceeds — a fleet that does not use git must not be refused over it.\n */\nasync function refuseUncommitted(docsDir: DocsDir, dirs: string[], json: boolean): Promise<boolean> {\n const dirty = await gitDirtyPaths(docsDir, dirs.map((d) => repoPath(docsDir, d)));\n if (dirty === null || dirty.length === 0) return false;\n fail(\n json,\n \"move-uncommitted\",\n // \"or untracked\", and `git stash -u` by name: the check fires on ANY\n // porcelain entry, untracked files included, and plain `git stash` does\n // not stash those — advice that said \"stash\" sent the user in a loop,\n // refused again with the same sentence after doing what it asked.\n `git reports ${dirty.length} uncommitted or untracked path(s) under the directory(ies) being moved: ${dirty.join(\", \")}. ` +\n \"Renaming now would sweep them into a move nobody reviewed — commit them, `git stash -u`, or remove them, then re-run. \" +\n \"Nothing was moved.\",\n );\n return true;\n}\n\n/**\n * Stage the move's whole delta, silently: the rename pairs (both ends — the\n * delete side and the add side) AND BOTH regenerated views files. They ride\n * along for the same reason the transaction writes them in the same commit: a\n * user whose next `git commit` captured the renames without them would commit\n * a tree `validate --all` fails (`subsystem.views-stale`) — the exact \"failing\n * between two commits\" state the roadmap forbids.\n *\n * A generated file that is neither ON DISK nor REMOVED BY THIS COMMIT is left\n * out of the pathspec, and that is a correctness rule rather than tidiness:\n * `gitStageRenames` runs one `git add -A -- <paths>`, and a pathspec matching\n * neither the worktree nor the index makes git refuse the WHOLE invocation\n * (silently — that write is failure-silent by contract) — so naming an absent\n * `architecture/services.likec4` (a fleet whose map draws no service renders\n * none) would take the other paths out of the index with it.\n *\n * THE `removed` ARM IS WHY `existsSync` ALONE IS NOT THE FILTER. A move can be\n * the commit that DELETES a generated file rather than rewriting it: a\n * committed `architecture/subsystems.likec4` standing over a tree that no\n * longer marks any subsystem (the marker went in an earlier commit) must not\n * exist, so the window renders null and the transaction removes it — and by the\n * time this runs the file is gone from disk. Measured 2026-09-07 on exactly that\n * fixture: under a disk-only filter the path never reached the pathspec, git\n * reported the deletion as ` D` (unstaged) while both rename ends went in as\n * `R `, and the user's next `git commit` captured the renames plus a generated\n * file the tree no longer licenses — `subsystem.views-stale` on a commit loam\n * itself produced, the exact state the paragraph above says this staging exists\n * to prevent. A path this commit deleted is still in the INDEX, so it matches\n * the pathspec and `-A` stages the deletion; the commit window's own\n * `ViewsActions` is what says which file that was, so no second guess about disk\n * is needed.\n *\n * TWO INVOCATIONS, not one, and the split is what makes the `removed` arm safe\n * to add: a generated file that was never committed and is deleted here is in\n * neither the worktree nor the index, and folded into one pathspec it would take\n * the renames down with it — the failure this function's first rule exists to\n * refuse. Staging in two calls costs one extra best-effort spawn and cannot\n * cost the renames. git records a rename from the index state at commit time,\n * never from which `git add` put the two ends there.\n */\nasync function stageInGit(docsDir: DocsDir, renames: { from: string; to: string }[], views: ViewsActions): Promise<void> {\n await gitStageRenames(docsDir, renames.flatMap((r) => [repoPath(docsDir, r.from), repoPath(docsDir, r.to)]));\n const generated = [\n [subsystemViewsPath(docsDir), views.subsystems] as const,\n [serviceViewsPath(docsDir), views.services] as const,\n ];\n await gitStageRenames(\n docsDir,\n generated\n .filter(([path, action]) => action === \"removed\" || existsSync(path))\n .map(([path]) => repoPath(docsDir, path)),\n );\n}\n\n/**\n * Which archived features hold a VERSION-2 snapshot addressing a path under\n * one of these directories — the notice, never a refusal, a move prints\n * before it proceeds. A version-2 manifest predates the tree and records\n * literal `services/<id>/…` paths, so after this move an `unarchive --force`\n * of that feature restores into the OLD path, resurrecting the pre-move\n * directory beside the moved one (two claimants, `subsystem.name-collision`\n * — loud, but avoidable by being told now). Version-3 manifests key rows by\n * service id and follow the enumeration, so they are not named. Every\n * failure to read reads as \"nothing to warn about\": a warning needs positive\n * evidence exactly as the move's one refusal does.\n */\nasync function v2SnapshotNotices(docsDir: DocsDir, dirs: string[]): Promise<string[]> {\n const rels = dirs.map((d) => repoPath(docsDir, d));\n const notices: string[] = [];\n let features: FeatureEntry[];\n try {\n features = await listFeatures(docsDir, { includeArchived: true });\n } catch {\n return notices;\n }\n for (const f of features.filter((entry) => entry.archived)) {\n let manifest: unknown;\n try {\n manifest = JSON.parse(await readFile(join(snapshotDir(f.dir), SNAPSHOT_MANIFEST), \"utf8\"));\n } catch {\n continue;\n }\n if (!isRecord(manifest) || manifest.version !== SNAPSHOT_COMPAT_VERSION || !Array.isArray(manifest.files)) continue;\n const addressed = rels.filter((rel) =>\n (manifest.files as unknown[]).some(\n (row) => isRecord(row) && typeof row.path === \"string\" && row.path.startsWith(`${rel}/`),\n ),\n );\n if (addressed.length > 0) {\n notices.push(\n `${f.id}'s archived snapshot is version 2 and addresses ${addressed.join(\", \")} by literal path — ` +\n `\\`loam unarchive ${f.id} --force\\` after this move would restore into the old location, ` +\n `resurrecting the pre-move directory beside the moved one.`,\n );\n }\n }\n return notices;\n}\n"]}