@ybotok/loam 0.1.0-beta.3 → 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 +5992 -82
- package/COMPARISON.md +168 -63
- package/CONTRIBUTING.md +121 -0
- package/MIGRATING-from-OpenSpec.md +238 -55
- package/QUICKSTART.md +302 -0
- package/README.md +653 -144
- package/ROADMAP.md +1035 -0
- package/SCHEMA.md +3916 -263
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +927 -0
- package/dist/cli.js +133 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +204 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +309 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +74 -0
- package/dist/commands/archive/archive.js.map +1 -0
- 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 +172 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- 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 +193 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- 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 +319 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +298 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- 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 +106 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +318 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +30 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +355 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +166 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +305 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +367 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +221 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +6 -8
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +86 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +65 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +227 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +39 -28
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +152 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +66 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +105 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +262 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +146 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +72 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +142 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +63 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +155 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +358 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +344 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- 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 +108 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +238 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +75 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +175 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +18 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- 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 +62 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +328 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +279 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +199 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +300 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +221 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +278 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +174 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +182 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +53 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/show/service.js +239 -0
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +87 -0
- package/dist/commands/show/show.js.map +1 -0
- 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 +47 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +209 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +115 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +269 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +325 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +113 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +98 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +318 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- 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 +196 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +249 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- 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 +176 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/unarchive/restore.js +254 -0
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +59 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +245 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +204 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +58 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- 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 +264 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +85 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- 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 +222 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +93 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +371 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +118 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- 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 +266 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +71 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- 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 +75 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- 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 +52 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +89 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- 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 +145 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +252 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- 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 +241 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +177 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- 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 +310 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +279 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +148 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- 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 +363 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +178 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +81 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +263 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +278 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +206 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +328 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +220 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +266 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +141 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +230 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +111 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +155 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +169 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +299 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +46 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +44 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +78 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +104 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +138 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +273 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md.js +203 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +254 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +144 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +151 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +193 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +280 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +373 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +323 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +220 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +188 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +311 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +67 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +210 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- 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 +19 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +338 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +43 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +146 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +92 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +38 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +290 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +195 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +83 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/asyncapi/read.js +263 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +285 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +385 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +273 -0
- package/dist/core/brief/landscape.js.map +1 -0
- 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 +304 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +58 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +190 -0
- package/dist/core/c4/arch.js.map +1 -0
- 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 +243 -0
- package/dist/core/c4/likec4.js.map +1 -0
- 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 +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +110 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +113 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- 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 +161 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- 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 +89 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +219 -0
- package/dist/core/c4/project/load.js.map +1 -0
- 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 +174 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- 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/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +173 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- 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 +369 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +308 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +167 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +30 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- 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 +73 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- 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 +337 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- 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 +298 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- 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 +166 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +47 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +338 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +174 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +123 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +205 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +104 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +267 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +185 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +75 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- 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 +332 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- 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 +295 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +191 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +335 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +189 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +63 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +95 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- 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/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.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/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +341 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- 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 +230 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +237 -0
- package/dist/core/diff/base-state.js.map +1 -0
- 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 +204 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- 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 +312 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/docs.js +37 -85
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +238 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +139 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +355 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +224 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +286 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +238 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +234 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +89 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +209 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +180 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +194 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- 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 +103 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/explore/explore.js +204 -0
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +174 -146
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +208 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +246 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +176 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +210 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +109 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +73 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- 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/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/{records.js → kernel/records.js} +11 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +66 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +118 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +265 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +212 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +73 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +324 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +207 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +142 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +174 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- 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 +136 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +239 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +54 -108
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +199 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +16 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +204 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +232 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +110 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +220 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +78 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +70 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +241 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +191 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +304 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +116 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +157 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +120 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +244 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +201 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +139 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +280 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +220 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +322 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +308 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +61 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +90 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- 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 +255 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +146 -14
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +239 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +252 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +268 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +95 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +204 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/snapshot/snapshot.js +196 -0
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +181 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +60 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +126 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +214 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +163 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- 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 +216 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +302 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +216 -0
- package/dist/core/status/verification.js.map +1 -0
- 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 +166 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +140 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +101 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- 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 +76 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +296 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/grade/capability-tag.js +93 -0
- 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/core/usecases/grade/requirement-tag.js +94 -0
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/core/usecases/grade/steps.js +266 -0
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/core/usecases/grade/usecases.js +112 -0
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +123 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- 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/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +180 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +170 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +259 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +158 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/read/shape.js +169 -0
- 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 +165 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +99 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +61 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +59 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +216 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/vocabulary/report.js +90 -0
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +232 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +336 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +18 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +8 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +92 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +134 -0
- package/examples/docs/services/order-service/asyncapi.yaml +109 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +126 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +76 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +68 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
- package/examples/docs/services/platform/notification-service/health.yaml +40 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js +0 -320
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js +0 -317
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js +0 -253
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js +0 -225
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js +0 -47
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
package/WORKFLOW.md
ADDED
|
@@ -0,0 +1,927 @@
|
|
|
1
|
+
# The loam workflow
|
|
2
|
+
|
|
3
|
+
How work actually moves through a loam repository: what a feature owes, how loam decides where that
|
|
4
|
+
work stands, what gates and what only advises, and how an agent drives the whole thing from
|
|
5
|
+
`--json`.
|
|
6
|
+
|
|
7
|
+
[SCHEMA.md](SCHEMA.md) is the companion to this file. It is the reference — every artifact's
|
|
8
|
+
grammar, every rule, every decision. This one is the protocol: the order things happen in, and why
|
|
9
|
+
that order.
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
- [The two flows](#the-two-flows) · [Topology and the governed boundary](#topology-and-the-governed-boundary) ·
|
|
14
|
+
[The artifact graph](#the-artifact-graph) · [Derived, never stored](#derived-never-stored)
|
|
15
|
+
- [Actions, not phases](#actions-not-phases) · [What actually gates](#what-actually-gates)
|
|
16
|
+
- [The six workflows](#the-six-workflows) · [Support reports](#support-reports) ·
|
|
17
|
+
[The honestly-small change](#the-honestly-small-change) · [Driving it from an agent](#driving-it-from-an-agent)
|
|
18
|
+
- [Presence is not trust](#presence-is-not-trust) ·
|
|
19
|
+
[Why there is no task list](#why-there-is-no-task-list)
|
|
20
|
+
- [Picking the work back up](#picking-the-work-back-up)
|
|
21
|
+
- [Day zero: onboarding a fleet](#day-zero-onboarding-a-fleet) · [Command notes](#command-notes) ·
|
|
22
|
+
[The MCP server](#the-mcp-server) · [Build on the envelope](#build-on-the-envelope)
|
|
23
|
+
|
|
24
|
+
## The two flows
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
BOOTSTRAP (once per governed boundary, reverse):
|
|
28
|
+
code ──adopt──► brief ──agent──► C4 baseline + capability spec [truth = code]
|
|
29
|
+
|
|
30
|
+
FORWARD (per feature, generative):
|
|
31
|
+
intent → C4 delta → Gherkin (BDD) → tests → code [truth = model]
|
|
32
|
+
▲ │
|
|
33
|
+
└──── done-check: verify ◄──────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
They run in opposite directions and that is the point. Bootstrap reads an implementation boundary
|
|
37
|
+
that already exists and writes down what is true about it; the code is the authority and the
|
|
38
|
+
document is the claim. Forward starts from an intent nobody has built yet; the model is the
|
|
39
|
+
authority and the code is the claim. Every rule below is downstream of which direction you are
|
|
40
|
+
facing.
|
|
41
|
+
|
|
42
|
+
**There is no extractor, and there will not be one.** Nothing deterministic reads a legacy service
|
|
43
|
+
and says what its architecture *means*, and a model that was guessed is worse than none — everyone
|
|
44
|
+
downstream has to re-derive it to know whether to believe it. loam takes the half of the job that is
|
|
45
|
+
mechanical: it **states the work** and it **checks the result**. An agent does the reading.
|
|
46
|
+
|
|
47
|
+
## Topology and the governed boundary
|
|
48
|
+
|
|
49
|
+
The lifecycle is topology-neutral; the storage vocabulary is deliberately not. Paths, flags and
|
|
50
|
+
finding codes use the frozen word `service` for one governed implementation boundary. That boundary
|
|
51
|
+
may be a network service, one modular monolith, a CLI, a worker, or another application whose code,
|
|
52
|
+
requirements, contracts and evidence are reviewed together.
|
|
53
|
+
|
|
54
|
+
In a modular monolith, one bound C4 root resolves to one `services/<app>/` directory and its nested
|
|
55
|
+
modules remain elements inside that boundary. They can be changed by `delta.likec4` and named by
|
|
56
|
+
architecture requirements through `Covers:` without acquiring invented service identities of their
|
|
57
|
+
own. In a distributed system, several bound roots resolve to several service directories and the
|
|
58
|
+
same model gains cross-boundary OpenAPI, AsyncAPI and use-case joins. A hybrid landscape contains
|
|
59
|
+
both shapes; the binding and its nearest bound ancestor decide ownership, not element depth.
|
|
60
|
+
|
|
61
|
+
This distinction matters operationally. Fleet reports, maturity and deploy dependencies aggregate
|
|
62
|
+
at the bound service boundary. Nested modules participate in model coverage and the change
|
|
63
|
+
lifecycle, but loam does not claim a separate repository, contract, maturity state or deploy order
|
|
64
|
+
for each one. The self-model under `meta/docs/` exercises that exact shape: one `loam` boundary,
|
|
65
|
+
with the source subjects nested inside it and governed through architecture requirements.
|
|
66
|
+
|
|
67
|
+
## Day zero: onboarding a fleet
|
|
68
|
+
|
|
69
|
+
This is the scale-up path of the
|
|
70
|
+
[five-minute trial](README.md#try-loam-on-one-governed-system-in-five-minutes): the same wiring, done
|
|
71
|
+
deliberately across every repository. A fleet of ten services is **eleven repositories**: one docs
|
|
72
|
+
repo and ten service repos, each with its own committed `loam.json`. There is no batch command and
|
|
73
|
+
no fleet manifest, deliberately — the wiring is one file per repo, and it is reviewable. In order:
|
|
74
|
+
|
|
75
|
+
1. **Create the docs repo.** In an empty directory that will be the shared source of truth:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
loam init --docs . --create
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
That scaffolds `services/`, `features/`, `architecture/landscape.likec4`, `AGENTS.md`, and the
|
|
82
|
+
docs repo's own `loam.json` (`docsDir: "."`, plus the `agentTools` it wrote for) — so every later
|
|
83
|
+
command run *inside* the docs repo finds the fleet. An empty directory holds no tool
|
|
84
|
+
dot-directory to detect, so the Claude Code fallback always fires here too: seven slash commands
|
|
85
|
+
and seven Agent Skills under `.claude/` — six lifecycle entries plus `loam-report` ([Working with AI
|
|
86
|
+
agents](README.md#working-with-ai-agents)). Commit all of it.
|
|
87
|
+
|
|
88
|
+
2. **Template the fleet map** from a tiny file you write by hand, rather than drawing it:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
loam seed --from fleet.yaml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`fleet.yaml` is service ids, optional `subsystems`, `externals`, and `a -> b` calls — nothing
|
|
95
|
+
else; [`examples/fleet.yaml`](https://github.com/ybotok/loam/blob/main/examples/fleet.yaml) is a
|
|
96
|
+
real one for the five-service example fleet. Seed templates `architecture/landscape.likec4` and one `services/<id>/` directory per
|
|
97
|
+
entry, in one journaled transaction, and guesses nothing: a human stated every fact in the file,
|
|
98
|
+
which is what keeps seed on the same side of the no-extractor line as `loam new`. Re-running is
|
|
99
|
+
safe — once the landscape has been hand-edited, seed refuses (`seed-landscape-edited`) rather
|
|
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.
|
|
104
|
+
|
|
105
|
+
Drawing it by hand instead is entirely legal, and the landscape is a **required** artifact
|
|
106
|
+
either way, not an optional one: `loam validate --all` reports `landscape.missing` as an error
|
|
107
|
+
the moment `services/` holds a directory (an empty one counts, before a single document lands in
|
|
108
|
+
it), because with no fleet map every cross-service check is blind rather than passing.
|
|
109
|
+
|
|
110
|
+
What seed deliberately does not write is the operation on each edge. That token —
|
|
111
|
+
`metadata { op 'createOrder' }` — is what turns a drawn arrow into a checked join, and adding it
|
|
112
|
+
is what makes the [spine-first first hour](README.md#start-from-the-fleet-spine) pay off before
|
|
113
|
+
any of the steps below have run.
|
|
114
|
+
|
|
115
|
+
3. **Bind each service repo.** Once per service, in that service's own checkout, beside the docs
|
|
116
|
+
repo:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
loam init --docs ../docs-repo --service payment-service --agent-profile service # no --create: it JOINS
|
|
120
|
+
loam doctor # confirms the wiring
|
|
121
|
+
```
|
|
122
|
+
|
|
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
|
|
126
|
+
`loam verify --service --record` / `--results` refuse to attest, because none of them will write
|
|
127
|
+
a service's documents from a repo that has not said which service it is. Reading —
|
|
128
|
+
`loam verify --service` on its own — needs no binding, because it writes nothing. Commit the
|
|
129
|
+
`loam.json`.
|
|
130
|
+
|
|
131
|
+
4. **Adopt each service.** In its repo: `loam adopt --service <id> --json` emits the brief — every
|
|
132
|
+
file to write, the grammar of each, what the fleet map already says, and the block the map still
|
|
133
|
+
owes this service. An agent reads the code and writes the baseline as `draft`. `warnings[]`
|
|
134
|
+
catches the typo case, where an id one letter off would have produced a complete, validating
|
|
135
|
+
baseline for a service that does not exist.
|
|
136
|
+
|
|
137
|
+
5. **Grade it, twice.** `loam validate --service <id> --json` in the service repo (its own axes plus
|
|
138
|
+
`sources`, which only that repo can resolve), then `loam validate --all --json` in the docs repo
|
|
139
|
+
— the fleet cross-check that catches a landscape edit which never landed.
|
|
140
|
+
|
|
141
|
+
6. **Promote it.** A human runs `loam vouch --service <id>` in the service repo: `draft → verified`,
|
|
142
|
+
stamping the source and content digests that make later staleness detectable. `loam list --json`
|
|
143
|
+
in the docs repo then grades the whole fleet on the presence ladder
|
|
144
|
+
`empty → partial → documented → sourced → vouched`, and `loam list --needs-work` is the remaining
|
|
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`.
|
|
147
|
+
|
|
148
|
+
Steps 3–6 repeat per service and are independent — no ordering, no lock, no shared state between two
|
|
149
|
+
services' runs — so ten services can be onboarded by ten people in parallel. The one file they all
|
|
150
|
+
touch is the landscape: step 2 draws it, step 4's brief tells each of them to *add* their own
|
|
151
|
+
element to it where the map does not yet know the service, and step 5's `--all` reads it.
|
|
152
|
+
|
|
153
|
+
## The artifact graph
|
|
154
|
+
|
|
155
|
+
A feature is a directory. What it owes is a fixed set of artifacts — no per-project schema, no
|
|
156
|
+
configurable graph, because a governed system needs one lifecycle and one meaning of green:
|
|
157
|
+
|
|
158
|
+
| Artifact | Per | Required | What it is |
|
|
159
|
+
|---|---|---|---|
|
|
160
|
+
| `intent.md` | feature | yes | The problem in business terms. The proposal: why this exists, before any structure |
|
|
161
|
+
| `delta.likec4` | feature | no | New elements and edges, each tagged with the feature id. The design. A requirements-only change deletes it |
|
|
162
|
+
| `specs/<svc>/spec.md` | service | yes | The behaviour delta — `ADDED` / `MODIFIED` / `REMOVED` requirements, each with Given/When/Then scenarios |
|
|
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 |
|
|
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 |
|
|
167
|
+
|
|
168
|
+
Two fleet/living axes sit beside this feature graph. `services/<svc>/asyncapi.yaml` joins
|
|
169
|
+
`publishes`/`consumes` edges to `Publishes:`/`Consumes:` requirements, and the event axis carries
|
|
170
|
+
the full feature lifecycle: the delta above is slot-pinned by `loam rebase`, graded by
|
|
171
|
+
`validate --feature` (baseline, removal-justification and conflict findings), merged by
|
|
172
|
+
`loam archive` inside the same transaction as every other write, undone by `loam unarchive`, and
|
|
173
|
+
asked about by `loam verify` (`event.declares`). `architecture/permissions.yaml` is the opt-in
|
|
174
|
+
authorization vocabulary: requirements name `<subject>/<permission>` pairs with `Requires:`; unknown
|
|
175
|
+
pairs are errors and unused declarations are warnings. [SCHEMA.md](SCHEMA.md#canonical-joins) is the
|
|
176
|
+
canonical join table.
|
|
177
|
+
|
|
178
|
+
Three of those "no"s are load-bearing. An artifact that is legitimately absent reads `done` —
|
|
179
|
+
nothing is owed — with `exists: false` beside it, so a reader can tell that from a file that is
|
|
180
|
+
present and fine. Marking everything required is how an axis that is optional everywhere gets
|
|
181
|
+
reported as missing everywhere and then ignored.
|
|
182
|
+
|
|
183
|
+
**Dependencies are enablers, not gates — with one real exception.** You can author these in any
|
|
184
|
+
order. The verification record is the exception, and it is a genuine impossibility rather than a
|
|
185
|
+
preference: its checklist is *derived* from the delta and the per-service specs, so with none of
|
|
186
|
+
them written there is no question set to answer. That artifact alone comes back `blocked`, naming
|
|
187
|
+
what it is waiting on.
|
|
188
|
+
|
|
189
|
+
### The states
|
|
190
|
+
|
|
191
|
+
Every artifact grades to one of five words:
|
|
192
|
+
|
|
193
|
+
| State | Means |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `missing` | Required, and not there |
|
|
196
|
+
| `blocked` | Cannot be authored yet — its inputs do not exist |
|
|
197
|
+
| `draft` | It is there, and a check reported something that names it |
|
|
198
|
+
| `ready` | Everything is answered, but not yet confirmed the strong way |
|
|
199
|
+
| `done` | Nothing is owed here |
|
|
200
|
+
|
|
201
|
+
The grading asks **two questions in order**: is it there, and does anything reported name it. That
|
|
202
|
+
second question is what separates loam's graph from a file-existence check. A `spec.md` that exists
|
|
203
|
+
and contradicts the living spec is `draft`, not `done` — the file is present, and presence was never
|
|
204
|
+
the claim. A graph that reads existence alone would call that feature finished.
|
|
205
|
+
|
|
206
|
+
## Derived, never stored
|
|
207
|
+
|
|
208
|
+
Nothing above is written down anywhere. `loam status` recomputes the whole table on every run, from
|
|
209
|
+
the files, and writes nothing:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
loam status --json
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
There is no state file, no database, no cache, and therefore nothing to go stale, nothing to
|
|
216
|
+
reconcile after someone edits a file by hand, and no second source of truth to disagree with the
|
|
217
|
+
first. Delete loam and every artifact remains as Markdown, LikeC4 DSL, Gherkin and YAML.
|
|
218
|
+
|
|
219
|
+
The cost is honest: `status` re-reads and re-parses. On a 120-service fleet with ten features in
|
|
220
|
+
flight that is about 1.3 seconds, most of it the per-feature C4 parse, and it is nearly flat in the
|
|
221
|
+
size of the fleet. That is the price of never being wrong about what is on disk.
|
|
222
|
+
|
|
223
|
+
The fleet scorecard follows the same rule at fleet scale. `loam validate --all --json` carries an
|
|
224
|
+
additive `scorecard` key of ceiling-vs-actual pairs — operations defined → governed, messages
|
|
225
|
+
defined → linked, the maturity rollup, verification verdicts, feature stages, per-axis adoption
|
|
226
|
+
counts (an axis no service participates in reads "not started", expected mid-adoption) — recomputed
|
|
227
|
+
from that run's own reads. loam keeps no history for it, so tracking the trend week over week is the
|
|
228
|
+
pipeline's job: capture the key from each fleet-gate run into a metrics store and diff there.
|
|
229
|
+
|
|
230
|
+
## Actions, not phases
|
|
231
|
+
|
|
232
|
+
There is no phase lock. Any action, any time — because real work does not proceed in one direction:
|
|
233
|
+
building reveals a design flaw, which rewrites a requirement, which regenerates a suite.
|
|
234
|
+
`loam status`'s `next[]` is ordered *advice*, not a sequence you are held to, and running a step out
|
|
235
|
+
of order is not an error state loam has to be talked out of.
|
|
236
|
+
|
|
237
|
+
What loam does instead is make the consequences of going backwards visible. Change a requirement
|
|
238
|
+
after generating its Gherkin and the suite's digest no longer matches, so `loam validate` reports
|
|
239
|
+
the suite stale — by digest, not by anybody's intentions. Edit a feature's documents while another
|
|
240
|
+
feature is in flight and `loam rebase` is what stops the two silently reverting each other. The
|
|
241
|
+
protocol is not "do these in order"; it is "when you go back, here is what tells you what moved".
|
|
242
|
+
|
|
243
|
+
## What actually gates
|
|
244
|
+
|
|
245
|
+
Two things, and it is worth being precise about which, because everything else is advice.
|
|
246
|
+
|
|
247
|
+
**1. The archive coherence gate.** `loam archive` is the one command that rewrites the source of
|
|
248
|
+
truth. It computes the whole three-axis merge first, checks it for cross-axis coherence, and refuses
|
|
249
|
+
if the plan is incoherent. `--approve` carries the judgement calls; it deliberately does **not**
|
|
250
|
+
carry the two mechanical losses — a living document still holding git conflict markers, and a living
|
|
251
|
+
requirement that has strayed outside its `## Requirements` section. Those are not opinions about
|
|
252
|
+
risk, they are data loss, and an override for them is a footgun with a label on it.
|
|
253
|
+
|
|
254
|
+
**2. The human vouch.** `draft → verified` is a person's act. `loam vouch` stamps the source and
|
|
255
|
+
content digests that make later staleness detectable, and no command promotes a service on its own.
|
|
256
|
+
That is the whole trust chain's anchor.
|
|
257
|
+
|
|
258
|
+
Re-vouching starts with `loam vouch --pack`: a read-only run that diffs the document's body from its
|
|
259
|
+
last vouched ancestor in the docs repo's history, lists the source files that moved since the stamp,
|
|
260
|
+
and names the sections a previous vouch already covers — so the person re-reads what changed instead
|
|
261
|
+
of everything. An agent may prepare the pack; the vouch itself is unchanged, still a person's act,
|
|
262
|
+
and `--pack` can never stamp (`--pack --yes` is refused).
|
|
263
|
+
|
|
264
|
+
**`verify` does not gate `archive`,** deliberately. Coherence gates because loam *computed* it. A
|
|
265
|
+
verdict is somebody's word about code loam never read, and a gate in front of shipping only teaches
|
|
266
|
+
everyone that the cheapest way past it is to say yes.
|
|
267
|
+
|
|
268
|
+
**`loam gate` does not add a third.** It is a pure query for DEPLOY pipelines outside loam's own
|
|
269
|
+
lifecycle — Pact's can-i-deploy insight: the gate executes nothing and asks what evidence previous
|
|
270
|
+
runs already recorded (the join partners' documentation state, staleness, the verification verdicts
|
|
271
|
+
of the features touching the service, an interrupted docs commit). Its verdict is advice to a
|
|
272
|
+
pipeline loam does not own — advisory by default, `--strict` the per-invocation CI lever — and it
|
|
273
|
+
deliberately changes nothing about what gates the archive: verify still never gates the merge, and
|
|
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.
|
|
297
|
+
|
|
298
|
+
**`loam diff` does not add one either — it is the review lens.** On a docs-repo PR,
|
|
299
|
+
`loam diff --base origin/main` says what the branch *changes* in fleet-meaningful terms: services,
|
|
300
|
+
requirements (by identity and content digest, so a rebase pin is not a change), operations,
|
|
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
|
|
307
|
+
checks for free, but a green diff is not a valid fleet: run both. For the byte-level OpenAPI
|
|
308
|
+
breaking-change catalogue, use oasdiff on the two states of one contract; [the `loam diff` command
|
|
309
|
+
note](#command-notes) below has the exact invocation, and loam deliberately does not reimplement
|
|
310
|
+
those checks.
|
|
311
|
+
|
|
312
|
+
Severity and gating are also two different questions. A coherence finding marked `gates` stops the
|
|
313
|
+
archive even when it is only a warning; an error in `validate` fails the check without necessarily
|
|
314
|
+
blocking a merge. Read the code, not the colour.
|
|
315
|
+
|
|
316
|
+
## The six workflows
|
|
317
|
+
|
|
318
|
+
Each is a protocol that ships inside the binary. `loam instructions <name>` prints it, with `$1`,
|
|
319
|
+
`$2` filled in from the arguments you pass:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
loam instructions loam-feature FEAT-101 "Refund on partial capture"
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
The reliable chat path is explicit: `/loam-feature FEAT-101 "Refund on partial capture"`, then
|
|
326
|
+
`/loam-implement FEAT-101 payment-service`, `/loam-check`, `/loam-verify FEAT-101` and
|
|
327
|
+
`/loam-ship FEAT-101`. That spelling is flat on most hosts; Gemini renders the same entry as
|
|
328
|
+
`/loam:feature`, Amazon Q as `@loam-feature`, and a skills-only host uses its explicit skill syntax.
|
|
329
|
+
A natural-language request may load the matching Agent Skill instead. This is dual delivery, not
|
|
330
|
+
two workflows: both point at the same `loam instructions` page and the agent owns the internal
|
|
331
|
+
status/edit/validate loop after either entry.
|
|
332
|
+
|
|
333
|
+
`loam init` writes a slash command and an Agent Skill per selected workflow, plus `loam-report` in
|
|
334
|
+
every profile, into whichever AI tools it finds in the repo (`--agent-profile full|service|docs`).
|
|
335
|
+
Those files are **pointers** at
|
|
336
|
+
`loam instructions`, not copies of it — they carry the
|
|
337
|
+
purpose and the spine, and defer the flags, the finding codes and the fix tables to the binary you
|
|
338
|
+
are actually about to run. Init records each pointer's digest and refreshes it only while the bytes
|
|
339
|
+
still match; editing one revokes that authority. A protocol copy would still be as old as the
|
|
340
|
+
repository, while the runtime page cannot go out of date the same way.
|
|
341
|
+
|
|
342
|
+
`AGENTS.md` — the one file `init` lays down that every host auto-loads, and so the first thing an
|
|
343
|
+
agent reads — now works the same way, which changes the reading order. It is orientation only (the
|
|
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.
|
|
351
|
+
|
|
352
|
+
| Workflow | When | What it drives |
|
|
353
|
+
|---|---|---|
|
|
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 |
|
|
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` |
|
|
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 |
|
|
357
|
+
| `loam-check` | Any time; always before shipping | `loam validate`, and fixing what it reports by code |
|
|
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 |
|
|
359
|
+
| `loam-ship` | When it is really finished | `loam validate --feature`, `loam archive --dry-run`, then the merge |
|
|
360
|
+
|
|
361
|
+
### Support reports
|
|
362
|
+
|
|
363
|
+
`loam-report` is generated beside the workflows but is deliberately not a seventh step. Invoke
|
|
364
|
+
`/loam-report` (or the host's skill syntax) when loam, its generated integration, or the agent
|
|
365
|
+
following it behaves unexpectedly. Its version-matched body comes from
|
|
366
|
+
`loam instructions loam-report`.
|
|
367
|
+
|
|
368
|
+
The agent preserves the original symptom before investigating, collects the binary version,
|
|
369
|
+
`doctor --json`, relevant `status --json` and the smallest safe reproduction, then writes
|
|
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
|
|
376
|
+
problem, agent-workflow problem, host/infrastructure problem or inconclusive. A report contains
|
|
377
|
+
stable envelope/finding codes and short relevant excerpts, not a full environment or document
|
|
378
|
+
dump. Secrets and home paths are redacted. A writer is never repeated just to reproduce a failure,
|
|
379
|
+
and the protocol does not repair, upload, submit or send the report. The Markdown file is the handoff
|
|
380
|
+
artifact; a person decides whether to commit or share it.
|
|
381
|
+
|
|
382
|
+
### Deciding what a feature touches
|
|
383
|
+
|
|
384
|
+
This is the one decision in the cycle that nothing downstream catches, so it gets its own command.
|
|
385
|
+
`loam new --touches a --touches b` takes the answer as an argument and scaffolds whatever it was
|
|
386
|
+
told; a list short by one service produces a feature that validates, archives and ships with a
|
|
387
|
+
consumer nobody updated.
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
loam explore payment-service --json --as FEAT-101
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
It writes nothing and reports: the ring one hop out in the fleet map, each service's documentation
|
|
394
|
+
rung, what each already exposes, who already calls whom, the active features covering the same
|
|
395
|
+
services, and the literal `loam new` line the seeds imply. `--op <operationId>` seeds from an
|
|
396
|
+
operation when you know the call but not who owns it.
|
|
397
|
+
|
|
398
|
+
What it does **not** do is fold the neighbours into that command line. loam knows those services are
|
|
399
|
+
connected; it does not know whether this change touches them, and a suggestion that quietly included
|
|
400
|
+
them would make the judgement on your behalf while looking derived. Weighing the ring is the work —
|
|
401
|
+
this command just makes sure you are weighing all of it.
|
|
402
|
+
|
|
403
|
+
### The honestly-small change
|
|
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
|
+
|
|
421
|
+
Most changes are not cross-service features. A one-service, requirements-only change — a new
|
|
422
|
+
refusal, a tightened invariant, behaviour behind an endpoint that already exists — walks the same
|
|
423
|
+
graph with most of it not owed, and the tooling already says so. The whole loop:
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
loam new FEAT-214 --touches payment-service
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Delete the scaffolded `delta.likec4` — `loam new` says so on the way out: a requirements-only
|
|
430
|
+
feature is complete without it. Then author the two files that *are* the change: `intent.md` (why),
|
|
431
|
+
and `specs/payment-service/spec.md` (the ADDED/MODIFIED requirements, each with its scenarios).
|
|
432
|
+
|
|
433
|
+
Everything else is not owed, and `loam status` says which per row rather than leaving you to infer
|
|
434
|
+
it: the `arch.spec.md` and `asyncapi.yaml` rows read `done` with `(not written — none owed)`, and so
|
|
435
|
+
does `openapi.yaml` while the living contract already defines what the requirements govern — write
|
|
436
|
+
an OpenAPI delta only when the change governs operations the living contract does not have. `next[]`
|
|
437
|
+
collapses to three steps: `next.generate-tests` (emit the acceptance scenarios into the service's
|
|
438
|
+
own repository), `next.verify` (answer the checklist, the suite answering the scenario claims),
|
|
439
|
+
`next.archive` (merge the requirement into the living spec). A MODIFIED requirement still takes its
|
|
440
|
+
`loam rebase` pin on the way — the one step size never waives, because the pin is what keeps two
|
|
441
|
+
small changes from silently reverting each other.
|
|
442
|
+
|
|
443
|
+
Small is a fact about the change, not a lighter process: the same gate grades it and the same merge
|
|
444
|
+
ships it. What makes it honestly small is that every skipped artifact is skipped because nothing
|
|
445
|
+
joins into it — status prints the proof beside each row — never because somebody decided the
|
|
446
|
+
documentation could wait.
|
|
447
|
+
|
|
448
|
+
## Driving it from an agent
|
|
449
|
+
|
|
450
|
+
Every command takes `--json`, and the contract is built so an agent never has to read prose:
|
|
451
|
+
|
|
452
|
+
- **Findings carry stable codes** — `c4.valid`, `spine.op-undefined`, `coherence.ok`. Branch on the
|
|
453
|
+
code. Prose gets reworded; codes do not.
|
|
454
|
+
- **The protocol has a narrowed form, and one code is answerable as data** —
|
|
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.
|
|
464
|
+
- **`validate --json` already carries the fix for every code it raised** — `fixes` is a map keyed by
|
|
465
|
+
code, so joining `findings[].code` to `fixes[code]` answers "what now" out of the payload you are
|
|
466
|
+
holding: no `loam explain` round trip per code, and no fix table loaded into context to read one.
|
|
467
|
+
Only codes a run actually raised appear, and a run with nothing to fix carries `{}` rather than
|
|
468
|
+
nothing, so no consumer has to test for the key before looking one up.
|
|
469
|
+
- **`next[]` is ordered and executable without parsing prose.** The legacy `command` hint remains,
|
|
470
|
+
while `execution` says `kind`, `cwd`, whether it is `runnable`, the concrete `command` only when
|
|
471
|
+
it is safe to run, and otherwise the `needs`/`after` facts required to finish the step.
|
|
472
|
+
- **Findings point back to files.** Every serialized finding has `locations[]`: exact primary
|
|
473
|
+
line/pointer data where its producer knows it, otherwise the narrowest service, feature or
|
|
474
|
+
landscape scope loam can prove.
|
|
475
|
+
- **Three questions are kept apart**, each on the command that can answer it: `ok` (the command ran)
|
|
476
|
+
on every envelope, `valid` (the docs pass) on `validate`, and `verified` on `verify` — beside
|
|
477
|
+
`verdict`, which carries the third state, `attested`.
|
|
478
|
+
- **`loam status` takes the union** of what `validate --feature` errors on and what `archive`
|
|
479
|
+
refuses to merge. It may be redder than either and is never greener than both.
|
|
480
|
+
- **`loam context <service> --json` is the one-command briefing** an agent loads before working in
|
|
481
|
+
that service's repository: the living requirements verbatim, both contracts, the fleet edges one
|
|
482
|
+
hop out, the permission and capability joins, and every feature in flight over the service — one
|
|
483
|
+
deterministic payload, so two runs over the same state are byte-diffable. `--feature <FEAT>`
|
|
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.
|
|
490
|
+
- **`loam show <FEAT> --json` is the review hand-off.** Its `review` object joins the intent summary,
|
|
491
|
+
exact C4 objects, API/event slices, dependencies, artifact states, verification, blockers,
|
|
492
|
+
advisories, use cases and executable next actions without making the reviewer reopen each file.
|
|
493
|
+
|
|
494
|
+
The loop is the same every time: `loam status --json`, read `next[0].execution`, run its command only
|
|
495
|
+
when `runnable` is true, otherwise satisfy its named edit/external input, then repeat. When a command
|
|
496
|
+
refuses, it refuses with a code and a sentence naming the fix —
|
|
497
|
+
`loam doctor`'s findings carry the exact command in a `fix` field.
|
|
498
|
+
|
|
499
|
+
## Presence is not trust
|
|
500
|
+
|
|
501
|
+
Documentation existing and documentation being *believed* are different facts, and loam refuses to
|
|
502
|
+
let one read as the other.
|
|
503
|
+
|
|
504
|
+
Services climb a ladder — `empty → partial → documented → sourced → vouched`. The rungs are derived
|
|
505
|
+
from artifact presence and provenance state only, never from what the artifacts say: a service with
|
|
506
|
+
one endpoint documented out of thirty climbs exactly as fast as a thorough one, which is why no rung
|
|
507
|
+
is called "adopted". `sources` names the code a document was written from. `vouch` stamps digests
|
|
508
|
+
over both. Later, `content.stale` says the document moved and `sources.stale` says the code did —
|
|
509
|
+
the second one only answerable inside that service's own repository.
|
|
510
|
+
|
|
511
|
+
The same distinction runs the done-check. `loam verify` derives the claims; a `scenario.tested`
|
|
512
|
+
claim is confirmed **mechanically in the record** when a digest-matched green Cucumber report
|
|
513
|
+
answers it, and an `api.exposes` claim when an API contract-test report names its operationId green
|
|
514
|
+
(`--contract-results`, recorded as `answered_by: external-runner` with the consumed report pinned
|
|
515
|
+
beside the cucumber one). That proves which passing report bytes loam accepted; it does not prove
|
|
516
|
+
the report was produced by executing the attested commit. An agent may confirm one too — a legacy
|
|
517
|
+
service with no runnable suite has to be able to record its answers — but the record then reads
|
|
518
|
+
**`verdict: "attested"`**, not `verified`, and says so on every surface. `verified: true` in the
|
|
519
|
+
envelope means every scenario claim came from a test run.
|
|
520
|
+
|
|
521
|
+
loam does not claim agent answers are impossible. It claims they are *distinguishable*.
|
|
522
|
+
|
|
523
|
+
## Why there is no task list
|
|
524
|
+
|
|
525
|
+
There is no `tasks.md`, and that is a decision rather than an omission.
|
|
526
|
+
|
|
527
|
+
A task list authored beside a spec is a second mutable state. It drifts — the spec changes, the
|
|
528
|
+
checklist does not, and now two documents describe the work and only one of them is checked. The
|
|
529
|
+
question a task list answers is a good one; the file is the wrong place to answer it.
|
|
530
|
+
|
|
531
|
+
loam derives the answer instead, at three altitudes:
|
|
532
|
+
|
|
533
|
+
- **What to do next**, from `loam status`: the artifact table plus an ordered `next[]`, recomputed
|
|
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.
|
|
538
|
+
- **What to build**, from `loam delta <FEAT> --service <svc>`: the intent, every requirement body
|
|
539
|
+
and every Given/When/Then line reproduced verbatim, the endpoints added or retired, and the edges
|
|
540
|
+
around it. That output *is* the coding task, and it is regenerated from the spec each time rather
|
|
541
|
+
than transcribed from it once.
|
|
542
|
+
|
|
543
|
+
Then `loam gherkin` turns the scenarios into digest-stamped `.feature` files — a checklist that
|
|
544
|
+
executes. A valid Markdown table becomes the `Examples:` of a Scenario Outline, so a permission or
|
|
545
|
+
status-code matrix remains one requirement scenario rather than twenty copied ones. A box you tick
|
|
546
|
+
is a claim about work; a scenario that goes green is evidence of it.
|
|
547
|
+
|
|
548
|
+
The same reasoning is why `intent.md` is a real artifact and a `design.md` is not. The intent is
|
|
549
|
+
input — a human's statement of the problem, which nothing can derive. The design is the
|
|
550
|
+
`delta.likec4`, which is checkable: its elements and edges resolve against the fleet map, its
|
|
551
|
+
operations against the contracts. A prose design document beside those would be a third description
|
|
552
|
+
of the same change, and the only one nothing grades.
|
|
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
|
+
|
|
563
|
+
## Picking the work back up
|
|
564
|
+
|
|
565
|
+
The three states worth naming, because each has one command:
|
|
566
|
+
|
|
567
|
+
**You joined halfway, or lost the session.** `loam status --json` — for the fleet, or `loam status
|
|
568
|
+
<FEAT> --json` for one feature. It is derived, so it is correct about a repository you have never
|
|
569
|
+
seen, and `next[]` tells you whether the work is even to continue this feature.
|
|
570
|
+
|
|
571
|
+
**Somebody else is mid-merge.** `archive` takes an advisory lock on the docs repo for the whole
|
|
572
|
+
plan-and-commit; a second writer refuses with `docs-busy` rather than interleaving. Re-run when it
|
|
573
|
+
finishes.
|
|
574
|
+
|
|
575
|
+
**A merge was killed mid-write.** An intent journal is fsynced before the first file swap, and the
|
|
576
|
+
next `archive` or `unarchive` recovers from it under the lock: an interrupted archive is undone, an
|
|
577
|
+
interrupted unarchive is *finished* — the merged text it was replacing is written down nowhere else.
|
|
578
|
+
Where a file has been edited since, it refuses with `commit-interrupted` rather than writing over
|
|
579
|
+
the evidence. `loam doctor` reports that state instead of calling the repo healthy.
|
|
580
|
+
|
|
581
|
+
And the fourth, which is not recovery but is the same instinct: **you do not know what a command
|
|
582
|
+
will do.** `archive`, `unarchive` and `rebase` all take `--dry-run`, and `explore`, `status`,
|
|
583
|
+
`list`, `show`, `adopt`, `delta`, `dependencies`, `doctor`, `validate` and `instructions` write
|
|
584
|
+
nothing at all, ever.
|
|
585
|
+
|
|
586
|
+
## Command notes
|
|
587
|
+
|
|
588
|
+
One note per command that has behaviour a table cannot hold — the refusals, the flag interactions,
|
|
589
|
+
and the reason each is shaped the way it is. [README's command table](README.md#commands) is the
|
|
590
|
+
index: every command and every flag, one row each.
|
|
591
|
+
|
|
592
|
+
**`loam init`** — `--docs` **joins** an existing docs repo; `--create` is required to make a new
|
|
593
|
+
one, so a mistyped path cannot scaffold a second source of truth. `--service <id>` is what a
|
|
594
|
+
**service** repo needs: it is the binding `vouch`, `gherkin` and
|
|
595
|
+
`verify --service --record`/`--results` require before they will write for that service.
|
|
596
|
+
`--tools <ids>|all` overrides the tool scan; `--no-commands` / `--no-skills` drop one delivery — and
|
|
597
|
+
the two are exclusive, refused together, since one names the files to write and the other suppresses
|
|
598
|
+
them. `docsDir` is stored exactly as you typed it and resolved against `loam.json`, so a relative
|
|
599
|
+
`../docs-repo` works on every clone — and `--docs` wins only when you actually pass it, so a re-run
|
|
600
|
+
in a wired repo keeps the pointer its committed `loam.json` already spells, `--create` included
|
|
601
|
+
(`docsDirSource: "flag" | "config" | "default"` in `--json` says which).
|
|
602
|
+
|
|
603
|
+
**`loam status`** — the question an agent has when it joins a repo halfway or loses its session.
|
|
604
|
+
Artifacts come back `missing`/`blocked`/`draft`/`ready`/`done`, and `next[]` is ordered, each entry
|
|
605
|
+
a stable code plus its explicit `execution` plan. When this repository's `loam.json` binds a boundary the
|
|
606
|
+
fleet already has, that boundary's own steps are partitioned to the front of the fleet worklist
|
|
607
|
+
before its ten-entry cap applies — a stable partition, not a sort, so every other boundary keeps the
|
|
608
|
+
order an unbound reader sees and the work you are standing in can no longer be the entry elided. It
|
|
609
|
+
takes the union of what `validate --feature` errors on and what `archive` refuses to merge, so it
|
|
610
|
+
may be redder than either and is never greener than both. There is no state file to go stale.
|
|
611
|
+
|
|
612
|
+
**`loam new`** — the scaffold passes `loam validate --feature` with **zero errors**, and its
|
|
613
|
+
unauthored state is named in warnings that *gate the archive*: `intent.empty` until you write the
|
|
614
|
+
Why, `scaffold.placeholder` while any template text survives (a feature that introduces a service
|
|
615
|
+
also starts on `c4.uncovered`, until its `arch.spec.md` delta carries a `Covers:` line for the
|
|
616
|
+
element the delta adds). An untouched scaffold can never fold into the living docs — `loam archive`
|
|
617
|
+
refuses it until a person authors the content, or deliberately overrides with `--approve`. For a
|
|
618
|
+
requirements-only feature you delete the scaffolded `delta.likec4` yourself — `new` says so on the
|
|
619
|
+
way out.
|
|
620
|
+
|
|
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
|
|
624
|
+
an orientation block before any of that: how many of those targets are required and still
|
|
625
|
+
outstanding, named, and what each flag in the artifact table means — `MISSING` required and absent,
|
|
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).
|
|
634
|
+
|
|
635
|
+
**`loam diff`** — the base state is read out of the docs repo's own git history
|
|
636
|
+
(`rev-parse`/`ls-tree`/`show`, read-only, no checkout), so it refuses (`repository-unavailable`)
|
|
637
|
+
when the docs repo has no history to ask and (`unknown-target`) when `--base` resolves to no commit
|
|
638
|
+
there. What it reports is the *joined*, fleet-meaningful delta — a removed operation is graded
|
|
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
|
|
644
|
+
unreadable on either side suspends that subject's axis and exits 1, because "nobody could look" must
|
|
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.
|
|
654
|
+
For the byte-level OpenAPI breaking-change catalogue, run oasdiff on the two states of one contract:
|
|
655
|
+
`git -C <docs> show <ref>:./services/<id>/openapi.yaml > base.yaml && oasdiff breaking base.yaml <docs>/services/<id>/openapi.yaml`
|
|
656
|
+
(the `./` resolves the path relative to the docs directory rather than the git root, so this holds
|
|
657
|
+
when the docs repo lives inside a larger repository) — loam deliberately does not reimplement those
|
|
658
|
+
checks.
|
|
659
|
+
|
|
660
|
+
**`loam validate`** — `--base <ref>` takes `--all` and nothing else (a positional target,
|
|
661
|
+
`--service` or `--feature` beside it is refused `invalid-option`, since two scopes is a
|
|
662
|
+
contradiction rather than a narrowing), and it narrows the run to the boundaries, features and
|
|
663
|
+
landscape the branch changed since a base git ref of the docs repo — which is the only setting
|
|
664
|
+
both passing on the first day of adoption and tightening after it, and which for that reason
|
|
665
|
+
grades nothing outside the branch: the consumer whose living requirement still names an operation
|
|
666
|
+
this branch removed is not in scope, so that finding is `loam diff`'s and never this run's, and a
|
|
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.
|
|
672
|
+
|
|
673
|
+
**`loam gherkin`** — a feature's changed requirements, or (without a feature) the full living suite.
|
|
674
|
+
Deterministic, digest-stamped, regeneration-owned; run in the service's own repo.
|
|
675
|
+
|
|
676
|
+
**`loam rebase`** — writes `Based-On:` on every MODIFIED/REMOVED requirement and `x-loam-based-on`
|
|
677
|
+
on every operation in the contract delta that the living docs already hold; what this feature is
|
|
678
|
+
*adding* has nothing to pin against, and the output says so per item. On the requirement axis that
|
|
679
|
+
stops a second feature rewriting the same requirement from landing on top of the first in silence;
|
|
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,
|
|
698
|
+
digest-matched, so only a green run confirms one, and the record writes down which file it read
|
|
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.
|
|
719
|
+
|
|
720
|
+
**`loam unarchive`** — it refuses rather than guesses: `snapshot-stale` when a merged file moved
|
|
721
|
+
since (`--force` says that was meant), and `snapshot-corrupt` when a pre-image no longer hashes to
|
|
722
|
+
what the archive recorded for it, which `--force` deliberately does **not** override — the damage
|
|
723
|
+
there is to the undo itself.
|
|
724
|
+
|
|
725
|
+
**`loam audit-openspec` / `loam migrate-openspec`** — the audit reports capabilities, active and
|
|
726
|
+
archived changes, counts, RENAMED and unsupported shapes, and every capability→service decision
|
|
727
|
+
still needing a human. The migration validates your completed mapping against a re-read of the
|
|
728
|
+
source, and with `--apply --target <empty-dir>` materializes **staged migration docs** into a
|
|
729
|
+
separate directory. `--map` is required — there is no one-shot form.
|
|
730
|
+
|
|
731
|
+
### How `archive` protects the source of truth
|
|
732
|
+
|
|
733
|
+
`archive` is the command that merges a feature into the living source of truth and records the
|
|
734
|
+
reversible pre-images. Other commands also write canonical artifacts (`vouch`, `rebase`, `verify`,
|
|
735
|
+
`new`, and `init`), but archive has the strongest multi-file transaction contract: it takes an
|
|
736
|
+
advisory lock on the docs repo for the whole plan-and-commit (a second writer — another `archive`,
|
|
737
|
+
an `unarchive`, a `rebase` — refuses with `docs-busy` rather than interleaving), computes the whole
|
|
738
|
+
merge before touching disk, commits each file through a temp file swapped in atomically after
|
|
739
|
+
re-checking the bytes it read (a rename for an overwrite, a no-clobber `link(2)` for a create, so a
|
|
740
|
+
file that appeared after the plan was computed is never buried), and rolls back what it already
|
|
741
|
+
swapped if any part fails. It also records the bytes it overwrote inside the archived feature — with
|
|
742
|
+
a digest of each pre-image, so `unarchive` can tell an intact one from an edited one — which is what
|
|
743
|
+
makes `unarchive` an undo rather than a guess. A process **killed mid-commit** is covered too: an
|
|
744
|
+
intent journal (`.loam-commit`) is fsynced before the first swap, and the next `archive`/`unarchive`
|
|
745
|
+
recovers from it under the lock, rewriting each half-written file from the snapshot — an interrupted
|
|
746
|
+
archive is undone, an interrupted unarchive is *finished*, because the merged text it was replacing
|
|
747
|
+
is written down nowhere else — or refusing with `commit-interrupted` when a file has been edited
|
|
748
|
+
since. `loam doctor` reports that state rather than calling the repo healthy.
|
|
749
|
+
|
|
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
|
|
752
|
+
does not — a living document still holding git conflict markers (`merge-failed`) and a living
|
|
753
|
+
requirement that has strayed outside `## Requirements` (`living-outside-requirements`). loam's docs
|
|
754
|
+
files must be **UTF-8** for the same reason: undecodable bytes refuse the merge (`merge-failed`,
|
|
755
|
+
naming the file) instead of being rewritten as U+FFFD, and a non-UTF-8 `openapi.yaml` grades
|
|
756
|
+
`openapi.invalid`. **`verify` does not gate `archive`** — coherence gates because loam *computed*
|
|
757
|
+
it; a verdict is somebody's word about code loam never read, and a gate in front of shipping only
|
|
758
|
+
teaches everyone that the cheapest way past it is to say yes.
|
|
759
|
+
|
|
760
|
+
API retirement is explicit and reviewable: a feature marks the exact path/method operation with
|
|
761
|
+
`x-loam-remove: true` — **inside the operation being retired, beside its `operationId`** — and
|
|
762
|
+
removes the governing requirement in the same delta. A marker written one level up, at path level
|
|
763
|
+
beside the methods, addresses no operation and retires nothing; archive refuses it
|
|
764
|
+
(`openapi.remove-marker-path-level`) rather than publishing a meaningless key into the fleet's
|
|
765
|
+
living contract. Validation refuses stale, mismatched, or unjustified markers; archive deletes the
|
|
766
|
+
method without persisting the marker or garbage-collecting components, and reports the removals in
|
|
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.
|
|
786
|
+
|
|
787
|
+
## The MCP server
|
|
788
|
+
|
|
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
|
|
798
|
+
`loam://orientation` and every `loam://instructions/<name>` page as Markdown resources, so the host
|
|
799
|
+
can load version-matched guidance progressively; `loam://instructions/loam-check/compact` omits the
|
|
800
|
+
large fix table and pairs with `loam explain <code>`. A typical host entry:
|
|
801
|
+
|
|
802
|
+
```json
|
|
803
|
+
{
|
|
804
|
+
"mcpServers": {
|
|
805
|
+
"loam": { "command": "loam", "args": ["mcp"] }
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
`loam init --mcp` writes that file at the repository root for you, choosing `npx --no loam mcp` over
|
|
811
|
+
the bare binary shown above when `node_modules/.bin/loam` is there — the per-repo devDependency
|
|
812
|
+
install, whose binary is on no PATH a host inherits. It is opt-in, and it never merges: an
|
|
813
|
+
`.mcp.json` that already exists is reported skipped, byte for byte, with the `loam` key printed for
|
|
814
|
+
you to paste. `loam init --mcp-author` writes the same entry with `mcp --author`: that explicit mode
|
|
815
|
+
adds `new`, `rebase`, `gherkin`, and archive planning with `--dry-run` enforced by the server.
|
|
816
|
+
|
|
817
|
+
There is one machine contract, not two: every tool declares the common envelope `outputSchema` and
|
|
818
|
+
every result carries the command's `--json` envelope **verbatim** in text plus structured content.
|
|
819
|
+
Even malformed command stdout gets a structured `internal` envelope, so the schema has no missing
|
|
820
|
+
branch. The MCP error flag
|
|
821
|
+
following the envelope's `ok` — so `ok` and the stable `error.code` strings mean exactly what they
|
|
822
|
+
mean at the CLI, and everything above about branching on codes applies unchanged. (Not the exit
|
|
823
|
+
code, deliberately: `doctor`, `validate` and `gate` grade — they can exit 1 while answering
|
|
824
|
+
`ok: true` — and a graded verdict rendered as a failed call would be a verdict discarded.) The
|
|
825
|
+
server serves the repository it is launched in (each call resolves `loam.json` from that directory,
|
|
826
|
+
exactly as the CLI would) and never changes directory — a host that launches it in the wrong place
|
|
827
|
+
gets coherent `no-config` envelopes, not silence. Calls run strictly one at a time, so a fleet-wide
|
|
828
|
+
`loam_validate` blocks the queue for its duration; MCP requests carry ids and hosts tolerate the
|
|
829
|
+
latency. Even author mode excludes `vouch`, verification recording and a committing archive:
|
|
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.
|