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

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 (273) hide show
  1. package/CHANGELOG.md +901 -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 +264 -11
  6. package/SCHEMA.md +439 -38
  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 +5 -2
  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/plan.js +97 -3
  25. package/dist/commands/seed/plan.js.map +1 -1
  26. package/dist/commands/seed/seed.js +7 -2
  27. package/dist/commands/seed/seed.js.map +1 -1
  28. package/dist/commands/show/feature.js +2 -1
  29. package/dist/commands/show/feature.js.map +1 -1
  30. package/dist/commands/show/marks.js +3 -5
  31. package/dist/commands/show/marks.js.map +1 -1
  32. package/dist/commands/show/service.js +39 -18
  33. package/dist/commands/show/service.js.map +1 -1
  34. package/dist/commands/subsystem/sync.js +128 -74
  35. package/dist/commands/subsystem/sync.js.map +1 -1
  36. package/dist/commands/subsystem/txn/exclude.js +132 -0
  37. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  38. package/dist/commands/subsystem/txn/report.js +124 -0
  39. package/dist/commands/subsystem/txn/report.js.map +1 -0
  40. package/dist/commands/subsystem/txn/txn.js +10 -3
  41. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  42. package/dist/commands/subsystem/txn/views.js +113 -16
  43. package/dist/commands/subsystem/txn/views.js.map +1 -1
  44. package/dist/commands/validate/arch-coverage.js +16 -9
  45. package/dist/commands/validate/arch-coverage.js.map +1 -1
  46. package/dist/commands/validate/checks/fleet-shape.js +30 -77
  47. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  48. package/dist/commands/validate/checks/vocabulary.js +4 -19
  49. package/dist/commands/validate/checks/vocabulary.js.map +1 -1
  50. package/dist/commands/validate/feature.js +1 -1
  51. package/dist/commands/validate/feature.js.map +1 -1
  52. package/dist/commands/validate/fleet/census.js +11 -10
  53. package/dist/commands/validate/fleet/census.js.map +1 -1
  54. package/dist/commands/validate/fleet/landscape.js +127 -119
  55. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  56. package/dist/commands/validate/fleet/load.js +66 -0
  57. package/dist/commands/validate/fleet/load.js.map +1 -1
  58. package/dist/commands/validate/fleet/map/attest.js +103 -0
  59. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  60. package/dist/commands/validate/fleet/map/bindings.js +96 -0
  61. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  62. package/dist/commands/validate/fleet/map/consumers.js +298 -0
  63. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  64. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  65. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  66. package/dist/commands/validate/fleet/map/usecases.js +56 -0
  67. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  68. package/dist/commands/validate/fleet/usecases/steps.js +49 -17
  69. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -1
  70. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  71. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  72. package/dist/commands/validate/fleet/views/ids.js +13 -9
  73. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  74. package/dist/commands/validate/fleet/views/projects.js +258 -70
  75. package/dist/commands/validate/fleet/views/projects.js.map +1 -1
  76. package/dist/commands/validate/fleet/views/root-documents.js +97 -0
  77. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  78. package/dist/commands/validate/fleet/views/stale.js +2 -2
  79. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  80. package/dist/commands/validate/service/model/diverged.js +226 -0
  81. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  82. package/dist/commands/validate/service/model/grade.js +163 -0
  83. package/dist/commands/validate/service/model/grade.js.map +1 -0
  84. package/dist/commands/validate/service/service.js +110 -34
  85. package/dist/commands/validate/service/service.js.map +1 -1
  86. package/dist/commands/validate/service/specs.js +39 -5
  87. package/dist/commands/validate/service/specs.js.map +1 -1
  88. package/dist/commands/validate/service/spine.js +41 -3
  89. package/dist/commands/validate/service/spine.js.map +1 -1
  90. package/dist/commands/validate/service/usecases/tags.js +113 -0
  91. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  92. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  93. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  94. package/dist/commands/validate/validate.js +10 -24
  95. package/dist/commands/validate/validate.js.map +1 -1
  96. package/dist/core/agent/agents-md/artifacts.js +1 -0
  97. package/dist/core/agent/agents-md/artifacts.js.map +1 -1
  98. package/dist/core/agent/agents-md/command-map.js +18 -4
  99. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  100. package/dist/core/agent/agents-md/cycle.js +24 -9
  101. package/dist/core/agent/agents-md/cycle.js.map +1 -1
  102. package/dist/core/agent/agents-md/map/lenses/context.js +4 -3
  103. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  104. package/dist/core/agent/agents-md/map/subsystem.js +51 -11
  105. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  106. package/dist/core/agent/agents-md/map/usecases.js +45 -3
  107. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  108. package/dist/core/agent/agents-md.js +14 -4
  109. package/dist/core/agent/agents-md.js.map +1 -1
  110. package/dist/core/agent/support/report.js +39 -5
  111. package/dist/core/agent/support/report.js.map +1 -1
  112. package/dist/core/agent/workflows/adopt.js +123 -14
  113. package/dist/core/agent/workflows/adopt.js.map +1 -1
  114. package/dist/core/agent/workflows/check.js +35 -20
  115. package/dist/core/agent/workflows/check.js.map +1 -1
  116. package/dist/core/agent/workflows/closing.js +3 -1
  117. package/dist/core/agent/workflows/closing.js.map +1 -1
  118. package/dist/core/brief/brief.js +63 -11
  119. package/dist/core/brief/brief.js.map +1 -1
  120. package/dist/core/brief/checks.js +133 -7
  121. package/dist/core/brief/checks.js.map +1 -1
  122. package/dist/core/brief/landscape.js +212 -129
  123. package/dist/core/brief/landscape.js.map +1 -1
  124. package/dist/core/brief/map/extend.js +81 -0
  125. package/dist/core/brief/map/extend.js.map +1 -0
  126. package/dist/core/brief/map/owed.js +284 -0
  127. package/dist/core/brief/map/owed.js.map +1 -0
  128. package/dist/core/brief/targets.js +30 -29
  129. package/dist/core/brief/targets.js.map +1 -1
  130. package/dist/core/brief/unchecked.js +12 -2
  131. package/dist/core/brief/unchecked.js.map +1 -1
  132. package/dist/core/c4/likec4.js +23 -1
  133. package/dist/core/c4/likec4.js.map +1 -1
  134. package/dist/core/c4/parsed/deployment.js +5 -3
  135. package/dist/core/c4/parsed/deployment.js.map +1 -1
  136. package/dist/core/c4/parsed/view-ids.js +39 -1
  137. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  138. package/dist/core/c4/prefetch/fleet.js +142 -0
  139. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  140. package/dist/core/c4/project/architecture.js +52 -4
  141. package/dist/core/c4/project/architecture.js.map +1 -1
  142. package/dist/core/c4/project/batch.js +140 -0
  143. package/dist/core/c4/project/batch.js.map +1 -0
  144. package/dist/core/c4/project/documents.js +9 -4
  145. package/dist/core/c4/project/documents.js.map +1 -1
  146. package/dist/core/c4/project/load.js +77 -38
  147. package/dist/core/c4/project/load.js.map +1 -1
  148. package/dist/core/c4/project/staged.js +46 -12
  149. package/dist/core/c4/project/staged.js.map +1 -1
  150. package/dist/core/c4/resolve/attested.js +0 -0
  151. package/dist/core/c4/resolve/attested.js.map +1 -0
  152. package/dist/core/c4/resolve/service.js +8 -17
  153. package/dist/core/c4/resolve/service.js.map +1 -1
  154. package/dist/core/c4/resolve/steps.js +18 -0
  155. package/dist/core/c4/resolve/steps.js.map +1 -1
  156. package/dist/core/c4/root-project/exclude.js +352 -0
  157. package/dist/core/c4/root-project/exclude.js.map +1 -0
  158. package/dist/core/c4/service-model/documents.js +47 -0
  159. package/dist/core/c4/service-model/documents.js.map +1 -0
  160. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  161. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  162. package/dist/core/c4/service-model/load.js +165 -0
  163. package/dist/core/c4/service-model/load.js.map +1 -0
  164. package/dist/core/c4/service-model/renderer.js +128 -0
  165. package/dist/core/c4/service-model/renderer.js.map +1 -0
  166. package/dist/core/c4/service-model/shape.js +126 -0
  167. package/dist/core/c4/service-model/shape.js.map +1 -0
  168. package/dist/core/c4/service-model/slice.js +188 -0
  169. package/dist/core/c4/service-model/slice.js.map +1 -0
  170. package/dist/core/c4/source-scan.js +26 -0
  171. package/dist/core/c4/source-scan.js.map +1 -1
  172. package/dist/core/c4/splice/authored-source.js +60 -13
  173. package/dist/core/c4/splice/authored-source.js.map +1 -1
  174. package/dist/core/c4/splice/contract.js.map +1 -1
  175. package/dist/core/c4/splice/identity/declared.js +87 -0
  176. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  177. package/dist/core/c4/splice/identity/edges.js +17 -0
  178. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  179. package/dist/core/c4/splice/identity/existing.js +80 -0
  180. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  181. package/dist/core/c4/splice/identity/interior.js +80 -0
  182. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  183. package/dist/core/c4/splice/identity/owner.js +50 -0
  184. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  185. package/dist/core/c4/splice/landscape-merge.js +154 -100
  186. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  187. package/dist/core/c4/splice/model/merge.js +140 -0
  188. package/dist/core/c4/splice/model/merge.js.map +1 -0
  189. package/dist/core/c4/splice/placement.js +14 -4
  190. package/dist/core/c4/splice/placement.js.map +1 -1
  191. package/dist/core/c4/workspace.js +2 -1
  192. package/dist/core/c4/workspace.js.map +1 -1
  193. package/dist/core/coherence/coherence.js +7 -0
  194. package/dist/core/coherence/coherence.js.map +1 -1
  195. package/dist/core/delta/delta.js +9 -0
  196. package/dist/core/delta/delta.js.map +1 -1
  197. package/dist/core/deployment/delta.js +4 -0
  198. package/dist/core/deployment/delta.js.map +1 -1
  199. package/dist/core/diff/base-state.js +21 -5
  200. package/dist/core/diff/base-state.js.map +1 -1
  201. package/dist/core/diff/victims.js +10 -1
  202. package/dist/core/diff/victims.js.map +1 -1
  203. package/dist/core/docs.js +29 -24
  204. package/dist/core/docs.js.map +1 -1
  205. package/dist/core/doctor/config.js +7 -3
  206. package/dist/core/doctor/config.js.map +1 -1
  207. package/dist/core/doctor/doctor.js +36 -8
  208. package/dist/core/doctor/doctor.js.map +1 -1
  209. package/dist/core/doctor/report.js.map +1 -1
  210. package/dist/core/doctor/reports/scan.js +242 -0
  211. package/dist/core/doctor/reports/scan.js.map +1 -0
  212. package/dist/core/explain/refusals.js +1 -1
  213. package/dist/core/explain/refusals.js.map +1 -1
  214. package/dist/core/explore/explore.js +44 -9
  215. package/dist/core/explore/explore.js.map +1 -1
  216. package/dist/core/fleet-context.js +47 -0
  217. package/dist/core/fleet-context.js.map +1 -1
  218. package/dist/core/gate/partners.js +5 -9
  219. package/dist/core/gate/partners.js.map +1 -1
  220. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  221. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  222. package/dist/core/pack/living.js +47 -13
  223. package/dist/core/pack/living.js.map +1 -1
  224. package/dist/core/pack/pack.js +9 -6
  225. package/dist/core/pack/pack.js.map +1 -1
  226. package/dist/core/projection/arch-slice.js +2 -2
  227. package/dist/core/projection/arch-slice.js.map +1 -1
  228. package/dist/core/repo/paths.js +11 -9
  229. package/dist/core/repo/paths.js.map +1 -1
  230. package/dist/core/repo/tree/render/projects.js +93 -35
  231. package/dist/core/repo/tree/render/projects.js.map +1 -1
  232. package/dist/core/repo/tree/render/stale.js +2 -3
  233. package/dist/core/repo/tree/render/stale.js.map +1 -1
  234. package/dist/core/repo/tree/render/views.js +51 -3
  235. package/dist/core/repo/tree/render/views.js.map +1 -1
  236. package/dist/core/repo/tree/walk.js +45 -2
  237. package/dist/core/repo/tree/walk.js.map +1 -1
  238. package/dist/core/scaffold/landscape.js +219 -9
  239. package/dist/core/scaffold/landscape.js.map +1 -1
  240. package/dist/core/staging/writes.js.map +1 -1
  241. package/dist/core/usecases/delta/claims.js +1 -0
  242. package/dist/core/usecases/delta/claims.js.map +1 -1
  243. package/dist/core/usecases/delta/overlay.js +4 -0
  244. package/dist/core/usecases/delta/overlay.js.map +1 -1
  245. package/dist/core/usecases/fleet.js +18 -6
  246. package/dist/core/usecases/fleet.js.map +1 -1
  247. package/dist/core/usecases/operations.js +7 -0
  248. package/dist/core/usecases/operations.js.map +1 -1
  249. package/dist/core/usecases/service/exclude.js +119 -0
  250. package/dist/core/usecases/service/exclude.js.map +1 -0
  251. package/dist/core/usecases/service/flows.js +161 -0
  252. package/dist/core/usecases/service/flows.js.map +1 -0
  253. package/dist/core/vocabulary/maturity.js +10 -0
  254. package/dist/core/vocabulary/maturity.js.map +1 -1
  255. package/examples/README.md +24 -6
  256. package/examples/docs/architecture/landscape.likec4 +41 -0
  257. package/examples/docs/architecture/usecases/order-notification.likec4 +5 -2
  258. package/examples/docs/likec4.config.json +0 -1
  259. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  260. package/examples/docs/services/order-service/arch.spec.md +13 -6
  261. package/examples/docs/services/order-service/model.likec4 +53 -67
  262. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  263. package/examples/docs/services/payment-service/model.likec4 +32 -35
  264. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  265. package/examples/docs/services/platform/identity-service/model.likec4 +29 -33
  266. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  267. package/examples/docs/services/platform/notification-service/model.likec4 +39 -59
  268. package/package.json +1 -1
  269. package/examples/docs/services/checkout-web/likec4.config.json +0 -4
  270. package/examples/docs/services/order-service/likec4.config.json +0 -4
  271. package/examples/docs/services/payment-service/likec4.config.json +0 -4
  272. package/examples/docs/services/platform/identity-service/likec4.config.json +0 -4
  273. package/examples/docs/services/platform/notification-service/likec4.config.json +0 -4
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/archive/run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The archive itself, under the docs lock: gate, plan, commit.\n *\n * The order is the command's whole safety property. Every refusal happens before\n * a byte is planned (`./plan/gate.ts`), the plan is computed entirely in memory\n * so a failure on any axis leaves the living docs untouched (`./plan/specs.ts`,\n * `./plan/contracts/`, `./plan/landscape.ts`), and only a plan that succeeded\n * on every axis is staged\n * and swapped. `--dry-run` returns between the second and the third.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, rename } from \"node:fs/promises\";\nimport { emitJson, repoPath, sayExplain } from \"../../core/envelope/json.js\";\nimport {\n message,\n quietPruneEmptyParents,\n quietRm,\n rollbackError,\n rollbackStaged,\n stageWrites,\n swapStaged,\n} from \"../../core/staging/commit.js\";\nimport { clearCommitIntent, writeCommitIntent } from \"../../core/staging/recovery/intent.js\";\nimport {\n SNAPSHOT_DIR,\n SnapshotClobberError,\n snapshotDir,\n writeSnapshot,\n type ServiceKey,\n} from \"../../core/staging/snapshot.js\";\nimport { enumeratedServices } from \"../../core/repo/service-target.js\";\nimport { listFleetTree } from \"../../core/repo/repo.js\";\nimport { subsystemViewsPath } from \"../../core/repo/paths.js\";\nimport { viewsState } from \"../../core/repo/tree/render/stale.js\";\nimport { loadArchitecture } from \"../../core/c4/project/architecture.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { gate } from \"./plan/gate.js\";\nimport { type ArchiveOptions } from \"./plan/refusal.js\";\nimport { planCapabilities, planGlossary, planSpecs } from \"./plan/specs.js\";\nimport { planOpenapiContracts } from \"./plan/contracts/openapi.js\";\nimport { planAsyncapiContracts } from \"./plan/contracts/asyncapi.js\";\nimport { planDeployments, planFlows, planLandscape } from \"./plan/landscape.js\";\nimport { emptyPlan } from \"./plan/state.js\";\nimport { issueJson, refuseJson } from \"./plan/refusal.js\";\nimport { ArchiveFailure } from \"./plan/refusal.js\";\nimport { printPlan } from \"./plan/refusal.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\nexport async function archiveLocked(\n config: { docsDir: DocsDir },\n featureId: string,\n opts: ArchiveOptions,\n): Promise<void> {\n const dryRun = opts.dryRun === true;\n const json = opts.json === true;\n // All prose goes through here so `--json` keeps stdout a single JSON document.\n const say = (line = \"\"): void => {\n if (!json) console.log(line);\n };\n\n // One read index for the whole run, threaded through every planner's\n // config record: gate, the spec merge and both contract merges each hold\n // per-service loops that resolve living paths through the enumeration, and\n // without a shared context every one of those calls re-walks the fleet —\n // O(services²) work under a lock that guarantees the tree is not moving.\n // The snapshot resolver below reads through the same context, so it pays\n // for that enumeration too.\n const read = { docsDir: config.docsDir, fleet: new FleetContext() };\n const gated = await gate(read, featureId, opts, say);\n if (gated === null) return;\n const { id, dirName, featureDir, gating, advisory, archiveDir, archiveDest, recovered, issues } = gated;\n\n say(`archive ${id}${dryRun ? \" (dry run)\" : \"\"}\\n`);\n\n // PLAN — compute every merge in memory. Nothing is written until the whole plan\n // succeeds, so a failure on any axis leaves the living docs untouched.\n const planned = emptyPlan();\n await planSpecs(read, gated, planned, say);\n // The business corpus, beside the service one and before the contracts: both\n // are requirement merges, and reading them together is how a plan stays\n // legible as \"what this feature promises\" followed by \"how it is built\".\n await planCapabilities(read, gated, planned, say);\n // The vocabulary the change brings with it, beside the promises it makes:\n // a create-only whole-file copy, refused at the gate if the word already\n // lives (`core/glossary/delta.ts`).\n await planGlossary(read, gated, planned, say);\n await planOpenapiContracts(read, gated, planned, say);\n await planAsyncapiContracts(read, gated, planned, say);\n await planLandscape(config, gated, planned, say);\n // The flows this feature brings, after the elements they draw hops over: the\n // copy is create-only and refused at the gate if the living tree already holds\n // one (`core/usecases/delta/flows.ts`), and it is ordered after the landscape\n // merge so a reader of the plan sees the map change before the sequence drawn\n // on it.\n await planFlows(config, gated, planned, say);\n await planDeployments(config, gated, planned, say);\n const { writes, planWarns, planGates, openapiRemovals, asyncapiRemovals } = planned;\n\n // Gate on what only the plan could see: a merged operation pointing at a\n // component that exists nowhere, a removal marker addressing no operation.\n // Same doctrine as the coherence gate — a judgment call --approve overrides\n // (unlike the mechanical merge-failed refusals), and a dry run is gated too.\n // Checked after the whole plan so the refusal costs nothing: no write has\n // happened yet either way.\n if (planGates.length > 0 && !opts.approve) {\n const msg = `archive ${id} — BLOCKED: ${planGates.length} issue(s) in the contract merge`;\n if (json) {\n refuseJson(\n \"not-coherent\",\n msg,\n [...issues, ...planWarns, ...planGates],\n `features/${dirName}`,\n );\n return;\n }\n console.error(`${msg}:`);\n for (const i of planGates) console.error(` ✗ ${i.message}`);\n console.error(`\\nFix them in the feature's openapi.yaml / asyncapi.yaml — or re-run with --approve to merge anyway.`);\n sayExplain(\"not-coherent\");\n process.exitCode = 1;\n return;\n }\n if (planGates.length > 0) {\n say(`\\n ⚠ archiving despite ${planGates.length} contract merge issue(s) (--approve):`);\n for (const i of planGates) say(` ✗ ${i.message}`);\n }\n\n // The plan as data, verb decided now — after the commit everything would read\n // as an update. The `--json` payload is identical for a dry run and the real\n // thing except for `archived`; what WOULD happen is what DOES happen.\n const warnings = [...advisory, ...planWarns];\n const overridden = opts.approve === true ? [...gating, ...planGates] : [];\n const plan: Array<Record<string, unknown>> = writes.map((w) => ({\n path: repoPath(config.docsDir, w.path),\n action: existsSync(w.path) ? \"update\" : \"create\",\n }));\n plan.push({ path: `features/${dirName}`, action: \"move\", to: `features/archive/${dirName}` });\n const payload = (archived: boolean): Record<string, unknown> => ({\n command: \"archive\",\n feature: id,\n archived,\n path: repoPath(config.docsDir, archiveDest),\n plan,\n warnings: warnings.map((issue) => issueJson(issue, repoPath(config.docsDir, archiveDest))),\n overridden: overridden.map((issue) => issueJson(issue, repoPath(config.docsDir, archiveDest))),\n openapiRemovals,\n asyncapiRemovals,\n // Present only when this run found an interrupted commit and dealt with it:\n // an agent that sees the docs change under it deserves to be told why, and\n // the absent field is the ordinary case.\n ...(recovered === null ? {} : { recovered }),\n });\n\n if (dryRun) {\n if (json) emitJson(payload(false));\n else printPlan(config.docsDir, writes, dirName);\n return;\n }\n\n // COMMIT — the whole plan computed cleanly. Stage every new version beside its\n // target, snapshot what is about to be overwritten, then swap them into place.\n // Staging touches the filesystem — a read-only `architecture/`, a full disk,\n // a target whose pre-image cannot be read. None of that is a bug in loam, and\n // reporting `internal` sends the reader looking for one; it is the same\n // answer as any other merge that could not be computed: nothing was written.\n let staged;\n try {\n staged = await stageWrites(writes);\n } catch (err) {\n throw new ArchiveFailure(\"merge-failed\", `${message(err)} — nothing was written`);\n }\n let snapshot = false;\n let createdArchiveDir: string | undefined;\n try {\n // The snapshot's resolver pair: how a docs-relative path decomposes into a\n // service identity, and where that identity lives NOW. Built here — the\n // command layer's view of the tree — and injected, so the snapshot module\n // never learns the repo layout. The seam the flat wave left is now\n // threaded: both answers come from the enumeration, so a service filed\n // into a subsystem keys its snapshot rows by the directory it actually\n // lives in, and the clobber guard grades a leftover claim at that same\n // address. The root-level parse stays as the fallback for the one path\n // shape the enumeration cannot know yet — a service this archive CREATES,\n // which always materialises unfiled at services/<id>/.\n // Tolerant on purpose: a docs repo whose services/ is absent still\n // archives a landscape-only feature exactly as before — the enumeration\n // is empty, every row keys by the flat fallback, and the missing\n // directory stays doctor's diagnosis rather than a merge-failed here.\n const dirOf = new Map(\n (await enumeratedServices(config.docsDir, read.fleet)).map((s) => [s.id as string, repoPath(config.docsDir, s.dir)]),\n );\n const serviceKeyOf = (rel: string): ServiceKey | null => {\n for (const [service, dir] of dirOf) {\n if (rel.startsWith(`${dir}/`)) return { service, artifact: rel.slice(dir.length + 1) };\n }\n const m = /^services\\/([^/]+)\\/(.+)$/.exec(rel);\n return m ? { service: m[1]!, artifact: m[2]! } : null;\n };\n const serviceDirOf = (service: string): string | null => dirOf.get(service) ?? null;\n await writeSnapshot({\n featureDir,\n docsDir: config.docsDir,\n feature: { featureId: id, dirName },\n staged,\n serviceKeyOf,\n serviceDirOf,\n });\n snapshot = true;\n // The journal, fsynced, BEFORE the first rename: swapStaged is N renames and\n // only each one of them is atomic, so a kill between two used to leave a\n // half-merged repo that nothing could name — `doctor` and `status` called it\n // healthy and `validate --all` blamed the delta. Written from `staged`, so\n // it records the same digests the swaps are about to produce.\n await writeCommitIntent(\n config.docsDir,\n { command: \"archive\", restore: \"before\", feature: id, moveFrom: featureDir, moveTo: archiveDest },\n staged,\n );\n await swapStaged(staged);\n createdArchiveDir = await mkdir(archiveDir, { recursive: true });\n await rename(featureDir, archiveDest);\n // Last: while it exists, the commit is in flight.\n await clearCommitIntent(config.docsDir);\n } catch (err) {\n if (err instanceof SnapshotClobberError) {\n // Nothing swapped — the refusal happens before the journal is even\n // written — so this only takes the temp files away. Its own code, because\n // the answer is not \"re-run\": a previous archive of this feature is still\n // sitting in the living docs.\n await rollbackStaged(staged);\n throw new ArchiveFailure(\"commit-interrupted\", err.message);\n }\n // Everything this run made, unmade: the swapped files, the snapshot inside the\n // feature that is staying put, and features/archive/ if we are the ones who\n // created it (mkdir reports nothing when it was already there).\n const failures = await rollbackStaged(staged);\n // The rollback decided the outcome, so the journal has nothing left to\n // describe — including on rollback-incomplete, where the files it names are\n // the ones the message tells a human to look at.\n await clearCommitIntent(config.docsDir);\n // The snapshot goes only when the rollback HELD. On rollback-incomplete it\n // holds the only on-disk pre-images of the very files the message tells the\n // reader to repair by hand — a MODIFIED requirement's previous text appears\n // nowhere else. Retaining it is safe: the next archive of this feature reads\n // it before it would replace it, and refuses if the living docs have moved.\n if (snapshot && failures.length === 0) await quietRm(snapshotDir(featureDir));\n // `features/archive/` is shared the moment it exists: another archive can\n // have moved a whole feature into it between our mkdir and this rollback,\n // and a recursive remove of \"the directory we created\" took that feature —\n // snapshot and all — with it, on OUR failure path, in silence. Empty\n // directories only, stopping at the first that is not.\n if (createdArchiveDir !== undefined) await quietPruneEmptyParents(archiveDir, createdArchiveDir);\n // The code is a caller's answer to \"can I trust the repo?\": merge-failed\n // means yes (rolled back), rollback-incomplete means look at it by hand.\n const wrapped = rollbackError(err, failures);\n const kept =\n snapshot && failures.length > 0\n ? ` Pre-images of the overwritten files are kept in features/${dirName}/${SNAPSHOT_DIR}/files/.`\n : \"\";\n throw new ArchiveFailure(failures.length > 0 ? \"rollback-incomplete\" : \"merge-failed\", wrapped.message + kept);\n }\n\n // This merge just changed the map, and the generated views file is a\n // function of the tree AND the map: a delta whose element lands inside a\n // group that exactly covered a subsystem takes that subsystem's boundary\n // line away, and a delta binding an element to a filed service adds an\n // include. Archive does not rewrite the file — `loam subsystem sync` owns it\n // outright, and folding a second generated artifact into this transaction\n // would mean archive computing the post-merge tree AND the post-merge map,\n // which is how the two writers disagree — but it must not report a repo as\n // current when the next `validate --all` will call it stale. Graded through\n // validate's own function, so the two cannot answer differently.\n const staleViews = await subsystemViewsStale(config.docsDir);\n\n if (json) {\n emitJson({ ...payload(true), ...(staleViews ? { subsystemViewsStale: true } : {}) });\n return;\n }\n console.log(`\\n archived: features/${dirName} → features/archive/${dirName}`);\n console.log(` snapshot: features/archive/${dirName}/${SNAPSHOT_DIR}/ — \\`loam unarchive ${id}\\` puts it back`);\n // The closing line is a claim about the whole docs repo, and it is the line a\n // reader stops at. It may be printed only when this archive left nothing the\n // next `validate --all` will fail on — a service with no model, or a gate the\n // caller told it to merge past. Printing it over either is how a red fleet\n // gets reported as a finished one.\n const incomplete = planWarns.filter((w) => w.code === \"service.no-model\");\n if (incomplete.length === 0 && overridden.length === 0 && !staleViews) {\n console.log(\" living spec + landscape are now complete + current.\");\n return;\n }\n if (staleViews) {\n console.log(\n \" ⚠ architecture/subsystems.likec4 no longer matches the tree and this map — run `loam subsystem sync`.\",\n );\n }\n for (const w of incomplete) console.log(` ⚠ ${w.message}`);\n if (overridden.length > 0) {\n console.log(\n ` ⚠ merged past ${overridden.length} gating issue(s) with --approve — the living docs carry them now; \\`loam validate --all\\` says what they cost.`,\n );\n }\n}\n\n/**\n * Would the next `validate --all` report `subsystem.views-stale`?\n *\n * Asked through validate's OWN function rather than a second compare, so the\n * warning archive prints and the error validate raises can never disagree —\n * including about the gate validate holds: a map that does not parse is\n * `landscape.invalid`'s business, and grading a generated file against a map\n * nobody can read would cascade a second complaint behind the first. An\n * unreadable map therefore answers \"no claim\", exactly as validate does.\n */\nasync function subsystemViewsStale(docsDir: DocsDir): Promise<boolean> {\n try {\n const doc = await loadArchitecture(docsDir);\n if (doc.errors.length > 0) return false;\n const state = await viewsState(subsystemViewsPath(docsDir), await listFleetTree(docsDir), doc.elements);\n return !state.agrees;\n } catch {\n // Tolerant for the reason the snapshot resolver above is: a docs repo with\n // no `services/` at all still archives a landscape-only feature, and this\n // question is an ADVISORY printed after a commit that already succeeded.\n // Nothing here may turn a landed archive into a non-zero exit.\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/archive/run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The archive itself, under the docs lock: gate, plan, commit.\n *\n * The order is the command's whole safety property. Every refusal happens before\n * a byte is planned (`./plan/gate.ts`), the plan is computed entirely in memory\n * so a failure on any axis leaves the living docs untouched (`./plan/specs.ts`,\n * `./plan/contracts/`, `./plan/landscape.ts`), and only a plan that succeeded\n * on every axis is staged\n * and swapped. `--dry-run` returns between the second and the third.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, rename } from \"node:fs/promises\";\nimport { emitJson, repoPath, sayExplain } from \"../../core/envelope/json.js\";\nimport {\n message,\n quietPruneEmptyParents,\n quietRm,\n rollbackError,\n rollbackStaged,\n stageWrites,\n swapStaged,\n} from \"../../core/staging/commit.js\";\nimport { clearCommitIntent, writeCommitIntent } from \"../../core/staging/recovery/intent.js\";\nimport {\n SNAPSHOT_DIR,\n SnapshotClobberError,\n snapshotDir,\n writeSnapshot,\n type ServiceKey,\n} from \"../../core/staging/snapshot.js\";\nimport { enumeratedServices } from \"../../core/repo/service-target.js\";\nimport { listFleetTree } from \"../../core/repo/repo.js\";\nimport { subsystemViewsPath } from \"../../core/repo/paths.js\";\nimport { viewsState } from \"../../core/repo/tree/render/stale.js\";\nimport { loadArchitecture } from \"../../core/c4/project/architecture.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { gate } from \"./plan/gate.js\";\nimport { type ArchiveOptions } from \"./plan/refusal.js\";\nimport { planCapabilities, planGlossary, planSpecs } from \"./plan/specs.js\";\nimport { planOpenapiContracts } from \"./plan/contracts/openapi.js\";\nimport { planAsyncapiContracts } from \"./plan/contracts/asyncapi.js\";\nimport { planDeployments, planFlows, planLandscape } from \"./plan/landscape.js\";\nimport { emptyPlan } from \"./plan/state.js\";\nimport { issueJson, refuseJson } from \"./plan/refusal.js\";\nimport { ArchiveFailure } from \"./plan/refusal.js\";\nimport { printPlan } from \"./plan/refusal.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\nexport async function archiveLocked(\n config: { docsDir: DocsDir },\n featureId: string,\n opts: ArchiveOptions,\n): Promise<void> {\n const dryRun = opts.dryRun === true;\n const json = opts.json === true;\n // All prose goes through here so `--json` keeps stdout a single JSON document.\n const say = (line = \"\"): void => {\n if (!json) console.log(line);\n };\n\n // One read index for the whole run, threaded through every planner's\n // config record: gate, the spec merge and both contract merges each hold\n // per-service loops that resolve living paths through the enumeration, and\n // without a shared context every one of those calls re-walks the fleet —\n // O(services²) work under a lock that guarantees the tree is not moving.\n // The snapshot resolver below reads through the same context, so it pays\n // for that enumeration too.\n const read = { docsDir: config.docsDir, fleet: new FleetContext() };\n const gated = await gate(read, featureId, opts, say);\n if (gated === null) return;\n const { id, dirName, featureDir, gating, advisory, archiveDir, archiveDest, recovered, issues } = gated;\n\n say(`archive ${id}${dryRun ? \" (dry run)\" : \"\"}\\n`);\n\n // PLAN — compute every merge in memory. Nothing is written until the whole plan\n // succeeds, so a failure on any axis leaves the living docs untouched.\n const planned = emptyPlan();\n await planSpecs(read, gated, planned, say);\n // The business corpus, beside the service one and before the contracts: both\n // are requirement merges, and reading them together is how a plan stays\n // legible as \"what this feature promises\" followed by \"how it is built\".\n await planCapabilities(read, gated, planned, say);\n // The vocabulary the change brings with it, beside the promises it makes:\n // a create-only whole-file copy, refused at the gate if the word already\n // lives (`core/glossary/delta.ts`).\n await planGlossary(read, gated, planned, say);\n await planOpenapiContracts(read, gated, planned, say);\n await planAsyncapiContracts(read, gated, planned, say);\n // `read`, not `config`: the C4 merge now asks which services own their own\n // interior, and that answer comes from the fleet enumeration this run has\n // already paid for.\n await planLandscape(read, gated, planned, say);\n // The flows this feature brings, after the elements they draw hops over: the\n // copy is create-only and refused at the gate if the living tree already holds\n // one (`core/usecases/delta/flows.ts`), and it is ordered after the landscape\n // merge so a reader of the plan sees the map change before the sequence drawn\n // on it.\n await planFlows(config, gated, planned, say);\n await planDeployments(config, gated, planned, say);\n const { writes, planWarns, planGates, openapiRemovals, asyncapiRemovals } = planned;\n\n // Gate on what only the plan could see: a merged operation pointing at a\n // component that exists nowhere, a removal marker addressing no operation.\n // Same doctrine as the coherence gate — a judgment call --approve overrides\n // (unlike the mechanical merge-failed refusals), and a dry run is gated too.\n // Checked after the whole plan so the refusal costs nothing: no write has\n // happened yet either way.\n if (planGates.length > 0 && !opts.approve) {\n const msg = `archive ${id} — BLOCKED: ${planGates.length} issue(s) in the contract merge`;\n if (json) {\n refuseJson(\n \"not-coherent\",\n msg,\n [...issues, ...planWarns, ...planGates],\n `features/${dirName}`,\n );\n return;\n }\n console.error(`${msg}:`);\n for (const i of planGates) console.error(` ✗ ${i.message}`);\n console.error(`\\nFix them in the feature's openapi.yaml / asyncapi.yaml — or re-run with --approve to merge anyway.`);\n sayExplain(\"not-coherent\");\n process.exitCode = 1;\n return;\n }\n if (planGates.length > 0) {\n say(`\\n ⚠ archiving despite ${planGates.length} contract merge issue(s) (--approve):`);\n for (const i of planGates) say(` ✗ ${i.message}`);\n }\n\n // The plan as data, verb decided now — after the commit everything would read\n // as an update. The `--json` payload is identical for a dry run and the real\n // thing except for `archived`; what WOULD happen is what DOES happen.\n const warnings = [...advisory, ...planWarns];\n const overridden = opts.approve === true ? [...gating, ...planGates] : [];\n const plan: Array<Record<string, unknown>> = writes.map((w) => ({\n path: repoPath(config.docsDir, w.path),\n action: existsSync(w.path) ? \"update\" : \"create\",\n }));\n plan.push({ path: `features/${dirName}`, action: \"move\", to: `features/archive/${dirName}` });\n const payload = (archived: boolean): Record<string, unknown> => ({\n command: \"archive\",\n feature: id,\n archived,\n path: repoPath(config.docsDir, archiveDest),\n plan,\n warnings: warnings.map((issue) => issueJson(issue, repoPath(config.docsDir, archiveDest))),\n overridden: overridden.map((issue) => issueJson(issue, repoPath(config.docsDir, archiveDest))),\n openapiRemovals,\n asyncapiRemovals,\n // Present only when this run found an interrupted commit and dealt with it:\n // an agent that sees the docs change under it deserves to be told why, and\n // the absent field is the ordinary case.\n ...(recovered === null ? {} : { recovered }),\n });\n\n if (dryRun) {\n if (json) emitJson(payload(false));\n else printPlan(config.docsDir, writes, dirName);\n return;\n }\n\n // COMMIT — the whole plan computed cleanly. Stage every new version beside its\n // target, snapshot what is about to be overwritten, then swap them into place.\n // Staging touches the filesystem — a read-only `architecture/`, a full disk,\n // a target whose pre-image cannot be read. None of that is a bug in loam, and\n // reporting `internal` sends the reader looking for one; it is the same\n // answer as any other merge that could not be computed: nothing was written.\n let staged;\n try {\n staged = await stageWrites(writes);\n } catch (err) {\n throw new ArchiveFailure(\"merge-failed\", `${message(err)} — nothing was written`);\n }\n let snapshot = false;\n let createdArchiveDir: string | undefined;\n try {\n // The snapshot's resolver pair: how a docs-relative path decomposes into a\n // service identity, and where that identity lives NOW. Built here — the\n // command layer's view of the tree — and injected, so the snapshot module\n // never learns the repo layout. The seam the flat wave left is now\n // threaded: both answers come from the enumeration, so a service filed\n // into a subsystem keys its snapshot rows by the directory it actually\n // lives in, and the clobber guard grades a leftover claim at that same\n // address. The root-level parse stays as the fallback for the one path\n // shape the enumeration cannot know yet — a service this archive CREATES,\n // which always materialises unfiled at services/<id>/.\n // Tolerant on purpose: a docs repo whose services/ is absent still\n // archives a landscape-only feature exactly as before — the enumeration\n // is empty, every row keys by the flat fallback, and the missing\n // directory stays doctor's diagnosis rather than a merge-failed here.\n const dirOf = new Map(\n (await enumeratedServices(config.docsDir, read.fleet)).map((s) => [s.id as string, repoPath(config.docsDir, s.dir)]),\n );\n const serviceKeyOf = (rel: string): ServiceKey | null => {\n for (const [service, dir] of dirOf) {\n if (rel.startsWith(`${dir}/`)) return { service, artifact: rel.slice(dir.length + 1) };\n }\n const m = /^services\\/([^/]+)\\/(.+)$/.exec(rel);\n return m ? { service: m[1]!, artifact: m[2]! } : null;\n };\n const serviceDirOf = (service: string): string | null => dirOf.get(service) ?? null;\n await writeSnapshot({\n featureDir,\n docsDir: config.docsDir,\n feature: { featureId: id, dirName },\n staged,\n serviceKeyOf,\n serviceDirOf,\n });\n snapshot = true;\n // The journal, fsynced, BEFORE the first rename: swapStaged is N renames and\n // only each one of them is atomic, so a kill between two used to leave a\n // half-merged repo that nothing could name — `doctor` and `status` called it\n // healthy and `validate --all` blamed the delta. Written from `staged`, so\n // it records the same digests the swaps are about to produce.\n await writeCommitIntent(\n config.docsDir,\n { command: \"archive\", restore: \"before\", feature: id, moveFrom: featureDir, moveTo: archiveDest },\n staged,\n );\n await swapStaged(staged);\n createdArchiveDir = await mkdir(archiveDir, { recursive: true });\n await rename(featureDir, archiveDest);\n // Last: while it exists, the commit is in flight.\n await clearCommitIntent(config.docsDir);\n } catch (err) {\n if (err instanceof SnapshotClobberError) {\n // Nothing swapped — the refusal happens before the journal is even\n // written — so this only takes the temp files away. Its own code, because\n // the answer is not \"re-run\": a previous archive of this feature is still\n // sitting in the living docs.\n await rollbackStaged(staged);\n throw new ArchiveFailure(\"commit-interrupted\", err.message);\n }\n // Everything this run made, unmade: the swapped files, the snapshot inside the\n // feature that is staying put, and features/archive/ if we are the ones who\n // created it (mkdir reports nothing when it was already there).\n const failures = await rollbackStaged(staged);\n // The rollback decided the outcome, so the journal has nothing left to\n // describe — including on rollback-incomplete, where the files it names are\n // the ones the message tells a human to look at.\n await clearCommitIntent(config.docsDir);\n // The snapshot goes only when the rollback HELD. On rollback-incomplete it\n // holds the only on-disk pre-images of the very files the message tells the\n // reader to repair by hand — a MODIFIED requirement's previous text appears\n // nowhere else. Retaining it is safe: the next archive of this feature reads\n // it before it would replace it, and refuses if the living docs have moved.\n if (snapshot && failures.length === 0) await quietRm(snapshotDir(featureDir));\n // `features/archive/` is shared the moment it exists: another archive can\n // have moved a whole feature into it between our mkdir and this rollback,\n // and a recursive remove of \"the directory we created\" took that feature —\n // snapshot and all — with it, on OUR failure path, in silence. Empty\n // directories only, stopping at the first that is not.\n if (createdArchiveDir !== undefined) await quietPruneEmptyParents(archiveDir, createdArchiveDir);\n // The code is a caller's answer to \"can I trust the repo?\": merge-failed\n // means yes (rolled back), rollback-incomplete means look at it by hand.\n const wrapped = rollbackError(err, failures);\n const kept =\n snapshot && failures.length > 0\n ? ` Pre-images of the overwritten files are kept in features/${dirName}/${SNAPSHOT_DIR}/files/.`\n : \"\";\n throw new ArchiveFailure(failures.length > 0 ? \"rollback-incomplete\" : \"merge-failed\", wrapped.message + kept);\n }\n\n // This merge just changed the map, and the generated views file is a\n // function of the tree AND the map: a delta whose element lands inside a\n // group that exactly covered a subsystem takes that subsystem's boundary\n // line away, and a delta binding an element to a filed service adds an\n // include. Archive does not rewrite the file — `loam subsystem sync` owns it\n // outright, and folding a second generated artifact into this transaction\n // would mean archive computing the post-merge tree AND the post-merge map,\n // which is how the two writers disagree — but it must not report a repo as\n // current when the next `validate --all` will call it stale. Graded through\n // validate's own function, so the two cannot answer differently.\n const staleViews = await subsystemViewsStale(config.docsDir);\n\n if (json) {\n emitJson({ ...payload(true), ...(staleViews ? { subsystemViewsStale: true } : {}) });\n return;\n }\n console.log(`\\n archived: features/${dirName} → features/archive/${dirName}`);\n console.log(` snapshot: features/archive/${dirName}/${SNAPSHOT_DIR}/ — \\`loam unarchive ${id}\\` puts it back`);\n // The closing line is a claim about the whole docs repo, and it is the line a\n // reader stops at. It may be printed only when this archive left nothing the\n // next `validate --all` will fail on — a service with no model, or a gate the\n // caller told it to merge past. Printing it over either is how a red fleet\n // gets reported as a finished one.\n const incomplete = planWarns.filter((w) => w.code === \"service.no-model\");\n if (incomplete.length === 0 && overridden.length === 0 && !staleViews) {\n console.log(\" living spec + landscape are now complete + current.\");\n return;\n }\n if (staleViews) {\n console.log(\n \" ⚠ architecture/subsystems.likec4 no longer matches the tree and this map — run `loam subsystem sync`.\",\n );\n }\n for (const w of incomplete) console.log(` ⚠ ${w.message}`);\n if (overridden.length > 0) {\n console.log(\n ` ⚠ merged past ${overridden.length} gating issue(s) with --approve — the living docs carry them now; \\`loam validate --all\\` says what they cost.`,\n );\n }\n}\n\n/**\n * Would the next `validate --all` report `subsystem.views-stale`?\n *\n * Asked through validate's OWN function rather than a second compare, so the\n * warning archive prints and the error validate raises can never disagree —\n * including about the gate validate holds: a map that does not parse is\n * `landscape.invalid`'s business, and grading a generated file against a map\n * nobody can read would cascade a second complaint behind the first. An\n * unreadable map therefore answers \"no claim\", exactly as validate does.\n */\nasync function subsystemViewsStale(docsDir: DocsDir): Promise<boolean> {\n try {\n const doc = await loadArchitecture(docsDir);\n if (doc.errors.length > 0) return false;\n const state = await viewsState(subsystemViewsPath(docsDir), await listFleetTree(docsDir), doc);\n return !state.agrees;\n } catch {\n // Tolerant for the reason the snapshot resolver above is: a docs repo with\n // no `services/` at all still archives a landscape-only feature, and this\n // question is an ADVISORY printed after a commit that already succeeded.\n // Nothing here may turn a landed archive into a non-zero exit.\n return false;\n }\n}\n"]}
@@ -41,7 +41,17 @@ export function printPack(pack) {
41
41
  // discipline): every empty section below could otherwise be read as "nothing
42
42
  // here", which is the one conclusion an unreadable document never supports.
43
43
  if (pack.landscape.present && !pack.landscape.parses) {
44
- console.log("! architecture/landscape.likec4 does not parse — no edge below is derived, and none is missing either\n");
44
+ // The `architecture/` PROJECT is what `parses` answers for, so the document
45
+ // at fault is very often a SIBLING beside a landscape that reads perfectly
46
+ // — and naming the landscape sent a reader to bytes loam read fine
47
+ // (verification 2026-09-04). `adopt` and `validate --all` name the file; so
48
+ // does this. The project keeps the fallback: a failure LikeC4 reports with
49
+ // no source document behind it is still a project that does not parse.
50
+ const broken = pack.landscape.broken;
51
+ const named = broken.length === 0 ? "the fleet map (architecture/)" : broken.join(", ");
52
+ // `> 1`, not `=== 1`: the empty arm's subject is the singular "fleet map".
53
+ const verb = broken.length > 1 ? "do" : "does";
54
+ console.log(`! ${named} ${verb} not parse — no edge below is derived, and none is missing either\n`);
45
55
  }
46
56
  if (pack.openapi.unreadable) {
47
57
  console.log(`! openapi.yaml does not parse — nothing here lists what ${pack.service} exposes`);
@@ -1 +1 @@
1
- {"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/context/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The context pack as a Markdown document on stdout — for pasting into an\n * agent's context, or reading in a terminal that renders neither.\n *\n * Rendering only. Everything printed here comes from `core/pack/`, which is\n * also what `--json` emits, so a printed section can never disagree with the\n * payload beside it. Requirement bodies and Given/When/Then lines go out\n * VERBATIM — they are the acceptance criteria, and paraphrasing them here\n * would put a second wording of the contract in front of whoever implements\n * it. The living sections use the canonical `### Requirement:` /\n * `#### Scenario:` heading levels; the in-flight blocks print the same lines\n * one level deeper, because each sits under its feature's own `###` heading.\n */\nimport { type ContextPack } from \"../../core/pack/pack.js\";\nimport { type PackRequirement } from \"../../core/pack/living.js\";\nimport { type PackFeature } from \"../../core/pack/features.js\";\n\nexport function printPack(pack: ContextPack): void {\n console.log(`# ${pack.service} — context pack\\n`);\n const badge = [pack.frontmatter.status, pack.frontmatter.owner].filter((s) => s !== null);\n console.log(`${pack.path} · ${pack.maturity}${badge.length > 0 ? ` · ${badge.join(\" · \")}` : \"\"}`);\n if (pack.missing.length > 0) console.log(`missing: ${pack.missing.join(\", \")}`);\n if (pack.frontmatter.last_verified !== null) console.log(`last_verified: ${pack.frontmatter.last_verified}`);\n // Under the date it qualifies: that vouch read the sections this names and\n // no others, so `verified` above covers less of the document than it looks.\n if (pack.frontmatter.vouch_scope !== null) {\n console.log(`vouch_scope: ${pack.frontmatter.vouch_scope} — the rest was not read at that vouch`);\n }\n // Per axis and named, `show`'s discipline: the sample is per FILE, so one\n // run can read a short spec.md in full and stamp a long arch.spec.md\n // sampled. Printing only the first line said `verified` over arch\n // requirements this pack then reproduced verbatim, half of them unread.\n if (pack.archSpec.vouch_scope !== null) {\n console.log(\n `archSpec.vouch_scope: ${pack.archSpec.vouch_scope} — the rest of arch.spec.md was not read at that vouch`,\n );\n }\n for (const s of pack.frontmatter.sources) console.log(`sources: ${s}`);\n console.log();\n\n // Unreadable documents are said FIRST and without hedging (explore's print\n // discipline): every empty section below could otherwise be read as \"nothing\n // here\", which is the one conclusion an unreadable document never supports.\n if (pack.landscape.present && !pack.landscape.parses) {\n console.log(\"! architecture/landscape.likec4 does not parse — no edge below is derived, and none is missing either\\n\");\n }\n if (pack.openapi.unreadable) {\n console.log(`! openapi.yaml does not parse — nothing here lists what ${pack.service} exposes`);\n if (pack.openapi.error !== undefined) console.log(` ${pack.openapi.error}`);\n console.log();\n }\n if (pack.asyncapi.unreadable) {\n console.log(`! asyncapi.yaml does not parse — nothing here lists what ${pack.service} publishes or consumes`);\n if (pack.asyncapi.error !== undefined) console.log(` ${pack.asyncapi.error}`);\n console.log();\n }\n // The vocabulary failures lead with the contract failures: each empties a\n // section below into something that reads as an answer (\"declared: false\"\n // on every permission, \"(none realized here)\"), and a warning printed down\n // beside the section is a warning a reader pasting the top of the pack\n // never sees.\n if (pack.permissionsVocabulary.invalid !== undefined) {\n console.log(\"! architecture/permissions.yaml does not read as a vocabulary — every permission below reports declared: false because nobody could look\");\n console.log(` ${pack.permissionsVocabulary.invalid}`);\n console.log();\n }\n if (pack.capabilitiesVocabulary.invalid !== undefined) {\n console.log(\"! architecture/capabilities.yaml does not read as a vocabulary — no capability below is derived, and none is missing either\");\n console.log(` ${pack.capabilitiesVocabulary.invalid}`);\n console.log();\n }\n for (const path of pack.capabilitiesUnread) {\n console.log(`! ${path} could not be read while joining capabilities — that service's realizations are missing from the rollup this pack filtered`);\n }\n if (pack.capabilitiesUnread.length > 0) console.log();\n if (pack.useCaseScan.unreadable) {\n console.log(\"! architecture/ does not parse as one LikeC4 project — every use case below is missing because nobody could look, not because none is drawn\");\n if (pack.useCaseScan.error !== undefined) console.log(` ${pack.useCaseScan.error}`);\n console.log();\n }\n\n printRequirements(\"Requirements\", pack.requirements);\n printRequirements(\"Arch requirements\", pack.archRequirements);\n\n console.log(\"## Operations\\n\");\n if (pack.operations.length === 0) console.log(pack.openapi.unreadable ? \"(unreadable — see above)\\n\" : \"(none)\\n\");\n for (const op of pack.operations) {\n const by = op.governedBy.length > 0\n ? `governed by ${op.governedBy.map((n) => `\"${n}\"`).join(\", \")}`\n : \"not governed by any requirement\";\n console.log(`- ${op.method} ${op.path} ${op.id} — ${by}`);\n }\n if (pack.operations.length > 0) console.log();\n\n console.log(\"## Messages\\n\");\n if (pack.messages.length === 0) console.log(pack.asyncapi.unreadable ? \"(unreadable — see above)\\n\" : \"(none)\\n\");\n for (const m of pack.messages) {\n const direction = m.direction === null ? \"declared, not wired\" : m.direction.toUpperCase();\n console.log(`- ${direction} ${m.name} (${m.slot})`);\n }\n if (pack.messages.length > 0) console.log();\n\n console.log(\"## Permissions\\n\");\n if (pack.permissions.length === 0) console.log(\"(none required)\\n\");\n for (const p of pack.permissions) {\n if (!p.declared) {\n console.log(`- ${p.id} — not declared in architecture/permissions.yaml`);\n continue;\n }\n const notes = [\n ...(p.description === undefined ? [] : [p.description]),\n ...(p.ownedBy === undefined ? [] : [`owned by ${p.ownedBy}`]),\n ...(p.enforcedBy.length === 0 ? [] : [`enforced by ${p.enforcedBy.join(\", \")}`]),\n ];\n console.log(`- ${p.id}${notes.length > 0 ? ` — ${notes.join(\"; \")}` : \"\"}`);\n }\n if (pack.permissions.length > 0) console.log();\n\n console.log(\"## Capabilities\\n\");\n if (pack.capabilities.length === 0) {\n console.log(pack.capabilitiesVocabulary.invalid !== undefined ? \"(unreadable — see above)\\n\" : \"(none realized here)\\n\");\n }\n for (const c of pack.capabilities) {\n const label = c.description === undefined ? c.id : `${c.id} — ${c.description}`;\n console.log(`- ${label} (realized by: ${c.requirements.map((n) => `\"${n}\"`).join(\", \")})`);\n // The flows that claim the capability, fleet-wide — the answer to \"what is\n // this requirement FOR\", which the requirement's own text rarely gives.\n for (const flow of c.useCases) console.log(` - flow: ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n }\n if (pack.capabilities.length > 0) console.log();\n\n console.log(\"## Use cases\\n\");\n if (pack.useCaseSteps.length === 0) {\n console.log(pack.useCaseScan.unreadable ? \"(unreadable — see above)\\n\" : \"(no declared flow draws this service)\\n\");\n }\n for (const flow of pack.useCaseSteps) {\n console.log(`- ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n for (const step of flow.steps) {\n const label = step.title === undefined ? \"\" : ` '${step.title}'`;\n console.log(` - step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);\n }\n }\n if (pack.useCaseSteps.length > 0) console.log();\n\n console.log(\"## Landscape\\n\");\n if (!pack.landscape.present) console.log(\"(no architecture/landscape.likec4)\\n\");\n else if (!pack.landscape.parses) console.log(\"(unreadable — see above)\\n\");\n else {\n if (!pack.landscape.modelled) console.log(`${pack.service} is not in the fleet map — no edge into it can be checked`);\n for (const e of pack.landscape.inbound) console.log(`- ← ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of pack.landscape.outbound) console.log(`- → ${e.service}${edgeNote(e.op, e.title)}`);\n if (pack.landscape.modelled && pack.landscape.inbound.length === 0 && pack.landscape.outbound.length === 0) {\n console.log(\"(modelled, no edges touch it)\");\n }\n console.log();\n }\n\n console.log(\"## Pointers\\n\");\n const mark = (present: boolean): string => (present ? \"present\" : \"absent\");\n console.log(`- runbook: ${mark(pack.pointers.runbook.present)} (${pack.pointers.runbook.path})`);\n console.log(`- health: ${mark(pack.pointers.health.present)} (${pack.pointers.health.path})`);\n console.log(`- adrs: ${pack.pointers.adrs.count} (${pack.pointers.adrs.path})`);\n console.log();\n\n // The narrowing is said in the heading: a narrowed pack differs from the\n // default only by what it leaves OUT, and a reader (or a diff) must not\n // mistake one for a fleet gone quiet.\n console.log(pack.feature === null ? \"## In flight\\n\" : `## In flight (narrowed to ${pack.feature})\\n`);\n if (pack.features.length === 0) console.log(\"(no active feature touches this service)\");\n for (const f of pack.features) printFeature(f, pack.service);\n}\n\nfunction printRequirements(label: string, reqs: PackRequirement[], level = \"##\"): void {\n console.log(`${level} ${label}\\n`);\n if (reqs.length === 0) console.log(\"(none)\\n\");\n for (const r of reqs) {\n const tag = r.kind === \"BASE\" ? \"\" : `[${r.kind}] `;\n console.log(`${level}# Requirement: ${tag}${r.name}`);\n if (r.text.length > 0) console.log(r.text);\n for (const s of r.scenarios) {\n console.log(`\\n${level}## Scenario: ${s.name}`);\n // Verbatim, bullets and markdown emphasis included: these lines are the\n // acceptance criteria.\n for (const line of s.lines) console.log(line);\n }\n console.log();\n }\n}\n\nfunction printFeature(f: PackFeature, service: string): void {\n console.log(`### ${f.feature} (${f.path})\\n`);\n if (!f.services.includes(service)) {\n console.log(`(no delta for ${service} — ${f.feature} touches: ${f.services.length > 0 ? f.services.join(\", \") : \"(no services)\"})\\n`);\n }\n // Intent prose arrives with its own headings — usually an H1 title — and\n // pasted raw under this feature's `###` those restructure the whole pack: a\n // second H1 splits the document, and an intent section named \"Operations\"\n // collides with the pack's own. Demoted three levels (below the feature\n // heading), capped at H6 because a seventh `#` renders as literal text.\n // Body lines are untouched — the demotion is structural, not a paraphrase.\n if (f.intent !== null && f.intent.length > 0) console.log(`${demoteHeadings(f.intent)}\\n`);\n if (f.requirements.length > 0) printRequirements(\"Requirement delta\", f.requirements, \"###\");\n if (f.archRequirements.length > 0) printRequirements(\"Arch requirement delta\", f.archRequirements, \"###\");\n\n if (f.openapi.unreadable) {\n // Worded like the delta brief's answer for the same failure, and without a\n // \"run `loam validate`\" hint: the parser's own message is quoted and the\n // exit code carries the failure.\n console.log(\"API: openapi.yaml does not parse\");\n if (f.openapi.error !== undefined) console.log(` ${f.openapi.error}`);\n console.log();\n } else if (f.api.length > 0) {\n console.log(\"API changes:\");\n for (const op of f.api) {\n const marker = op.remove ? \"REMOVE \" : \"\";\n console.log(`- ${marker}${op.method} ${op.path} ${op.operationId}${op.summary === null ? \"\" : ` — ${op.summary}`}`);\n }\n console.log();\n }\n\n if (f.events.unreadable) {\n console.log(\"Events: asyncapi.yaml does not parse\");\n if (f.events.error !== undefined) console.log(` ${f.events.error}`);\n console.log();\n } else if (f.events.changes.length > 0) {\n console.log(\"Event changes:\");\n for (const m of f.events.changes) {\n const marker = m.remove ? \"REMOVE \" : \"\";\n const direction = m.direction === null ? \"\" : `${m.direction.toUpperCase()} `;\n console.log(`- ${marker}${direction}${m.message} (${m.slot})`);\n }\n console.log();\n }\n\n const arch = f.architecture;\n if (arch.errors.length > 0) {\n console.log(\"Architecture: delta.likec4 has errors\");\n for (const e of arch.errors) console.log(` ${e}`);\n console.log();\n } else if (arch.isNew || arch.inbound.length > 0 || arch.outbound.length > 0) {\n console.log(\"Architecture:\");\n if (arch.isNew) console.log(`- NEW service — create ${service}`);\n for (const e of arch.outbound) console.log(`- → ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of arch.inbound) console.log(`- ← ${e.service}${edgeNote(e.op, e.title)}`);\n console.log();\n }\n\n // Both interpolants passed their grammars at the boundary — the service\n // through assertServiceId, the feature id as the CANONICAL id the\n // enumeration derived — so the printed command parses. That property is the\n // exact lesson explore's `--as` records: this line is assembled from data,\n // which is the one shape test/agent-commands-runnable.test.ts cannot see.\n console.log(`next: loam delta ${f.feature} --service ${service}\\n`);\n}\n\nfunction edgeNote(op: string | null, title: string | null): string {\n if (op !== null) return ` ${op}`;\n return title !== null && title.length > 0 ? ` \"${title}\"` : \"\";\n}\n\n/** Every ATX heading pushed three levels down, capped at H6 — see the intent comment above. */\nfunction demoteHeadings(md: string): string {\n return md.replace(/^(#{1,6})(?= )/gm, (h) => \"#\".repeat(Math.min(6, h.length + 3)));\n}\n"]}
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/context/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The context pack as a Markdown document on stdout — for pasting into an\n * agent's context, or reading in a terminal that renders neither.\n *\n * Rendering only. Everything printed here comes from `core/pack/`, which is\n * also what `--json` emits, so a printed section can never disagree with the\n * payload beside it. Requirement bodies and Given/When/Then lines go out\n * VERBATIM — they are the acceptance criteria, and paraphrasing them here\n * would put a second wording of the contract in front of whoever implements\n * it. The living sections use the canonical `### Requirement:` /\n * `#### Scenario:` heading levels; the in-flight blocks print the same lines\n * one level deeper, because each sits under its feature's own `###` heading.\n */\nimport { type ContextPack } from \"../../core/pack/pack.js\";\nimport { type PackRequirement } from \"../../core/pack/living.js\";\nimport { type PackFeature } from \"../../core/pack/features.js\";\n\nexport function printPack(pack: ContextPack): void {\n console.log(`# ${pack.service} — context pack\\n`);\n const badge = [pack.frontmatter.status, pack.frontmatter.owner].filter((s) => s !== null);\n console.log(`${pack.path} · ${pack.maturity}${badge.length > 0 ? ` · ${badge.join(\" · \")}` : \"\"}`);\n if (pack.missing.length > 0) console.log(`missing: ${pack.missing.join(\", \")}`);\n if (pack.frontmatter.last_verified !== null) console.log(`last_verified: ${pack.frontmatter.last_verified}`);\n // Under the date it qualifies: that vouch read the sections this names and\n // no others, so `verified` above covers less of the document than it looks.\n if (pack.frontmatter.vouch_scope !== null) {\n console.log(`vouch_scope: ${pack.frontmatter.vouch_scope} — the rest was not read at that vouch`);\n }\n // Per axis and named, `show`'s discipline: the sample is per FILE, so one\n // run can read a short spec.md in full and stamp a long arch.spec.md\n // sampled. Printing only the first line said `verified` over arch\n // requirements this pack then reproduced verbatim, half of them unread.\n if (pack.archSpec.vouch_scope !== null) {\n console.log(\n `archSpec.vouch_scope: ${pack.archSpec.vouch_scope} — the rest of arch.spec.md was not read at that vouch`,\n );\n }\n for (const s of pack.frontmatter.sources) console.log(`sources: ${s}`);\n console.log();\n\n // Unreadable documents are said FIRST and without hedging (explore's print\n // discipline): every empty section below could otherwise be read as \"nothing\n // here\", which is the one conclusion an unreadable document never supports.\n if (pack.landscape.present && !pack.landscape.parses) {\n // The `architecture/` PROJECT is what `parses` answers for, so the document\n // at fault is very often a SIBLING beside a landscape that reads perfectly\n // — and naming the landscape sent a reader to bytes loam read fine\n // (verification 2026-09-04). `adopt` and `validate --all` name the file; so\n // does this. The project keeps the fallback: a failure LikeC4 reports with\n // no source document behind it is still a project that does not parse.\n const broken = pack.landscape.broken;\n const named = broken.length === 0 ? \"the fleet map (architecture/)\" : broken.join(\", \");\n // `> 1`, not `=== 1`: the empty arm's subject is the singular \"fleet map\".\n const verb = broken.length > 1 ? \"do\" : \"does\";\n console.log(`! ${named} ${verb} not parse — no edge below is derived, and none is missing either\\n`);\n }\n if (pack.openapi.unreadable) {\n console.log(`! openapi.yaml does not parse — nothing here lists what ${pack.service} exposes`);\n if (pack.openapi.error !== undefined) console.log(` ${pack.openapi.error}`);\n console.log();\n }\n if (pack.asyncapi.unreadable) {\n console.log(`! asyncapi.yaml does not parse — nothing here lists what ${pack.service} publishes or consumes`);\n if (pack.asyncapi.error !== undefined) console.log(` ${pack.asyncapi.error}`);\n console.log();\n }\n // The vocabulary failures lead with the contract failures: each empties a\n // section below into something that reads as an answer (\"declared: false\"\n // on every permission, \"(none realized here)\"), and a warning printed down\n // beside the section is a warning a reader pasting the top of the pack\n // never sees.\n if (pack.permissionsVocabulary.invalid !== undefined) {\n console.log(\"! architecture/permissions.yaml does not read as a vocabulary — every permission below reports declared: false because nobody could look\");\n console.log(` ${pack.permissionsVocabulary.invalid}`);\n console.log();\n }\n if (pack.capabilitiesVocabulary.invalid !== undefined) {\n console.log(\"! architecture/capabilities.yaml does not read as a vocabulary — no capability below is derived, and none is missing either\");\n console.log(` ${pack.capabilitiesVocabulary.invalid}`);\n console.log();\n }\n for (const path of pack.capabilitiesUnread) {\n console.log(`! ${path} could not be read while joining capabilities — that service's realizations are missing from the rollup this pack filtered`);\n }\n if (pack.capabilitiesUnread.length > 0) console.log();\n if (pack.useCaseScan.unreadable) {\n console.log(\"! architecture/ does not parse as one LikeC4 project — every use case below is missing because nobody could look, not because none is drawn\");\n if (pack.useCaseScan.error !== undefined) console.log(` ${pack.useCaseScan.error}`);\n console.log();\n }\n\n printRequirements(\"Requirements\", pack.requirements);\n printRequirements(\"Arch requirements\", pack.archRequirements);\n\n console.log(\"## Operations\\n\");\n if (pack.operations.length === 0) console.log(pack.openapi.unreadable ? \"(unreadable — see above)\\n\" : \"(none)\\n\");\n for (const op of pack.operations) {\n const by = op.governedBy.length > 0\n ? `governed by ${op.governedBy.map((n) => `\"${n}\"`).join(\", \")}`\n : \"not governed by any requirement\";\n console.log(`- ${op.method} ${op.path} ${op.id} — ${by}`);\n }\n if (pack.operations.length > 0) console.log();\n\n console.log(\"## Messages\\n\");\n if (pack.messages.length === 0) console.log(pack.asyncapi.unreadable ? \"(unreadable — see above)\\n\" : \"(none)\\n\");\n for (const m of pack.messages) {\n const direction = m.direction === null ? \"declared, not wired\" : m.direction.toUpperCase();\n console.log(`- ${direction} ${m.name} (${m.slot})`);\n }\n if (pack.messages.length > 0) console.log();\n\n console.log(\"## Permissions\\n\");\n if (pack.permissions.length === 0) console.log(\"(none required)\\n\");\n for (const p of pack.permissions) {\n if (!p.declared) {\n console.log(`- ${p.id} — not declared in architecture/permissions.yaml`);\n continue;\n }\n const notes = [\n ...(p.description === undefined ? [] : [p.description]),\n ...(p.ownedBy === undefined ? [] : [`owned by ${p.ownedBy}`]),\n ...(p.enforcedBy.length === 0 ? [] : [`enforced by ${p.enforcedBy.join(\", \")}`]),\n ];\n console.log(`- ${p.id}${notes.length > 0 ? ` — ${notes.join(\"; \")}` : \"\"}`);\n }\n if (pack.permissions.length > 0) console.log();\n\n console.log(\"## Capabilities\\n\");\n if (pack.capabilities.length === 0) {\n console.log(pack.capabilitiesVocabulary.invalid !== undefined ? \"(unreadable — see above)\\n\" : \"(none realized here)\\n\");\n }\n for (const c of pack.capabilities) {\n const label = c.description === undefined ? c.id : `${c.id} — ${c.description}`;\n console.log(`- ${label} (realized by: ${c.requirements.map((n) => `\"${n}\"`).join(\", \")})`);\n // The flows that claim the capability, fleet-wide — the answer to \"what is\n // this requirement FOR\", which the requirement's own text rarely gives.\n for (const flow of c.useCases) console.log(` - flow: ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n }\n if (pack.capabilities.length > 0) console.log();\n\n console.log(\"## Use cases\\n\");\n if (pack.useCaseSteps.length === 0) {\n console.log(pack.useCaseScan.unreadable ? \"(unreadable — see above)\\n\" : \"(no declared flow draws this service)\\n\");\n }\n for (const flow of pack.useCaseSteps) {\n console.log(`- ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n for (const step of flow.steps) {\n const label = step.title === undefined ? \"\" : ` '${step.title}'`;\n console.log(` - step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);\n }\n }\n if (pack.useCaseSteps.length > 0) console.log();\n\n console.log(\"## Landscape\\n\");\n if (!pack.landscape.present) console.log(\"(no architecture/landscape.likec4)\\n\");\n else if (!pack.landscape.parses) console.log(\"(unreadable — see above)\\n\");\n else {\n if (!pack.landscape.modelled) console.log(`${pack.service} is not in the fleet map — no edge into it can be checked`);\n for (const e of pack.landscape.inbound) console.log(`- ← ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of pack.landscape.outbound) console.log(`- → ${e.service}${edgeNote(e.op, e.title)}`);\n if (pack.landscape.modelled && pack.landscape.inbound.length === 0 && pack.landscape.outbound.length === 0) {\n console.log(\"(modelled, no edges touch it)\");\n }\n console.log();\n }\n\n console.log(\"## Pointers\\n\");\n const mark = (present: boolean): string => (present ? \"present\" : \"absent\");\n console.log(`- runbook: ${mark(pack.pointers.runbook.present)} (${pack.pointers.runbook.path})`);\n console.log(`- health: ${mark(pack.pointers.health.present)} (${pack.pointers.health.path})`);\n console.log(`- adrs: ${pack.pointers.adrs.count} (${pack.pointers.adrs.path})`);\n console.log();\n\n // The narrowing is said in the heading: a narrowed pack differs from the\n // default only by what it leaves OUT, and a reader (or a diff) must not\n // mistake one for a fleet gone quiet.\n console.log(pack.feature === null ? \"## In flight\\n\" : `## In flight (narrowed to ${pack.feature})\\n`);\n if (pack.features.length === 0) console.log(\"(no active feature touches this service)\");\n for (const f of pack.features) printFeature(f, pack.service);\n}\n\nfunction printRequirements(label: string, reqs: PackRequirement[], level = \"##\"): void {\n console.log(`${level} ${label}\\n`);\n if (reqs.length === 0) console.log(\"(none)\\n\");\n for (const r of reqs) {\n const tag = r.kind === \"BASE\" ? \"\" : `[${r.kind}] `;\n console.log(`${level}# Requirement: ${tag}${r.name}`);\n if (r.text.length > 0) console.log(r.text);\n for (const s of r.scenarios) {\n console.log(`\\n${level}## Scenario: ${s.name}`);\n // Verbatim, bullets and markdown emphasis included: these lines are the\n // acceptance criteria.\n for (const line of s.lines) console.log(line);\n }\n console.log();\n }\n}\n\nfunction printFeature(f: PackFeature, service: string): void {\n console.log(`### ${f.feature} (${f.path})\\n`);\n if (!f.services.includes(service)) {\n console.log(`(no delta for ${service} — ${f.feature} touches: ${f.services.length > 0 ? f.services.join(\", \") : \"(no services)\"})\\n`);\n }\n // Intent prose arrives with its own headings — usually an H1 title — and\n // pasted raw under this feature's `###` those restructure the whole pack: a\n // second H1 splits the document, and an intent section named \"Operations\"\n // collides with the pack's own. Demoted three levels (below the feature\n // heading), capped at H6 because a seventh `#` renders as literal text.\n // Body lines are untouched — the demotion is structural, not a paraphrase.\n if (f.intent !== null && f.intent.length > 0) console.log(`${demoteHeadings(f.intent)}\\n`);\n if (f.requirements.length > 0) printRequirements(\"Requirement delta\", f.requirements, \"###\");\n if (f.archRequirements.length > 0) printRequirements(\"Arch requirement delta\", f.archRequirements, \"###\");\n\n if (f.openapi.unreadable) {\n // Worded like the delta brief's answer for the same failure, and without a\n // \"run `loam validate`\" hint: the parser's own message is quoted and the\n // exit code carries the failure.\n console.log(\"API: openapi.yaml does not parse\");\n if (f.openapi.error !== undefined) console.log(` ${f.openapi.error}`);\n console.log();\n } else if (f.api.length > 0) {\n console.log(\"API changes:\");\n for (const op of f.api) {\n const marker = op.remove ? \"REMOVE \" : \"\";\n console.log(`- ${marker}${op.method} ${op.path} ${op.operationId}${op.summary === null ? \"\" : ` — ${op.summary}`}`);\n }\n console.log();\n }\n\n if (f.events.unreadable) {\n console.log(\"Events: asyncapi.yaml does not parse\");\n if (f.events.error !== undefined) console.log(` ${f.events.error}`);\n console.log();\n } else if (f.events.changes.length > 0) {\n console.log(\"Event changes:\");\n for (const m of f.events.changes) {\n const marker = m.remove ? \"REMOVE \" : \"\";\n const direction = m.direction === null ? \"\" : `${m.direction.toUpperCase()} `;\n console.log(`- ${marker}${direction}${m.message} (${m.slot})`);\n }\n console.log();\n }\n\n const arch = f.architecture;\n if (arch.errors.length > 0) {\n console.log(\"Architecture: delta.likec4 has errors\");\n for (const e of arch.errors) console.log(` ${e}`);\n console.log();\n } else if (arch.isNew || arch.inbound.length > 0 || arch.outbound.length > 0) {\n console.log(\"Architecture:\");\n if (arch.isNew) console.log(`- NEW service — create ${service}`);\n for (const e of arch.outbound) console.log(`- → ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of arch.inbound) console.log(`- ← ${e.service}${edgeNote(e.op, e.title)}`);\n console.log();\n }\n\n // Both interpolants passed their grammars at the boundary — the service\n // through assertServiceId, the feature id as the CANONICAL id the\n // enumeration derived — so the printed command parses. That property is the\n // exact lesson explore's `--as` records: this line is assembled from data,\n // which is the one shape test/agent-commands-runnable.test.ts cannot see.\n console.log(`next: loam delta ${f.feature} --service ${service}\\n`);\n}\n\nfunction edgeNote(op: string | null, title: string | null): string {\n if (op !== null) return ` ${op}`;\n return title !== null && title.length > 0 ? ` \"${title}\"` : \"\";\n}\n\n/** Every ATX heading pushed three levels down, capped at H6 — see the intent comment above. */\nfunction demoteHeadings(md: string): string {\n return md.replace(/^(#{1,6})(?= )/gm, (h) => \"#\".repeat(Math.min(6, h.length + 3)));\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { diagnose } from "../core/doctor/doctor.js";
2
2
  import {} from "../core/doctor/report.js";
3
+ import { REPORTS_DIR } from "../core/doctor/reports/scan.js";
3
4
  import { emitJson } from "../core/envelope/json.js";
4
5
  export function registerDoctor(program) {
5
6
  program
@@ -50,6 +51,46 @@ function writePathLabel(residue) {
50
51
  ];
51
52
  return parts.length === 0 ? "clean" : parts.join(" · ");
52
53
  }
54
+ /**
55
+ * The order the statuses are printed in — the lifecycle a report walks, so the
56
+ * row reads left to right the way the corpus drains.
57
+ *
58
+ * A `Record` over the union rather than an array of strings, because that makes
59
+ * tsc the thing that notices a new status: adding one to `ProblemReportStatus`
60
+ * fails to compile here instead of silently never being printed.
61
+ */
62
+ const REPORT_STATUS_ORDER = {
63
+ open: 0,
64
+ sent: 1,
65
+ fixed: 2,
66
+ superseded: 3,
67
+ unstated: 4,
68
+ };
69
+ /**
70
+ * The report corpus as one line: how many there are, how they split by status,
71
+ * and which ordinal the next one takes.
72
+ *
73
+ * Zero counts are left out — a status nothing is in is not news, and this row
74
+ * is read at a glance — while the total is always there, because "twelve
75
+ * reports" is the fact somebody scanning for the corpus is looking for. An
76
+ * absent or empty directory prints `(none)` rather than a row of zeroes: a
77
+ * repository that has never had to write a report is the normal one.
78
+ */
79
+ function reportsLabel(reports) {
80
+ if (!reports.present || reports.total === 0)
81
+ return "(none)";
82
+ const counted = new Map();
83
+ for (const entry of reports.entries) {
84
+ counted.set(entry.status, (counted.get(entry.status) ?? 0) + 1);
85
+ }
86
+ const split = [...counted]
87
+ .sort(([a], [b]) => REPORT_STATUS_ORDER[a] - REPORT_STATUS_ORDER[b])
88
+ .map(([status, count]) => `${status} ${count}`);
89
+ // The directory's NAME, not `reports.dir`: the payload spells the absolute
90
+ // path so an agent can act on it, while the row is read by a person standing
91
+ // in the repository, for whom the absolute spelling is only longer.
92
+ return [`${REPORTS_DIR}/ ${reports.total}`, ...split, `next ${reports.next}`].join(" · ");
93
+ }
53
94
  function printDoctor(report) {
54
95
  console.log(`loam doctor — ${report.healthy ? "healthy" : "blocked"}`);
55
96
  console.log(` runtime ${report.runtime.package}@${report.runtime.version}`);
@@ -68,6 +109,11 @@ function printDoctor(report) {
68
109
  console.log(` agents ${agents.tools.length === 0 ? "(none)" : agents.tools.join(", ")} · ${agents.profile}`
69
110
  + ` (${agents.toolsSource}) · ${agents.plannedFiles} files · ${agents.missingFiles.length} missing`
70
111
  + ` · ${agents.staleFiles.length} stale · AGENTS.md ${stampLabel(agents.stamp)}`);
112
+ // The problem reports, for the same reason and with a stronger one behind it:
113
+ // the `loam-report` protocol asks a repository to accumulate this corpus, and
114
+ // until now no loam command mentioned the directory at all. Printed as state,
115
+ // never as a finding — an open report is not a defect in the repo holding it.
116
+ console.log(` reports ${reportsLabel(report.reports)}`);
71
117
  // The write path is state too, and its clean answer is the one worth printing
72
118
  // most often: a reader who has just been told the docs are half-written needs
73
119
  // to see it go away.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { diagnose } from \"../core/doctor/doctor.js\";\nimport { type DoctorReport } from \"../core/doctor/report.js\";\nimport { emitJson } from \"../core/envelope/json.js\";\n\ninterface DoctorOptions {\n json?: boolean;\n}\n\nexport function registerDoctor(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Diagnose local loam configuration and docs-repo accessibility without writing\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: DoctorOptions) => {\n const report = await diagnose();\n if (opts.json === true) emitJson({ command: \"doctor\", ...report });\n else printDoctor(report);\n if (!report.healthy) process.exitCode = 1;\n });\n}\n\nfunction yesNo(value: boolean): string {\n return value ? \"yes\" : \"no\";\n}\n\n/**\n * The stamp as one readable token. \"absent\" and \"unstamped\" are kept apart\n * because they are different repos: the first has no AGENTS.md at all, the\n * second has one nobody has claimed a version for.\n */\nfunction stampLabel(stamp: DoctorReport[\"agents\"][\"stamp\"]): string {\n if (!stamp.present) return \"absent\";\n if (stamp.version === null) return \"unstamped\";\n return `v${stamp.version}${stamp.stale ? \" (stale)\" : \"\"}`;\n}\n\n/**\n * What a killed writer left in the docs repo, as one line. \"clean\" is the\n * answer on every healthy repo, and \"(unresolved)\" keeps it apart from clean:\n * a docsDir that never resolved was never looked at.\n */\nfunction writePathLabel(residue: DoctorReport[\"writePath\"]): string {\n if (residue === null) return \"(unresolved)\";\n const parts = [\n ...(residue.lock === null ? [] : [`lock held${residue.lock.stale ? \" (stale)\" : \"\"}`]),\n ...(residue.intentUnreadable\n ? [\"interrupted commit (unreadable)\"]\n : residue.intent === null\n ? []\n : [`interrupted ${residue.intent.command} of ${\"feature\" in residue.intent ? residue.intent.feature : residue.intent.target}`]),\n ...(residue.temps.length === 0 ? [] : [`${residue.temps.length} orphaned temp file(s)`]),\n ];\n return parts.length === 0 ? \"clean\" : parts.join(\" · \");\n}\n\nfunction printDoctor(report: DoctorReport): void {\n console.log(`loam doctor — ${report.healthy ? \"healthy\" : \"blocked\"}`);\n console.log(` runtime ${report.runtime.package}@${report.runtime.version}`);\n console.log(` node ${report.runtime.node} ${report.runtime.platform}/${report.runtime.arch}`);\n console.log(` config ${report.config.status} ${report.config.path}`);\n if (report.config.error !== null) console.log(` ${report.config.error}`);\n console.log(` docsDir ${report.docs.path ?? \"(unresolved)\"}`);\n console.log(\n ` access exists ${yesNo(report.docs.exists)} · read ${yesNo(report.docs.readable)} · write ${yesNo(report.docs.writable)}`,\n );\n console.log(\n ` fleet services/ ${yesNo(report.docs.servicesDir)} · landscape ${yesNo(report.docs.landscape)} · ${report.counts.services} services · ${report.counts.activeFeatures} active features`,\n );\n console.log(\n ` binding ${report.currentService.configured ?? \"(none)\"} · ${report.currentService.status}`,\n );\n // The agent surface is reported whether or not it has drifted — like every\n // line above it, this is state, not a complaint. Only the findings block is\n // silent when there is nothing to say.\n const agents = report.agents;\n console.log(\n ` agents ${agents.tools.length === 0 ? \"(none)\" : agents.tools.join(\", \")} · ${agents.profile}`\n + ` (${agents.toolsSource}) · ${agents.plannedFiles} files · ${agents.missingFiles.length} missing`\n + ` · ${agents.staleFiles.length} stale · AGENTS.md ${stampLabel(agents.stamp)}`,\n );\n // The write path is state too, and its clean answer is the one worth printing\n // most often: a reader who has just been told the docs are half-written needs\n // to see it go away.\n console.log(` write path ${writePathLabel(report.writePath)}`);\n if (report.findings.length > 0) {\n console.log(\"\\n findings\");\n for (const finding of report.findings) {\n console.log(` ${finding.severity === \"blocker\" ? \"✗\" : \"⚠\"} ${finding.code}: ${finding.message}`);\n // The fix is printed on its own indented line rather than appended to the\n // message: what is wrong and what to type are two different sentences,\n // and someone scanning a blocked repo reads down the `fix:` column.\n console.log(` fix: ${finding.fix}`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { diagnose } from \"../core/doctor/doctor.js\";\nimport { type DoctorReport, type ProblemReportStatus } from \"../core/doctor/report.js\";\nimport { REPORTS_DIR } from \"../core/doctor/reports/scan.js\";\nimport { emitJson } from \"../core/envelope/json.js\";\n\ninterface DoctorOptions {\n json?: boolean;\n}\n\nexport function registerDoctor(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Diagnose local loam configuration and docs-repo accessibility without writing\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: DoctorOptions) => {\n const report = await diagnose();\n if (opts.json === true) emitJson({ command: \"doctor\", ...report });\n else printDoctor(report);\n if (!report.healthy) process.exitCode = 1;\n });\n}\n\nfunction yesNo(value: boolean): string {\n return value ? \"yes\" : \"no\";\n}\n\n/**\n * The stamp as one readable token. \"absent\" and \"unstamped\" are kept apart\n * because they are different repos: the first has no AGENTS.md at all, the\n * second has one nobody has claimed a version for.\n */\nfunction stampLabel(stamp: DoctorReport[\"agents\"][\"stamp\"]): string {\n if (!stamp.present) return \"absent\";\n if (stamp.version === null) return \"unstamped\";\n return `v${stamp.version}${stamp.stale ? \" (stale)\" : \"\"}`;\n}\n\n/**\n * What a killed writer left in the docs repo, as one line. \"clean\" is the\n * answer on every healthy repo, and \"(unresolved)\" keeps it apart from clean:\n * a docsDir that never resolved was never looked at.\n */\nfunction writePathLabel(residue: DoctorReport[\"writePath\"]): string {\n if (residue === null) return \"(unresolved)\";\n const parts = [\n ...(residue.lock === null ? [] : [`lock held${residue.lock.stale ? \" (stale)\" : \"\"}`]),\n ...(residue.intentUnreadable\n ? [\"interrupted commit (unreadable)\"]\n : residue.intent === null\n ? []\n : [`interrupted ${residue.intent.command} of ${\"feature\" in residue.intent ? residue.intent.feature : residue.intent.target}`]),\n ...(residue.temps.length === 0 ? [] : [`${residue.temps.length} orphaned temp file(s)`]),\n ];\n return parts.length === 0 ? \"clean\" : parts.join(\" · \");\n}\n\n/**\n * The order the statuses are printed in — the lifecycle a report walks, so the\n * row reads left to right the way the corpus drains.\n *\n * A `Record` over the union rather than an array of strings, because that makes\n * tsc the thing that notices a new status: adding one to `ProblemReportStatus`\n * fails to compile here instead of silently never being printed.\n */\nconst REPORT_STATUS_ORDER: Record<ProblemReportStatus, number> = {\n open: 0,\n sent: 1,\n fixed: 2,\n superseded: 3,\n unstated: 4,\n};\n\n/**\n * The report corpus as one line: how many there are, how they split by status,\n * and which ordinal the next one takes.\n *\n * Zero counts are left out — a status nothing is in is not news, and this row\n * is read at a glance — while the total is always there, because \"twelve\n * reports\" is the fact somebody scanning for the corpus is looking for. An\n * absent or empty directory prints `(none)` rather than a row of zeroes: a\n * repository that has never had to write a report is the normal one.\n */\nfunction reportsLabel(reports: DoctorReport[\"reports\"]): string {\n if (!reports.present || reports.total === 0) return \"(none)\";\n const counted = new Map<ProblemReportStatus, number>();\n for (const entry of reports.entries) {\n counted.set(entry.status, (counted.get(entry.status) ?? 0) + 1);\n }\n const split = [...counted]\n .sort(([a], [b]) => REPORT_STATUS_ORDER[a] - REPORT_STATUS_ORDER[b])\n .map(([status, count]) => `${status} ${count}`);\n // The directory's NAME, not `reports.dir`: the payload spells the absolute\n // path so an agent can act on it, while the row is read by a person standing\n // in the repository, for whom the absolute spelling is only longer.\n return [`${REPORTS_DIR}/ ${reports.total}`, ...split, `next ${reports.next}`].join(\" · \");\n}\n\nfunction printDoctor(report: DoctorReport): void {\n console.log(`loam doctor — ${report.healthy ? \"healthy\" : \"blocked\"}`);\n console.log(` runtime ${report.runtime.package}@${report.runtime.version}`);\n console.log(` node ${report.runtime.node} ${report.runtime.platform}/${report.runtime.arch}`);\n console.log(` config ${report.config.status} ${report.config.path}`);\n if (report.config.error !== null) console.log(` ${report.config.error}`);\n console.log(` docsDir ${report.docs.path ?? \"(unresolved)\"}`);\n console.log(\n ` access exists ${yesNo(report.docs.exists)} · read ${yesNo(report.docs.readable)} · write ${yesNo(report.docs.writable)}`,\n );\n console.log(\n ` fleet services/ ${yesNo(report.docs.servicesDir)} · landscape ${yesNo(report.docs.landscape)} · ${report.counts.services} services · ${report.counts.activeFeatures} active features`,\n );\n console.log(\n ` binding ${report.currentService.configured ?? \"(none)\"} · ${report.currentService.status}`,\n );\n // The agent surface is reported whether or not it has drifted — like every\n // line above it, this is state, not a complaint. Only the findings block is\n // silent when there is nothing to say.\n const agents = report.agents;\n console.log(\n ` agents ${agents.tools.length === 0 ? \"(none)\" : agents.tools.join(\", \")} · ${agents.profile}`\n + ` (${agents.toolsSource}) · ${agents.plannedFiles} files · ${agents.missingFiles.length} missing`\n + ` · ${agents.staleFiles.length} stale · AGENTS.md ${stampLabel(agents.stamp)}`,\n );\n // The problem reports, for the same reason and with a stronger one behind it:\n // the `loam-report` protocol asks a repository to accumulate this corpus, and\n // until now no loam command mentioned the directory at all. Printed as state,\n // never as a finding — an open report is not a defect in the repo holding it.\n console.log(` reports ${reportsLabel(report.reports)}`);\n // The write path is state too, and its clean answer is the one worth printing\n // most often: a reader who has just been told the docs are half-written needs\n // to see it go away.\n console.log(` write path ${writePathLabel(report.writePath)}`);\n if (report.findings.length > 0) {\n console.log(\"\\n findings\");\n for (const finding of report.findings) {\n console.log(` ${finding.severity === \"blocker\" ? \"✗\" : \"⚠\"} ${finding.code}: ${finding.message}`);\n // The fix is printed on its own indented line rather than appended to the\n // message: what is wrong and what to type are two different sentences,\n // and someone scanning a blocked repo reads down the `fix:` column.\n console.log(` fix: ${finding.fix}`);\n }\n }\n}\n"]}
@@ -117,8 +117,18 @@ function print(r) {
117
117
  // Said first and without hedging: with no readable map there IS no ring,
118
118
  // and a reader who takes the empty neighbour list at face value concludes
119
119
  // the change is contained when nothing checked that.
120
- const why = r.landscape.present ? "does not parse" : "does not exist";
121
- console.log(`! architecture/landscape.likec4 ${why} — no neighbour below is derived, and none is missing either\n`);
120
+ // Same rule as `context`'s printer: name the document that actually failed.
121
+ // `parses` answers for the `architecture/` PROJECT, so the document at fault
122
+ // is very often a SIBLING beside a landscape that reads perfectly, and
123
+ // naming the landscape was a claim about bytes loam read fine (verification
124
+ // 2026-09-04). `present` is still about the FILE — it is the write target
125
+ // every brief asks for edits to — so the absent arm keeps the file name.
126
+ const named = !r.landscape.present
127
+ ? "architecture/landscape.likec4 does not exist"
128
+ : r.landscape.broken.length === 0
129
+ ? "the fleet map (architecture/) does not parse"
130
+ : `${r.landscape.broken.join(", ")} ${r.landscape.broken.length > 1 ? "do" : "does"} not parse`;
131
+ console.log(`! ${named} — no neighbour below is derived, and none is missing either\n`);
122
132
  }
123
133
  for (const s of r.services) {
124
134
  console.log(`${s.id} ${label(s)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/commands/explore.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAyC,MAAM,4BAA4B,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AACnG,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,GAAG,UAAU,CAAC;AAS/B,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,QAAQ,CAAC,cAAc,EAAE,oCAAoC,CAAC;SAC9D,WAAW,CAAC,6EAA6E,CAAC;SAC1F,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACvE,MAAM,CACL,oBAAoB,EACpB,yDAAyD,EACzD,CAAC,KAAa,EAAE,IAAI,GAAa,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CACzD;SACA,MAAM,CACL,mBAAmB,EACnB,kEAAkE,EAClE,CAAC,KAAa,EAAE,IAAI,GAAa,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CACzD;SACA,MAAM,CAAC,aAAa,EAAE,uDAAuD,WAAW,GAAG,CAAC;SAC5F,MAAM,CAAC,KAAK,EAAE,WAAqB,EAAE,IAAoB,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAChC,MAAM,QAAQ,GAAG,WAAW,IAAI,EAAE,CAAC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAE3C,sEAAsE;QACtE,yEAAyE;QACzE,yEAAyE;QACzE,qEAAqE;QACrE,qEAAqE;QACrE,sEAAsE;QACtE,qEAAqE;QACrE,wFAAwF;QACxF,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC;YACjE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;gBACtC,OAAO;YACT,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClF,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,uGAAuG;gBACrG,2EAA2E;gBAC3E,sDAAsD,CACzD,CAAC;YACF,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,oFAAoF;QACpF,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,mBAAmB;QACnB,EAAE;QACF,sEAAsE;QACtE,yEAAyE;QACzE,6DAA6D;QAC7D,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,qEAAqE;QACrE,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC;YAAE,OAAO;QAEtD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;gBAC3B,OAAO;gBACP,QAAQ,EAAE,KAAK,CAAC,GAAG;gBACnB,UAAU;gBACV,YAAY;gBACZ,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,WAAW;gBACjC,OAAO,EAAE,IAAI,YAAY,EAAE;aAC5B,CAAC,CAAC;YACH,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,wBAAwB,EAAE,CAAC;gBAC5C,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC/B,OAAO;YACT,CAAC;YACD,uEAAuE;YACvE,sEAAsE;YACtE,wDAAwD;YACxD,2BAA2B,CAAC,IAAI,EAAE,GAAG,EAAE,4CAA4C,EAAE,OAAO,CAAC,CAAC;QAChG,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,wEAAwE;AAExE,SAAS,KAAK,CAAC,CAAc;IAC3B,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAChD,yEAAyE;QACzE,0EAA0E;QAC1E,qDAAqD;QACrD,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACtE,OAAO,CAAC,GAAG,CACT,mCAAmC,GAAG,gEAAgE,CACvG,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YACb,oEAAoE;YACpE,yEAAyE;YACzE,wEAAwE;YACxE,4DAA4D;YAC5D,yEAAyE;YACzE,qEAAqE;YACrE,kDAAkD;YAClD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC;YACjE,MAAM,GAAG,GACP,CAAC,CAAC,MAAM,KAAK,MAAM;gBACjB,CAAC,CAAC,gDAAgD;gBAClD,CAAC,CAAC,qDAAqD,CAAC;YAC5D,OAAO,CAAC,GAAG,CACT,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,EAAE;gBACjC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACpE,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,CAAC,CAAC,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;YAC1F,yEAAyE;YACzE,0EAA0E;YAC1E,uEAAuE;YACvE,aAAa;YACb,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC3F,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;oBAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAC7E,CAAC;iBAAM,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CACT,gCAAgC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACpE,yBAAyB,CAAC,CAAC,oBAAoB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,wBAAwB,CACvG,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CACT,gCAAgC,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACtE,uFAAuF,CAC1F,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,4EAA4E;QAC5E,2EAA2E;QAC3E,wCAAwC;QACxC,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;IACjG,CAAC;IAED,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,mFAAmF,CAAC,CAAC;IACnG,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,KAAK,CAAC,CAAiB;IAC9B,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC7G,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,6CAA6C;IAC7C,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,yBAAyB,CAAC;AAClF,CAAC;AAED,SAAS,QAAQ,CAAC,EAAiB,EAAE,KAAoB;IACvD,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,KAAK,EAAE,EAAE,CAAC;IAClC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC","sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"../core/envelope/config.js\";\nimport { explore, type Exploration, type ExploreService } from \"../core/explore/explore.js\";\nimport { FleetContext } from \"../core/fleet-context.js\";\nimport { emitJson, fail, reportNoConfig } from \"../core/envelope/json.js\";\nimport { featureIdProblem } from \"../core/kernel/ids/feature.js\";\nimport { parseServiceIds } from \"../core/kernel/ids/service.js\";\nimport { DocsRepoUnavailableError } from \"../core/repo/state.js\";\nimport { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from \"./policy/gate.js\";\nimport { plural } from \"./policy/format.js\";\n\n/**\n * The feature id in the suggested command line when `--as` did not say.\n *\n * It has to satisfy the feature-id grammar, because `scaffold` is documented as\n * the literal `loam new` line and AGENTS.md's rule is that an instruction loam\n * prints and loam refuses is a defect. `FEAT-NNN` — the obvious placeholder —\n * is exactly that: `loam new FEAT-NNN` comes back `invalid-option`, so the last\n * line of every default run was a command that could not be run.\n *\n * `FEAT-000` parses and is still unmistakably a placeholder, which buys the\n * property the refusal was standing in for: an agent that pastes it unedited\n * gets a feature called FEAT-000, visible in `loam list` within seconds and\n * deletable with `git rm -r`. A plausible id (FEAT-1) would not be.\n */\nconst PLACEHOLDER = \"FEAT-000\";\n\ninterface ExploreOptions {\n json?: boolean;\n op?: string[];\n capability?: string[];\n as?: string;\n}\n\nexport function registerExplore(program: Command): void {\n program\n .command(\"explore\")\n .argument(\"[service...]\", \"service ids the change starts from\")\n .description(\"Read the fleet around a change nobody has written down yet — writes nothing\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .option(\n \"--op <operationId>\",\n \"seed from an operation instead of a service; repeatable\",\n (value: string, prev: string[] = []) => [...prev, value],\n )\n .option(\n \"--capability <id>\",\n \"seed from a declared capability's realizing services; repeatable\",\n (value: string, prev: string[] = []) => [...prev, value],\n )\n .option(\"--as <FEAT>\", `feature id for the suggested command line (default: ${PLACEHOLDER})`)\n .action(async (serviceArgs: string[], opts: ExploreOptions) => {\n const json = opts.json === true;\n const services = serviceArgs ?? [];\n const operations = opts.op ?? [];\n const capabilities = opts.capability ?? [];\n\n // `--as` is interpolated into the `loam new` line this command prints\n // under `next:` and returns as `scaffold`, and `loam-feature` teaches an\n // agent to pass `$1` straight into it. Unchecked, `explore` hands back a\n // command `loam new` then refuses — loam instructing an agent to run\n // something loam rejects, which is the one thing the printed-command\n // guard exists to prevent and the one shape it cannot see, because it\n // reads literal source strings and this line is assembled from argv.\n // Same grammar as `new`'s, from core/kernel/ids/feature.ts, so the two cannot disagree.\n if (opts.as !== undefined) {\n const problem = featureIdProblem(opts.as, \"feature id for --as\");\n if (problem !== null) {\n fail(json, \"invalid-option\", problem);\n return;\n }\n }\n if (services.length === 0 && operations.length === 0 && capabilities.length === 0) {\n fail(\n json,\n \"invalid-option\",\n \"Nothing to explore from. Name at least one service, or pass --op <operationId> or --capability <id>. \" +\n \"`loam list services` is the fleet; `loam show <service>` is one of them; \" +\n \"`loam list capabilities` is what the fleet promises.\",\n );\n return;\n }\n\n // Rule 6 in docs/DESIGN.md: a raw argv string that reaches a path join is\n // guarded at the command boundary. Every id here reaches the service path builders.\n // Before `loadConfig`, exactly as `loam new` guards its `--touches` list:\n // the grammar is a fact about the argument, not about the repository, so\n // an unusable id should answer the same whether or not you are standing\n // in a wired repo.\n //\n // A seed naming a service that does not EXIST is fine and reported as\n // `unknown` — the feature may be introducing it — but one that could not\n // be a service directory at all is a typo, not an intention.\n const seeds = parseServiceIds(services, \"service\");\n if (!seeds.ok) {\n fail(json, \"invalid-option\", seeds.problem);\n return;\n }\n\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n const { docsDir } = config;\n // `services`, not `docs`: every answer here is a statement about the\n // fleet, and an empty ring read out of a directory that is not a docs\n // repo says \"nothing calls this service\" about a repo nobody looked in.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n\n try {\n const result = await explore({\n docsDir,\n services: seeds.ids,\n operations,\n capabilities,\n featureId: opts.as ?? PLACEHOLDER,\n context: new FleetContext(),\n });\n if (json) {\n emitJson({ command: \"explore\", docsDir, ...result });\n return;\n }\n print(result);\n } catch (err) {\n if (err instanceof DocsRepoUnavailableError) {\n reportDocsRepoError(json, err);\n return;\n }\n // The scan is all-or-nothing — it reads every seed's contract to build\n // one table — so the honest answer to an unreadable file is a refusal\n // naming the path, not a ring with a silent hole in it.\n reportRepositoryUnavailable(json, err, \"the exploration would be missing a service\", docsDir);\n }\n });\n}\n\n/* ------------------------------------------------------------------ */\n\nfunction print(r: Exploration): void {\n if (!r.landscape.present || !r.landscape.parses) {\n // Said first and without hedging: with no readable map there IS no ring,\n // and a reader who takes the empty neighbour list at face value concludes\n // the change is contained when nothing checked that.\n const why = r.landscape.present ? \"does not parse\" : \"does not exist\";\n console.log(\n `! architecture/landscape.likec4 ${why} — no neighbour below is derived, and none is missing either\\n`,\n );\n }\n\n for (const s of r.services) {\n console.log(`${s.id} ${label(s)}`);\n if (!s.known) {\n // Two different facts wear the same absence. A SEED nobody typed by\n // accident is a service the feature introduces; one typed by accident is\n // a typo, and the near-miss list is what separates them. A neighbour is\n // neither — the fleet map drew an edge to something with no\n // `services/<id>/`, which is usually an external system and occasionally\n // a service nobody has adopted. Saying \"typo\" about that one sends a\n // reader looking for a mistake they did not make.\n const near = r.unknown.find((u) => u.id === s.id)?.nearest ?? [];\n const why =\n s.reason === \"seed\"\n ? \"the feature introduces it, or the id is a typo\"\n : \"an external system, or a service nobody has adopted\";\n console.log(\n ` no services/${s.id}/ — ${why}` +\n (near.length > 0 ? `; closest existing: ${near.join(\", \")}` : \"\"),\n );\n } else {\n if (s.missing.length > 0) console.log(` missing: ${s.missing.join(\", \")}`);\n if (!s.modelled) console.log(` not in the fleet map — no edge into it can be checked`);\n // Said before `exposes`, and said at all: an unreadable contract exposes\n // an empty list, and printing nothing there reads as \"this service offers\n // no endpoints\" — the answer that turns a MODIFIED requirement into an\n // ADDED one.\n if (s.openapi.unreadable) {\n console.log(` ! openapi.yaml does not parse — nothing here lists what ${s.id} exposes`);\n if (s.openapi.error !== undefined) console.log(` ${s.openapi.error}`);\n } else if (s.operations.length > 0) {\n console.log(` exposes: ${s.operations.join(\", \")}`);\n }\n }\n for (const e of s.inbound) console.log(` ← ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of s.outbound) console.log(` → ${e.service}${edgeNote(e.op, e.title)}`);\n console.log(\"\");\n }\n\n if (r.unresolvedOperations.length > 0) {\n console.log(\n `! no living contract defines ${r.unresolvedOperations.join(\", \")} — ` +\n `the feature is adding ${r.unresolvedOperations.length === 1 ? \"it\" : \"them\"}, or the id is wrong\\n`,\n );\n }\n\n if (r.unresolvedCapabilities.length > 0) {\n console.log(\n `! no realizing service seeds ${r.unresolvedCapabilities.join(\", \")} — ` +\n `not declared in architecture/capabilities.yaml, or declared and realized by nothing\\n`,\n );\n }\n\n if (r.neighbours.length > 0) {\n // The whole point of the command, so it is stated as a question rather than\n // a list: these are candidates for --touches, and loam does not know which\n // of them this change actually touches.\n console.log(\n `${plural(r.neighbours.length, \"neighbour\")} one hop out: ${r.neighbours.join(\", \")}`,\n );\n console.log(\" weigh each one — loam knows they are connected, not whether you change them\\n\");\n }\n\n if (r.overlaps.length > 0) {\n console.log(\"already in flight over this ground\");\n for (const o of r.overlaps) console.log(` ${o.feature} ${o.services.join(\", \")}`);\n console.log(\" `loam dependencies` says which must archive first, and what no ordering fixes\\n\");\n }\n\n console.log(`next: ${r.scaffold}`);\n}\n\nfunction label(s: ExploreService): string {\n const where = s.reason === \"seed\" ? \"seed\" : s.reason === \"calls-seed\" ? \"calls a seed\" : \"called by a seed\";\n // `known`, matching the branch in `print` — not `maturity === null`. The two\n // are set together and cannot disagree today, but discriminating on different\n // fields for the same question is how they start to: a reader fixing one\n // branch has no reason to look at the other.\n return s.known ? `${where} · ${s.maturity}` : `${where} · not in the docs repo`;\n}\n\nfunction edgeNote(op: string | null, title: string | null): string {\n if (op !== null) return ` ${op}`;\n return title !== null ? ` \"${title}\"` : \"\";\n}\n"]}
1
+ {"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/commands/explore.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"../core/envelope/config.js\";\nimport { explore, type Exploration, type ExploreService } from \"../core/explore/explore.js\";\nimport { FleetContext } from \"../core/fleet-context.js\";\nimport { emitJson, fail, reportNoConfig } from \"../core/envelope/json.js\";\nimport { featureIdProblem } from \"../core/kernel/ids/feature.js\";\nimport { parseServiceIds } from \"../core/kernel/ids/service.js\";\nimport { DocsRepoUnavailableError } from \"../core/repo/state.js\";\nimport { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from \"./policy/gate.js\";\nimport { plural } from \"./policy/format.js\";\n\n/**\n * The feature id in the suggested command line when `--as` did not say.\n *\n * It has to satisfy the feature-id grammar, because `scaffold` is documented as\n * the literal `loam new` line and AGENTS.md's rule is that an instruction loam\n * prints and loam refuses is a defect. `FEAT-NNN` — the obvious placeholder —\n * is exactly that: `loam new FEAT-NNN` comes back `invalid-option`, so the last\n * line of every default run was a command that could not be run.\n *\n * `FEAT-000` parses and is still unmistakably a placeholder, which buys the\n * property the refusal was standing in for: an agent that pastes it unedited\n * gets a feature called FEAT-000, visible in `loam list` within seconds and\n * deletable with `git rm -r`. A plausible id (FEAT-1) would not be.\n */\nconst PLACEHOLDER = \"FEAT-000\";\n\ninterface ExploreOptions {\n json?: boolean;\n op?: string[];\n capability?: string[];\n as?: string;\n}\n\nexport function registerExplore(program: Command): void {\n program\n .command(\"explore\")\n .argument(\"[service...]\", \"service ids the change starts from\")\n .description(\"Read the fleet around a change nobody has written down yet — writes nothing\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .option(\n \"--op <operationId>\",\n \"seed from an operation instead of a service; repeatable\",\n (value: string, prev: string[] = []) => [...prev, value],\n )\n .option(\n \"--capability <id>\",\n \"seed from a declared capability's realizing services; repeatable\",\n (value: string, prev: string[] = []) => [...prev, value],\n )\n .option(\"--as <FEAT>\", `feature id for the suggested command line (default: ${PLACEHOLDER})`)\n .action(async (serviceArgs: string[], opts: ExploreOptions) => {\n const json = opts.json === true;\n const services = serviceArgs ?? [];\n const operations = opts.op ?? [];\n const capabilities = opts.capability ?? [];\n\n // `--as` is interpolated into the `loam new` line this command prints\n // under `next:` and returns as `scaffold`, and `loam-feature` teaches an\n // agent to pass `$1` straight into it. Unchecked, `explore` hands back a\n // command `loam new` then refuses — loam instructing an agent to run\n // something loam rejects, which is the one thing the printed-command\n // guard exists to prevent and the one shape it cannot see, because it\n // reads literal source strings and this line is assembled from argv.\n // Same grammar as `new`'s, from core/kernel/ids/feature.ts, so the two cannot disagree.\n if (opts.as !== undefined) {\n const problem = featureIdProblem(opts.as, \"feature id for --as\");\n if (problem !== null) {\n fail(json, \"invalid-option\", problem);\n return;\n }\n }\n if (services.length === 0 && operations.length === 0 && capabilities.length === 0) {\n fail(\n json,\n \"invalid-option\",\n \"Nothing to explore from. Name at least one service, or pass --op <operationId> or --capability <id>. \" +\n \"`loam list services` is the fleet; `loam show <service>` is one of them; \" +\n \"`loam list capabilities` is what the fleet promises.\",\n );\n return;\n }\n\n // Rule 6 in docs/DESIGN.md: a raw argv string that reaches a path join is\n // guarded at the command boundary. Every id here reaches the service path builders.\n // Before `loadConfig`, exactly as `loam new` guards its `--touches` list:\n // the grammar is a fact about the argument, not about the repository, so\n // an unusable id should answer the same whether or not you are standing\n // in a wired repo.\n //\n // A seed naming a service that does not EXIST is fine and reported as\n // `unknown` — the feature may be introducing it — but one that could not\n // be a service directory at all is a typo, not an intention.\n const seeds = parseServiceIds(services, \"service\");\n if (!seeds.ok) {\n fail(json, \"invalid-option\", seeds.problem);\n return;\n }\n\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n const { docsDir } = config;\n // `services`, not `docs`: every answer here is a statement about the\n // fleet, and an empty ring read out of a directory that is not a docs\n // repo says \"nothing calls this service\" about a repo nobody looked in.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n\n try {\n const result = await explore({\n docsDir,\n services: seeds.ids,\n operations,\n capabilities,\n featureId: opts.as ?? PLACEHOLDER,\n context: new FleetContext(),\n });\n if (json) {\n emitJson({ command: \"explore\", docsDir, ...result });\n return;\n }\n print(result);\n } catch (err) {\n if (err instanceof DocsRepoUnavailableError) {\n reportDocsRepoError(json, err);\n return;\n }\n // The scan is all-or-nothing — it reads every seed's contract to build\n // one table — so the honest answer to an unreadable file is a refusal\n // naming the path, not a ring with a silent hole in it.\n reportRepositoryUnavailable(json, err, \"the exploration would be missing a service\", docsDir);\n }\n });\n}\n\n/* ------------------------------------------------------------------ */\n\nfunction print(r: Exploration): void {\n if (!r.landscape.present || !r.landscape.parses) {\n // Said first and without hedging: with no readable map there IS no ring,\n // and a reader who takes the empty neighbour list at face value concludes\n // the change is contained when nothing checked that.\n // Same rule as `context`'s printer: name the document that actually failed.\n // `parses` answers for the `architecture/` PROJECT, so the document at fault\n // is very often a SIBLING beside a landscape that reads perfectly, and\n // naming the landscape was a claim about bytes loam read fine (verification\n // 2026-09-04). `present` is still about the FILE — it is the write target\n // every brief asks for edits to — so the absent arm keeps the file name.\n const named = !r.landscape.present\n ? \"architecture/landscape.likec4 does not exist\"\n : r.landscape.broken.length === 0\n ? \"the fleet map (architecture/) does not parse\"\n : `${r.landscape.broken.join(\", \")} ${r.landscape.broken.length > 1 ? \"do\" : \"does\"} not parse`;\n console.log(`! ${named} — no neighbour below is derived, and none is missing either\\n`);\n }\n\n for (const s of r.services) {\n console.log(`${s.id} ${label(s)}`);\n if (!s.known) {\n // Two different facts wear the same absence. A SEED nobody typed by\n // accident is a service the feature introduces; one typed by accident is\n // a typo, and the near-miss list is what separates them. A neighbour is\n // neither — the fleet map drew an edge to something with no\n // `services/<id>/`, which is usually an external system and occasionally\n // a service nobody has adopted. Saying \"typo\" about that one sends a\n // reader looking for a mistake they did not make.\n const near = r.unknown.find((u) => u.id === s.id)?.nearest ?? [];\n const why =\n s.reason === \"seed\"\n ? \"the feature introduces it, or the id is a typo\"\n : \"an external system, or a service nobody has adopted\";\n console.log(\n ` no services/${s.id}/ — ${why}` +\n (near.length > 0 ? `; closest existing: ${near.join(\", \")}` : \"\"),\n );\n } else {\n if (s.missing.length > 0) console.log(` missing: ${s.missing.join(\", \")}`);\n if (!s.modelled) console.log(` not in the fleet map — no edge into it can be checked`);\n // Said before `exposes`, and said at all: an unreadable contract exposes\n // an empty list, and printing nothing there reads as \"this service offers\n // no endpoints\" — the answer that turns a MODIFIED requirement into an\n // ADDED one.\n if (s.openapi.unreadable) {\n console.log(` ! openapi.yaml does not parse — nothing here lists what ${s.id} exposes`);\n if (s.openapi.error !== undefined) console.log(` ${s.openapi.error}`);\n } else if (s.operations.length > 0) {\n console.log(` exposes: ${s.operations.join(\", \")}`);\n }\n }\n for (const e of s.inbound) console.log(` ← ${e.service}${edgeNote(e.op, e.title)}`);\n for (const e of s.outbound) console.log(` → ${e.service}${edgeNote(e.op, e.title)}`);\n console.log(\"\");\n }\n\n if (r.unresolvedOperations.length > 0) {\n console.log(\n `! no living contract defines ${r.unresolvedOperations.join(\", \")} — ` +\n `the feature is adding ${r.unresolvedOperations.length === 1 ? \"it\" : \"them\"}, or the id is wrong\\n`,\n );\n }\n\n if (r.unresolvedCapabilities.length > 0) {\n console.log(\n `! no realizing service seeds ${r.unresolvedCapabilities.join(\", \")} — ` +\n `not declared in architecture/capabilities.yaml, or declared and realized by nothing\\n`,\n );\n }\n\n if (r.neighbours.length > 0) {\n // The whole point of the command, so it is stated as a question rather than\n // a list: these are candidates for --touches, and loam does not know which\n // of them this change actually touches.\n console.log(\n `${plural(r.neighbours.length, \"neighbour\")} one hop out: ${r.neighbours.join(\", \")}`,\n );\n console.log(\" weigh each one — loam knows they are connected, not whether you change them\\n\");\n }\n\n if (r.overlaps.length > 0) {\n console.log(\"already in flight over this ground\");\n for (const o of r.overlaps) console.log(` ${o.feature} ${o.services.join(\", \")}`);\n console.log(\" `loam dependencies` says which must archive first, and what no ordering fixes\\n\");\n }\n\n console.log(`next: ${r.scaffold}`);\n}\n\nfunction label(s: ExploreService): string {\n const where = s.reason === \"seed\" ? \"seed\" : s.reason === \"calls-seed\" ? \"calls a seed\" : \"called by a seed\";\n // `known`, matching the branch in `print` — not `maturity === null`. The two\n // are set together and cannot disagree today, but discriminating on different\n // fields for the same question is how they start to: a reader fixing one\n // branch has no reason to look at the other.\n return s.known ? `${where} · ${s.maturity}` : `${where} · not in the docs repo`;\n}\n\nfunction edgeNote(op: string | null, title: string | null): string {\n if (op !== null) return ` ${op}`;\n return title !== null ? ` \"${title}\"` : \"\";\n}\n"]}
@@ -48,7 +48,11 @@ export async function serviceViews(docsDir, services, boundService, preloaded) {
48
48
  if (proven) {
49
49
  const svcOf = serviceResolver(land.elements, known);
50
50
  for (const r of land.relationships) {
51
- if (r.op !== undefined)
51
+ // …including its self-edge rule: an edge whose two endpoints resolve to
52
+ // one service is that service's own internal wiring, and counting it made
53
+ // a service nobody calls owe an OpenAPI contract — `partial` here while
54
+ // `loam context` (which reads the shared derivation) said `documented`.
55
+ if (r.op !== undefined && svcOf(r.source) !== svcOf(r.target))
52
56
  called.add(svcOf(r.target));
53
57
  }
54
58
  }