@ybotok/loam 0.2.0-alpha.1 → 0.2.0-alpha.13
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.
- package/CHANGELOG.md +3448 -0
- package/COMPARISON.md +91 -3
- package/CONTRIBUTING.md +37 -0
- package/MIGRATING-from-OpenSpec.md +47 -23
- package/QUICKSTART.md +189 -12
- package/README.md +274 -65
- package/ROADMAP.md +572 -31
- package/SCHEMA.md +1709 -155
- package/WORKFLOW.md +298 -72
- package/dist/cli.js +26 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +5 -10
- package/dist/commands/adopt/adopt.js.map +1 -1
- package/dist/commands/adopt/render.js +50 -9
- package/dist/commands/adopt/render.js.map +1 -1
- package/dist/commands/archive/archive.js +16 -19
- package/dist/commands/archive/archive.js.map +1 -1
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +77 -43
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +21 -19
- package/dist/commands/archive/plan/gate.js.map +1 -1
- package/dist/commands/archive/plan/landscape.js +167 -30
- package/dist/commands/archive/plan/landscape.js.map +1 -1
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +14 -19
- package/dist/commands/archive/plan/refusal.js.map +1 -1
- package/dist/commands/archive/plan/specs.js +137 -56
- package/dist/commands/archive/plan/specs.js.map +1 -1
- package/dist/commands/archive/plan/state.js +3 -0
- package/dist/commands/archive/plan/state.js.map +1 -1
- package/dist/commands/archive/run.js +134 -30
- package/dist/commands/archive/run.js.map +1 -1
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +85 -18
- package/dist/commands/context/context.js.map +1 -1
- package/dist/commands/context/print.js +29 -7
- package/dist/commands/context/print.js.map +1 -1
- package/dist/commands/delta/delta.js +102 -14
- package/dist/commands/delta/delta.js.map +1 -1
- package/dist/commands/delta/print.js +17 -1
- package/dist/commands/delta/print.js.map +1 -1
- package/dist/commands/dependencies.js +3 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +20 -27
- package/dist/commands/diff/diff.js.map +1 -1
- package/dist/commands/doctor.js +60 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +89 -13
- package/dist/commands/explain/explain.js.map +1 -1
- package/dist/commands/explore.js +16 -10
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +45 -8
- package/dist/commands/gate/gate.js.map +1 -1
- package/dist/commands/gate/print.js +15 -3
- package/dist/commands/gate/print.js.map +1 -1
- package/dist/commands/gherkin/commit.js +13 -54
- package/dist/commands/gherkin/commit.js.map +1 -1
- package/dist/commands/gherkin/gherkin.js +36 -20
- package/dist/commands/gherkin/gherkin.js.map +1 -1
- package/dist/commands/gherkin/reconcile.js +10 -13
- package/dist/commands/gherkin/reconcile.js.map +1 -1
- package/dist/commands/init/first-hour.js +44 -0
- package/dist/commands/init/first-hour.js.map +1 -1
- package/dist/commands/init/init.js +18 -22
- package/dist/commands/init/init.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +4 -6
- package/dist/commands/list/campaign/campaign.js.map +1 -1
- package/dist/commands/list/json.js +5 -7
- package/dist/commands/list/json.js.map +1 -1
- package/dist/commands/list/list.js +44 -29
- package/dist/commands/list/list.js.map +1 -1
- package/dist/commands/list/print.js +52 -9
- package/dist/commands/list/print.js.map +1 -1
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +37 -34
- package/dist/commands/list/views.js.map +1 -1
- package/dist/commands/mcp/dispatch.js +91 -36
- package/dist/commands/mcp/dispatch.js.map +1 -1
- package/dist/commands/mcp/mcp.js +56 -15
- package/dist/commands/mcp/mcp.js.map +1 -1
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/active.js +27 -22
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/target.js +2 -2
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/error.js +7 -8
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +8 -22
- package/dist/commands/new/commit.js.map +1 -1
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +59 -14
- package/dist/commands/new/new.js.map +1 -1
- package/dist/commands/new/templates.js +48 -124
- package/dist/commands/new/templates.js.map +1 -1
- package/dist/commands/open.js +3 -7
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/policy/gate.js +27 -0
- package/dist/commands/policy/gate.js.map +1 -1
- package/dist/commands/rebase/plan.js +2 -2
- package/dist/commands/rebase/plan.js.map +1 -1
- package/dist/commands/rebase/rebase.js +60 -35
- package/dist/commands/rebase/rebase.js.map +1 -1
- package/dist/commands/seed/commit.js +55 -26
- package/dist/commands/seed/commit.js.map +1 -1
- package/dist/commands/seed/plan.js +158 -13
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/seed/seed.js +13 -11
- package/dist/commands/seed/seed.js.map +1 -1
- package/dist/commands/show/feature.js +9 -5
- package/dist/commands/show/feature.js.map +1 -1
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +35 -6
- package/dist/commands/show/marks.js.map +1 -1
- package/dist/commands/show/service.js +41 -33
- package/dist/commands/show/service.js.map +1 -1
- package/dist/commands/show/show.js +17 -7
- package/dist/commands/show/show.js.map +1 -1
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +2 -0
- package/dist/commands/status/json.js.map +1 -1
- package/dist/commands/status/print.js +89 -37
- package/dist/commands/status/print.js.map +1 -1
- package/dist/commands/status/status.js +3 -7
- package/dist/commands/status/status.js.map +1 -1
- package/dist/commands/steps/steps.js +103 -23
- package/dist/commands/steps/steps.js.map +1 -1
- package/dist/commands/subsystem/edit.js +7 -7
- package/dist/commands/subsystem/edit.js.map +1 -1
- package/dist/commands/subsystem/move.js +106 -46
- package/dist/commands/subsystem/move.js.map +1 -1
- package/dist/commands/subsystem/query.js +2 -4
- package/dist/commands/subsystem/query.js.map +1 -1
- package/dist/commands/subsystem/subsystem.js +4 -7
- package/dist/commands/subsystem/subsystem.js.map +1 -1
- package/dist/commands/subsystem/sync.js +289 -74
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +147 -45
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +200 -21
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +42 -26
- package/dist/commands/unarchive/manifest.js.map +1 -1
- package/dist/commands/unarchive/restore.js +83 -33
- package/dist/commands/unarchive/restore.js.map +1 -1
- package/dist/commands/unarchive/unarchive.js +22 -30
- package/dist/commands/unarchive/unarchive.js.map +1 -1
- package/dist/commands/validate/arch-coverage.js +78 -27
- package/dist/commands/validate/arch-coverage.js.map +1 -1
- package/dist/commands/validate/checks/fleet-shape.js +34 -126
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
- package/dist/commands/validate/checks/health-deps.js +9 -6
- package/dist/commands/validate/checks/health-deps.js.map +1 -1
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +18 -8
- package/dist/commands/validate/checks/requirements.js.map +1 -1
- package/dist/commands/validate/checks/sources.js +11 -2
- package/dist/commands/validate/checks/sources.js.map +1 -1
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +26 -20
- package/dist/commands/validate/feature.js.map +1 -1
- package/dist/commands/validate/fleet/census.js +37 -13
- package/dist/commands/validate/fleet/census.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +144 -126
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/load.js +66 -0
- package/dist/commands/validate/fleet/load.js.map +1 -1
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +44 -14
- package/dist/commands/validate/fleet/obligations.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/print.js +10 -2
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +50 -15
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +40 -47
- package/dist/commands/validate/fleet/views/stale.js.map +1 -1
- package/dist/commands/validate/links/corpus.js +1 -4
- package/dist/commands/validate/links/corpus.js.map +1 -1
- package/dist/commands/validate/links/glossary.js.map +1 -1
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +36 -160
- package/dist/commands/validate/report.js.map +1 -1
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +21 -107
- package/dist/commands/validate/service/api.js.map +1 -1
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +36 -14
- package/dist/commands/validate/service/events/events.js.map +1 -1
- package/dist/commands/validate/service/events/message-producers.js +1 -1
- package/dist/commands/validate/service/events/message-producers.js.map +1 -1
- package/dist/commands/validate/service/evidence-pins.js +56 -10
- package/dist/commands/validate/service/evidence-pins.js.map +1 -1
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +121 -61
- package/dist/commands/validate/service/service.js.map +1 -1
- package/dist/commands/validate/service/specs.js +88 -28
- package/dist/commands/validate/service/specs.js.map +1 -1
- package/dist/commands/validate/service/spine.js +38 -3
- package/dist/commands/validate/service/spine.js.map +1 -1
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +85 -60
- package/dist/commands/validate/validate.js.map +1 -1
- package/dist/commands/verify/cross/diff.js +2 -6
- package/dist/commands/verify/cross/diff.js.map +1 -1
- package/dist/commands/verify/evidence/contract.js +1 -1
- package/dist/commands/verify/evidence/contract.js.map +1 -1
- package/dist/commands/verify/evidence/read.js +12 -3
- package/dist/commands/verify/evidence/read.js.map +1 -1
- package/dist/commands/verify/frozen.js +45 -23
- package/dist/commands/verify/frozen.js.map +1 -1
- package/dist/commands/verify/record.js +69 -17
- package/dist/commands/verify/record.js.map +1 -1
- package/dist/commands/verify/report.js +27 -44
- package/dist/commands/verify/report.js.map +1 -1
- package/dist/commands/verify/results.js +112 -30
- package/dist/commands/verify/results.js.map +1 -1
- package/dist/commands/verify/verify.js +55 -52
- package/dist/commands/verify/verify.js.map +1 -1
- package/dist/commands/vouch/pack/pack.js +2 -2
- package/dist/commands/vouch/pack/pack.js.map +1 -1
- package/dist/commands/vouch/pack/print.js +1 -6
- package/dist/commands/vouch/pack/print.js.map +1 -1
- package/dist/commands/vouch/pack/sections.js +1 -2
- package/dist/commands/vouch/pack/sections.js.map +1 -1
- package/dist/commands/vouch/run.js +26 -81
- package/dist/commands/vouch/run.js.map +1 -1
- package/dist/commands/vouch/sample/plan.js +20 -34
- package/dist/commands/vouch/sample/plan.js.map +1 -1
- package/dist/commands/vouch/vet/verify.js +39 -7
- package/dist/commands/vouch/vet/verify.js.map +1 -1
- package/dist/commands/vouch/vouch.js +10 -17
- package/dist/commands/vouch/vouch.js.map +1 -1
- package/dist/core/agent/agents-md/command-map.js +81 -106
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/explain.js +21 -9
- package/dist/core/agent/agents-md/map/explain.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
- package/dist/core/agent/agents-md/map/mcp.js +10 -7
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
- package/dist/core/agent/agents-md/map/status.js +24 -8
- package/dist/core/agent/agents-md/map/status.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +80 -8
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md/map/usecases.js +88 -10
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
- package/dist/core/agent/agents-md/refusals.js +49 -22
- package/dist/core/agent/agents-md/refusals.js.map +1 -1
- package/dist/core/agent/agents-md.js +39 -6
- package/dist/core/agent/agents-md.js.map +1 -1
- package/dist/core/agent/agents-stamp.js +10 -0
- package/dist/core/agent/agents-stamp.js.map +1 -1
- package/dist/core/agent/protocol.js +1 -1
- package/dist/core/agent/protocol.js.map +1 -1
- package/dist/core/agent/scaffold.js +10 -15
- package/dist/core/agent/scaffold.js.map +1 -1
- package/dist/core/agent/support/report.js +46 -5
- package/dist/core/agent/support/report.js.map +1 -1
- package/dist/core/agent/tools/dialects.js +1 -0
- package/dist/core/agent/tools/dialects.js.map +1 -1
- package/dist/core/agent/tools/registry.js +41 -76
- package/dist/core/agent/tools/registry.js.map +1 -1
- package/dist/core/agent/workflows/adopt.js +158 -11
- package/dist/core/agent/workflows/adopt.js.map +1 -1
- package/dist/core/agent/workflows/check.js +78 -39
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/agent/workflows/closing.js +88 -27
- package/dist/core/agent/workflows/closing.js.map +1 -1
- package/dist/core/agent/workflows/feature.js +128 -13
- package/dist/core/agent/workflows/feature.js.map +1 -1
- package/dist/core/agent/workflows/implement.js +96 -13
- package/dist/core/agent/workflows/implement.js.map +1 -1
- package/dist/core/agent/workflows/reference/authoring.js +106 -4
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
- package/dist/core/agent/workflows/reference/codes.js +8 -6
- package/dist/core/agent/workflows/reference/codes.js.map +1 -1
- package/dist/core/agent/workflows/reference/done-check.js +37 -15
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +6 -3
- package/dist/core/agent/workflows/reference/reference.js.map +1 -1
- package/dist/core/agent/workflows/reference/spine.js +68 -27
- package/dist/core/agent/workflows/reference/spine.js.map +1 -1
- package/dist/core/asyncapi/baseline/plan.js +14 -81
- package/dist/core/asyncapi/baseline/plan.js.map +1 -1
- package/dist/core/asyncapi/digest.js +30 -25
- package/dist/core/asyncapi/digest.js.map +1 -1
- package/dist/core/asyncapi/merge/components.js +5 -4
- package/dist/core/asyncapi/merge/components.js.map +1 -1
- package/dist/core/asyncapi/merge/error.js +7 -2
- package/dist/core/asyncapi/merge/error.js.map +1 -1
- package/dist/core/asyncapi/merge/markers.js +32 -50
- package/dist/core/asyncapi/merge/markers.js.map +1 -1
- package/dist/core/asyncapi/merge/merge.js +33 -53
- package/dist/core/asyncapi/merge/merge.js.map +1 -1
- package/dist/core/asyncapi/merge/pin.js +12 -36
- package/dist/core/asyncapi/merge/pin.js.map +1 -1
- package/dist/core/asyncapi/model.js.map +1 -1
- package/dist/core/asyncapi/read.js +36 -12
- package/dist/core/asyncapi/read.js.map +1 -1
- package/dist/core/brief/brief.js +96 -36
- package/dist/core/brief/brief.js.map +1 -1
- package/dist/core/brief/checks.js +138 -3
- package/dist/core/brief/checks.js.map +1 -1
- package/dist/core/brief/landscape.js +209 -130
- package/dist/core/brief/landscape.js.map +1 -1
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +109 -31
- package/dist/core/brief/targets.js.map +1 -1
- package/dist/core/brief/unchecked.js +14 -3
- package/dist/core/brief/unchecked.js.map +1 -1
- package/dist/core/c4/arch.js +90 -182
- package/dist/core/c4/arch.js.map +1 -1
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +169 -14
- package/dist/core/c4/likec4.js.map +1 -1
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
- package/dist/core/c4/parsed/values.js +54 -1
- package/dist/core/c4/parsed/values.js.map +1 -1
- package/dist/core/c4/parsed/view-ids.js +39 -1
- package/dist/core/c4/parsed/view-ids.js.map +1 -1
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +123 -7
- package/dist/core/c4/project/architecture.js.map +1 -1
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +43 -12
- package/dist/core/c4/project/documents.js.map +1 -1
- package/dist/core/c4/project/load.js +79 -43
- package/dist/core/c4/project/load.js.map +1 -1
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +78 -17
- package/dist/core/c4/resolve/service.js.map +1 -1
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/template.js +65 -1
- package/dist/core/c4/seed/template.js.map +1 -1
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +297 -10
- package/dist/core/c4/source-mask.js.map +1 -1
- package/dist/core/c4/source-scan.js +222 -141
- package/dist/core/c4/source-scan.js.map +1 -1
- package/dist/core/c4/splice/authored-source.js +79 -13
- package/dist/core/c4/splice/authored-source.js.map +1 -1
- package/dist/core/c4/splice/contract.js +20 -0
- package/dist/core/c4/splice/contract.js.map +1 -1
- package/dist/core/c4/splice/delta-blocks.js +20 -20
- package/dist/core/c4/splice/delta-blocks.js.map +1 -1
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +37 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -1
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +182 -114
- package/dist/core/c4/splice/landscape-merge.js.map +1 -1
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +160 -56
- package/dist/core/c4/splice/placement.js.map +1 -1
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +13 -19
- package/dist/core/c4/workspace.js.map +1 -1
- package/dist/core/capabilities/capabilities.js +6 -6
- package/dist/core/capabilities/capabilities.js.map +1 -1
- package/dist/core/capabilities/delta/doc.js +7 -10
- package/dist/core/capabilities/delta/doc.js.map +1 -1
- package/dist/core/capabilities/delta/uncovered.js +2 -2
- package/dist/core/capabilities/delta/uncovered.js.map +1 -1
- package/dist/core/capabilities/findings.js +18 -22
- package/dist/core/capabilities/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/findings.js +12 -19
- package/dist/core/capabilities/realizes/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/join.js +0 -20
- package/dist/core/capabilities/realizes/join.js.map +1 -1
- package/dist/core/capabilities/rollup.js +6 -0
- package/dist/core/capabilities/rollup.js.map +1 -1
- package/dist/core/capabilities/tree.js +6 -28
- package/dist/core/capabilities/tree.js.map +1 -1
- package/dist/core/capabilities/usecase-join.js +3 -13
- package/dist/core/capabilities/usecase-join.js.map +1 -1
- package/dist/core/coherence/authoring/scaffold.js +11 -3
- package/dist/core/coherence/authoring/scaffold.js.map +1 -1
- package/dist/core/coherence/authoring/sentinels.js +2 -1
- package/dist/core/coherence/authoring/sentinels.js.map +1 -1
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +103 -22
- package/dist/core/coherence/coherence.js.map +1 -1
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +60 -34
- package/dist/core/coherence/declared.js.map +1 -1
- package/dist/core/coherence/events/declared.js +44 -59
- package/dist/core/coherence/events/declared.js.map +1 -1
- package/dist/core/coherence/events/events.js +147 -16
- package/dist/core/coherence/events/events.js.map +1 -1
- package/dist/core/coherence/events/grades.js +31 -8
- package/dist/core/coherence/events/grades.js.map +1 -1
- package/dist/core/coherence/events/lookups.js +28 -87
- package/dist/core/coherence/events/lookups.js.map +1 -1
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/lookups.js +18 -78
- package/dist/core/coherence/lookups.js.map +1 -1
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/delta.js +51 -6
- package/dist/core/delta/delta.js.map +1 -1
- package/dist/core/dependencies/fanin.js +2 -2
- package/dist/core/dependencies/fanin.js.map +1 -1
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +94 -12
- package/dist/core/diff/base-git.js.map +1 -1
- package/dist/core/diff/base-state.js +49 -21
- package/dist/core/diff/base-state.js.map +1 -1
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +22 -6
- package/dist/core/diff/scope/changed-paths.js.map +1 -1
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +100 -31
- package/dist/core/diff/semantic.js.map +1 -1
- package/dist/core/docs.js +31 -22
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +34 -18
- package/dist/core/doctor/agents.js.map +1 -1
- package/dist/core/doctor/config.js +7 -3
- package/dist/core/doctor/config.js.map +1 -1
- package/dist/core/doctor/doctor.js +91 -11
- package/dist/core/doctor/doctor.js.map +1 -1
- package/dist/core/doctor/report.js.map +1 -1
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/document/apply.js +158 -11
- package/dist/core/document/apply.js.map +1 -1
- package/dist/core/document/frontmatter.js +55 -0
- package/dist/core/document/frontmatter.js.map +1 -1
- package/dist/core/document/parse.js +29 -6
- package/dist/core/document/parse.js.map +1 -1
- package/dist/core/document/scenarios.js +17 -0
- package/dist/core/document/scenarios.js.map +1 -1
- package/dist/core/document/spec.js +4 -11
- package/dist/core/document/spec.js.map +1 -1
- package/dist/core/envelope/config.js +10 -0
- package/dist/core/envelope/config.js.map +1 -1
- package/dist/core/envelope/json.js +34 -0
- package/dist/core/envelope/json.js.map +1 -1
- package/dist/core/explain/families.js +26 -21
- package/dist/core/explain/families.js.map +1 -1
- package/dist/core/explain/lookup.js +14 -1
- package/dist/core/explain/lookup.js.map +1 -1
- package/dist/core/explain/refusals.js +5 -5
- package/dist/core/explain/refusals.js.map +1 -1
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +68 -109
- package/dist/core/explain/terms.js.map +1 -1
- package/dist/core/explore/explore.js +40 -10
- package/dist/core/explore/explore.js.map +1 -1
- package/dist/core/fleet-context.js +81 -95
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +11 -4
- package/dist/core/gate/checks.js.map +1 -1
- package/dist/core/gate/partners.js +69 -28
- package/dist/core/gate/partners.js.map +1 -1
- package/dist/core/gate/report.js.map +1 -1
- package/dist/core/gate/verification.js +75 -12
- package/dist/core/gate/verification.js.map +1 -1
- package/dist/core/gherkin/stale.js +13 -37
- package/dist/core/gherkin/stale.js.map +1 -1
- package/dist/core/glossary/delta.js +10 -7
- package/dist/core/glossary/delta.js.map +1 -1
- package/dist/core/glossary/tree.js +6 -19
- package/dist/core/glossary/tree.js.map +1 -1
- package/dist/core/kernel/concurrency.js +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -1
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/path-safety.js +38 -0
- package/dist/core/kernel/path-safety.js.map +1 -1
- package/dist/core/kernel/records.js +11 -0
- package/dist/core/kernel/records.js.map +1 -1
- package/dist/core/links/backlinks.js +1 -3
- package/dist/core/links/backlinks.js.map +1 -1
- package/dist/core/links/corpus.js +51 -37
- package/dist/core/links/corpus.js.map +1 -1
- package/dist/core/links/findings.js.map +1 -1
- package/dist/core/links/parse.js +38 -9
- package/dist/core/links/parse.js.map +1 -1
- package/dist/core/mcp/argv.js +101 -0
- package/dist/core/mcp/argv.js.map +1 -1
- package/dist/core/mcp/author-tools.js +2 -1
- package/dist/core/mcp/author-tools.js.map +1 -1
- package/dist/core/mcp/protocol.js +2 -2
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/mcp/tools.js +43 -33
- package/dist/core/mcp/tools.js.map +1 -1
- package/dist/core/openapi/baseline/gate.js +53 -12
- package/dist/core/openapi/baseline/gate.js.map +1 -1
- package/dist/core/openapi/baseline/plan.js +40 -10
- package/dist/core/openapi/baseline/plan.js.map +1 -1
- package/dist/core/openapi/baseline/record.js +0 -1
- package/dist/core/openapi/baseline/record.js.map +1 -1
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +38 -24
- package/dist/core/openapi/depth.js.map +1 -1
- package/dist/core/openapi/digest.js +52 -2
- package/dist/core/openapi/digest.js.map +1 -1
- package/dist/core/openapi/doc.js +12 -4
- package/dist/core/openapi/doc.js.map +1 -1
- package/dist/core/openapi/merge/components.js +25 -60
- package/dist/core/openapi/merge/components.js.map +1 -1
- package/dist/core/openapi/merge/error.js +3 -13
- package/dist/core/openapi/merge/error.js.map +1 -1
- package/dist/core/openapi/merge/markers.js +26 -30
- package/dist/core/openapi/merge/markers.js.map +1 -1
- package/dist/core/openapi/merge/merge.js +28 -52
- package/dist/core/openapi/merge/merge.js.map +1 -1
- package/dist/core/openapi/merge/pin.js +17 -35
- package/dist/core/openapi/merge/pin.js.map +1 -1
- package/dist/core/openspec/decide/verdict.js.map +1 -1
- package/dist/core/openspec/inventory.js +4 -5
- package/dist/core/openspec/inventory.js.map +1 -1
- package/dist/core/openspec/model/mapping.js +30 -28
- package/dist/core/openspec/model/mapping.js.map +1 -1
- package/dist/core/openspec/model/model.js +12 -7
- package/dist/core/openspec/model/model.js.map +1 -1
- package/dist/core/openspec/scan/changes.js +10 -4
- package/dist/core/openspec/scan/changes.js.map +1 -1
- package/dist/core/openspec/scan/config.js +7 -16
- package/dist/core/openspec/scan/config.js.map +1 -1
- package/dist/core/openspec/scan/shape.js +63 -19
- package/dist/core/openspec/scan/shape.js.map +1 -1
- package/dist/core/openspec/scan/walk.js +21 -38
- package/dist/core/openspec/scan/walk.js.map +1 -1
- package/dist/core/pack/living.js +43 -4
- package/dist/core/pack/living.js.map +1 -1
- package/dist/core/pack/pack.js +50 -6
- package/dist/core/pack/pack.js.map +1 -1
- package/dist/core/projection/arch-slice.js +2 -2
- package/dist/core/projection/arch-slice.js.map +1 -1
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +48 -12
- package/dist/core/provenance/findings.js.map +1 -1
- package/dist/core/provenance/git.js +33 -57
- package/dist/core/provenance/git.js.map +1 -1
- package/dist/core/provenance/gitq/moves.js +71 -114
- package/dist/core/provenance/gitq/moves.js.map +1 -1
- package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
- package/dist/core/provenance/sources.js +23 -6
- package/dist/core/provenance/sources.js.map +1 -1
- package/dist/core/provenance/stamp.js +5 -17
- package/dist/core/provenance/stamp.js.map +1 -1
- package/dist/core/repo/authored/paths.js +18 -0
- package/dist/core/repo/authored/paths.js.map +1 -1
- package/dist/core/repo/entries.js.map +1 -1
- package/dist/core/repo/paths.js +92 -6
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/repo.js +74 -14
- package/dist/core/repo/repo.js.map +1 -1
- package/dist/core/repo/tree/find.js +12 -3
- package/dist/core/repo/tree/find.js.map +1 -1
- package/dist/core/repo/tree/fs.js +27 -1
- package/dist/core/repo/tree/fs.js.map +1 -1
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +53 -32
- package/dist/core/repo/tree/walk.js.map +1 -1
- package/dist/core/results.js +47 -12
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +121 -13
- package/dist/core/scaffold/landscape.js.map +1 -1
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/staging/commit.js +26 -15
- package/dist/core/staging/commit.js.map +1 -1
- package/dist/core/staging/lock.js +74 -12
- package/dist/core/staging/lock.js.map +1 -1
- package/dist/core/staging/recovery/intent.js +2 -5
- package/dist/core/staging/recovery/intent.js.map +1 -1
- package/dist/core/staging/recovery/recover.js +84 -6
- package/dist/core/staging/recovery/recover.js.map +1 -1
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +24 -14
- package/dist/core/staging/txn/forward.js.map +1 -1
- package/dist/core/staging/writes.js.map +1 -1
- package/dist/core/status/actions/execution.js +11 -0
- package/dist/core/status/actions/execution.js.map +1 -1
- package/dist/core/status/contracts.js +39 -15
- package/dist/core/status/contracts.js.map +1 -1
- package/dist/core/status/feature/artifacts.js +33 -8
- package/dist/core/status/feature/artifacts.js.map +1 -1
- package/dist/core/status/feature/feature.js +24 -17
- package/dist/core/status/feature/feature.js.map +1 -1
- package/dist/core/status/feature/next.js +20 -7
- package/dist/core/status/feature/next.js.map +1 -1
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +43 -14
- package/dist/core/status/fleet/fleet.js.map +1 -1
- package/dist/core/status/fleet/next.js +153 -58
- package/dist/core/status/fleet/next.js.map +1 -1
- package/dist/core/status/report.js.map +1 -1
- package/dist/core/status/scan.js.map +1 -1
- package/dist/core/status/verification.js +30 -15
- package/dist/core/status/verification.js.map +1 -1
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +11 -14
- package/dist/core/usecases/capability.js.map +1 -1
- package/dist/core/usecases/delta/claims.js +31 -7
- package/dist/core/usecases/delta/claims.js.map +1 -1
- package/dist/core/usecases/delta/flows.js +5 -7
- package/dist/core/usecases/delta/flows.js.map +1 -1
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +32 -191
- package/dist/core/usecases/delta/overlay.js.map +1 -1
- package/dist/core/usecases/fleet.js +195 -36
- package/dist/core/usecases/fleet.js.map +1 -1
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +26 -14
- package/dist/core/usecases/operations.js.map +1 -1
- package/dist/core/usecases/place.js.map +1 -1
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/verify/answers.js +12 -5
- package/dist/core/verify/answers.js.map +1 -1
- package/dist/core/verify/build.js +102 -82
- package/dist/core/verify/build.js.map +1 -1
- package/dist/core/verify/checklist.js +70 -12
- package/dist/core/verify/checklist.js.map +1 -1
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +3 -2
- package/dist/core/verify/pins/lint.js.map +1 -1
- package/dist/core/verify/pins/pin.js +1 -1
- package/dist/core/verify/pins/pin.js.map +1 -1
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/{file.js → read/shape.js} +16 -104
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +35 -12
- package/dist/core/verify/record.js.map +1 -1
- package/dist/core/verify/store/commit.js +40 -30
- package/dist/core/verify/store/commit.js.map +1 -1
- package/dist/core/verify/store/render.js +8 -4
- package/dist/core/verify/store/render.js.map +1 -1
- package/dist/core/vocabulary/issue.js +4 -0
- package/dist/core/vocabulary/issue.js.map +1 -1
- package/dist/core/vocabulary/maturity.js +75 -4
- package/dist/core/vocabulary/maturity.js.map +1 -1
- package/dist/core/vocabulary/report.js +16 -1
- package/dist/core/vocabulary/report.js.map +1 -1
- package/examples/README.md +54 -11
- package/examples/docs/architecture/landscape.likec4 +62 -6
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +7 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
- package/examples/docs/likec4.config.json +0 -1
- package/examples/docs/services/checkout-web/model.likec4 +39 -56
- package/examples/docs/services/order-service/arch.spec.md +13 -6
- package/examples/docs/services/order-service/asyncapi.yaml +3 -2
- package/examples/docs/services/order-service/model.likec4 +58 -70
- package/examples/docs/services/payment-service/arch.spec.md +7 -4
- package/examples/docs/services/payment-service/model.likec4 +38 -37
- package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
- package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
- package/examples/docs/services/platform/notification-service/health.yaml +8 -3
- package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
- package/package.json +1 -1
- package/dist/commands/validate/checks/vocabulary.js +0 -31
- package/dist/commands/validate/checks/vocabulary.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
- package/dist/core/agent/agents-md/artifacts.js +0 -220
- package/dist/core/agent/agents-md/artifacts.js.map +0 -1
- package/dist/core/agent/agents-md/cycle.js +0 -165
- package/dist/core/agent/agents-md/cycle.js.map +0 -1
- package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
- package/dist/core/agent/agents-md/spine.js +0 -40
- package/dist/core/agent/agents-md/spine.js.map +0 -1
- package/dist/core/coherence/events/merged.js +0 -40
- package/dist/core/coherence/events/merged.js.map +0 -1
- package/dist/core/diff/current-state.js +0 -96
- package/dist/core/diff/current-state.js.map +0 -1
- package/dist/core/diff/victims.js +0 -247
- package/dist/core/diff/victims.js.map +0 -1
- package/dist/core/repo/tree/views.js +0 -172
- package/dist/core/repo/tree/views.js.map +0 -1
- package/dist/core/staging/snapshot.js.map +0 -1
- package/dist/core/verify/file.js.map +0 -1
package/WORKFLOW.md
CHANGED
|
@@ -19,7 +19,7 @@ that order.
|
|
|
19
19
|
[Why there is no task list](#why-there-is-no-task-list)
|
|
20
20
|
- [Picking the work back up](#picking-the-work-back-up)
|
|
21
21
|
- [Day zero: onboarding a fleet](#day-zero-onboarding-a-fleet) · [Command notes](#command-notes) ·
|
|
22
|
-
[The MCP server](#the-mcp-server)
|
|
22
|
+
[The MCP server](#the-mcp-server) · [Build on the envelope](#build-on-the-envelope)
|
|
23
23
|
|
|
24
24
|
## The two flows
|
|
25
25
|
|
|
@@ -97,7 +97,10 @@ no fleet manifest, deliberately — the wiring is one file per repo, and it is r
|
|
|
97
97
|
entry, in one journaled transaction, and guesses nothing: a human stated every fact in the file,
|
|
98
98
|
which is what keeps seed on the same side of the no-extractor line as `loam new`. Re-running is
|
|
99
99
|
safe — once the landscape has been hand-edited, seed refuses (`seed-landscape-edited`) rather
|
|
100
|
-
than overwrite it.
|
|
100
|
+
than overwrite it. That makes seed a day-zero step: list every service id you already know in
|
|
101
|
+
`fleet.yaml` up front, because the first `metadata { op }` below has no spelling in
|
|
102
|
+
`fleet.yaml`. From then on the map grows without seed — `loam adopt --service <id>` briefs the
|
|
103
|
+
element and edges a new service adds, and a feature's C4 delta carries every other change.
|
|
101
104
|
|
|
102
105
|
Drawing it by hand instead is entirely legal, and the landscape is a **required** artifact
|
|
103
106
|
either way, not an optional one: `loam validate --all` reports `landscape.missing` as an error
|
|
@@ -113,11 +116,13 @@ no fleet manifest, deliberately — the wiring is one file per repo, and it is r
|
|
|
113
116
|
repo:
|
|
114
117
|
|
|
115
118
|
```bash
|
|
116
|
-
loam init --docs ../docs-repo --service payment-service # no --create: it JOINS
|
|
117
|
-
loam doctor
|
|
119
|
+
loam init --docs ../docs-repo --service payment-service --agent-profile service # no --create: it JOINS
|
|
120
|
+
loam doctor # confirms the wiring
|
|
118
121
|
```
|
|
119
122
|
|
|
120
|
-
`--service`
|
|
123
|
+
`--agent-profile service` writes the five workflows that run beside the code. Without it the
|
|
124
|
+
profile is `full`, which also writes `loam-feature` and `loam-ship` — the two workflows the docs
|
|
125
|
+
repo keeps — into the service checkout. `--service` is the binding: without it `loam vouch` and `loam gherkin` refuse outright, and
|
|
121
126
|
`loam verify --service --record` / `--results` refuse to attest, because none of them will write
|
|
122
127
|
a service's documents from a repo that has not said which service it is. Reading —
|
|
123
128
|
`loam verify --service` on its own — needs no binding, because it writes nothing. Commit the
|
|
@@ -137,7 +142,8 @@ no fleet manifest, deliberately — the wiring is one file per repo, and it is r
|
|
|
137
142
|
stamping the source and content digests that make later staleness detectable. `loam list --json`
|
|
138
143
|
in the docs repo then grades the whole fleet on the presence ladder
|
|
139
144
|
`empty → partial → documented → sourced → vouched`, and `loam list --needs-work` is the remaining
|
|
140
|
-
worklist
|
|
145
|
+
worklist — including any vouched service whose spec moved after the vouch (`vouched (stale)`,
|
|
146
|
+
missing a re-vouch), which `loam status` names as `next.revouch`.
|
|
141
147
|
|
|
142
148
|
Steps 3–6 repeat per service and are independent — no ordering, no lock, no shared state between two
|
|
143
149
|
services' runs — so ten services can be onboarded by ten people in parallel. The one file they all
|
|
@@ -155,9 +161,9 @@ configurable graph, because a governed system needs one lifecycle and one meanin
|
|
|
155
161
|
| `delta.likec4` | feature | no | New elements and edges, each tagged with the feature id. The design. A requirements-only change deletes it |
|
|
156
162
|
| `specs/<svc>/spec.md` | service | yes | The behaviour delta — `ADDED` / `MODIFIED` / `REMOVED` requirements, each with Given/When/Then scenarios |
|
|
157
163
|
| `specs/<svc>/arch.spec.md` | service | no | The architectural obligations a business spec never mentions: outbox, retries, idempotency, alerts. Same grammar, plus `Covers:` lines tying each to the C4 elements it accounts for |
|
|
158
|
-
| `specs/<svc>/openapi.yaml` | service | conditional | The contract delta.
|
|
159
|
-
| `specs/<svc>/asyncapi.yaml` | service | no | The event-contract delta:
|
|
160
|
-
| `verification
|
|
164
|
+
| `specs/<svc>/openapi.yaml` | service | conditional | The contract delta: only the operations the feature adds, changes or removes — an operation it leaves out stays as the living contract has it. Owed when the living docs hold no contract for the service and something the feature writes joins into one — an `Operations:` line, or a tagged edge calling an operation on it — the same evidence `service.no-openapi` reads once the service is living. A service nothing calls owes none, whether the feature introduces it or it is already adopted |
|
|
165
|
+
| `specs/<svc>/asyncapi.yaml` | service | no | The event-contract delta: an AsyncAPI 3.0 document holding only the slots the feature adds, changes or removes. `loam rebase` pins each one the living contract already has (`x-loam-based-on`), `x-loam-remove: true` retires one |
|
|
166
|
+
| `verification/<svc>.yaml` | feature | yes | The done-check record, one file per attesting service: every claim, its answer, its evidence, and who gave it. The all-at-once form writes the one file `verification.yaml` instead |
|
|
161
167
|
|
|
162
168
|
Two fleet/living axes sit beside this feature graph. `services/<svc>/asyncapi.yaml` joins
|
|
163
169
|
`publishes`/`consumes` edges to `Publishes:`/`Consumes:` requirements, and the event axis carries
|
|
@@ -175,7 +181,7 @@ present and fine. Marking everything required is how an axis that is optional ev
|
|
|
175
181
|
reported as missing everywhere and then ignored.
|
|
176
182
|
|
|
177
183
|
**Dependencies are enablers, not gates — with one real exception.** You can author these in any
|
|
178
|
-
order.
|
|
184
|
+
order. The verification record is the exception, and it is a genuine impossibility rather than a
|
|
179
185
|
preference: its checklist is *derived* from the delta and the per-service specs, so with none of
|
|
180
186
|
them written there is no question set to answer. That artifact alone comes back `blocked`, naming
|
|
181
187
|
what it is waiting on.
|
|
@@ -265,16 +271,39 @@ runs already recorded (the join partners' documentation state, staleness, the ve
|
|
|
265
271
|
of the features touching the service, an interrupted docs commit). Its verdict is advice to a
|
|
266
272
|
pipeline loam does not own — advisory by default, `--strict` the per-invocation CI lever — and it
|
|
267
273
|
deliberately changes nothing about what gates the archive: verify still never gates the merge, and
|
|
268
|
-
archive still reads no verification record.
|
|
274
|
+
archive still reads no verification record. Know what `--strict` buys before wiring it: its
|
|
275
|
+
freshness check reads `content.stale` over the gated service **and every documented join partner**,
|
|
276
|
+
so one partner whose spec moved under its vouch — every archive into a vouched spec does that —
|
|
277
|
+
turns this service's `gate --strict` red until that partner's owner re-vouches from their own repo.
|
|
278
|
+
That is the question asked honestly (a deploy joins documents nobody has re-read), but it is
|
|
279
|
+
another team's queue: a pipeline that must not wait on it runs `gate` without `--strict` and
|
|
280
|
+
branches on the `content.stale` findings in `checks[]` itself.
|
|
281
|
+
|
|
282
|
+
Which features it grades is the one thing a pipeline has to say. Without `--since`, the gate reads
|
|
283
|
+
**in-flight features only**: a feature leaves the check the moment it is archived, so a slice that
|
|
284
|
+
deploys after its feature shipped is gated without it — and under `--strict`, archiving would be
|
|
285
|
+
the cheapest way past an unverified-feature warning. `loam gate --since <ref>` closes that: pass
|
|
286
|
+
the docs-repo commit your last deploy recorded, and every feature archived after it (its
|
|
287
|
+
`features/archive/<FEAT>/` directory absent at the ref, or changed since — a feature unarchived,
|
|
288
|
+
edited and archived again ships again) that touches the service is graded too, under the same
|
|
289
|
+
`gate.feature-unverified`, its `features[]` row carrying `archived: true`. Its record is frozen, but
|
|
290
|
+
held to the checklist `loam archive` captured as the feature merged (`checklistAtArchive` on the
|
|
291
|
+
row): a record that had stopped answering the feature before it shipped reads `stale`, so archiving
|
|
292
|
+
is no longer a way past the warning. A feature archived by a loam that captured no checklist is read
|
|
293
|
+
as frozen history, and the row says so (`checklistAtArchive: null`). The ref is
|
|
294
|
+
read from the docs repo's own git exactly as `loam diff --base` reads its base, with the same
|
|
295
|
+
refusals when git cannot answer. loam stores nothing for it — the pipeline already knows which docs
|
|
296
|
+
commit it deployed from.
|
|
269
297
|
|
|
270
298
|
**`loam diff` does not add one either — it is the review lens.** On a docs-repo PR,
|
|
271
299
|
`loam diff --base origin/main` says what the branch *changes* in fleet-meaningful terms: services,
|
|
272
300
|
requirements (by identity and content digest, so a rebase pin is not a change), operations,
|
|
273
|
-
messages, and the cross-service joins between them — with the
|
|
274
|
-
named, which is what a reviewer actually needs to know.
|
|
275
|
-
diff exits 1 on a removal the fleet still consumes
|
|
276
|
-
`diff.message-removed-consumed`) — and also whenever a document on
|
|
277
|
-
because a suspended axis is reported, never graded as "nothing
|
|
301
|
+
messages, and the cross-service joins between them — with the authored consumers of every removal,
|
|
302
|
+
deprecation and contract modification named, which is what a reviewer actually needs to know.
|
|
303
|
+
`validate --all` remains the fleet gate; diff exits 1 on a removal the fleet still consumes
|
|
304
|
+
(`diff.op-removed-consumed`, `diff.message-removed-consumed`) — and also whenever a document on
|
|
305
|
+
either side could not be read, because a suspended axis is reported, never graded as "nothing
|
|
306
|
+
changed" — so a PR job gets those
|
|
278
307
|
checks for free, but a green diff is not a valid fleet: run both. For the byte-level OpenAPI
|
|
279
308
|
breaking-change catalogue, use oasdiff on the two states of one contract; [the `loam diff` command
|
|
280
309
|
note](#command-notes) below has the exact invocation, and loam deliberately does not reimplement
|
|
@@ -312,16 +341,18 @@ repository, while the runtime page cannot go out of date the same way.
|
|
|
312
341
|
|
|
313
342
|
`AGENTS.md` — the one file `init` lays down that every host auto-loads, and so the first thing an
|
|
314
343
|
agent reads — now works the same way, which changes the reading order. It is orientation only (the
|
|
315
|
-
layout, the cycle, what gates and what only advises,
|
|
316
|
-
four **reference pages** it used to carry inline come
|
|
317
|
-
arises: `loam instructions loam-codes`, `loam-spine`,
|
|
318
|
-
taking no arguments and printing whole, listed beside
|
|
319
|
-
|
|
344
|
+
layout, the cycle, what gates and what only advises, held under a 12,000-byte ceiling a test enforces
|
|
345
|
+
where it used to be 109,399 bytes), and the four **reference pages** it used to carry inline come
|
|
346
|
+
out of the binary at the moment the question arises: `loam instructions loam-codes`, `loam-spine`,
|
|
347
|
+
`loam-authoring` and `loam-done-check`, each taking no arguments and printing whole, listed beside
|
|
348
|
+
the six workflows by a bare `loam instructions`. A fifth reference page, `loam-drawing`, was never
|
|
349
|
+
part of `AGENTS.md`: read it before drawing an edge or a view, for the relationship kinds, the
|
|
350
|
+
legend and the overview views a person can read. `init` writes no file for any of them, so nothing new landed in the repo.
|
|
320
351
|
|
|
321
352
|
| Workflow | When | What it drives |
|
|
322
353
|
|---|---|---|
|
|
323
354
|
| `loam-adopt` | Once per service, before any feature touches it | `loam adopt` briefs the baseline; an agent reads the code and writes it as `draft`; validate twice — the service, then the fleet — and hand to a human to vouch |
|
|
324
|
-
| `loam-feature` | Starting a change | `loam explore` to decide what it touches, `loam new` to scaffold, author the delta and the specs, `loam rebase` to pin, `loam validate`, `loam dependencies` |
|
|
355
|
+
| `loam-feature` | Starting a change — after asking whether it needs a feature at all (step 0) | `loam explore` to decide what it touches, `loam new` to scaffold, author the delta and the specs, write what they leave open under `## Open questions` in `intent.md` (ungraded), `loam rebase` to pin, `loam validate`, `loam dependencies` |
|
|
325
356
|
| `loam-implement` | Building one service's slice, in that service's repo | `loam delta` is the task, `loam gherkin` emits the acceptance criteria, step definitions come before code |
|
|
326
357
|
| `loam-check` | Any time; always before shipping | `loam validate`, and fixing what it reports by code |
|
|
327
358
|
| `loam-verify` | When the code is built | `loam verify` derives the checklist; the test runner answers what it can; you answer the rest with evidence |
|
|
@@ -336,7 +367,12 @@ following it behaves unexpectedly. Its version-matched body comes from
|
|
|
336
367
|
|
|
337
368
|
The agent preserves the original symptom before investigating, collects the binary version,
|
|
338
369
|
`doctor --json`, relevant `status --json` and the smallest safe reproduction, then writes
|
|
339
|
-
`loam-reports/YYYY-MM-DD-<slug>.md
|
|
370
|
+
`loam-reports/NNN-YYYY-MM-DD-<slug>.md` — `NNN` the next ordinal, at least three digits and
|
|
371
|
+
zero-padded, which `loam doctor` reports, and a
|
|
372
|
+
`Status: open` header line the team later edits to `sent`, `fixed in <version>` or
|
|
373
|
+
`superseded by <NNN>`. `doctor` reads that line from the header field block above the first `##`
|
|
374
|
+
heading, so a report quoting the protocol's template counts as whatever its own header says. It
|
|
375
|
+
classifies the evidence as a loam defect, project-data
|
|
340
376
|
problem, agent-workflow problem, host/infrastructure problem or inconclusive. A report contains
|
|
341
377
|
stable envelope/finding codes and short relevant excerpts, not a full environment or document
|
|
342
378
|
dump. Secrets and home paths are redacted. A writer is never repeated just to reproduce a failure,
|
|
@@ -366,6 +402,22 @@ this command just makes sure you are weighing all of it.
|
|
|
366
402
|
|
|
367
403
|
### The honestly-small change
|
|
368
404
|
|
|
405
|
+
**The smallest change needs no feature at all.** A change that touches no requirement, no operation
|
|
406
|
+
and no fleet edge — a refactor, a dependency bump, a fix that brings the code back to behaviour the
|
|
407
|
+
living spec already documents — changes nothing in the docs repo, so there is nothing to scaffold,
|
|
408
|
+
pin or archive. It is a code PR in the service repo, and then, in that repo:
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
loam validate --service payment-service # the only place sources.stale is visible
|
|
412
|
+
loam vouch --pack --service payment-service # read-only: what the moved sources owe a re-read
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
`sources.stale` names the paths that moved since the spec was last vouched, the pack is the reading
|
|
416
|
+
list, and the vouch itself is a person's. That is lighter than a feature by construction rather than
|
|
417
|
+
by exemption: there is no delta for a gate to grade, and the one signal that did move — the vouch —
|
|
418
|
+
is still owed. The moment the change alters what a requirement promises, it is a feature, however
|
|
419
|
+
small, and the lane below is the floor. `loam-feature`'s step 0 asks the same question first.
|
|
420
|
+
|
|
369
421
|
Most changes are not cross-service features. A one-service, requirements-only change — a new
|
|
370
422
|
refusal, a tightened invariant, behaviour behind an endpoint that already exists — walks the same
|
|
371
423
|
graph with most of it not owed, and the tooling already says so. The whole loop:
|
|
@@ -400,15 +452,15 @@ Every command takes `--json`, and the contract is built so an agent never has to
|
|
|
400
452
|
- **Findings carry stable codes** — `c4.valid`, `spine.op-undefined`, `coherence.ok`. Branch on the
|
|
401
453
|
code. Prose gets reworded; codes do not.
|
|
402
454
|
- **The protocol has a narrowed form, and one code is answerable as data** —
|
|
403
|
-
`loam instructions loam-check` is
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
455
|
+
`loam instructions loam-check` is almost all per-code fix tables, and `--no-fix-tables` prints the
|
|
456
|
+
same page in a few kilobytes with each table's scope paragraph kept. Branch on the code, then
|
|
457
|
+
`loam explain <code> --json` for the two or three a run reported, or `loam explain --codes --json`
|
|
458
|
+
once for the whole vocabulary — every finding and refusal code `loam explain` answers. The four
|
|
459
|
+
families no fix table grades (`doctor.*`, `next.*`, `diff.*`, `gate.*`) are among them, so a code
|
|
460
|
+
read out of a `status`, `doctor`, `diff` or `gate` payload is answerable as data like any other;
|
|
461
|
+
the codes that are not are the OpenSpec migration surface (`openspec.*`, `mapping.*`), which an
|
|
462
|
+
agent meets once before the repository is governed at all, and a couple of `ok`-severity
|
|
463
|
+
confirmations.
|
|
412
464
|
- **`validate --json` already carries the fix for every code it raised** — `fixes` is a map keyed by
|
|
413
465
|
code, so joining `findings[].code` to `fixes[code]` answers "what now" out of the payload you are
|
|
414
466
|
holding: no `loam explain` round trip per code, and no fix table loaded into context to read one.
|
|
@@ -429,7 +481,12 @@ Every command takes `--json`, and the contract is built so an agent never has to
|
|
|
429
481
|
that service's repository: the living requirements verbatim, both contracts, the fleet edges one
|
|
430
482
|
hop out, the permission and capability joins, and every feature in flight over the service — one
|
|
431
483
|
deterministic payload, so two runs over the same state are byte-diffable. `--feature <FEAT>`
|
|
432
|
-
narrows the in-flight section to the feature being implemented.
|
|
484
|
+
narrows the in-flight section to the feature being implemented. Its `landscape` object carries
|
|
485
|
+
`broken` beside `parses` — the `architecture/` documents that failed, docs-relative POSIX, deduped
|
|
486
|
+
and sorted, `[]` while `parses` is true — spelled exactly as `landscape.invalid` and the adopt
|
|
487
|
+
brief spell them. `parses` answers for the `architecture/` PROJECT, so the document at fault is
|
|
488
|
+
very often a sibling beside a landscape that reads perfectly, which is why the key exists.
|
|
489
|
+
`loam explore --json` carries the same key with the same meaning.
|
|
433
490
|
- **`loam show <FEAT> --json` is the review hand-off.** Its `review` object joins the intent summary,
|
|
434
491
|
exact C4 objects, API/event slices, dependencies, artifact states, verification, blockers,
|
|
435
492
|
advisories, use cases and executable next actions without making the reviewer reopen each file.
|
|
@@ -471,10 +528,13 @@ A task list authored beside a spec is a second mutable state. It drifts — the
|
|
|
471
528
|
checklist does not, and now two documents describe the work and only one of them is checked. The
|
|
472
529
|
question a task list answers is a good one; the file is the wrong place to answer it.
|
|
473
530
|
|
|
474
|
-
loam derives the answer instead, at
|
|
531
|
+
loam derives the answer instead, at three altitudes:
|
|
475
532
|
|
|
476
533
|
- **What to do next**, from `loam status`: the artifact table plus an ordered `next[]`, recomputed
|
|
477
534
|
every run, so it cannot disagree with the files.
|
|
535
|
+
- **Which promise to pick up, and what closes it**, from `loam tasks <FEAT>`: one unit per promise
|
|
536
|
+
the feature makes, each carrying the step it is waiting on and the fact that retires it. `--next`
|
|
537
|
+
narrows it to the single leaf packet an orchestrator hands one coding agent.
|
|
478
538
|
- **What to build**, from `loam delta <FEAT> --service <svc>`: the intent, every requirement body
|
|
479
539
|
and every Given/When/Then line reproduced verbatim, the endpoints added or retired, and the edges
|
|
480
540
|
around it. That output *is* the coding task, and it is regenerated from the spec each time rather
|
|
@@ -491,6 +551,15 @@ input — a human's statement of the problem, which nothing can derive. The desi
|
|
|
491
551
|
operations against the contracts. A prose design document beside those would be a third description
|
|
492
552
|
of the same change, and the only one nothing grades.
|
|
493
553
|
|
|
554
|
+
The third altitude is new; the decision above is not. `loam tasks` is the `loam verify` checklist
|
|
555
|
+
read forwards — the same claims under the same ids, one unit per promise, each with the fact that
|
|
556
|
+
closes it — recomputed on every run from the delta, the generated suite and the verification record.
|
|
557
|
+
It is still not a file: nothing to tick, nothing to commit, nothing that can disagree with the
|
|
558
|
+
documents it was derived from, and so the reason there is no `tasks.md` is unchanged. A unit leaves
|
|
559
|
+
the list only when a confirmed claim in a non-stale verification record retires it, and an
|
|
560
|
+
agent-attested scenario stays on it at `attested` rather than being ticked off — the work list must
|
|
561
|
+
not be able to say more than the record does.
|
|
562
|
+
|
|
494
563
|
## Picking the work back up
|
|
495
564
|
|
|
496
565
|
The three states worth naming, because each has one command:
|
|
@@ -549,25 +618,39 @@ refuses it until a person authors the content, or deliberately overrides with `-
|
|
|
549
618
|
requirements-only feature you delete the scaffolded `delta.likec4` yourself — `new` says so on the
|
|
550
619
|
way out.
|
|
551
620
|
|
|
552
|
-
**`loam adopt`** — the brief names the target paths, the grammar of each, what the
|
|
553
|
-
says
|
|
621
|
+
**`loam adopt`** — the brief names the target paths, the grammar of each, what the fleet map already
|
|
622
|
+
says — the whole `architecture/` project, not the landscape file alone — the checks that follow, and
|
|
623
|
+
the ones that do not exist. The default human view now opens with
|
|
554
624
|
an orientation block before any of that: how many of those targets are required and still
|
|
555
625
|
outstanding, named, and what each flag in the artifact table means — `MISSING` required and absent,
|
|
556
|
-
lowercase `missing` optional and absent, `present` a document to diff rather than replace, and
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
626
|
+
lowercase `missing` optional and absent, `present` a document to diff rather than replace, and two
|
|
627
|
+
rows for the one target that is the whole system's shared map: `UNDRAWN` while nothing in the map
|
|
628
|
+
resolves to this boundary, and `EDGELESS` while an element does and no edge touches it. The map owes
|
|
629
|
+
an element in the first state and edges in the second, and `landscape.instruction` says which.
|
|
630
|
+
`--targets` drops the half that is identical for every service — the code walk,
|
|
631
|
+
the frontmatter rules, the 52 named checks and the seventeen statements of what nothing checks — and
|
|
632
|
+
replaces it with a `full` field naming the one run that carries them, which is 54,833 bytes down to
|
|
633
|
+
20,062 on the example fleet (measured 2026-09-04).
|
|
562
634
|
|
|
563
635
|
**`loam diff`** — the base state is read out of the docs repo's own git history
|
|
564
636
|
(`rev-parse`/`ls-tree`/`show`, read-only, no checkout), so it refuses (`repository-unavailable`)
|
|
565
637
|
when the docs repo has no history to ask and (`unknown-target`) when `--base` resolves to no commit
|
|
566
638
|
there. What it reports is the *joined*, fleet-meaningful delta — a removed operation is graded
|
|
567
|
-
against the
|
|
568
|
-
|
|
639
|
+
against the consumers the archive gate reads too ([SCHEMA.md](SCHEMA.md), "Who still consumes it"):
|
|
640
|
+
the edges of the `architecture/` project, other services' `Operations:` lines in either spec file
|
|
641
|
+
(not one naming its own service's operation of the same id) and the use-case hops attributed to it
|
|
642
|
+
(`diff.op-removed-consumed`, exit 1); a removed message against its `Consumes:` lines,
|
|
643
|
+
consumes-edges and hops — and an artifact
|
|
569
644
|
unreadable on either side suspends that subject's axis and exits 1, because "nobody could look" must
|
|
570
|
-
never read as "nothing changed".
|
|
645
|
+
never read as "nothing changed". The exception is an `openapi.yaml` or `asyncapi.yaml` that cannot be
|
|
646
|
+
read but is byte-identical at the base (an AsyncAPI 2.x file nobody has converted yet): the branch did
|
|
647
|
+
not touch it, so it is skipped rather than failing every PR. A spec file stays suspended even then,
|
|
648
|
+
because another service's removal may be the one that could not be checked against it.
|
|
649
|
+
A landscape edge into the provider drawn with no `metadata { op }`
|
|
650
|
+
is the same doubt at warning strength: it is listed as a consumer nobody could check, never dropped.
|
|
651
|
+
An operation or message whose own node or `$ref` closure moved is `diff.op-modified` /
|
|
652
|
+
`diff.message-modified` — a warning that names the same consumers and does not say whether the
|
|
653
|
+
change breaks them. `validate --all` remains the fleet gate; diff is the review lens.
|
|
571
654
|
For the byte-level OpenAPI breaking-change catalogue, run oasdiff on the two states of one contract:
|
|
572
655
|
`git -C <docs> show <ref>:./services/<id>/openapi.yaml > base.yaml && oasdiff breaking base.yaml <docs>/services/<id>/openapi.yaml`
|
|
573
656
|
(the `./` resolves the path relative to the docs directory rather than the git root, so this holds
|
|
@@ -581,7 +664,11 @@ landscape the branch changed since a base git ref of the docs repo — which is
|
|
|
581
664
|
both passing on the first day of adoption and tightening after it, and which for that reason
|
|
582
665
|
grades nothing outside the branch: the consumer whose living requirement still names an operation
|
|
583
666
|
this branch removed is not in scope, so that finding is `loam diff`'s and never this run's, and a
|
|
584
|
-
scope holding no target says it graded nothing rather than reporting the word valid.
|
|
667
|
+
scope holding no target says it graded nothing rather than reporting the word valid. The landscape
|
|
668
|
+
is graded by what in it the branch changed: a call edge the branch added or edited is checked
|
|
669
|
+
against its provider's contract even when the provider is out of scope, and the fleet-wide
|
|
670
|
+
vocabulary warnings (a permission, capability, obligation or glossary term nothing cites) and the
|
|
671
|
+
AGENTS.md stamp ride the run only when the file that carries them changed.
|
|
585
672
|
|
|
586
673
|
**`loam gherkin`** — a feature's changed requirements, or (without a feature) the full living suite.
|
|
587
674
|
Deterministic, digest-stamped, regeneration-owned; run in the service's own repo.
|
|
@@ -590,21 +677,45 @@ Deterministic, digest-stamped, regeneration-owned; run in the service's own repo
|
|
|
590
677
|
on every operation in the contract delta that the living docs already hold; what this feature is
|
|
591
678
|
*adding* has nothing to pin against, and the output says so per item. On the requirement axis that
|
|
592
679
|
stops a second feature rewriting the same requirement from landing on top of the first in silence;
|
|
593
|
-
on the contract axis it also
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
the
|
|
597
|
-
|
|
598
|
-
|
|
680
|
+
on the contract axis it also tells an edit from a **quotation** — the merge upserts every operation
|
|
681
|
+
the delta spells, so without the pin an operation you only quoted reverts whatever landed on it.
|
|
682
|
+
The cheaper fix is not to quote: a feature's `openapi.yaml` or `asyncapi.yaml` holds only what it
|
|
683
|
+
adds, changes or removes, the merge leaves every operation it does not spell exactly as the living
|
|
684
|
+
contract has it, and a local `$ref` resolves into the living document — so an add-only contract
|
|
685
|
+
delta has nothing to pin and needs no rebase. Each quote costs a pin, and a pinned quote whose living
|
|
686
|
+
operation a parallel feature removes becomes `openapi.baseline-invalid`, an error that blocks the
|
|
687
|
+
archive until the quote is deleted, with `openapi.op-revived` beside it — while an unpinned one is
|
|
688
|
+
`openapi.op-revived` alone (`asyncapi.slot-revived` on the event axis), which gates the archive too,
|
|
689
|
+
because the merge would read the retired operation as an addition and put it back. Rebase pins neither as new: it prints
|
|
690
|
+
the same finding (`revived[]` in `--json`), and whether the quote goes or the feature re-adds the
|
|
691
|
+
operation on purpose is the author's call. It judges the delta as it will write it, pins included:
|
|
692
|
+
a quote repinned over whatever now lives at an address an archived feature moved the operation away
|
|
693
|
+
from becomes an edit the merge writes, and that revival is reported by the rebase (or `--dry-run`)
|
|
694
|
+
that makes it, not first by the next validate. Restamping is the last step of resolving a collision,
|
|
695
|
+
not the resolution — the output says which pins moved.
|
|
696
|
+
|
|
697
|
+
**`loam verify`** — `--results <report.json>` answers the scenario claims from a test run,
|
|
599
698
|
digest-matched, so only a green run confirms one, and the record writes down which file it read
|
|
600
|
-
(path, sha256, mtime). It
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
699
|
+
(path, sha256, mtime). It reads two shapes: a cucumber JSON report (cucumber-js, cucumber-jvm,
|
|
700
|
+
behave, SpecFlow/Reqnroll, pytest-bdd `--cucumberjson` and godog's cucumber formatter all write
|
|
701
|
+
one), in which a matched scenario must also have run exactly the stamped scenario's number of
|
|
702
|
+
steps — a hand-tagged stub is not that scenario's run — or loam's runner-neutral
|
|
703
|
+
`{"loamScenarioReport": 1, "results": [{"digest": "…", "status": "passed"}]}`, which a JUnit,
|
|
704
|
+
pytest, Vitest or house runner's report is adapted into. Anything else, JUnit XML included, is
|
|
705
|
+
refused naming both (`answers-unreadable`). It answers *only* those claims, so on a feature with
|
|
706
|
+
open `service.exists` / `api.exposes` claims it is passed alongside `--record` or refused
|
|
707
|
+
(`answers-mismatch`). `--record <answers.json>` takes the agent's answers, refusing anything
|
|
708
|
+
unevidenced — a `file:line` that does not resolve to a real line in this repository, and under
|
|
709
|
+
`--service` one that does not resolve at the attested commit — and a scenario claim answered that
|
|
710
|
+
way makes the record `attested` rather than `verified`. A
|
|
711
|
+
cross-service feature is recorded **once per service repo** with `--service <id>`, each run writing
|
|
712
|
+
its own commit-bound attestation to a file of its own, `features/<FEAT>/verification/<id>.yaml` —
|
|
713
|
+
the directory is the record, so two teams' attestations on two docs-repo branches merge cleanly. The
|
|
714
|
+
`--service`-less `--record` form writes the whole record from one place, into the one file
|
|
715
|
+
`verification.yaml`, and is refused (`record-federated`) once anyone else has attested. A record
|
|
716
|
+
file that will not read (`record-unreadable`, git conflict markers included) is named with its safe
|
|
717
|
+
repair: a service's own file may be deleted and recorded again by that service; the one-file
|
|
718
|
+
`verification.yaml` may hold other services' attestations and is restored, never deleted.
|
|
608
719
|
|
|
609
720
|
**`loam unarchive`** — it refuses rather than guesses: `snapshot-stale` when a merged file moved
|
|
610
721
|
since (`--force` says that was meant), and `snapshot-corrupt` when a pre-image no longer hashes to
|
|
@@ -636,8 +747,8 @@ archive is undone, an interrupted unarchive is *finished*, because the merged te
|
|
|
636
747
|
is written down nowhere else — or refusing with `commit-interrupted` when a file has been edited
|
|
637
748
|
since. `loam doctor` reports that state rather than calling the repo healthy.
|
|
638
749
|
|
|
639
|
-
The gate itself comes in two kinds. Coherence
|
|
640
|
-
calls, and `--approve` carries them; two refusals are mechanical loss and `--approve` deliberately
|
|
750
|
+
The gate itself comes in two kinds. Coherence (a revived retired operation among it), an unknown
|
|
751
|
+
service and the OpenAPI plan are judgement calls, and `--approve` carries them; two refusals are mechanical loss and `--approve` deliberately
|
|
641
752
|
does not — a living document still holding git conflict markers (`merge-failed`) and a living
|
|
642
753
|
requirement that has strayed outside `## Requirements` (`living-outside-requirements`). loam's docs
|
|
643
754
|
files must be **UTF-8** for the same reason: undecodable bytes refuse the merge (`merge-failed`,
|
|
@@ -653,19 +764,37 @@ beside the methods, addresses no operation and retires nothing; archive refuses
|
|
|
653
764
|
(`openapi.remove-marker-path-level`) rather than publishing a meaningless key into the fleet's
|
|
654
765
|
living contract. Validation refuses stale, mismatched, or unjustified markers; archive deletes the
|
|
655
766
|
method without persisting the marker or garbage-collecting components, and reports the removals in
|
|
656
|
-
both text and JSON. See [SCHEMA.md](SCHEMA.md) for the lifecycle contract.
|
|
767
|
+
both text and JSON. See [SCHEMA.md](SCHEMA.md) for the lifecycle contract. A delta that defines
|
|
768
|
+
another operationId where a living operation lives replaces it there, and when the merged contract
|
|
769
|
+
then defines it nowhere the gate grades it like a retirement: `openapi.remove-op-consumed` while an
|
|
770
|
+
edge of the `architecture/` project, another service's requirement, a use-case hop, or the
|
|
771
|
+
provider's own requirement as the merge would leave it still names the old id — so a rename redraws
|
|
772
|
+
the edge and restates its requirement in the same change, or defines the old operation at another
|
|
773
|
+
address if it is to stay. Every consumer is read after the feature's merge, so retiring one in the
|
|
774
|
+
same feature (MODIFY or REMOVE the requirement that names it) is a fix the gate sees.
|
|
775
|
+
|
|
776
|
+
A retirement also stays retired. The archive gate reads the removal markers every feature under
|
|
777
|
+
`features/archive/` left behind, and refuses a delta that spells an HTTP operation, a channel, an
|
|
778
|
+
event operation or a message one of them retired while the living contract no longer holds it —
|
|
779
|
+
or spells one at an address one of them retired it from or moved it away from while it lives on
|
|
780
|
+
elsewhere, which would put it back beside where it lives, judged on the contract the merge would
|
|
781
|
+
write (`openapi.op-revived`, `asyncapi.slot-revived` — warnings that gate). Without it, a parallel
|
|
782
|
+
feature that had merely quoted the operation archived second and put it back at exit 0.
|
|
783
|
+
`--approve` re-adds it on purpose, and the archive output names what came back and whose
|
|
784
|
+
retirement it reverses. A removal made by hand-editing a living contract, or an archive deleted
|
|
785
|
+
from disk, leaves no marker, and the gate cannot see it.
|
|
657
786
|
|
|
658
787
|
## The MCP server
|
|
659
788
|
|
|
660
|
-
For hosts that reach tools through MCP rather than a shell, `loam mcp` serves the
|
|
661
|
-
commands — `validate`, `status`, `list`, `show`, `delta`, `
|
|
662
|
-
`doctor`, `context`, `gate`, `steps`, `explain`, `instructions` — as MCP tools
|
|
663
|
-
`loam_instructions`) over stdio, newline-delimited JSON-RPC 2.0, protocol
|
|
664
|
-
revisions negotiated down; JSON-RPC batch arrays refused). Every tool is
|
|
665
|
-
`readOnlyHint: true` and `openWorldHint: false`, which is what a host needs to run one
|
|
666
|
-
stopping to ask its user: the first says the call cannot change the repository, the second
|
|
667
|
-
cannot reach anything outside the directory the server was launched in — and both are true
|
|
668
|
-
whole base table only because the writing commands are kept out of it. It also publishes
|
|
789
|
+
For hosts that reach tools through MCP rather than a shell, `loam mcp` serves the sixteen read
|
|
790
|
+
commands — `validate`, `status`, `list`, `show`, `delta`, `tasks`, `explore`, `dependencies`,
|
|
791
|
+
`diff`, `doctor`, `context`, `adopt`, `gate`, `steps`, `explain`, `instructions` — as MCP tools
|
|
792
|
+
(`loam_validate` … `loam_instructions`) over stdio, newline-delimited JSON-RPC 2.0, protocol
|
|
793
|
+
revision 2025-06-18 (older revisions negotiated down; JSON-RPC batch arrays refused). Every tool is
|
|
794
|
+
advertised `readOnlyHint: true` and `openWorldHint: false`, which is what a host needs to run one
|
|
795
|
+
without stopping to ask its user: the first says the call cannot change the repository, the second
|
|
796
|
+
that it cannot reach anything outside the directory the server was launched in — and both are true
|
|
797
|
+
of the whole base table only because the writing commands are kept out of it. It also publishes
|
|
669
798
|
`loam://orientation` and every `loam://instructions/<name>` page as Markdown resources, so the host
|
|
670
799
|
can load version-matched guidance progressively; `loam://instructions/loam-check/compact` omits the
|
|
671
800
|
large fix table and pairs with `loam explain <code>`. A typical host entry:
|
|
@@ -699,3 +828,100 @@ gets coherent `no-config` envelopes, not silence. Calls run strictly one at a ti
|
|
|
699
828
|
`loam_validate` blocks the queue for its duration; MCP requests carry ids and hosts tolerate the
|
|
700
829
|
latency. Even author mode excludes `vouch`, verification recording and a committing archive:
|
|
701
830
|
human trust and irreversible lifecycle transitions stay under the CLI permission flow.
|
|
831
|
+
|
|
832
|
+
## Build on the envelope
|
|
833
|
+
|
|
834
|
+
loam makes no network call, so it syncs with no tracker, dashboard or catalog — and does not need
|
|
835
|
+
to. Every command's `--json` is a stable contract, and the integrations are a few lines of shell
|
|
836
|
+
over it, owned by whoever runs them. Four recipes, each run against `examples/docs`.
|
|
837
|
+
|
|
838
|
+
**Feature work into a tracker.** `loam tasks <FEAT> --json`, run from the docs repo, lists every
|
|
839
|
+
open unit of a feature (from a service repository it lists that service's, when the feature touches it):
|
|
840
|
+
`id`, `subject` (the owning service), `claim`, `done` (its `check` is the fact that closes it) and
|
|
841
|
+
`dependsOn` (unit ids to finish first). The unit id is the idempotency key — prefixed with the
|
|
842
|
+
feature id, so one tracker holds every feature's units and each title says which — and a re-run
|
|
843
|
+
opens issues only for units it has not seen:
|
|
844
|
+
|
|
845
|
+
```bash
|
|
846
|
+
existing=$(gh issue list --state all --limit 1000 --json title --jq '.[].title')
|
|
847
|
+
loam tasks FEAT-101 --json \
|
|
848
|
+
| jq -r '.feature as $f | .units[] | ["[\($f) \(.id)]", .subject, .claim, .done.check, (.dependsOn | map("[\($f) \(.)]") | join(" "))] | @tsv' \
|
|
849
|
+
| while IFS=$'\t' read -r key svc claim check after; do
|
|
850
|
+
grep -qF "$key" <<<"$existing" && continue
|
|
851
|
+
gh issue create --title "$key $claim" --body "Service: $svc. Done when: $check. After: ${after:-nothing}"
|
|
852
|
+
done
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
On the example's FEAT-101 that is nineteen issues the first time and none the second. A finished
|
|
856
|
+
unit leaves `units[]` once the evidence its `check` names is recorded, so the issues to close are a
|
|
857
|
+
set difference against the last export. **A unit's id is a hash of what it says**, which is what
|
|
858
|
+
makes it a key and also its one hazard: rewording a scenario — its name or any Given/When/Then line
|
|
859
|
+
— or renaming a requirement that carries no `Requirement-ID:` mints a new id. The next export opens
|
|
860
|
+
a fresh issue, and the old one is orphaned: it drops out of `units[]` exactly as a finished unit
|
|
861
|
+
does, so read the set difference before closing anything as done, and carry the orphan's history
|
|
862
|
+
over by hand. Renaming a requirement that does carry a `Requirement-ID:` keeps every id. The same
|
|
863
|
+
loop drives `jira` or any CLI that creates an issue from a title and a body.
|
|
864
|
+
|
|
865
|
+
**The fleet view of every service repo's CI.** Staleness is visible only from each service repo,
|
|
866
|
+
so each one's CI publishes the per-service summary (SCHEMA.md, "The per-service summary a CI
|
|
867
|
+
pipeline publishes") wherever your fleet view reads. Rolling those up is a join against the list of
|
|
868
|
+
services the docs repo knows, so a service that never reported reads as unknown and never as clean:
|
|
869
|
+
|
|
870
|
+
```bash
|
|
871
|
+
jq -s 'map({(.service): .}) | add // {}' summaries/*.json > reports.json
|
|
872
|
+
loam list --json | jq -r --slurpfile r reports.json '
|
|
873
|
+
.services[] | .id as $id | $r[0][$id] as $s
|
|
874
|
+
| [$id,
|
|
875
|
+
if $s == null then "unknown: no report"
|
|
876
|
+
elif now - ($s.generatedAt | fromdateiso8601) > 86400 then "unknown: last report \($s.generatedAt)"
|
|
877
|
+
elif $s.valid | not then "invalid: \($s.errors) error(s)"
|
|
878
|
+
elif $s.sources.stale + $s.contentStale > 0 then "owes a re-vouch: \($s.sources.stale) source-stale, \($s.contentStale) content-stale"
|
|
879
|
+
else "clean" end]
|
|
880
|
+
| @tsv'
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
The day-old cutoff is a policy and yours to set; what is not a policy is that `generatedAt` comes
|
|
884
|
+
from the CI's clock, never loam's, so an old one means that repo stopped reporting.
|
|
885
|
+
|
|
886
|
+
**Which services must be up for suite X.** A fleet usually keeps that answer by hand — a compose
|
|
887
|
+
file, a CI matrix, a paragraph in a runbook — and it drifts from the journeys it is for. Tag each
|
|
888
|
+
cross-service use case with the suites it runs in (`#suite-smoke` on its `dynamic view`, declared in
|
|
889
|
+
the landscape's `specification`; one journey may carry several) and `loam list suites <name>`
|
|
890
|
+
derives it: the union of the suite's participants, resolved to service ids through the same join the
|
|
891
|
+
step grades use. The participants no service stands for are listed beside them rather than dropped —
|
|
892
|
+
the person who drives the flow, an `#external` topic or partner — because a stand that comes up
|
|
893
|
+
short fails its journey against something nobody was told to start:
|
|
894
|
+
|
|
895
|
+
```bash
|
|
896
|
+
loam list suites smoke --json | jq -r '
|
|
897
|
+
if .useCases.unreadable then error("architecture/ did not parse: \(.useCases.error)") else . end
|
|
898
|
+
| .suites[0] | (.services[] | "up \(.)"), (.unresolved[] | "stand-in \(.element)\(if .external then " (#external)" else "" end)")'
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
On the example that is three services up — checkout-web, notification-service, order-service — and
|
|
902
|
+
two stand-ins: `customer`, and `kafka.orderEvents`, `#external` through its kind. Tagging a journey
|
|
903
|
+
also opts it in to grading, so a suite cannot list a hop the map does not declare
|
|
904
|
+
(`usecase.step-unbacked`); `ungrouped[]` names the use cases in no suite, and an unknown suite name
|
|
905
|
+
refuses `unknown-target` rather than answering an empty environment.
|
|
906
|
+
|
|
907
|
+
**LikeC4's own MCP server beside loam's.** The fleet map is plain LikeC4, so LikeC4's MCP server
|
|
908
|
+
runs on the same docs repo with no configuration — `npx likec4 mcp --stdio .` from the docs root
|
|
909
|
+
exposed eighteen tools on the example, measured at the 1.59.2 pin loam carries: element, view and
|
|
910
|
+
relationship reads, graph traversals, metadata and tag queries. Run the likec4 loam itself depends
|
|
911
|
+
on (`npm ls likec4` names it), so the server parses the grammar loam validates. The two answer
|
|
912
|
+
different questions: `loam mcp` the joins, gates and lifecycle state; `likec4 mcp` the model as a
|
|
913
|
+
graph. One host entry carries both:
|
|
914
|
+
|
|
915
|
+
```json
|
|
916
|
+
{
|
|
917
|
+
"mcpServers": {
|
|
918
|
+
"loam": { "command": "loam", "args": ["mcp"] },
|
|
919
|
+
"likec4": { "command": "npx", "args": ["likec4", "mcp", "--stdio", "."] }
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
Two differences to know. LikeC4's server reads the root project, which excludes `features/**`, so
|
|
925
|
+
it sees the living map and never an in-flight delta — ask `loam show <FEAT> --json` for those. And
|
|
926
|
+
seventeen of its tools advertise `readOnlyHint`; `apply-semantic-layout` does not, so a host will
|
|
927
|
+
ask before running it.
|