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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/CHANGELOG.md +1063 -0
  2. package/MIGRATING-from-OpenSpec.md +7 -4
  3. package/QUICKSTART.md +8 -3
  4. package/README.md +13 -7
  5. package/ROADMAP.md +285 -11
  6. package/SCHEMA.md +566 -45
  7. package/WORKFLOW.md +23 -10
  8. package/dist/commands/adopt/render.js +47 -8
  9. package/dist/commands/adopt/render.js.map +1 -1
  10. package/dist/commands/archive/plan/landscape.js +45 -1
  11. package/dist/commands/archive/plan/landscape.js.map +1 -1
  12. package/dist/commands/archive/plan/model/extending.js +85 -0
  13. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  14. package/dist/commands/archive/run.js +53 -23
  15. package/dist/commands/archive/run.js.map +1 -1
  16. package/dist/commands/context/print.js +11 -1
  17. package/dist/commands/context/print.js.map +1 -1
  18. package/dist/commands/doctor.js +46 -0
  19. package/dist/commands/doctor.js.map +1 -1
  20. package/dist/commands/explore.js +12 -2
  21. package/dist/commands/explore.js.map +1 -1
  22. package/dist/commands/list/views.js +5 -1
  23. package/dist/commands/list/views.js.map +1 -1
  24. package/dist/commands/seed/commit.js +34 -1
  25. package/dist/commands/seed/commit.js.map +1 -1
  26. package/dist/commands/seed/plan.js +158 -13
  27. package/dist/commands/seed/plan.js.map +1 -1
  28. package/dist/commands/seed/seed.js +7 -2
  29. package/dist/commands/seed/seed.js.map +1 -1
  30. package/dist/commands/show/feature.js +2 -1
  31. package/dist/commands/show/feature.js.map +1 -1
  32. package/dist/commands/show/marks.js +3 -5
  33. package/dist/commands/show/marks.js.map +1 -1
  34. package/dist/commands/show/service.js +39 -18
  35. package/dist/commands/show/service.js.map +1 -1
  36. package/dist/commands/subsystem/edit.js +4 -2
  37. package/dist/commands/subsystem/edit.js.map +1 -1
  38. package/dist/commands/subsystem/move.js +55 -17
  39. package/dist/commands/subsystem/move.js.map +1 -1
  40. package/dist/commands/subsystem/sync.js +238 -87
  41. package/dist/commands/subsystem/sync.js.map +1 -1
  42. package/dist/commands/subsystem/txn/exclude.js +132 -0
  43. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  44. package/dist/commands/subsystem/txn/report.js +174 -0
  45. package/dist/commands/subsystem/txn/report.js.map +1 -0
  46. package/dist/commands/subsystem/txn/txn.js +126 -22
  47. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  48. package/dist/commands/subsystem/txn/views.js +159 -19
  49. package/dist/commands/subsystem/txn/views.js.map +1 -1
  50. package/dist/commands/validate/arch-coverage.js +16 -9
  51. package/dist/commands/validate/arch-coverage.js.map +1 -1
  52. package/dist/commands/validate/checks/fleet-shape.js +30 -77
  53. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  54. package/dist/commands/validate/checks/health-deps.js +9 -6
  55. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  56. package/dist/commands/validate/checks/vocabulary.js +4 -19
  57. package/dist/commands/validate/checks/vocabulary.js.map +1 -1
  58. package/dist/commands/validate/feature.js +1 -1
  59. package/dist/commands/validate/feature.js.map +1 -1
  60. package/dist/commands/validate/fleet/census.js +37 -13
  61. package/dist/commands/validate/fleet/census.js.map +1 -1
  62. package/dist/commands/validate/fleet/landscape.js +131 -120
  63. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  64. package/dist/commands/validate/fleet/load.js +66 -0
  65. package/dist/commands/validate/fleet/load.js.map +1 -1
  66. package/dist/commands/validate/fleet/map/attest.js +102 -0
  67. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  68. package/dist/commands/validate/fleet/map/bindings.js +109 -0
  69. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  70. package/dist/commands/validate/fleet/map/consumers.js +219 -0
  71. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  72. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  73. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  74. package/dist/commands/validate/fleet/map/usecases.js +56 -0
  75. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  76. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  77. package/dist/commands/validate/fleet/usecases/steps.js +49 -17
  78. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -1
  79. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  80. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  81. package/dist/commands/validate/fleet/views/ids.js +45 -15
  82. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  83. package/dist/commands/validate/fleet/views/projects.js +258 -70
  84. package/dist/commands/validate/fleet/views/projects.js.map +1 -1
  85. package/dist/commands/validate/fleet/views/root-documents.js +99 -0
  86. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  87. package/dist/commands/validate/fleet/views/stale.js +32 -15
  88. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  89. package/dist/commands/validate/service/model/diverged.js +226 -0
  90. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  91. package/dist/commands/validate/service/model/grade.js +163 -0
  92. package/dist/commands/validate/service/model/grade.js.map +1 -0
  93. package/dist/commands/validate/service/service.js +110 -34
  94. package/dist/commands/validate/service/service.js.map +1 -1
  95. package/dist/commands/validate/service/specs.js +39 -5
  96. package/dist/commands/validate/service/specs.js.map +1 -1
  97. package/dist/commands/validate/service/spine.js +41 -3
  98. package/dist/commands/validate/service/spine.js.map +1 -1
  99. package/dist/commands/validate/service/usecases/tags.js +113 -0
  100. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  101. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  102. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  103. package/dist/commands/validate/validate.js +10 -24
  104. package/dist/commands/validate/validate.js.map +1 -1
  105. package/dist/core/agent/agents-md/artifacts.js +1 -0
  106. package/dist/core/agent/agents-md/artifacts.js.map +1 -1
  107. package/dist/core/agent/agents-md/command-map.js +19 -5
  108. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  109. package/dist/core/agent/agents-md/cycle.js +24 -9
  110. package/dist/core/agent/agents-md/cycle.js.map +1 -1
  111. package/dist/core/agent/agents-md/map/lenses/context.js +4 -3
  112. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  113. package/dist/core/agent/agents-md/map/subsystem.js +70 -17
  114. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  115. package/dist/core/agent/agents-md/map/usecases.js +45 -3
  116. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  117. package/dist/core/agent/agents-md/refusals.js +5 -3
  118. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  119. package/dist/core/agent/agents-md.js +26 -7
  120. package/dist/core/agent/agents-md.js.map +1 -1
  121. package/dist/core/agent/support/report.js +39 -5
  122. package/dist/core/agent/support/report.js.map +1 -1
  123. package/dist/core/agent/workflows/adopt.js +123 -14
  124. package/dist/core/agent/workflows/adopt.js.map +1 -1
  125. package/dist/core/agent/workflows/check.js +34 -20
  126. package/dist/core/agent/workflows/check.js.map +1 -1
  127. package/dist/core/agent/workflows/closing.js +3 -1
  128. package/dist/core/agent/workflows/closing.js.map +1 -1
  129. package/dist/core/agent/workflows/reference/spine.js +12 -6
  130. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  131. package/dist/core/brief/brief.js +88 -19
  132. package/dist/core/brief/brief.js.map +1 -1
  133. package/dist/core/brief/checks.js +133 -7
  134. package/dist/core/brief/checks.js.map +1 -1
  135. package/dist/core/brief/landscape.js +212 -129
  136. package/dist/core/brief/landscape.js.map +1 -1
  137. package/dist/core/brief/map/extend.js +81 -0
  138. package/dist/core/brief/map/extend.js.map +1 -0
  139. package/dist/core/brief/map/owed.js +284 -0
  140. package/dist/core/brief/map/owed.js.map +1 -0
  141. package/dist/core/brief/targets.js +94 -29
  142. package/dist/core/brief/targets.js.map +1 -1
  143. package/dist/core/brief/unchecked.js +13 -3
  144. package/dist/core/brief/unchecked.js.map +1 -1
  145. package/dist/core/c4/likec4.js +23 -1
  146. package/dist/core/c4/likec4.js.map +1 -1
  147. package/dist/core/c4/parsed/deployment.js +5 -3
  148. package/dist/core/c4/parsed/deployment.js.map +1 -1
  149. package/dist/core/c4/parsed/view-ids.js +39 -1
  150. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  151. package/dist/core/c4/prefetch/fleet.js +142 -0
  152. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  153. package/dist/core/c4/project/architecture.js +77 -7
  154. package/dist/core/c4/project/architecture.js.map +1 -1
  155. package/dist/core/c4/project/batch.js +140 -0
  156. package/dist/core/c4/project/batch.js.map +1 -0
  157. package/dist/core/c4/project/documents.js +12 -6
  158. package/dist/core/c4/project/documents.js.map +1 -1
  159. package/dist/core/c4/project/load.js +85 -42
  160. package/dist/core/c4/project/load.js.map +1 -1
  161. package/dist/core/c4/project/staged.js +53 -15
  162. package/dist/core/c4/project/staged.js.map +1 -1
  163. package/dist/core/c4/resolve/attested.js +0 -0
  164. package/dist/core/c4/resolve/attested.js.map +1 -0
  165. package/dist/core/c4/resolve/service.js +8 -17
  166. package/dist/core/c4/resolve/service.js.map +1 -1
  167. package/dist/core/c4/resolve/steps.js +18 -0
  168. package/dist/core/c4/resolve/steps.js.map +1 -1
  169. package/dist/core/c4/root-project/exclude.js +352 -0
  170. package/dist/core/c4/root-project/exclude.js.map +1 -0
  171. package/dist/core/c4/service-model/documents.js +47 -0
  172. package/dist/core/c4/service-model/documents.js.map +1 -0
  173. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  174. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  175. package/dist/core/c4/service-model/load.js +165 -0
  176. package/dist/core/c4/service-model/load.js.map +1 -0
  177. package/dist/core/c4/service-model/renderer.js +128 -0
  178. package/dist/core/c4/service-model/renderer.js.map +1 -0
  179. package/dist/core/c4/service-model/shape.js +126 -0
  180. package/dist/core/c4/service-model/shape.js.map +1 -0
  181. package/dist/core/c4/service-model/slice.js +188 -0
  182. package/dist/core/c4/service-model/slice.js.map +1 -0
  183. package/dist/core/c4/source-scan.js +26 -0
  184. package/dist/core/c4/source-scan.js.map +1 -1
  185. package/dist/core/c4/splice/authored-source.js +60 -13
  186. package/dist/core/c4/splice/authored-source.js.map +1 -1
  187. package/dist/core/c4/splice/contract.js.map +1 -1
  188. package/dist/core/c4/splice/identity/declared.js +87 -0
  189. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  190. package/dist/core/c4/splice/identity/edges.js +17 -0
  191. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  192. package/dist/core/c4/splice/identity/existing.js +80 -0
  193. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  194. package/dist/core/c4/splice/identity/interior.js +80 -0
  195. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  196. package/dist/core/c4/splice/identity/owner.js +50 -0
  197. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  198. package/dist/core/c4/splice/landscape-merge.js +154 -100
  199. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  200. package/dist/core/c4/splice/model/merge.js +140 -0
  201. package/dist/core/c4/splice/model/merge.js.map +1 -0
  202. package/dist/core/c4/splice/placement.js +14 -4
  203. package/dist/core/c4/splice/placement.js.map +1 -1
  204. package/dist/core/c4/workspace.js +2 -1
  205. package/dist/core/c4/workspace.js.map +1 -1
  206. package/dist/core/coherence/coherence.js +7 -0
  207. package/dist/core/coherence/coherence.js.map +1 -1
  208. package/dist/core/delta/delta.js +9 -0
  209. package/dist/core/delta/delta.js.map +1 -1
  210. package/dist/core/deployment/delta.js +16 -10
  211. package/dist/core/deployment/delta.js.map +1 -1
  212. package/dist/core/diff/base-state.js +21 -5
  213. package/dist/core/diff/base-state.js.map +1 -1
  214. package/dist/core/diff/victims.js +10 -1
  215. package/dist/core/diff/victims.js.map +1 -1
  216. package/dist/core/docs.js +29 -24
  217. package/dist/core/docs.js.map +1 -1
  218. package/dist/core/doctor/config.js +7 -3
  219. package/dist/core/doctor/config.js.map +1 -1
  220. package/dist/core/doctor/doctor.js +36 -8
  221. package/dist/core/doctor/doctor.js.map +1 -1
  222. package/dist/core/doctor/report.js.map +1 -1
  223. package/dist/core/doctor/reports/scan.js +242 -0
  224. package/dist/core/doctor/reports/scan.js.map +1 -0
  225. package/dist/core/explain/refusals.js +1 -1
  226. package/dist/core/explain/refusals.js.map +1 -1
  227. package/dist/core/explore/explore.js +44 -9
  228. package/dist/core/explore/explore.js.map +1 -1
  229. package/dist/core/fleet-context.js +47 -0
  230. package/dist/core/fleet-context.js.map +1 -1
  231. package/dist/core/gate/checks.js +5 -1
  232. package/dist/core/gate/checks.js.map +1 -1
  233. package/dist/core/gate/partners.js +65 -26
  234. package/dist/core/gate/partners.js.map +1 -1
  235. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  236. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  237. package/dist/core/pack/living.js +47 -13
  238. package/dist/core/pack/living.js.map +1 -1
  239. package/dist/core/pack/pack.js +9 -6
  240. package/dist/core/pack/pack.js.map +1 -1
  241. package/dist/core/projection/arch-slice.js +2 -2
  242. package/dist/core/projection/arch-slice.js.map +1 -1
  243. package/dist/core/repo/paths.js +45 -38
  244. package/dist/core/repo/paths.js.map +1 -1
  245. package/dist/core/repo/tree/render/body.js +45 -6
  246. package/dist/core/repo/tree/render/body.js.map +1 -1
  247. package/dist/core/repo/tree/render/projects.js +93 -35
  248. package/dist/core/repo/tree/render/projects.js.map +1 -1
  249. package/dist/core/repo/tree/render/service/header.js +125 -0
  250. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  251. package/dist/core/repo/tree/render/service/peers.js +28 -0
  252. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  253. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  254. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  255. package/dist/core/repo/tree/render/service/views.js +78 -0
  256. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  257. package/dist/core/repo/tree/render/stale.js +20 -4
  258. package/dist/core/repo/tree/render/stale.js.map +1 -1
  259. package/dist/core/repo/tree/render/views.js +149 -32
  260. package/dist/core/repo/tree/render/views.js.map +1 -1
  261. package/dist/core/repo/tree/walk.js +45 -2
  262. package/dist/core/repo/tree/walk.js.map +1 -1
  263. package/dist/core/scaffold/landscape.js +219 -9
  264. package/dist/core/scaffold/landscape.js.map +1 -1
  265. package/dist/core/staging/writes.js.map +1 -1
  266. package/dist/core/usecases/delta/claims.js +1 -0
  267. package/dist/core/usecases/delta/claims.js.map +1 -1
  268. package/dist/core/usecases/delta/overlay.js +4 -0
  269. package/dist/core/usecases/delta/overlay.js.map +1 -1
  270. package/dist/core/usecases/fleet.js +18 -6
  271. package/dist/core/usecases/fleet.js.map +1 -1
  272. package/dist/core/usecases/operations.js +7 -0
  273. package/dist/core/usecases/operations.js.map +1 -1
  274. package/dist/core/usecases/service/exclude.js +119 -0
  275. package/dist/core/usecases/service/exclude.js.map +1 -0
  276. package/dist/core/usecases/service/flows.js +161 -0
  277. package/dist/core/usecases/service/flows.js.map +1 -0
  278. package/dist/core/verify/checklist.js +42 -10
  279. package/dist/core/verify/checklist.js.map +1 -1
  280. package/dist/core/vocabulary/issue.js.map +1 -1
  281. package/dist/core/vocabulary/maturity.js +51 -1
  282. package/dist/core/vocabulary/maturity.js.map +1 -1
  283. package/examples/README.md +30 -8
  284. package/examples/docs/architecture/landscape.likec4 +47 -0
  285. package/examples/docs/architecture/services.likec4 +70 -0
  286. package/examples/docs/architecture/subsystems.likec4 +3 -0
  287. package/examples/docs/architecture/usecases/order-notification.likec4 +5 -2
  288. package/examples/docs/likec4.config.json +0 -1
  289. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  290. package/examples/docs/services/order-service/arch.spec.md +13 -6
  291. package/examples/docs/services/order-service/model.likec4 +58 -70
  292. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  293. package/examples/docs/services/payment-service/model.likec4 +38 -39
  294. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  295. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  296. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  297. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  298. package/package.json +1 -1
  299. package/examples/docs/services/checkout-web/likec4.config.json +0 -4
  300. package/examples/docs/services/order-service/likec4.config.json +0 -4
  301. package/examples/docs/services/payment-service/likec4.config.json +0 -4
  302. package/examples/docs/services/platform/identity-service/likec4.config.json +0 -4
  303. package/examples/docs/services/platform/notification-service/likec4.config.json +0 -4
@@ -312,10 +312,13 @@ services, loam frontmatter, Operations/Covers links and feature identity still r
312
312
  specs intentionally remain `status: draft`.
313
313
  - `Operations:` links to provider OpenAPI `operationId`s, and `Covers:` links where architecture
314
314
  requirements are created.
315
- - `architecture/landscape.likec4`, service `model.likec4`, and explicit fleet relationships — then
316
- `loam subsystem sync`, which writes each model's `likec4.config.json` (the staged repo already
317
- carries the root one) so the models render beside the map; `validate --all` warns
318
- `service.likec4-config-missing` for any model still without one.
315
+ - `architecture/landscape.likec4`, service `model.likec4` (written to extend the map's element —
316
+ no `specification` block of its own; SCHEMA.md, "Two shapes of a service model"), and explicit
317
+ fleet relationships — then `loam subsystem sync`, which keeps the root `likec4.config.json`'s
318
+ `exclude` covering exactly the models that stand alone (the staged repo already carries the
319
+ root file), so every model that extends the map renders beside it; `validate --all` warns
320
+ `service.likec4-config-missing` for a standalone model still without a project file of its own,
321
+ and `service.model-unexcluded` for one the root project does not exclude.
319
322
  - Service OpenAPI contracts and provider-before-consumer sequencing where inbound edges already name
320
323
  operations.
321
324
  - LikeC4 and OpenAPI deltas for the already mapped active feature ids (`FEAT-12`, `BUG-42`, and so
package/QUICKSTART.md CHANGED
@@ -103,11 +103,16 @@ Or ask naturally: “Create a loam problem report for what just happened.” The
103
103
  relevant status and the smallest safe reproduction, and writes a separate file:
104
104
 
105
105
  ```text
106
- loam-reports/YYYY-MM-DD-short-symptom.md
106
+ loam-reports/NNN-YYYY-MM-DD-short-symptom.md
107
107
  ```
108
108
 
109
- The report records expected versus actual behavior, stable codes, relevant locations, write state,
110
- classification and missing evidence. It replaces secrets with `<redacted>`, prefers repo-relative
109
+ `NNN` is the report's ordinal — at least three digits, zero-padded, one more than the highest
110
+ already in the directory, which
111
+ `loam doctor` reports together with how many reports are open, sent, fixed or superseded — and a
112
+ `Status: open` line in the header is where the report's own state is kept (`doctor` reads it from
113
+ the header block above the first `##` heading, never from a quoted template inside the body). The report records
114
+ expected versus actual behavior, stable codes, relevant locations, write state, classification and
115
+ missing evidence. It replaces secrets with `<redacted>`, prefers repo-relative
111
116
  paths, does not copy source/spec bodies, does not retry a writer merely to reproduce it, and never
112
117
  uploads or submits anything automatically. Review the file before sharing or committing it.
113
118
 
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![CI](https://github.com/ybotok/loam/actions/workflows/ci.yml/badge.svg)](https://github.com/ybotok/loam/actions/workflows/ci.yml)
8
8
  [![npm](https://img.shields.io/npm/v/@ybotok/loam/alpha.svg?label=npm%20alpha)](https://www.npmjs.com/package/@ybotok/loam)
9
9
 
10
- > **Pre-release: `0.2.0-alpha.5`**, the fourth published release of the 0.2 line and the newest published
10
+ > **Pre-release: `0.2.0-alpha.7`**, the sixth published release of the 0.2 line and the newest published
11
11
  > version of [`@ybotok/loam`](https://www.npmjs.com/package/@ybotok/loam). It publishes under the
12
12
  > `alpha` npm dist-tag — which is what the badge above reads: `npm i @ybotok/loam@alpha`, or the
13
13
  > exact version, always installs this line. `latest` is moved onto a release by hand once it has
@@ -71,7 +71,8 @@ Topology changes where loam's checks pay off; it does not change the lifecycle:
71
71
  nesting depth, decides which `services/<id>/` owns an element.
72
72
 
73
73
  For example, the frozen `service` term can name an application while its internal modules remain
74
- ordinary C4 elements:
74
+ ordinary C4 elements. This is `architecture/landscape.likec4`, the fleet map — the one document
75
+ that declares the kinds:
75
76
 
76
77
  ```likec4
77
78
  specification {
@@ -92,6 +93,11 @@ model {
92
93
  }
93
94
  ```
94
95
 
96
+ The modules can equally live in `services/commerce-app/model.likec4`, which is the ordinary place
97
+ for them once the application has one — as an **extending model**, declaring no kinds of its own and
98
+ saying `extend commerce { … }` on the element above. SCHEMA.md's "Two shapes of a service model" has
99
+ that shape, the older one that parses alone, and the rule that picks between them.
100
+
95
101
  An internal edge normally carries no `metadata { op }`: that key specifically joins a call to the
96
102
  governed boundary's OpenAPI contract. An architecture requirement can instead say
97
103
  `Covers: commerce.orders -> commerce.billing`. Fleet-level maturity, dependency and scorecard views
@@ -109,7 +115,7 @@ both halves are written down: the question in the brief or the checklist, the an
109
115
 
110
116
  Most of this category will tell you what it checks. loam ships the other list too, in the binary:
111
117
  **[`src/core/brief/unchecked.ts`](https://github.com/ybotok/loam/blob/main/src/core/brief/unchecked.ts)
112
- is sixteen statements of what no check will ever tell you**, printed into the adoption brief beside
118
+ is seventeen statements of what no check will ever tell you**, printed into the adoption brief beside
113
119
  the checks that do run. It says, in loam's own words, that nothing here knows whether the model is
114
120
  the architecture the code actually has, whether a requirement is *true*, whether an `operationId` is
115
121
  the one the code serves, or whether `sources` names the files anybody read. And it says the one that
@@ -359,7 +365,7 @@ cannot hold.
359
365
  | `loam new <FEAT>` | `--title <text>` `--touches <id>` `--new-service <id>` `--capability <id>` | Scaffold a feature: intent, C4 delta, a requirement delta per service named by `--touches`/`--new-service`, and a capability delta per promise named by `--capability` (all repeatable) |
360
366
  | `loam show <service\|FEAT>` | `--type <kind>` | Everything loam knows about one service or feature. A feature's JSON includes a semantic `review` pack: intent, exact architecture objects, API/event slices, dependencies, artifacts, verification, blockers and next actions. `--type` forces an ambiguous reading |
361
367
  | `loam subsystem <verb> [names...]` | `--into <name>` `--under <name>` `--title <text>` `--description <text>` `--owner <name>` | Manage the grouping tree under `services/` — a navigable tree no identity depends on. `new`/`rm`, `move … --into`, `rename`, `list`, `history`, `sync` |
362
- | `loam adopt` | `--service <id>` `--subsystem <name>` `--targets` | Brief an agent to write this service's baseline into the docs repo as `draft`: the target paths, the grammar of each, what the landscape already says, and the checks that follow. Writes nothing. `--targets` narrows it to what varies by service — the walk, the 37 checks and the sixteen statements of what nothing checks are the same bytes everywhere, so a `full` field names the one run that carries them: 42,873 bytes to 17,805 |
368
+ | `loam adopt` | `--service <id>` `--subsystem <name>` `--targets` | Brief an agent to write this service's baseline into the docs repo as `draft`: the target paths, the grammar of each, what the landscape already says — and, for an element no edge touches, the edges the service's own model.likec4 attests — and the checks that follow. Writes nothing. `--targets` narrows it to what varies by service — the walk, the 52 checks and the seventeen statements of what nothing checks are the same bytes everywhere, so a `full` field names the one run that carries them: 54,833 bytes to 20,062 on the example fleet's payment-service (measured 2026-09-04) |
363
369
  | `loam delta <FEAT>` | `--service <id>` | Project a feature onto one service: the intent, its requirement deltas with every body and Given/When/Then line verbatim, the endpoints it adds or retires, and the edges around it. Doubles as a coding-agent task |
364
370
  | `loam gherkin [<FEAT>]` | `--service <id>` `--dry-run` | Emit spec scenarios as digest-stamped Gherkin `.feature` files into the service repo's `<gherkinDir>/loam/` |
365
371
  | `loam rebase [<FEAT>]` | `--service <id>` `--dry-run` `--living` | Pin the feature to the living versions it was written against, on the requirement axis and the contract axis. `--living` takes no feature: it pins the living corpus's `Realizes:` entries to the capability requirements they name, which is what makes `capability.realizes-stale` able to fire later |
@@ -487,7 +493,7 @@ always preserved byte for byte, with the entry printed for manual merge.
487
493
  maps, what is lost, what must be added.
488
494
  - [ROADMAP.md](ROADMAP.md) — the evidence-backed improvement plan, priorities, non-goals and exit
489
495
  criteria.
490
- - [CHANGELOG.md](CHANGELOG.md) — released beta.1–alpha.5 plus the changes on `main` under
496
+ - [CHANGELOG.md](CHANGELOG.md) — released beta.1–alpha.7 plus the changes on `main` under
491
497
  `[Unreleased]`.
492
498
  - [docs/BENCHMARKS.md](https://github.com/ybotok/loam/blob/main/docs/BENCHMARKS.md) — what a
493
499
  fleet-sized run costs, with the method, the machine and the committed runs behind every number.
@@ -523,12 +529,12 @@ authored-capability axes with the `Realizes:` join, use cases graded as `dynamic
523
529
  `architecture/obligations.yaml` architectural obligations checked through `#obl-` tags and
524
530
  `Covers:`. Known limits, each with its owner in [ROADMAP.md](ROADMAP.md): the scheduled CI
525
531
  `stability` job has still to be observed green. Speculative `render`, health composition and UI
526
- generation come later. Behind that status stand **159 test files** (counted 2026-09-02): the count is graded
532
+ generation come later. Behind that status stand **174 test files** (counted 2026-09-07): the count is graded
527
533
  against a live readdir by `test/docs-facts.test.ts`, so this sentence fails the suite the moment it
528
534
  trails the tree.
529
535
 
530
536
  The package is published as [`@ybotok/loam`](https://www.npmjs.com/package/@ybotok/loam), currently
531
- `0.2.0-alpha.5`: the unscoped `loam` name is taken by an unrelated GDAL wrapper, so the package ships
537
+ `0.2.0-alpha.7`: the unscoped `loam` name is taken by an unrelated GDAL wrapper, so the package ships
532
538
  under the maintainer's own npm user scope. Releases are tag-driven and maintainer-only
533
539
  ([CONTRIBUTING.md](CONTRIBUTING.md)); the version this line names is pinned to `package.json` by a
534
540
  drift test, so it cannot silently trail a release.
package/ROADMAP.md CHANGED
@@ -18,19 +18,19 @@ acceptance tests, and implementation evidence remain ordinary files in repositor
18
18
  state inside a service. The CLI is small enough to audit, and every writer — not only archive — now
19
19
  commits through a locked, journaled transaction that a crash cannot leave half-applied.
20
20
 
21
- The tree contains **429 TypeScript modules in 130 source packages**, with an acyclic package graph
21
+ The tree contains **468 TypeScript modules in 144 source packages**, with an acyclic package graph
22
22
  checked by
23
23
  [scripts/package-graph.mjs](https://github.com/ybotok/loam/blob/main/scripts/package-graph.mjs). The
24
24
  CLI exposes **29 commands** from [src/cli.ts](https://github.com/ybotok/loam/blob/main/src/cli.ts),
25
- and the suite stands at **159 test files**. Those four counts are deliberately stated OUTSIDE the
25
+ and the suite stands at **174 test files**. Those four counts are deliberately stated OUTSIDE the
26
26
  dated snapshot below: each derives from the tree in one readdir, so
27
27
  [test/docs-facts.test.ts](https://github.com/ybotok/loam/blob/main/test/docs-facts.test.ts) grades
28
28
  them live and this paragraph cannot quietly trail the code the way its predecessor did.
29
29
 
30
- _Measured 2026-09-03 at `0.2.0-alpha.5`, and dated because neither number has a cheap derivation:_
30
+ _Measured 2026-09-07 at `0.2.0-alpha.7`, and dated because neither number has a cheap derivation:_
31
31
  lint, typecheck, `npm run arch:check` and `npm run meta:check` green; `npm test` passing
32
- **3,434/3,434 tests**, with two `skipIf(asRoot)` cases the root gate container cannot run; the
33
- coverage gate passing with **92.30% statements, 84.11% branches, 96.64% functions, and 94.24%
32
+ **3,802/3,802 tests**, with two `skipIf(asRoot)` cases the root gate container cannot run; the
33
+ coverage gate passing with **92.88% statements, 84.83% branches, 97.14% functions, and 94.70%
34
34
  lines** against its thresholds of 91 / 82 / 95 / 93; and `npm run release:check` plus
35
35
  `npm run test:package` green against the real tarball.
36
36
 
@@ -127,9 +127,219 @@ exactly the invented need the non-goals forbid.
127
127
  Closed since the 2026-08-18 assessment, each with the commit or commit range that landed it on
128
128
  `main`. [CHANGELOG.md](CHANGELOG.md) is the user-facing record; the full item texts — required
129
129
  changes, exit criteria, and what each review surfaced — are in this file's history (`git show
130
- 5cd3942:ROADMAP.md`). The three use-case entries below carry no range yet: they are green in the
131
- working tree and not committed, and the range goes in with the commit rather than being guessed at
132
- here.
130
+ 5cd3942:ROADMAP.md`). The four 2026-09-03 problem-report entries that follow — the extending model
131
+ and the report ordinal, which open the list — landed together in `f751909`, one change built as
132
+ four disjoint workstreams and gated as one; the three before them — the edgeless brief, the
133
+ intra-service use case, and the styling paragraph under the generated views — landed together in
134
+ `0eaa101` the same way.
135
+
136
+ #### One model, many documents — a service model may extend the fleet map
137
+
138
+ **Landed 2026-09-04** in `f751909`, from three problem reports that turned out to be one cause,
139
+ with a fourth landing beside it in the same change. #010 measured the cause: a service model must
140
+ parse alone, so it re-declares its own `specification` and every partner it names — 78 double
141
+ declarations in a 56-service fleet with four services adopted, projected to ~448 at full adoption —
142
+ and the copies had already diverged, `#platform` missing from every copy of the broker and the
143
+ identity provider but the map's, with no finding code for "two documents describe one element
144
+ differently" because no check read two documents together. #009 measured the symptom: 57 flat
145
+ entries in the renderer's project picker, 52 of them a single box, forced by the per-service
146
+ project file `0.2.0-alpha.5` had to write **because** the models could not share a project. #011 is
147
+ the structural proposal, every claim of it executed against copies of `examples/docs`: `extend`
148
+ resolves across documents of one project, a model rewritten that way makes its containers visible
149
+ in the fleet project with one copy of the broker in the whole model, and deleting a model's
150
+ `specification` under the old loader is eleven `c4.invalid` errors — so the change had to be
151
+ loam's, not a convention a repository could adopt. (#012, reports having no ordinal and loam never
152
+ reading `loam-reports/`, landed in the same commit and has its own entry below.)
153
+
154
+ **What landed.** The shape of a model is now read from the file's own grammar — a top-level
155
+ `specification { }` block containing an `element` declaration means STANDALONE, its absence means
156
+ EXTENDING — and each shape gets the grade the other cannot need: `c4.declaration-diverged` for a
157
+ standalone model whose copies of the map's elements disagree with it, `c4.element-unowned` for an
158
+ extending model that declares an element outside its own. Around them, the renderer wiring
159
+ `loam subsystem sync` now owns end to end (`service.likec4-config-stray`, `service.model-excluded`,
160
+ `service.model-unexcluded`, the narrowed `service.likec4-config-missing`, and the root project's
161
+ `exclude` rewritten to cover exactly the models that stand alone), and `c4.fleet-project-invalid`,
162
+ which loads the fleet project the way the renderer builds it and reports what only that load can
163
+ see. `examples/docs` is migrated whole, and its ten deliberate warnings are unchanged. CHANGELOG
164
+ has every code, key and message; SCHEMA's new "Two shapes of a service model" has the rules and the
165
+ migration recipe.
166
+
167
+ **Rejected, each with the reason.** Migrating repositories automatically — the recipe is documented
168
+ and an agent performs it, because a real model's comments are the team's and not loam's to reflow.
169
+ Making the shape a key in `loam.json` or `likec4.config.json` — the file's grammar already decides
170
+ how it can be read, and a key would be a second answer able to disagree with the first. Widening
171
+ loam's fleet map to the renderer's root project — the map is graded as `architecture/` alone so
172
+ that one broken service model cannot blank the fleet's own picture, which is why a cross-service
173
+ flow in `architecture/usecases/` still names service elements and never a container. Retiring the
174
+ standalone shape — it is what lets a service's docs be validated from the service's own repository,
175
+ and a fleet that wants that keeps it, now with a check on the divergence it costs.
176
+
177
+ **The deliberate remainder**, stated so nobody reads it as an oversight. A cross-service call still
178
+ exists TWICE: container-level in the model, service-level in the map (#011's item 6). The spine,
179
+ the platform census and every other fleet check read the map alone, and `landscape.service-isolated`
180
+ remains the nudge that carries an attested call up into it. Thinning the map to elements plus
181
+ cross-service edges is the [Later](#later--promote-only-from-evidence) "Landscape scaling" row, and
182
+ it is what would remove the duplication. Beside it sits #011's item 5, also deliberate: a
183
+ cross-service flow cannot name a container, because loam grades the fleet map as its own document
184
+ set. Revisit that one when a fleet asks for a cross-service flow whose hops are containers — the
185
+ renderer already resolves such a hop, so the ask will be concrete when it arrives.
186
+
187
+ **Verified 2026-09-04**, and three things the verification changed. The report's own "next thing to
188
+ check" was the one that did not compose: `loam archive` spliced a delta's nested additions into the
189
+ fleet map, and the extending model could then never declare them — the service went `c4.invalid`
190
+ (duplicate) the moment it wrote the container the adopt brief prescribed. The merge now ROUTES each
191
+ addition to the document that owns the interior, and proves the merged model parses beside the
192
+ merged map before writing either. Second, the consumer census read `architecture/` alone, so under
193
+ this shape a private store's consuming edges — which live in the models now — counted for nothing:
194
+ `landscape.datastore-private` went silent or named the wrong service, and a nested store two
195
+ services reach was graded nowhere. It reads every extending model's attested calls now, and
196
+ `landscape.datastore-shared` fires for a nested store. (That census still stands; the code named
197
+ here does not — `landscape.datastore-private` was retired on 2026-09-07, because where a store is
198
+ drawn is the team's choice. See the CHANGELOG entry.) Third, the wiring guard this entry landed
199
+ failed open on every root `exclude` spelling except `services/<tree>/**`, `loam subsystem sync`
200
+ never removed the stray per-service project file it told repositories to delete (and that file
201
+ CLAIMS the model, rather than holding nothing as the design note said), and
202
+ `c4.fleet-project-invalid` enumerated three roots rather than the renderer's — a `.likec4` in a
203
+ subsystem directory was in none of them. All three are closed; CHANGELOG's `[Unreleased]` has the
204
+ codes and keys.
205
+
206
+ **The `import` question is answered.** Reports #010 and #011 left open whether LikeC4's
207
+ cross-project `import` could have delivered this without merging the projects. Measured at the
208
+ 1.59.2 pin: an import resolves REFERENCES across projects, and that is all — it carries no
209
+ `specification`, so a kind or tag the other project declares is not usable in this one, and it does
210
+ not support `extend`. A model importing the map could name the map's elements and still not add a
211
+ container to one. So the choice was never between two mechanisms; one project holding both
212
+ documents is what the shape requires.
213
+
214
+ **Known and carried, 2026-09-04.** The second verification round reproduced these and they were
215
+ NOT fixed. Each is written down with the repro that finds it again, so nobody spends a second
216
+ afternoon rediscovering one. They are carried, not closed.
217
+
218
+ - **Only the basename `likec4.config.json` is surveyed.** LikeC4 1.59.2 also accepts `.likec4rc` and
219
+ six other spellings; drop `{"name":"svc-a"}` into `services/svc-a/.likec4rc` on a synced extending
220
+ fleet and `validate --all`, `doctor` and `subsystem sync` all stay green while the renderer loads
221
+ three projects and refuses without `--project`. Carried on scope: the survey, the stray grade and
222
+ `sync`'s delete list are one table, and widening it is the same change as the two rows below —
223
+ worth doing once, together, with the pin's whole name list measured rather than guessed.
224
+ - **A `likec4.config.json` in a SUBSYSTEM directory claims every model beneath it.** Write one at
225
+ `services/platform/likec4.config.json` over three extending models and all three go
226
+ `Could not resolve reference to Element named 'svc_svc_d'` in the renderer, while loam names
227
+ nothing (`sync` → "nothing to write"). Carried on scope, with the row above: the checks look one
228
+ directory deep, at a service, and seeing this needs a walk of the whole docs tree.
229
+ - **`sync` keeps a config beside a model that is GONE, and that leftover project is not harmless.**
230
+ `rm services/svc-c/model.likec4` with its config left behind: loam is green everywhere, and
231
+ `likec4 validate` — and `likec4 build` — at the docs root then need `--project`. The keep is
232
+ deliberate ("that one really is the team's"), but its premise, that an empty nested project is
233
+ invisible to the renderer, is false at the pin. Carried on a design decision pending: deleting a
234
+ file loam never wrote needs a rule about whose file it is, not a bug fix.
235
+ - **`validate --feature` does not preview a merge refusal.** A delta drawing a cross-interior edge,
236
+ or naming a kind the map does not declare, validates clean and then refuses at `archive`
237
+ (`merge-failed`, nothing written). Carried on scope: the preview needs the archive's own merge
238
+ planner run from the validate path, which is a new seam rather than a message.
239
+ - **In the STANDALONE shape a broken UNTAGGED sibling is invisible to loam.** Make one service
240
+ standalone, `subsystem sync`, then write an unresolvable `services/<id>/usecases/plain.likec4`:
241
+ loam prints `c4.valid` and 0 errors while `likec4 validate --project <id> .` is Invalid. The
242
+ extending shape catches the same file through `c4.fleet-project-invalid`. Carried on scope: the
243
+ per-service load reads the model, and reading the standalone project the renderer builds is a
244
+ second loader.
245
+ - **A root `exclude` that no longer covers `features/**` is silent.** Delete that one entry from
246
+ `examples/docs`' config: loam reports 0 errors and `sync` says "nothing to write", while the
247
+ renderer's fleet project is at 346 errors. The scaffold always writes the entry, so this is a
248
+ hand edit, which is why it is carried rather than fixed — on the evidence bar: no repository has
249
+ hit it, and a grade on an entry loam did not write is a policy claim.
250
+ - **A root config the renderer REJECTS is reported only by `sync`'s note.** `"exclude": "services/**"`
251
+ as a string, or an array-valued `include`, is "loaded 0 projects out of 1" — nothing renders — and
252
+ `validate --all` is green; an unparseable file is the same. Carried on scope: loam reads the file
253
+ for one key, and schema-validating somebody else's config is a dependency on the renderer's own
254
+ schema at the pin.
255
+ - **`LivingSlice.landscape.modelled` is `false` where `adopt` says `null`.** Over an
256
+ `architecture/` project that did not parse, `loam context <svc> --json` says `modelled: false` and
257
+ `loam adopt --service <svc> --json` says `modelled: null` about the same tree. Carried on scope:
258
+ the field is typed non-nullable in the pack, so agreeing with `adopt` is a contract change.
259
+ - **`loam show` never mentions graded intra-service flows.** With a healthy `#req-…`-tagged flow
260
+ beside an extending model — `validate --service` prints "· 1 tagged flow(s) graded" — neither
261
+ `loam show <svc>` nor its `--json` names it anywhere. Carried on scope: `show`'s payload is a
262
+ frozen shape and the flow needs a section of its own.
263
+ - **`loam status` never names the isolated state.** `landscape.service-isolated` is a warning
264
+ `validate --all` prints and `status`'s next-action ladder has no rung for. Carried on a design
265
+ decision pending: the ladder is derived from artifact presence and provenance, and a finding-derived
266
+ rung is a different rule for what `next[0]` means.
267
+ - **The first ever container-level flow a FEATURE brings.** A cross-service flow cannot name a
268
+ container, because loam grades the fleet map as its own document set; the renderer already resolves
269
+ such a hop. Carried deliberately — the [Later](#later--promote-only-from-evidence) "Landscape
270
+ scaling" row owns it, and it is promoted when a fleet asks, not before.
271
+
272
+ #### Problem reports carry an ordinal, and loam reads the directory it prescribes
273
+
274
+ **Landed 2026-09-04**, from one problem report (#012). The `loam-report` protocol prescribed a
275
+ directory, a filename shape and a document structure and then stopped: files were named
276
+ `YYYY-MM-DD-<slug>.md` with a numeric suffix only on collision — a collision breaker, not an
277
+ identifier — so in a directory of eleven reports written in two days, none had one, four shared
278
+ their first eleven characters, and the discriminating part of every name sat far to the right of
279
+ what a terminal, a file picker or a chat message shows. There was no field anywhere in the document
280
+ for the one piece of state a report has (three of the eleven were already closed and one superseded,
281
+ all of it living in whoever remembered), and `validate --all`, `doctor`, `status` and `list`
282
+ mentioned `loam-reports` zero times between them. Landed: an unconditional ordinal at the front of
283
+ the name, which is the computation the protocol already described for its suffix applied where it is
284
+ visible; a `Status:` line in the template with a four-value vocabulary a report closes by editing;
285
+ and `loam doctor` reading the directory — total, per-status counts and the next ordinal — as an
286
+ additive `reports` key and one human row. Rejected: a `loam report list` verb (a new command for a
287
+ count `doctor` was already the place for, on a frozen CLI surface); an index file (the workaround
288
+ this replaces — a second place to keep in step, and the reason the state left the files in the first
289
+ place); grading the corpus (an open report is not a defect in the repository holding it, so `doctor`
290
+ reports it as state and `healthy` never moves); parsing past the first word of the status line (the
291
+ rest is prose an author writes for a reader). Cost: one `readdir` and one small read per report on
292
+ every `loam doctor`, and nothing is transmitted — which is the constraint the protocol is built
293
+ around and the reason the whole fix needed no new state.
294
+
295
+ #### The adopt brief on an edgeless landscape element
296
+
297
+ **Landed 2026-09-03**, from one problem report. `loam adopt` decided whether the fleet map still
298
+ owed a service from element EXISTENCE: a bound element with no edge — what
299
+ `loam seed --from fleet.yaml` leaves for every service absent from `calls:` — read as
300
+ `landscape.instruction: null`, no target, `inbound: []`, `outbound: []` in one payload, so an agent
301
+ following the protocol to the letter wrote a validating baseline and never drew one edge, and
302
+ `loam validate --all` stayed green over it. Landed: a fourth landscape state carried by two
303
+ additive keys (`landscape.touched`, and `landscape.attested` — the calls the service's own
304
+ model.likec4 declares across its boundary, derived once in `core/c4/resolve/attested.ts` for the
305
+ brief and the fleet check alike, so the two can never name different edges); a non-null instruction
306
+ in two arms (carry each attested call up as one edge on the existing element, naming the other
307
+ party as the map spells it; or, with nothing attested, draw NOTHING rather than invent — an edgeless
308
+ element that is true is a fact); the landscape target back as an edge-only `edit` whose shape
309
+ refuses a second element; the `EDGELESS` flag in the text view; the evidence-gated
310
+ `landscape.service-isolated` warning under `--all`; and a seventeenth unchecked statement about
311
+ visibility (placeholder tags, curated views, `include *` over a boundary). Rejected: folding the
312
+ state into `landscape.modelled` (an agent told `false` draws a second box); an unconditional "no
313
+ edge touches it" warning (no correct fix for a worker that calls nothing, and every seeded fleet
314
+ red-ish until adoption); grading the SET DIFFERENCE between the attested calls and the drawn edges
315
+ (loam cannot tell a call the map forgot from one the fleet does not draw at its own altitude, so
316
+ the difference reported as an omission is an invented edge with a code beside it — the check stays
317
+ touched/untouched, and the brief says so out loud); a check on placeholder tags or on what a view
318
+ shows (rule 26 — loam never
319
+ computes what a view shows). Cost: one LikeC4 load of `model.likec4`, only in the edgeless state, a
320
+ memo hit under `--all`.
321
+
322
+ **Corrected 2026-09-04** by the verification of this entry: the brief read
323
+ `architecture/landscape.likec4` alone where the fleet check reads the whole `architecture/` project,
324
+ so a fleet keeping a second `model { }` block in a sibling got a brief demanding edges it had
325
+ already drawn while `validate --all` reported `landscape.matched`. Both now read the project.
326
+
327
+ #### A home for an intra-service use case
328
+
329
+ **Landed 2026-09-03.** Measured: `architecture/usecases/` cannot resolve a container (one such file
330
+ is `landscape.invalid` plus a `spine.landscape-invalid` per service), and a view beside the model
331
+ rendered while nothing graded it. Landed: the service's own LikeC4 project as the slot — every
332
+ `.likec4` beside model.likec4 and any tagged view inside it — graded by `validate --service`/`--all`
333
+ with the five existing `usecase.*` codes, `#req-` scoped by the service's own Requirement-IDs,
334
+ `#cap-` refused by placement, a broken sibling one `usecase.flow-invalid` while the model keeps
335
+ grading; plus the tier-2 skip and the fourth `step-unlinked` guard in the shared graders. Rejected:
336
+ a fixed `usecases/` directory alone (the reporter's `views.likec4` would render ungraded),
337
+ `views.likec4` alone (a second file would be invisible), a new code for the broken sibling (nothing
338
+ branches differently), gating the read on `likec4.config.json` (create-only, deletable). Cost: one
339
+ recursive readdir per service; a workspace only where a view in model.likec4 opts in or a sibling
340
+ mentions a reserved prefix anywhere in its bytes — an untagged sibling is never graded, and once
341
+ the workspace is loaded a project that does not read is one `usecase.flow-invalid` whether or not a
342
+ view opted in.
133
343
 
134
344
  #### The service model, renderable from the fleet root
135
345
 
@@ -177,6 +387,13 @@ that project (LikeC4 projects are separate models); and the project name is not
177
387
  billing-core, `service-fleet` beside `fleet`), disclosed in SCHEMA rather than escaped away,
178
388
  because the picker shows the id.
179
389
 
390
+ **Superseded for extending models, one day later.** The last of those costs — one picker entry per
391
+ adopted service — is what report #009 measured at 57 entries, and the entry that opens this list is
392
+ what removed its cause rather than its symptom: a model that extends the fleet map shares the root
393
+ project with it, so it is owed no project file and adds no entry, and `loam subsystem sync` writes
394
+ the file only for a model that stands alone. Everything measured here still holds for that shape,
395
+ and is why it is still supported; it is no longer what a new model is written as.
396
+
180
397
  #### The generated subsystem views — a label, a boundary, and one reader of the map
181
398
 
182
399
  **Landed 2026-09-03.** Three problem reports from a fleet running loam, one axis. The generated
@@ -197,6 +414,20 @@ use-case document binding one element could produce a `subsystem.views-stale` th
197
414
  `loam subsystem sync` reported as `current` — reproduced on `examples/docs`, and fixed by pointing
198
415
  both sides at the same read.
199
416
 
417
+ **And the repository's palette (2026-09-03).** A generated view can carry no inline `style` rule —
418
+ the file is regenerated wholesale — and the one mechanism LikeC4 gives a view for borrowing a
419
+ repository's styling is a reference to a global style by id, which is a parse error that blanks the
420
+ whole `architecture/` project when nothing declares it. So the convention is one reserved name:
421
+ declare `global { styleGroup subsystems { … } }` anywhere in the `architecture/` project and every
422
+ generated view references it; declare nothing and the file is what it was. Rejected: reading the id
423
+ off a key in `likec4.config.json` (create-only, never re-read, and not a LikeC4 document whose
424
+ contents a parse can check), and "reference the single declared group" (a second group declared for
425
+ a hand-drawn view would silently switch the generated views' styling off and restale the file on a
426
+ change that touched no subsystem). The presence read is a census of the keys of
427
+ `$data.globals.styles`, a declaration read like `specification`; seven tripwire assertions in
428
+ `test/likec4-view-shape.test.ts` pin the shape so a likec4 bump fails there before it reaches a
429
+ generated file.
430
+
200
431
  #### The deployment axis — topology joined to requirements
201
432
 
202
433
  **Promoted 2026-09-02, and authored as a feature in loam's own docs repo** rather than as an item
@@ -435,9 +666,52 @@ item gets promoted — it went from here to `## Now` and from there to
435
666
  for every fleet that never writes one. Promote only on evidence from a second fleet, after living
436
667
  with the disclosure — the first report classified itself `inconclusive`, and one fleet is not
437
668
  enough to qualify an invariant that says placement is never part of any identity.
438
- - **Landscape scaling:** retain one landscape while conflicts are exceptional. If same-service
439
- conflicts become routine — the current trigger in [SCHEMA.md](SCHEMA.md) is weekly rather than
440
- monthly — evaluate service-owned model files plus a thin global cross-service map. Migration must
669
+ - **A feature brings an intra-service flow.** `features/<FEAT>/specs/<svc>/usecases/<name>.likec4`,
670
+ copied create-only by `loam archive` into `services/<…>/<svc>/usecases/` and taken back by
671
+ `loam unarchive`, graded before the copy against the service's own LikeC4 project with the
672
+ feature's `specs/<svc>/` requirement deltas in `#req-` scope — `usecase.flow-exists` and
673
+ `usecase.flow-invalid` reused, never `--approve`-overridable. Deliberately NOT built with the
674
+ living slot (2026-09-03): the version-3 snapshot manifest already carries an artifact path with a
675
+ directory in it, so nothing about the undo changes when it lands, and no model delta exists to
676
+ preview — what it waits for is one fleet asking for a container-level flow to ship in the same
677
+ change as the `arch.spec.md` requirement it answers. Until then a service-local flow is written
678
+ directly into the service directory in the same pull request, where git produces the conflict;
679
+ building the feature route ahead of that evidence is the invented need the non-goals forbid.
680
+ - **A subsystem-scoped use-case slot.** A flow whose hops all sit inside one subsystem's subtree
681
+ looks like it wants a home between the two that exist — `architecture/usecases/` is the fleet's
682
+ slot, `services/<…>/<svc>/usecases/` is one service's. Deliberately NOT built (2026-09-07), and
683
+ the reason is that the capability is already there: a subsystem-scoped flow IS a fleet use case
684
+ whose hops happen to share a subtree, `architecture/usecases/<name>.likec4` already grades it, and
685
+ its view already folds into the same title-path folders as the generated subsystem view above it.
686
+ A second slot would duplicate the grader, the tag vocabulary and the archive route for no
687
+ capability that does not exist today. Promote only on evidence that a fleet's subsystem flows are
688
+ being lost among its fleet flows in the renderer's view list — which is a naming problem before it
689
+ is a slot problem, and one the title convention answers first.
690
+ - **A flow-untagged check** (it would be spelled usecase.flow-untagged): a `.likec4` beside a
691
+ service's model that mentions a `req-` prefix while no view in that project carries the tag — an
692
+ author who reached for the intra-service use-case axis and missed, whose flow renders and is
693
+ graded by nothing. It grades a view that EXISTS rather than an absence, so docs/DESIGN.md rule 26
694
+ permits it, unlike the service.usecases-missing nobody may ever build. Not built (2026-09-07) for
695
+ a mechanical reason worth stating: `core/brief/checks.ts` sits at 399 of 400 lines inside a
696
+ five-file-capped package, so a new non-ok code forces a split-module commit before any behaviour
697
+ can land, and that split should be chosen for a seam rather than for a code. Promote when a second
698
+ fleet reports a flow that rendered and was graded by nothing.
699
+ - **Landscape scaling:** retain one landscape while conflicts are exceptional, and half of what
700
+ this row once asked for arrived on 2026-09-04. Per-service internals now live in
701
+ `services/<svc>/model.likec4` by default: `loam archive` routes a delta's fqn-spelled interior
702
+ into the owning service's extending model, and a team adopting a service adds nothing to
703
+ `architecture/landscape.likec4` but one element and its cross-service edges. The map holds a
704
+ service's interior only where a team puts it on purpose — a store nested under its owner so a
705
+ second service can name it (SCHEMA's "Private stores") — or where a delta spells its parent by
706
+ title rather than by the map's id (the archive's documented remainder). What is
707
+ left is the CROSS-SERVICE EDGE, which still exists twice — container-level in the model,
708
+ service-level in the map — and that duplication is **deliberate**, not a leftover: the spine, the
709
+ platform census, `landscape.service-isolated` and every other fleet check read the map alone,
710
+ which is what lets a fleet answer "who calls this service" from one diffable document without
711
+ parsing sixty. Thinning the map to elements plus cross-service edges means teaching those checks
712
+ to read the edges out of the models that attest them, and paying the blast radius that comes with
713
+ it. If same-service conflicts become routine — the current trigger in [SCHEMA.md](SCHEMA.md) is
714
+ weekly rather than monthly — evaluate that. Migration must
441
715
  preserve archive/undo, deterministic resolution, and readable plain files.
442
716
  - **Authored business axis — PROMOTED 2026-08-27, and landed in full; see
443
717
  [Recently landed](#recently-landed).** The gate asked for evidence of authorship: analyst edits