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