@ybotok/loam 0.1.0-beta.2 → 0.2.0-alpha.1
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 +2570 -61
- 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 +494 -0
- package/SCHEMA.md +2362 -245
- 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 +317 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +161 -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 +251 -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 +82 -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 +194 -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 +236 -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 +250 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +219 -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/agent/agents-stamp.js +155 -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 +334 -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/read.js +239 -0
- 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 +47 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +282 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +88 -0
- package/dist/core/c4/likec4.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 +183 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/resolve/service.js +113 -0
- package/dist/core/c4/resolve/service.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 +126 -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 +172 -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 +251 -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/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 +59 -55
- 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 +132 -77
- 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 +118 -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 +192 -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 +236 -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 +171 -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 +187 -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 +235 -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 +55 -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 -291
- 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 -254
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1591
- 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 -343
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2065
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js +0 -68
- 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/brief.js +0 -733
- 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 -559
- 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 -479
- 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 -720
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -436
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -481
- 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 -1104
- 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
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The family registry: `loam explain`'s content for the four code families no
|
|
3
|
+
* fix table anywhere grades — `doctor.*`, `next.*`, `diff.*` and `gate.*`.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS IS NOT THE DUPLICATION fix-tables.ts FORBIDS. That module's header
|
|
6
|
+
* argues against a second hand-maintained copy of the /loam-check prose, and
|
|
7
|
+
* the argument is right: the tables ship in the binary, test/codes-drift.test.ts
|
|
8
|
+
* holds every emitted finding code against them, and a registry restating them
|
|
9
|
+
* would be free to trail the bytes `loam instructions loam-check` prints. None
|
|
10
|
+
* of that applies here. These 65 codes have no fix-table row in any workflow
|
|
11
|
+
* body — /loam-check grades DOCUMENTS, and these four families grade a
|
|
12
|
+
* repository's wiring (`doctor`), a recommendation (`next`), a change between
|
|
13
|
+
* two refs (`diff`) and a deploy question (`gate`). There is nothing to trail:
|
|
14
|
+
* this registry is not a second copy, it is the only copy. The precedent is the
|
|
15
|
+
* sibling module refusals.ts, a hand-written map that is the sole source for
|
|
16
|
+
* the `ErrorCode` meanings for exactly the same reason — their prose lives in
|
|
17
|
+
* doc comments, which are erased, so there is no runtime constant to read.
|
|
18
|
+
*
|
|
19
|
+
* What that costs, stated rather than hidden: nothing mechanical proves an
|
|
20
|
+
* entry below still matches the message its emitter prints. Every meaning and
|
|
21
|
+
* every fix here was written FROM the emitter — `doctor` findings carry a `fix`
|
|
22
|
+
* field of their own (core/doctor/), a `next` step carries a `statement` and a
|
|
23
|
+
* literal `command` (core/status/), the `DiffCode` union carries a doc comment
|
|
24
|
+
* per member (core/diff/semantic.ts) — and the wording is theirs, not a
|
|
25
|
+
* paraphrase invented here. Two guards catch the two failures that CAN be
|
|
26
|
+
* caught: test/explain.test.ts asserts no code below is also answered by a fix
|
|
27
|
+
* table (the two sources must never be able to disagree), and
|
|
28
|
+
* test/agent-commands-runnable.test.ts parses every backticked `loam …` in this
|
|
29
|
+
* file against the real program, so a fix naming a command loam does not have —
|
|
30
|
+
* or a flag it does not declare — fails at gate time. A two-token span is a
|
|
31
|
+
* NAME rather than an invocation there and is only checked for the command
|
|
32
|
+
* existing, so a fix that means an invocation must carry its arguments.
|
|
33
|
+
*
|
|
34
|
+
* `severityNote` is the EMITTER's own word, not a fix table's parenthetical:
|
|
35
|
+
* `doctor` grades blocker/warning, `diff` and `gate` grade ok/warn/error, and a
|
|
36
|
+
* `next` step is graded not at all — it is a recommendation, so its note is
|
|
37
|
+
* `step`. Where a code's severity depends on what was found (`doctor.docs-locked`,
|
|
38
|
+
* `gate.partners-unknown`) the note says so in prose, the way the tables' own
|
|
39
|
+
* long notes do (`warn here; error at archive plan time`).
|
|
40
|
+
*
|
|
41
|
+
* `openspec.*` and `mapping.*` — 49 codes — are deliberately NOT here, and the
|
|
42
|
+
* reason is in test/explain.test.ts beside their backlog entries: they are the
|
|
43
|
+
* only codes in the vocabulary whose subject is not a loam document at all.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* `loam doctor` — the preflight. Every finding here already carries a `fix`
|
|
47
|
+
* field in doctor's own report (core/doctor/doctor.ts, config.ts, agents.ts,
|
|
48
|
+
* residue.ts); these rows say the same thing without a repository in front of
|
|
49
|
+
* them, which is the whole difference between a report and a lookup.
|
|
50
|
+
*/
|
|
51
|
+
const DOCTOR = {
|
|
52
|
+
scope: "loam doctor",
|
|
53
|
+
codes: {
|
|
54
|
+
"doctor.config-missing": { severityNote: "blocker", meaning: "No loam.json at or above the working directory, so nothing says which docs repo this checkout belongs to — every other command refuses with `no-config` until there is one.", fix: "Run `loam init --docs <dir>` in this repository; add `--create` when the docs repo does not exist yet." },
|
|
55
|
+
"doctor.config-invalid": { severityNote: "blocker", meaning: "A loam.json is there and `parseConfig` — the same loader every command uses — refuses it; the finding carries the parser's own words. doctor deliberately has no second validator: the one it used to carry accepted a config the commands rejected, and reported a healthy repo in which nothing could run.", fix: "Repair the file the finding names, or delete it and re-run `loam init`." },
|
|
56
|
+
"doctor.docs-missing": { severityNote: "blocker", meaning: "`docsDir` resolves to something that is missing or is not a directory — the docs repo was never cloned, or the path is wrong.", fix: "Fix `docsDir` in the loam.json the finding names, clone the docs repo to that path, or run `loam init --docs <dir> --create`." },
|
|
57
|
+
"doctor.services-missing": { severityNote: "blocker", meaning: "`docsDir` is a directory and holds no `services/`, so it is some other directory — most often the service repo itself, after a typo in the pointer.", fix: "Point `docsDir` at the shared docs repo, or run `loam init --docs <dir> --create` to scaffold one. Do not scaffold a second source of truth beside the real one." },
|
|
58
|
+
"doctor.docs-absolute": { severityNote: "warning", meaning: "`docsDir` is stored as an absolute path and loam.json is committed, so the pointer names a directory that exists on exactly one machine: it works for whoever ran `loam init` and for nobody who clones the repo afterwards.", fix: "Rewrite `docsDir` as a path relative to the loam.json holding it, such as `../docs`." },
|
|
59
|
+
"doctor.docs-unreadable": { severityNote: "warning", meaning: "The docs repo exists and this process cannot read it, so every command that reads the fleet will fail or report an empty one.", fix: "Grant read access to the directory the finding names — check ownership and mode." },
|
|
60
|
+
"doctor.docs-readonly": { severityNote: "warning", meaning: "The docs repo is readable and not writable: read-only commands work and the writing ones do not.", fix: "Grant write access if you need `loam new`, `loam adopt` or `loam archive`. A read-only checkout is a legitimate state for a reviewer, which is why this is a warning." },
|
|
61
|
+
"doctor.landscape-missing": { severityNote: "warning", meaning: "architecture/landscape.likec4 is missing, and it is the one artifact every cross-service check reads — nothing about who calls whom can be checked without it.", fix: "Create it with one element per service and an edge per call: `loam init --create` writes the empty map, and `loam seed --from fleet.yaml` templates one from stated facts." },
|
|
62
|
+
"doctor.landscape-unreadable": { severityNote: "blocker", meaning: "The landscape file exists and the read itself failed — permissions or an I/O error, carried verbatim in the message.", fix: "Check permissions on the path the finding names." },
|
|
63
|
+
"doctor.landscape-merge-conflict": { severityNote: "blocker", meaning: "The landscape still contains merge conflict markers, named by line. Checked BEFORE the parser on purpose: both sides of a conflict can be syntactically valid LikeC4, so the file sometimes parses and is still two halves of two different maps.", fix: "Resolve the conflict keeping BOTH services' elements and edges — the usual cause is several services adopted into one map in the same week — then re-run `loam doctor`." },
|
|
64
|
+
"doctor.landscape-invalid": { severityNote: "blocker", meaning: "The landscape exists, carries no conflict markers, and does not parse; the message quotes the first parser error with its line and counts the rest.", fix: "Fix the file — every fleet-wide check is blind until it parses." },
|
|
65
|
+
"doctor.likec4-config-missing": { severityNote: "warning", meaning: "The docs repo has no likec4.config.json, so the tree is not a loadable LikeC4 workspace: every service model and feature delta declares its own `specification` block, and a renderer pointed at the repo root merges them and reports every declaration as a duplicate. No loam check reads this file — the repo is only unrenderable, which is why it is a warning.", fix: "Write the project file the finding prints; it scopes the root project to architecture/, so `npx likec4 start` in the docs repo renders the fleet map. A service model or a feature delta is rendered by pointing the renderer at its own directory instead." },
|
|
66
|
+
"doctor.docs-locked": { severityNote: "warning while a live process holds it; blocker when its holder is dead or it names none", meaning: "A `.loam-lock` is present. Held by a running process it is a fact about right now. Held by a process that no longer exists on this host — or unreadable, so no holder can be named at all — nothing is ever going to release it, and every writing command refuses with `docs-busy` forever.", fix: "Wait and re-run while the holder is alive; nothing is read or written while it is held. Delete the lock file the finding names when its holder is dead or unnameable, then run `loam doctor` again for an interrupted commit underneath it." },
|
|
67
|
+
"doctor.commit-unreadable": { severityNote: "blocker", meaning: "A `.loam-commit` journal is present and cannot be read: a commit was interrupted and the one record of which files it had already written is unreadable.", fix: "Hand this to a human — compare the root's files against version control before running any loam command that writes there. Every journaled writer refuses with `commit-interrupted` while it is present." },
|
|
68
|
+
"doctor.commit-interrupted": { severityNote: "blocker", meaning: "A journaled writer — archive, unarchive, rebase, vouch, new, gherkin, or a recording verify — was killed mid-commit. The message names the host, pid and time, and every file or directory move that may be half-done. This is the surface that used to report a healthy repo over half-merged living docs.", fix: "Re-run the command the finding names: it recovers first, under the lock, rolling the staged bytes forward, and refuses rather than guessing if a file has been edited since. An interrupted `loam unarchive` is FINISHED, never undone — the merged text it was replacing is written down nowhere." },
|
|
69
|
+
"doctor.staging-temps": { severityNote: "warning", meaning: "Orphaned `.loam-*.tmp` scratch files from a killed writer, never linked into place — so nothing reads them and nothing depends on them. A journal's own recorded temps are excluded, because those are the durable copy its roll-forward recovery renames in. Litter, not damage.", fix: "The next journaled writer through that root removes its own; delete any that remain. They cost disk and nothing else." },
|
|
70
|
+
"doctor.inventory-unreadable": { severityNote: "warning", meaning: "The config and the docs repo are both fine and enumerating `services/` or `features/` threw, so doctor's fleet counts — and its verdict on the service binding — are about a fleet nobody could read.", fix: "Check that services/ and features/ under the docs repo are readable directories." },
|
|
71
|
+
"doctor.service-unbound": { severityNote: "warning", meaning: "loam.json declares no `service`, so nothing binds this checkout to one governed boundary and the service-repo checks have nothing to run against — `sources.stale`, a recording `loam verify`, `loam gherkin`. Deliberately not emitted inside the docs repo itself, where having no binding is the correct state rather than a gap.", fix: "Run `loam init --docs <dir> --service <id>` here." },
|
|
72
|
+
"doctor.service-unknown": { severityNote: "warning", meaning: "loam.json names a `service` the fleet has no services/<id>/ for — and the fleet WAS read, so this is a claim about a real inventory rather than one nobody could take.", fix: "Run `loam adopt --service <id>` to onboard it, or fix `service` in loam.json." },
|
|
73
|
+
"doctor.agent-files-missing": { severityNote: "warning", meaning: "Some of the command and skill files this loam lays down for the repo's recorded tools and profile are not here: the repo was initialized by an older loam, or they were deleted. An out-of-date command set costs entry points, never a refusal, which is why it is a warning.", fix: "Re-run `loam init --docs <dir> --tools <ids>` here. It creates absent files, refreshes only pointers whose current bytes still match their recorded digest, preserves every customized file, and keeps this repo's service binding." },
|
|
74
|
+
"doctor.agent-files-stale": { severityNote: "warning", meaning: "Command or skill files that ARE here carry no loam stamp, or one older than this binary, so the protocol and code tables they instruct an agent with may describe a loam that no longer exists. Staleness reads only the stamp; safe refresh is a separate digest check performed by init.", fix: "Re-run `loam init` to refresh a pointer only when its recorded digest still matches. Review a customized file against the current body yourself and update its stamp, or delete it so init can recreate it; your edits always outrank the template." },
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* `loam status` — both forms print `next[]`, and each entry carries a `code` to
|
|
79
|
+
* branch on, one sentence, and the literal `command` to run. So the "what to
|
|
80
|
+
* do" column is genuinely empty for this whole family: the step IS the action,
|
|
81
|
+
* and each `fix` below names the step's own command rather than inventing a
|
|
82
|
+
* second instruction beside it.
|
|
83
|
+
*/
|
|
84
|
+
const NEXT_STEPS = {
|
|
85
|
+
scope: "loam status",
|
|
86
|
+
codes: {
|
|
87
|
+
"next.adopt-bound": { severityNote: "step", meaning: "The fleet form's first entry: this repository's loam.json says it is a service the fleet has no services/<id>/ for, so nothing about the boundary you are standing in is written down yet. Ahead of every other service's adoption work, because it is the only step that is about HERE.", fix: "The step IS the action: run its `command`, `loam adopt --service <id> --json`." },
|
|
88
|
+
"next.author-landscape": { severityNote: "step", meaning: "The first rung of the first-hour ladder, over a fleet with no services and no features: architecture/landscape.likec4 does not exist, or is still the scaffold's untouched map with no service drawn on it.", fix: "The step IS the action: run its `command` — `loam init --create` when the file is absent, `loam seed --from fleet.yaml` when it is the untouched scaffold. loam never guesses who calls whom." },
|
|
89
|
+
"next.bind-service": { severityNote: "step", meaning: "First-hour ladder: no service repository is bound to this fleet yet, so no command can ever run from a service's own checkout.", fix: "The step IS the action: run its `command`, `loam init --docs <path-to-this-docs-repo> --service <service-id>`, from a service's own repo, and commit the loam.json it writes." },
|
|
90
|
+
"next.adopt-first": { severityNote: "step", meaning: "First-hour ladder: services/ is empty, so nothing about any service is written down and nothing can be graded against anything.", fix: "The step IS the action: run its `command`, `loam adopt --service <service-id> --json`; the brief it prints walks an agent through writing the baseline docs as draft." },
|
|
91
|
+
"next.adopt": { severityNote: "step", meaning: "One service in the fleet has no spec.md — nothing about it is written down, so no feature can be graded against it. One entry per undocumented service.", fix: "The step IS the action: run its `command`, `loam adopt --service <id> --json`." },
|
|
92
|
+
"next.complete-service": { severityNote: "step", meaning: "Adoption does not end at spec.md: a service has one and no model.likec4, the state archive warns about and the fleet gate reports incomplete until something models it.", fix: "The step IS the action: run its `command`, `loam validate --service <id> --json`." },
|
|
93
|
+
"next.feature": { severityNote: "step", meaning: "One feature in flight that is not ready to ship, named with the stage it sits at and what it is missing — or, when it is blocked by another feature, the features it is waiting on.", fix: "The step IS the action: run its `command`, `loam status <FEAT-id> --json`, for that feature's own next list." },
|
|
94
|
+
"next.archive": { severityNote: "step", meaning: "In the fleet form, a feature that is authored and verified: ship it, and everything queued behind it is released. In a feature's own list it is always the last entry, saying the feature ships once everything above it is done.", fix: "The step IS the action: run its `command`, `loam archive <FEAT-id> --dry-run --json`; the dry run writes nothing and lists every file the merge would touch." },
|
|
95
|
+
"next.elided": { severityNote: "step", meaning: "The fleet list is capped, and this says how many steps of the same kinds it left out. The list is ordered most-unblocking first, so what was elided is the least urgent — a list nobody reads is not navigation.", fix: "The step IS the action: run its `command`, `loam list --json`, or work down the printed list and run status again." },
|
|
96
|
+
"next.fleet-clean": { severityNote: "step", meaning: "Services exist, nothing is in flight, and nothing is owed. Only that truthful case: over an EMPTY fleet the same sentence was vacuously true, and the first-hour ladder owns that repository now.", fix: "The step IS the action: run its `command`, `loam validate --all --json`, then start the next feature." },
|
|
97
|
+
"next.fleet-gate": { severityNote: "step", meaning: "The last entry of every fleet list, and always present: `status` grades nothing, so the least it can do is say where grading happens — `loam validate --all` is the gate this repository has to pass and the one CI runs.", fix: "The step IS the action: run its `command`, `loam validate --all --json`." },
|
|
98
|
+
"next.recover-commit": { severityNote: "step", meaning: "Always first, and never elided by the fleet form's cap: a journaled writer was killed mid-commit, so everything below this step is derived from files that may be half-written. Where the journal itself cannot be read, nothing below can be trusted until a human compares the living docs against version control.", fix: "The step IS the action: run its `command` — the interrupted command re-run, which recovers first under the lock, or `loam doctor --json` when the journal is unreadable and no loam command can repair it." },
|
|
99
|
+
"next.archived": { severityNote: "step", meaning: "The whole `next[]` for a feature that already shipped: it is archived, and its delta is folded into the living docs.", fix: "The step IS the action: run its `command`, `loam show <FEAT-id> --json`." },
|
|
100
|
+
"next.author-intent": { severityNote: "step", meaning: "The feature has no intent document — what it is for, in prose, before anything is derived from it.", fix: "The step IS the action: write the file the step names, then run its `command`, `loam validate <FEAT-id> --json`. The command never writes the artifact: loam does not author." },
|
|
101
|
+
"next.touch-service": { severityNote: "step", meaning: "The feature carries no per-service delta at all, so nothing says which governed boundaries it changes.", fix: "The step IS the action: run its `command`, `loam list services --json`, then add specs/<service>/spec.md for every service the feature changes." },
|
|
102
|
+
"next.author-spec": { severityNote: "step", meaning: "One service the feature touches has no requirement delta — the ADDED / MODIFIED / REMOVED requirements the feature makes to that service, each with a scenario.", fix: "The step IS the action: write the file the step names, then run its `command`, `loam delta <FEAT-id> --service <id> --json`, which projects the delta onto the living document." },
|
|
103
|
+
"next.author-openapi": { severityNote: "step", meaning: "Nothing gives one of the feature's services a living openapi.yaml, so this feature is the only thing that can write down its API surface. Deliberately not phrased as the service being absent from the living docs: a service adopted without a contract is the commoner case, and that wording sent readers looking for a directory that was right there.", fix: "The step IS the action: write the file the step names, then run its `command`, `loam delta <FEAT-id> --service <id> --json`." },
|
|
104
|
+
"next.author-scenarios": { severityNote: "step", meaning: "Requirements in one service's delta carry no `#### Scenario:`, so they generate no test and no verify claim — a promise that reaches neither the suite nor the done-check. One entry per service and never per requirement, because a delta with forty bare requirements would otherwise BE the payload.", fix: "The step IS the action: write a scenario under each bare requirement, then run its `command`, `loam delta <FEAT-id> --service <id> --json`." },
|
|
105
|
+
"next.rebase": { severityNote: "step", meaning: "The feature carries requirements or operations with no baseline pin, on any of the three axes; until they have one the merge cannot tell what it EDITS from what it merely quotes.", fix: "The step IS the action: run its `command`, `loam rebase <FEAT-id>`." },
|
|
106
|
+
"next.archive-first": { severityNote: "step", meaning: "The feature builds on other features still in flight, which have to archive before it can.", fix: "The step IS the action: run its `command`, `loam dependencies <FEAT-id> --json`." },
|
|
107
|
+
"next.fix-coherence": { severityNote: "step", meaning: "The feature has findings that stop it, named starting with the first. Everything EITHER gate refuses on is counted, so a warning marked as gating archive is in the tally even though `validate` grades the feature valid — which is why its exit code alone will not show you why archive refuses.", fix: "The step IS the action: run its `command`, `loam validate <FEAT-id> --json`." },
|
|
108
|
+
"next.generate-tests": { severityNote: "step", meaning: "The feature's delta for a service carries scenarios no test run has answered yet. `loam gherkin` writes the .feature files whose green run is the only thing that may answer a `scenario.tested` claim, and it writes into the service's own repository — so the step names which repo to run it in when that is not this one.", fix: "The step IS the action: run its `command`, `loam gherkin <FEAT-id> --service <id>`, from that service's own checkout." },
|
|
109
|
+
"next.verify": { severityNote: "step", meaning: "The done-check has not been started, or its record cannot be used. Five situations share this code because they share the work — nothing recorded, a verification.yaml that does not read as a record, a record the feature has moved out from under, a record that answers no claims at all, and a feature with nothing to derive a checklist from yet — and the step's own statement says which.", fix: "The step IS the action: run its `command`, `loam verify <FEAT-id> --json`, which derives the checklist and prints what it asks. A record nothing can read is repaired or deleted by hand: nothing overwrites it while it is unreadable." },
|
|
110
|
+
"next.verify-unconfirmed": { severityNote: "step", meaning: "Claims on the feature are open — unconfirmed or unanswered — and this repository is not one of the services that owes an answer, so the recording form is not a step anyone can take from here.", fix: "The step IS the action: run its `command`, `loam verify <FEAT-id> --json`. The open claims are closed from each affected service's own repository." },
|
|
111
|
+
"next.attest-service": { severityNote: "step", meaning: "Claims are open AND this repository is one of the services that owes an answer, so the recording form is nameable here: `--record --service` binds the answers to this repo's HEAD and refuses anywhere else.", fix: "The step IS the action: run its `command`, `loam verify <FEAT-id> --record answers.json --service <id>`, answering the claims filed under this service; the rest belong to their own repositories." },
|
|
112
|
+
"next.verify-attested": { severityNote: "step", meaning: "Every claim is answered and some scenario claims are confirmed on an agent's word rather than on a test run (`verify.scenario-attested`) — complete work resting on an assertion, which is what `ready` has always meant here.", fix: "The step IS the action: run its `command`, `loam verify <FEAT-id> --results <cucumber-report.json>`, and the record stops resting on an assertion." },
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* `loam diff` — what CHANGED between a base git ref of the docs repo and the
|
|
117
|
+
* working tree, not what is WRONG with either. That is why most rows below have
|
|
118
|
+
* no repair: the meanings are the `DiffCode` union's own doc comments
|
|
119
|
+
* (core/diff/semantic.ts), and the two error rows are the only ones naming work.
|
|
120
|
+
*/
|
|
121
|
+
const DIFF = {
|
|
122
|
+
scope: "loam diff --base <ref>",
|
|
123
|
+
codes: {
|
|
124
|
+
"diff.service-added": { severityNote: "ok", meaning: "A services/<id>/ directory exists now that did not exist at the base ref.", fix: "Nothing to fix: `loam diff` says what changed between two points of the living docs, never what is wrong with them. This is the class of the change, for a reviewer to read." },
|
|
125
|
+
"diff.service-removed": { severityNote: "warn", meaning: "A service present at the base ref is gone from the working tree; the finding names the directory it occupied.", fix: "A review question rather than a defect: nothing in the working tree describes that boundary any more. `loam validate --all` is what grades the fleet that is left." },
|
|
126
|
+
"diff.requirement-added": { severityNote: "ok", meaning: "A living requirement not present at base — by `Requirement-ID:` where one is authored, by heading otherwise, the same join `loam rebase` pins against.", fix: "Nothing to fix: this is the class of the change, for a reviewer to read." },
|
|
127
|
+
"diff.requirement-removed": { severityNote: "warn", meaning: "A requirement present at the base ref is no longer in the living spec under the same identity.", fix: "A review question. A requirement that CHANGED identity — a new `Requirement-ID:`, a renamed heading — reads here as a removal plus an addition, which is the join being honest about what it can see rather than guessing a rename." },
|
|
128
|
+
"diff.requirement-modified": { severityNote: "ok", meaning: "The same requirement identity is on both sides and its digest moved. A rebase pin never moves that digest, so this is a real edit to the requirement's text.", fix: "Nothing to fix: this is the class of the change, for a reviewer to read." },
|
|
129
|
+
"diff.op-added": { severityNote: "ok", meaning: "An operationId in the living contract that was absent at the base ref; the message names its method and path.", fix: "Nothing to fix: this is the class of the change, for a reviewer to read." },
|
|
130
|
+
"diff.op-removed": { severityNote: "warn", meaning: "A base operationId is gone from the living contract and no current landscape edge or living requirement names it — or, in the second wording this code also carries, whether one does could NOT be fully answered because some consumer documents were not scannable, and the details name them.", fix: "Read which of the two sentences it is. Nobody could be scanned is never nobody names it: the unreadable documents carry the run to exit 1 on their own, and the removal stays unreviewed until they can be read." },
|
|
131
|
+
"diff.op-removed-consumed": { severityNote: "error", meaning: "An operation was removed since the base ref and the current fleet still names it — a landscape edge, or a foreign service's living requirement. The details list the victims, and the finding sets `breaking`.", fix: "These joins break. Either restore the operation, or land the consumers' own deltas in the same change so nothing in the fleet is left calling something that is gone." },
|
|
132
|
+
"diff.op-deprecated": { severityNote: "warn", meaning: "`deprecated: true` was introduced on an operation since the base ref. The details name the current consumers, under one of three deliberately honest phrasings: some still name it, none does, or whether any does could not be fully answered.", fix: "Deprecation is a promise to the consumers the details name, and nothing is broken yet. Read which phrasing it is before treating a silent list as an empty one." },
|
|
133
|
+
"diff.message-added": { severityNote: "ok", meaning: "An AsyncAPI message name absent at the base ref.", fix: "Nothing to fix: this is the class of the change, for a reviewer to read." },
|
|
134
|
+
"diff.message-removed": { severityNote: "warn", meaning: "A base message is gone. The finding says which of three cases it is: another current service still declares the name, nothing currently consumes it, or whether anything does could not be fully answered because some consumer documents were not scannable.", fix: "Read which case it is. A name another service still declares is not orphaned, and an unanswerable scan is not an empty one — only positive evidence vouches here." },
|
|
135
|
+
"diff.message-removed-consumed": { severityNote: "error", meaning: "A message was removed since the base ref and the current fleet still consumes it — a `Consumes:` line, or a consumes edge. The details list the victims, and the finding sets `breaking`.", fix: "These joins break. Either restore the message, or land the consumers' own deltas in the same change." },
|
|
136
|
+
"diff.consumer-added": { severityNote: "ok", meaning: "A cross-service join appeared since base: another service's living requirements now name this service's operation or message. Filed on the PROVIDER — the service whose surface the join lands on.", fix: "Nothing to fix, and the change class most worth reading: a new consumer is a new obligation on this service's contract, and removing that operation later is what `diff.op-removed-consumed` will be about." },
|
|
137
|
+
"diff.consumer-removed": { severityNote: "ok", meaning: "A cross-service join present at the base ref is gone: a consumer's living requirements no longer name this service's operation or message.", fix: "Nothing to fix: this is the class of the change, for a reviewer to read." },
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* `loam gate` — the can-i-deploy question, a pure query over evidence other
|
|
142
|
+
* commands already recorded. Nothing here re-derives a coherence plan, so every
|
|
143
|
+
* repair below is somebody else's command.
|
|
144
|
+
*/
|
|
145
|
+
const GATE = {
|
|
146
|
+
scope: "loam gate",
|
|
147
|
+
codes: {
|
|
148
|
+
"gate.partners-unknown": { severityNote: "warn when the map is absent; error when it exists and cannot be used", meaning: "The partner set for the gated service could not be derived from architecture/landscape.likec4 — it is absent, or it exists and does not parse. That means nobody could look, never that nothing joins this service. Absent is a warning because a repo before its first adopt legitimately has no map yet; a broken map is an error because `loam validate --all` fails that repo for the same file, and a deploy gate passing where the fleet gate fails would be the quieter of two contradictory verdicts.", fix: "Fix the landscape and re-run. `loam validate --all` diagnoses the file itself; this check only refuses the false silence." },
|
|
149
|
+
"gate.service-undocumented": { severityNote: "error", meaning: "The service being deployed sits below `documented` on the adoption ladder, so the docs cannot say what its joins even are and no recorded evidence can answer the deploy question. The details list what the next rung wants.", fix: "Author the baseline — `loam adopt --service <id>` briefs exactly what is missing — and this check passes once the required artifact set exists." },
|
|
150
|
+
"gate.partner-undocumented": { severityNote: "warn", meaning: "A service that joins the gated one has no services/<id>/ directory at all, or has one sitting below `documented`: its side of the join is not recorded, so the gate cannot see what that partner promises. An `#external` partner is exempt on purpose — somebody else's system is unrecorded by design.", fix: "Adopt the partner (`loam adopt --service <id>` briefs it), bind its landscape element to the right service with `metadata { service '<id>' }`, or tag it `#external` if it is not ours." },
|
|
151
|
+
"gate.feature-unverified": { severityNote: "warn", meaning: "An active feature touching the gated service is not verified: no record at all, a verification.yaml that does not read as a record, a record the feature moved out from under, a record answering no claims, or open claims counted in the message. A record that is merely `attested` is NOT reported under this code — it carries `verify.scenario-attested` instead, because complete work resting on an assertion is a different fact from work nobody checked.", fix: "Derive the checklist and answer every claim with evidence: `loam verify <FEAT-id> --json`. A record nothing can read is repaired or deleted by hand; nothing overwrites it while it is unreadable." },
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
/** In listing order, though every consumer sorts by code — the order is documentation, not contract. */
|
|
155
|
+
const FAMILIES = [DOCTOR, NEXT_STEPS, DIFF, GATE];
|
|
156
|
+
/**
|
|
157
|
+
* The registry's answer for one subject, or null.
|
|
158
|
+
*
|
|
159
|
+
* Built per call over constants already in memory, never cached at module
|
|
160
|
+
* level, for the reason lookup.ts's header gives: tests fork and chdir, and the
|
|
161
|
+
* MCP server outlives many calls.
|
|
162
|
+
*/
|
|
163
|
+
export function familyFinding(subject) {
|
|
164
|
+
for (const family of FAMILIES) {
|
|
165
|
+
const entry = family.codes[subject];
|
|
166
|
+
if (entry !== undefined)
|
|
167
|
+
return { scope: family.scope, ...entry };
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
/** Every code the registry answers, sorted — the same plain sort the code inventory uses. */
|
|
172
|
+
export function familyCodes() {
|
|
173
|
+
return FAMILIES.flatMap((family) => Object.keys(family.codes)).sort();
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=families.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"families.js","sourceRoot":"","sources":["../../../src/core/explain/families.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The family registry: `loam explain`'s content for the four code families no\n * fix table anywhere grades — `doctor.*`, `next.*`, `diff.*` and `gate.*`.\n *\n * WHY THIS IS NOT THE DUPLICATION fix-tables.ts FORBIDS. That module's header\n * argues against a second hand-maintained copy of the /loam-check prose, and\n * the argument is right: the tables ship in the binary, test/codes-drift.test.ts\n * holds every emitted finding code against them, and a registry restating them\n * would be free to trail the bytes `loam instructions loam-check` prints. None\n * of that applies here. These 65 codes have no fix-table row in any workflow\n * body — /loam-check grades DOCUMENTS, and these four families grade a\n * repository's wiring (`doctor`), a recommendation (`next`), a change between\n * two refs (`diff`) and a deploy question (`gate`). There is nothing to trail:\n * this registry is not a second copy, it is the only copy. The precedent is the\n * sibling module refusals.ts, a hand-written map that is the sole source for\n * the `ErrorCode` meanings for exactly the same reason — their prose lives in\n * doc comments, which are erased, so there is no runtime constant to read.\n *\n * What that costs, stated rather than hidden: nothing mechanical proves an\n * entry below still matches the message its emitter prints. Every meaning and\n * every fix here was written FROM the emitter — `doctor` findings carry a `fix`\n * field of their own (core/doctor/), a `next` step carries a `statement` and a\n * literal `command` (core/status/), the `DiffCode` union carries a doc comment\n * per member (core/diff/semantic.ts) — and the wording is theirs, not a\n * paraphrase invented here. Two guards catch the two failures that CAN be\n * caught: test/explain.test.ts asserts no code below is also answered by a fix\n * table (the two sources must never be able to disagree), and\n * test/agent-commands-runnable.test.ts parses every backticked `loam …` in this\n * file against the real program, so a fix naming a command loam does not have —\n * or a flag it does not declare — fails at gate time. A two-token span is a\n * NAME rather than an invocation there and is only checked for the command\n * existing, so a fix that means an invocation must carry its arguments.\n *\n * `severityNote` is the EMITTER's own word, not a fix table's parenthetical:\n * `doctor` grades blocker/warning, `diff` and `gate` grade ok/warn/error, and a\n * `next` step is graded not at all — it is a recommendation, so its note is\n * `step`. Where a code's severity depends on what was found (`doctor.docs-locked`,\n * `gate.partners-unknown`) the note says so in prose, the way the tables' own\n * long notes do (`warn here; error at archive plan time`).\n *\n * `openspec.*` and `mapping.*` — 49 codes — are deliberately NOT here, and the\n * reason is in test/explain.test.ts beside their backlog entries: they are the\n * only codes in the vocabulary whose subject is not a loam document at all.\n */\n\n/**\n * One code's answer. Structurally a `FindingEntry` (lookup.ts) minus `scope`,\n * which the family supplies — declared here rather than imported so this module\n * imports nothing at all and the package's file-level graph stays a tree.\n *\n * Every entry below is written on ONE line, however long that line runs, and\n * that is a deliberate concession to a counted limit rather than a style: 65\n * codes at four lines each is 260 lines of punctuation before a word of prose,\n * which does not fit the 400-line file limit — and src/core/explain/ is at its\n * five-file cap, so there is no second file to put the overflow in. The fields\n * stay named for the same reason a tuple was refused: `severityNote`, `meaning`\n * and `fix` say which column is which without counting commas.\n */\nexport interface FamilyEntry {\n /** The emitter's own severity word, or the prose a conditional one needs. */\n readonly severityNote: string;\n /** What the code is about, in the words the emitter already prints. */\n readonly meaning: string;\n /** What to do — for `next.*`, that the step's own `command` IS the action. */\n readonly fix: string;\n}\n\n/** One family: the invocation that emits it, and its codes. */\ninterface Family {\n /** The scope label, spelled as the fix tables spell theirs — the invocation that grades it. */\n readonly scope: string;\n readonly codes: Readonly<Record<string, FamilyEntry>>;\n}\n\n/**\n * `loam doctor` — the preflight. Every finding here already carries a `fix`\n * field in doctor's own report (core/doctor/doctor.ts, config.ts, agents.ts,\n * residue.ts); these rows say the same thing without a repository in front of\n * them, which is the whole difference between a report and a lookup.\n */\nconst DOCTOR: Family = {\n scope: \"loam doctor\",\n codes: {\n \"doctor.config-missing\": { severityNote: \"blocker\", meaning: \"No loam.json at or above the working directory, so nothing says which docs repo this checkout belongs to — every other command refuses with `no-config` until there is one.\", fix: \"Run `loam init --docs <dir>` in this repository; add `--create` when the docs repo does not exist yet.\" },\n \"doctor.config-invalid\": { severityNote: \"blocker\", meaning: \"A loam.json is there and `parseConfig` — the same loader every command uses — refuses it; the finding carries the parser's own words. doctor deliberately has no second validator: the one it used to carry accepted a config the commands rejected, and reported a healthy repo in which nothing could run.\", fix: \"Repair the file the finding names, or delete it and re-run `loam init`.\" },\n \"doctor.docs-missing\": { severityNote: \"blocker\", meaning: \"`docsDir` resolves to something that is missing or is not a directory — the docs repo was never cloned, or the path is wrong.\", fix: \"Fix `docsDir` in the loam.json the finding names, clone the docs repo to that path, or run `loam init --docs <dir> --create`.\" },\n \"doctor.services-missing\": { severityNote: \"blocker\", meaning: \"`docsDir` is a directory and holds no `services/`, so it is some other directory — most often the service repo itself, after a typo in the pointer.\", fix: \"Point `docsDir` at the shared docs repo, or run `loam init --docs <dir> --create` to scaffold one. Do not scaffold a second source of truth beside the real one.\" },\n \"doctor.docs-absolute\": { severityNote: \"warning\", meaning: \"`docsDir` is stored as an absolute path and loam.json is committed, so the pointer names a directory that exists on exactly one machine: it works for whoever ran `loam init` and for nobody who clones the repo afterwards.\", fix: \"Rewrite `docsDir` as a path relative to the loam.json holding it, such as `../docs`.\" },\n \"doctor.docs-unreadable\": { severityNote: \"warning\", meaning: \"The docs repo exists and this process cannot read it, so every command that reads the fleet will fail or report an empty one.\", fix: \"Grant read access to the directory the finding names — check ownership and mode.\" },\n \"doctor.docs-readonly\": { severityNote: \"warning\", meaning: \"The docs repo is readable and not writable: read-only commands work and the writing ones do not.\", fix: \"Grant write access if you need `loam new`, `loam adopt` or `loam archive`. A read-only checkout is a legitimate state for a reviewer, which is why this is a warning.\" },\n \"doctor.landscape-missing\": { severityNote: \"warning\", meaning: \"architecture/landscape.likec4 is missing, and it is the one artifact every cross-service check reads — nothing about who calls whom can be checked without it.\", fix: \"Create it with one element per service and an edge per call: `loam init --create` writes the empty map, and `loam seed --from fleet.yaml` templates one from stated facts.\" },\n \"doctor.landscape-unreadable\": { severityNote: \"blocker\", meaning: \"The landscape file exists and the read itself failed — permissions or an I/O error, carried verbatim in the message.\", fix: \"Check permissions on the path the finding names.\" },\n \"doctor.landscape-merge-conflict\": { severityNote: \"blocker\", meaning: \"The landscape still contains merge conflict markers, named by line. Checked BEFORE the parser on purpose: both sides of a conflict can be syntactically valid LikeC4, so the file sometimes parses and is still two halves of two different maps.\", fix: \"Resolve the conflict keeping BOTH services' elements and edges — the usual cause is several services adopted into one map in the same week — then re-run `loam doctor`.\" },\n \"doctor.landscape-invalid\": { severityNote: \"blocker\", meaning: \"The landscape exists, carries no conflict markers, and does not parse; the message quotes the first parser error with its line and counts the rest.\", fix: \"Fix the file — every fleet-wide check is blind until it parses.\" },\n \"doctor.likec4-config-missing\": { severityNote: \"warning\", meaning: \"The docs repo has no likec4.config.json, so the tree is not a loadable LikeC4 workspace: every service model and feature delta declares its own `specification` block, and a renderer pointed at the repo root merges them and reports every declaration as a duplicate. No loam check reads this file — the repo is only unrenderable, which is why it is a warning.\", fix: \"Write the project file the finding prints; it scopes the root project to architecture/, so `npx likec4 start` in the docs repo renders the fleet map. A service model or a feature delta is rendered by pointing the renderer at its own directory instead.\" },\n \"doctor.docs-locked\": { severityNote: \"warning while a live process holds it; blocker when its holder is dead or it names none\", meaning: \"A `.loam-lock` is present. Held by a running process it is a fact about right now. Held by a process that no longer exists on this host — or unreadable, so no holder can be named at all — nothing is ever going to release it, and every writing command refuses with `docs-busy` forever.\", fix: \"Wait and re-run while the holder is alive; nothing is read or written while it is held. Delete the lock file the finding names when its holder is dead or unnameable, then run `loam doctor` again for an interrupted commit underneath it.\" },\n \"doctor.commit-unreadable\": { severityNote: \"blocker\", meaning: \"A `.loam-commit` journal is present and cannot be read: a commit was interrupted and the one record of which files it had already written is unreadable.\", fix: \"Hand this to a human — compare the root's files against version control before running any loam command that writes there. Every journaled writer refuses with `commit-interrupted` while it is present.\" },\n \"doctor.commit-interrupted\": { severityNote: \"blocker\", meaning: \"A journaled writer — archive, unarchive, rebase, vouch, new, gherkin, or a recording verify — was killed mid-commit. The message names the host, pid and time, and every file or directory move that may be half-done. This is the surface that used to report a healthy repo over half-merged living docs.\", fix: \"Re-run the command the finding names: it recovers first, under the lock, rolling the staged bytes forward, and refuses rather than guessing if a file has been edited since. An interrupted `loam unarchive` is FINISHED, never undone — the merged text it was replacing is written down nowhere.\" },\n \"doctor.staging-temps\": { severityNote: \"warning\", meaning: \"Orphaned `.loam-*.tmp` scratch files from a killed writer, never linked into place — so nothing reads them and nothing depends on them. A journal's own recorded temps are excluded, because those are the durable copy its roll-forward recovery renames in. Litter, not damage.\", fix: \"The next journaled writer through that root removes its own; delete any that remain. They cost disk and nothing else.\" },\n \"doctor.inventory-unreadable\": { severityNote: \"warning\", meaning: \"The config and the docs repo are both fine and enumerating `services/` or `features/` threw, so doctor's fleet counts — and its verdict on the service binding — are about a fleet nobody could read.\", fix: \"Check that services/ and features/ under the docs repo are readable directories.\" },\n \"doctor.service-unbound\": { severityNote: \"warning\", meaning: \"loam.json declares no `service`, so nothing binds this checkout to one governed boundary and the service-repo checks have nothing to run against — `sources.stale`, a recording `loam verify`, `loam gherkin`. Deliberately not emitted inside the docs repo itself, where having no binding is the correct state rather than a gap.\", fix: \"Run `loam init --docs <dir> --service <id>` here.\" },\n \"doctor.service-unknown\": { severityNote: \"warning\", meaning: \"loam.json names a `service` the fleet has no services/<id>/ for — and the fleet WAS read, so this is a claim about a real inventory rather than one nobody could take.\", fix: \"Run `loam adopt --service <id>` to onboard it, or fix `service` in loam.json.\" },\n \"doctor.agent-files-missing\": { severityNote: \"warning\", meaning: \"Some of the command and skill files this loam lays down for the repo's recorded tools and profile are not here: the repo was initialized by an older loam, or they were deleted. An out-of-date command set costs entry points, never a refusal, which is why it is a warning.\", fix: \"Re-run `loam init --docs <dir> --tools <ids>` here. It creates absent files, refreshes only pointers whose current bytes still match their recorded digest, preserves every customized file, and keeps this repo's service binding.\" },\n \"doctor.agent-files-stale\": { severityNote: \"warning\", meaning: \"Command or skill files that ARE here carry no loam stamp, or one older than this binary, so the protocol and code tables they instruct an agent with may describe a loam that no longer exists. Staleness reads only the stamp; safe refresh is a separate digest check performed by init.\", fix: \"Re-run `loam init` to refresh a pointer only when its recorded digest still matches. Review a customized file against the current body yourself and update its stamp, or delete it so init can recreate it; your edits always outrank the template.\" },\n },\n};\n\n/**\n * `loam status` — both forms print `next[]`, and each entry carries a `code` to\n * branch on, one sentence, and the literal `command` to run. So the \"what to\n * do\" column is genuinely empty for this whole family: the step IS the action,\n * and each `fix` below names the step's own command rather than inventing a\n * second instruction beside it.\n */\nconst NEXT_STEPS: Family = {\n scope: \"loam status\",\n codes: {\n \"next.adopt-bound\": { severityNote: \"step\", meaning: \"The fleet form's first entry: this repository's loam.json says it is a service the fleet has no services/<id>/ for, so nothing about the boundary you are standing in is written down yet. Ahead of every other service's adoption work, because it is the only step that is about HERE.\", fix: \"The step IS the action: run its `command`, `loam adopt --service <id> --json`.\" },\n \"next.author-landscape\": { severityNote: \"step\", meaning: \"The first rung of the first-hour ladder, over a fleet with no services and no features: architecture/landscape.likec4 does not exist, or is still the scaffold's untouched map with no service drawn on it.\", fix: \"The step IS the action: run its `command` — `loam init --create` when the file is absent, `loam seed --from fleet.yaml` when it is the untouched scaffold. loam never guesses who calls whom.\" },\n \"next.bind-service\": { severityNote: \"step\", meaning: \"First-hour ladder: no service repository is bound to this fleet yet, so no command can ever run from a service's own checkout.\", fix: \"The step IS the action: run its `command`, `loam init --docs <path-to-this-docs-repo> --service <service-id>`, from a service's own repo, and commit the loam.json it writes.\" },\n \"next.adopt-first\": { severityNote: \"step\", meaning: \"First-hour ladder: services/ is empty, so nothing about any service is written down and nothing can be graded against anything.\", fix: \"The step IS the action: run its `command`, `loam adopt --service <service-id> --json`; the brief it prints walks an agent through writing the baseline docs as draft.\" },\n \"next.adopt\": { severityNote: \"step\", meaning: \"One service in the fleet has no spec.md — nothing about it is written down, so no feature can be graded against it. One entry per undocumented service.\", fix: \"The step IS the action: run its `command`, `loam adopt --service <id> --json`.\" },\n \"next.complete-service\": { severityNote: \"step\", meaning: \"Adoption does not end at spec.md: a service has one and no model.likec4, the state archive warns about and the fleet gate reports incomplete until something models it.\", fix: \"The step IS the action: run its `command`, `loam validate --service <id> --json`.\" },\n \"next.feature\": { severityNote: \"step\", meaning: \"One feature in flight that is not ready to ship, named with the stage it sits at and what it is missing — or, when it is blocked by another feature, the features it is waiting on.\", fix: \"The step IS the action: run its `command`, `loam status <FEAT-id> --json`, for that feature's own next list.\" },\n \"next.archive\": { severityNote: \"step\", meaning: \"In the fleet form, a feature that is authored and verified: ship it, and everything queued behind it is released. In a feature's own list it is always the last entry, saying the feature ships once everything above it is done.\", fix: \"The step IS the action: run its `command`, `loam archive <FEAT-id> --dry-run --json`; the dry run writes nothing and lists every file the merge would touch.\" },\n \"next.elided\": { severityNote: \"step\", meaning: \"The fleet list is capped, and this says how many steps of the same kinds it left out. The list is ordered most-unblocking first, so what was elided is the least urgent — a list nobody reads is not navigation.\", fix: \"The step IS the action: run its `command`, `loam list --json`, or work down the printed list and run status again.\" },\n \"next.fleet-clean\": { severityNote: \"step\", meaning: \"Services exist, nothing is in flight, and nothing is owed. Only that truthful case: over an EMPTY fleet the same sentence was vacuously true, and the first-hour ladder owns that repository now.\", fix: \"The step IS the action: run its `command`, `loam validate --all --json`, then start the next feature.\" },\n \"next.fleet-gate\": { severityNote: \"step\", meaning: \"The last entry of every fleet list, and always present: `status` grades nothing, so the least it can do is say where grading happens — `loam validate --all` is the gate this repository has to pass and the one CI runs.\", fix: \"The step IS the action: run its `command`, `loam validate --all --json`.\" },\n \"next.recover-commit\": { severityNote: \"step\", meaning: \"Always first, and never elided by the fleet form's cap: a journaled writer was killed mid-commit, so everything below this step is derived from files that may be half-written. Where the journal itself cannot be read, nothing below can be trusted until a human compares the living docs against version control.\", fix: \"The step IS the action: run its `command` — the interrupted command re-run, which recovers first under the lock, or `loam doctor --json` when the journal is unreadable and no loam command can repair it.\" },\n \"next.archived\": { severityNote: \"step\", meaning: \"The whole `next[]` for a feature that already shipped: it is archived, and its delta is folded into the living docs.\", fix: \"The step IS the action: run its `command`, `loam show <FEAT-id> --json`.\" },\n \"next.author-intent\": { severityNote: \"step\", meaning: \"The feature has no intent document — what it is for, in prose, before anything is derived from it.\", fix: \"The step IS the action: write the file the step names, then run its `command`, `loam validate <FEAT-id> --json`. The command never writes the artifact: loam does not author.\" },\n \"next.touch-service\": { severityNote: \"step\", meaning: \"The feature carries no per-service delta at all, so nothing says which governed boundaries it changes.\", fix: \"The step IS the action: run its `command`, `loam list services --json`, then add specs/<service>/spec.md for every service the feature changes.\" },\n \"next.author-spec\": { severityNote: \"step\", meaning: \"One service the feature touches has no requirement delta — the ADDED / MODIFIED / REMOVED requirements the feature makes to that service, each with a scenario.\", fix: \"The step IS the action: write the file the step names, then run its `command`, `loam delta <FEAT-id> --service <id> --json`, which projects the delta onto the living document.\" },\n \"next.author-openapi\": { severityNote: \"step\", meaning: \"Nothing gives one of the feature's services a living openapi.yaml, so this feature is the only thing that can write down its API surface. Deliberately not phrased as the service being absent from the living docs: a service adopted without a contract is the commoner case, and that wording sent readers looking for a directory that was right there.\", fix: \"The step IS the action: write the file the step names, then run its `command`, `loam delta <FEAT-id> --service <id> --json`.\" },\n \"next.author-scenarios\": { severityNote: \"step\", meaning: \"Requirements in one service's delta carry no `#### Scenario:`, so they generate no test and no verify claim — a promise that reaches neither the suite nor the done-check. One entry per service and never per requirement, because a delta with forty bare requirements would otherwise BE the payload.\", fix: \"The step IS the action: write a scenario under each bare requirement, then run its `command`, `loam delta <FEAT-id> --service <id> --json`.\" },\n \"next.rebase\": { severityNote: \"step\", meaning: \"The feature carries requirements or operations with no baseline pin, on any of the three axes; until they have one the merge cannot tell what it EDITS from what it merely quotes.\", fix: \"The step IS the action: run its `command`, `loam rebase <FEAT-id>`.\" },\n \"next.archive-first\": { severityNote: \"step\", meaning: \"The feature builds on other features still in flight, which have to archive before it can.\", fix: \"The step IS the action: run its `command`, `loam dependencies <FEAT-id> --json`.\" },\n \"next.fix-coherence\": { severityNote: \"step\", meaning: \"The feature has findings that stop it, named starting with the first. Everything EITHER gate refuses on is counted, so a warning marked as gating archive is in the tally even though `validate` grades the feature valid — which is why its exit code alone will not show you why archive refuses.\", fix: \"The step IS the action: run its `command`, `loam validate <FEAT-id> --json`.\" },\n \"next.generate-tests\": { severityNote: \"step\", meaning: \"The feature's delta for a service carries scenarios no test run has answered yet. `loam gherkin` writes the .feature files whose green run is the only thing that may answer a `scenario.tested` claim, and it writes into the service's own repository — so the step names which repo to run it in when that is not this one.\", fix: \"The step IS the action: run its `command`, `loam gherkin <FEAT-id> --service <id>`, from that service's own checkout.\" },\n \"next.verify\": { severityNote: \"step\", meaning: \"The done-check has not been started, or its record cannot be used. Five situations share this code because they share the work — nothing recorded, a verification.yaml that does not read as a record, a record the feature has moved out from under, a record that answers no claims at all, and a feature with nothing to derive a checklist from yet — and the step's own statement says which.\", fix: \"The step IS the action: run its `command`, `loam verify <FEAT-id> --json`, which derives the checklist and prints what it asks. A record nothing can read is repaired or deleted by hand: nothing overwrites it while it is unreadable.\" },\n \"next.verify-unconfirmed\": { severityNote: \"step\", meaning: \"Claims on the feature are open — unconfirmed or unanswered — and this repository is not one of the services that owes an answer, so the recording form is not a step anyone can take from here.\", fix: \"The step IS the action: run its `command`, `loam verify <FEAT-id> --json`. The open claims are closed from each affected service's own repository.\" },\n \"next.attest-service\": { severityNote: \"step\", meaning: \"Claims are open AND this repository is one of the services that owes an answer, so the recording form is nameable here: `--record --service` binds the answers to this repo's HEAD and refuses anywhere else.\", fix: \"The step IS the action: run its `command`, `loam verify <FEAT-id> --record answers.json --service <id>`, answering the claims filed under this service; the rest belong to their own repositories.\" },\n \"next.verify-attested\": { severityNote: \"step\", meaning: \"Every claim is answered and some scenario claims are confirmed on an agent's word rather than on a test run (`verify.scenario-attested`) — complete work resting on an assertion, which is what `ready` has always meant here.\", fix: \"The step IS the action: run its `command`, `loam verify <FEAT-id> --results <cucumber-report.json>`, and the record stops resting on an assertion.\" },\n },\n};\n\n/**\n * `loam diff` — what CHANGED between a base git ref of the docs repo and the\n * working tree, not what is WRONG with either. That is why most rows below have\n * no repair: the meanings are the `DiffCode` union's own doc comments\n * (core/diff/semantic.ts), and the two error rows are the only ones naming work.\n */\nconst DIFF: Family = {\n scope: \"loam diff --base <ref>\",\n codes: {\n \"diff.service-added\": { severityNote: \"ok\", meaning: \"A services/<id>/ directory exists now that did not exist at the base ref.\", fix: \"Nothing to fix: `loam diff` says what changed between two points of the living docs, never what is wrong with them. This is the class of the change, for a reviewer to read.\" },\n \"diff.service-removed\": { severityNote: \"warn\", meaning: \"A service present at the base ref is gone from the working tree; the finding names the directory it occupied.\", fix: \"A review question rather than a defect: nothing in the working tree describes that boundary any more. `loam validate --all` is what grades the fleet that is left.\" },\n \"diff.requirement-added\": { severityNote: \"ok\", meaning: \"A living requirement not present at base — by `Requirement-ID:` where one is authored, by heading otherwise, the same join `loam rebase` pins against.\", fix: \"Nothing to fix: this is the class of the change, for a reviewer to read.\" },\n \"diff.requirement-removed\": { severityNote: \"warn\", meaning: \"A requirement present at the base ref is no longer in the living spec under the same identity.\", fix: \"A review question. A requirement that CHANGED identity — a new `Requirement-ID:`, a renamed heading — reads here as a removal plus an addition, which is the join being honest about what it can see rather than guessing a rename.\" },\n \"diff.requirement-modified\": { severityNote: \"ok\", meaning: \"The same requirement identity is on both sides and its digest moved. A rebase pin never moves that digest, so this is a real edit to the requirement's text.\", fix: \"Nothing to fix: this is the class of the change, for a reviewer to read.\" },\n \"diff.op-added\": { severityNote: \"ok\", meaning: \"An operationId in the living contract that was absent at the base ref; the message names its method and path.\", fix: \"Nothing to fix: this is the class of the change, for a reviewer to read.\" },\n \"diff.op-removed\": { severityNote: \"warn\", meaning: \"A base operationId is gone from the living contract and no current landscape edge or living requirement names it — or, in the second wording this code also carries, whether one does could NOT be fully answered because some consumer documents were not scannable, and the details name them.\", fix: \"Read which of the two sentences it is. Nobody could be scanned is never nobody names it: the unreadable documents carry the run to exit 1 on their own, and the removal stays unreviewed until they can be read.\" },\n \"diff.op-removed-consumed\": { severityNote: \"error\", meaning: \"An operation was removed since the base ref and the current fleet still names it — a landscape edge, or a foreign service's living requirement. The details list the victims, and the finding sets `breaking`.\", fix: \"These joins break. Either restore the operation, or land the consumers' own deltas in the same change so nothing in the fleet is left calling something that is gone.\" },\n \"diff.op-deprecated\": { severityNote: \"warn\", meaning: \"`deprecated: true` was introduced on an operation since the base ref. The details name the current consumers, under one of three deliberately honest phrasings: some still name it, none does, or whether any does could not be fully answered.\", fix: \"Deprecation is a promise to the consumers the details name, and nothing is broken yet. Read which phrasing it is before treating a silent list as an empty one.\" },\n \"diff.message-added\": { severityNote: \"ok\", meaning: \"An AsyncAPI message name absent at the base ref.\", fix: \"Nothing to fix: this is the class of the change, for a reviewer to read.\" },\n \"diff.message-removed\": { severityNote: \"warn\", meaning: \"A base message is gone. The finding says which of three cases it is: another current service still declares the name, nothing currently consumes it, or whether anything does could not be fully answered because some consumer documents were not scannable.\", fix: \"Read which case it is. A name another service still declares is not orphaned, and an unanswerable scan is not an empty one — only positive evidence vouches here.\" },\n \"diff.message-removed-consumed\": { severityNote: \"error\", meaning: \"A message was removed since the base ref and the current fleet still consumes it — a `Consumes:` line, or a consumes edge. The details list the victims, and the finding sets `breaking`.\", fix: \"These joins break. Either restore the message, or land the consumers' own deltas in the same change.\" },\n \"diff.consumer-added\": { severityNote: \"ok\", meaning: \"A cross-service join appeared since base: another service's living requirements now name this service's operation or message. Filed on the PROVIDER — the service whose surface the join lands on.\", fix: \"Nothing to fix, and the change class most worth reading: a new consumer is a new obligation on this service's contract, and removing that operation later is what `diff.op-removed-consumed` will be about.\" },\n \"diff.consumer-removed\": { severityNote: \"ok\", meaning: \"A cross-service join present at the base ref is gone: a consumer's living requirements no longer name this service's operation or message.\", fix: \"Nothing to fix: this is the class of the change, for a reviewer to read.\" },\n },\n};\n\n/**\n * `loam gate` — the can-i-deploy question, a pure query over evidence other\n * commands already recorded. Nothing here re-derives a coherence plan, so every\n * repair below is somebody else's command.\n */\nconst GATE: Family = {\n scope: \"loam gate\",\n codes: {\n \"gate.partners-unknown\": { severityNote: \"warn when the map is absent; error when it exists and cannot be used\", meaning: \"The partner set for the gated service could not be derived from architecture/landscape.likec4 — it is absent, or it exists and does not parse. That means nobody could look, never that nothing joins this service. Absent is a warning because a repo before its first adopt legitimately has no map yet; a broken map is an error because `loam validate --all` fails that repo for the same file, and a deploy gate passing where the fleet gate fails would be the quieter of two contradictory verdicts.\", fix: \"Fix the landscape and re-run. `loam validate --all` diagnoses the file itself; this check only refuses the false silence.\" },\n \"gate.service-undocumented\": { severityNote: \"error\", meaning: \"The service being deployed sits below `documented` on the adoption ladder, so the docs cannot say what its joins even are and no recorded evidence can answer the deploy question. The details list what the next rung wants.\", fix: \"Author the baseline — `loam adopt --service <id>` briefs exactly what is missing — and this check passes once the required artifact set exists.\" },\n \"gate.partner-undocumented\": { severityNote: \"warn\", meaning: \"A service that joins the gated one has no services/<id>/ directory at all, or has one sitting below `documented`: its side of the join is not recorded, so the gate cannot see what that partner promises. An `#external` partner is exempt on purpose — somebody else's system is unrecorded by design.\", fix: \"Adopt the partner (`loam adopt --service <id>` briefs it), bind its landscape element to the right service with `metadata { service '<id>' }`, or tag it `#external` if it is not ours.\" },\n \"gate.feature-unverified\": { severityNote: \"warn\", meaning: \"An active feature touching the gated service is not verified: no record at all, a verification.yaml that does not read as a record, a record the feature moved out from under, a record answering no claims, or open claims counted in the message. A record that is merely `attested` is NOT reported under this code — it carries `verify.scenario-attested` instead, because complete work resting on an assertion is a different fact from work nobody checked.\", fix: \"Derive the checklist and answer every claim with evidence: `loam verify <FEAT-id> --json`. A record nothing can read is repaired or deleted by hand; nothing overwrites it while it is unreadable.\" },\n },\n};\n\n/** In listing order, though every consumer sorts by code — the order is documentation, not contract. */\nconst FAMILIES: readonly Family[] = [DOCTOR, NEXT_STEPS, DIFF, GATE];\n\n/** One family row, in the shape `FindingEntry` (lookup.ts) takes. */\nexport interface FamilyFinding extends FamilyEntry {\n readonly scope: string;\n}\n\n/**\n * The registry's answer for one subject, or null.\n *\n * Built per call over constants already in memory, never cached at module\n * level, for the reason lookup.ts's header gives: tests fork and chdir, and the\n * MCP server outlives many calls.\n */\nexport function familyFinding(subject: string): FamilyFinding | null {\n for (const family of FAMILIES) {\n const entry = family.codes[subject];\n if (entry !== undefined) return { scope: family.scope, ...entry };\n }\n return null;\n}\n\n/** Every code the registry answers, sorted — the same plain sort the code inventory uses. */\nexport function familyCodes(): string[] {\n return FAMILIES.flatMap((family) => Object.keys(family.codes)).sort();\n}\n"]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fix-table parser: `loam explain`'s finding-code content, read at runtime
|
|
3
|
+
* out of the workflow bodies the binary ships. Every protocol body in
|
|
4
|
+
* `COMMANDS` is walked, so a table added to any workflow is picked up without
|
|
5
|
+
* touching this parser — today the tables live in the /loam-check body
|
|
6
|
+
* (src/core/agent/workflows/check.ts) and the /loam-verify body's notice
|
|
7
|
+
* table (src/core/agent/workflows/closing.ts).
|
|
8
|
+
*
|
|
9
|
+
* A PARSER rather than a table of its own, deliberately: the /loam-check fix
|
|
10
|
+
* tables are already the documentation corpus test/codes-drift.test.ts holds
|
|
11
|
+
* every emitted finding code against, so they are the one place the
|
|
12
|
+
* meaning-and-fix prose is guaranteed to exist and to stay current. A second
|
|
13
|
+
* copy inside an `explain` registry would be exactly the hand-maintained map
|
|
14
|
+
* that silently trails the binary — worse than no command. Reading the shipped
|
|
15
|
+
* constant instead means `loam explain spine.op-undefined` and the /loam-check
|
|
16
|
+
* page cannot disagree, because they are the same bytes.
|
|
17
|
+
*
|
|
18
|
+
* The same walk also STRIPS those tables (`withoutFixTables`), which is what
|
|
19
|
+
* `loam instructions <workflow> --no-fix-tables` prints. One walk and not two,
|
|
20
|
+
* deliberately: a stripper carrying a regex of its own would be free to
|
|
21
|
+
* disagree with the parser about where a table begins and ends, and the failure
|
|
22
|
+
* that produces is both silent and precisely the wrong one — a narrowed
|
|
23
|
+
* protocol whose omitted rows `loam explain` cannot answer, telling an agent to
|
|
24
|
+
* look up a code nothing explains. Sharing the block detection makes "what was
|
|
25
|
+
* dropped" and "what can be explained" the same computation rather than two
|
|
26
|
+
* that agree today.
|
|
27
|
+
*
|
|
28
|
+
* The row grammar this depends on (test/explain.test.ts pins it with probes
|
|
29
|
+
* and a count floor, so a table reformat fails loudly instead of leaving the
|
|
30
|
+
* lookup silently empty):
|
|
31
|
+
*
|
|
32
|
+
* | `a.code` / `b.code` (severity note) | what it means | what to do |
|
|
33
|
+
*
|
|
34
|
+
* - the first cell holds one or more backticked codes and an optional trailing
|
|
35
|
+
* parenthetical severity note, printed verbatim (`(warn)`, `(error, or
|
|
36
|
+
* warn)`, `(warn, gates archive; one per service)`, `(ok)`); a row with no
|
|
37
|
+
* note is an error, the tables' own default;
|
|
38
|
+
* - cells never contain the ` | ` separator today; if a meaning cell ever
|
|
39
|
+
* grows one, the probes convict the mis-split rather than letting it ship;
|
|
40
|
+
* - the paragraph introducing each table (`` `--service <id>` — one service's
|
|
41
|
+
* own axes… ``) names the scope its rows are graded in, so a code that
|
|
42
|
+
* appears in two tables (`spec.merge-conflict`) explains both contexts.
|
|
43
|
+
*/
|
|
44
|
+
const CODE_SPAN = /`([a-z][a-z0-9.-]*)`/g;
|
|
45
|
+
const SEVERITY_NOTE = /\(([^)]+)\)\s*$/;
|
|
46
|
+
/**
|
|
47
|
+
* The scope label: the introducing paragraph's first line up to its ` — `
|
|
48
|
+
* dash, backticks stripped — "`--feature <FEAT-id>` — a change's three axes…"
|
|
49
|
+
* labels its rows `--feature <FEAT-id>`. A paragraph with no dash (none exist
|
|
50
|
+
* today) falls back to its whole first line minus the trailing colon.
|
|
51
|
+
*/
|
|
52
|
+
function scopeLabel(firstLine) {
|
|
53
|
+
const head = firstLine.split(" — ")[0] ?? firstLine;
|
|
54
|
+
return head.replace(/`/g, "").replace(/:$/, "").trim();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Split one table row into its cells, or null for a line that is not a
|
|
58
|
+
* three-cell row (the `|---|---|---|` separator has no ` | ` and yields one
|
|
59
|
+
* cell). More than three cells re-joins the tail into the fix column — the
|
|
60
|
+
* meaning cell is the split's second field either way, and the probe tests
|
|
61
|
+
* are what convict a cell that ever grows a ` | ` of its own.
|
|
62
|
+
*/
|
|
63
|
+
function splitRow(line) {
|
|
64
|
+
if (!line.startsWith("|") || !line.endsWith("|"))
|
|
65
|
+
return null;
|
|
66
|
+
const cells = line.slice(1, -1).split(" | ").map((cell) => cell.trim());
|
|
67
|
+
return cells.length >= 3 ? cells : null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Every fix table of one workflow body, in document order, each with its rows.
|
|
71
|
+
*
|
|
72
|
+
* The scope tracking is why this walks lines rather than matching rows
|
|
73
|
+
* globally: each table's introducing paragraph ends one blank line above the
|
|
74
|
+
* header row, so the label is the most recently COMPLETED paragraph when a
|
|
75
|
+
* table opens (or the one still being built, for a table glued directly under
|
|
76
|
+
* its intro).
|
|
77
|
+
*
|
|
78
|
+
* A run of consecutive `|` lines is one block, and the first line that is not
|
|
79
|
+
* one closes it. That is the whole grammar — markdown gives a table no other
|
|
80
|
+
* terminator — and it is why the blank line after a table belongs to what
|
|
81
|
+
* follows rather than to the block.
|
|
82
|
+
*/
|
|
83
|
+
function fixTableBlocks(body) {
|
|
84
|
+
const lines = body.split("\n");
|
|
85
|
+
const blocks = [];
|
|
86
|
+
let paragraph = [];
|
|
87
|
+
let lastParagraph = [];
|
|
88
|
+
let scope = "";
|
|
89
|
+
let open = null;
|
|
90
|
+
for (const [index, raw] of lines.entries()) {
|
|
91
|
+
const line = raw.trimEnd();
|
|
92
|
+
if (!line.startsWith("|")) {
|
|
93
|
+
if (open !== null) {
|
|
94
|
+
blocks.push({ start: open.start, end: index, rows: open.rows });
|
|
95
|
+
open = null;
|
|
96
|
+
}
|
|
97
|
+
if (line === "") {
|
|
98
|
+
if (paragraph.length > 0)
|
|
99
|
+
lastParagraph = paragraph;
|
|
100
|
+
paragraph = [];
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
paragraph.push(line);
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const intro = paragraph.length > 0 ? paragraph : lastParagraph;
|
|
108
|
+
if (intro.length > 0) {
|
|
109
|
+
scope = scopeLabel(intro[0]);
|
|
110
|
+
// Consumed: the next table needs its own intro, not this one again.
|
|
111
|
+
lastParagraph = [];
|
|
112
|
+
paragraph = [];
|
|
113
|
+
}
|
|
114
|
+
if (open === null)
|
|
115
|
+
open = { start: index, rows: [] };
|
|
116
|
+
const cells = splitRow(line);
|
|
117
|
+
if (cells === null)
|
|
118
|
+
continue;
|
|
119
|
+
const codeCell = cells[0];
|
|
120
|
+
const codes = [...codeCell.matchAll(CODE_SPAN)].map((m) => m[1]);
|
|
121
|
+
// The `| code | what it means | …` header row has no backticked code.
|
|
122
|
+
if (codes.length === 0)
|
|
123
|
+
continue;
|
|
124
|
+
open.rows.push({
|
|
125
|
+
codes,
|
|
126
|
+
severityNote: SEVERITY_NOTE.exec(codeCell)?.[1] ?? "error",
|
|
127
|
+
meaning: cells[1],
|
|
128
|
+
fix: cells.slice(2).join(" | "),
|
|
129
|
+
scope,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// A body ending mid-table has no closing line to end the block; today every
|
|
133
|
+
// body ends in prose, and a table that is the last thing in one must still
|
|
134
|
+
// be seen rather than silently dropped from the lookup.
|
|
135
|
+
if (open !== null)
|
|
136
|
+
blocks.push({ start: open.start, end: lines.length, rows: open.rows });
|
|
137
|
+
return blocks;
|
|
138
|
+
}
|
|
139
|
+
/** Every fix-table row of one workflow body, in document order. */
|
|
140
|
+
export function parseFixRows(body) {
|
|
141
|
+
return fixTableBlocks(body).flatMap((block) => [...block.rows]);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The same body with every fix table collapsed to one line naming what was
|
|
145
|
+
* dropped and how to get it back.
|
|
146
|
+
*
|
|
147
|
+
* What this is FOR: /loam-check's body is 83 KB, about a fifth of a 100k-token
|
|
148
|
+
* window, and every generated command and skill file opens by telling an agent
|
|
149
|
+
* to run it. The rows are the whole of that weight and almost none of them are
|
|
150
|
+
* about the run in hand — `loam explain <code>` answers one row in 473 bytes,
|
|
151
|
+
* which is the lazy path this makes payable.
|
|
152
|
+
*
|
|
153
|
+
* The introducing PARAGRAPH stays, and that is not a formatting nicety. It is
|
|
154
|
+
* the sentence that says which scope a code was graded in (`--service <id>`,
|
|
155
|
+
* `--feature <FEAT-id>`, `loam archive`), and the same code means different
|
|
156
|
+
* things in two of them — `spec.merge-conflict` is graded on a living document
|
|
157
|
+
* and on a delta of it. Drop the intro and the remaining prose stops saying
|
|
158
|
+
* which run it is describing.
|
|
159
|
+
*/
|
|
160
|
+
export function withoutFixTables(body) {
|
|
161
|
+
const lines = body.split("\n");
|
|
162
|
+
const out = [];
|
|
163
|
+
let at = 0;
|
|
164
|
+
for (const { start, end, rows } of fixTableBlocks(body)) {
|
|
165
|
+
// A block with no parsed rows is not a fix table — a two-column table, or
|
|
166
|
+
// a row grammar that has moved. Left standing rather than replaced by a
|
|
167
|
+
// line claiming rows nobody can look up.
|
|
168
|
+
if (rows.length === 0)
|
|
169
|
+
continue;
|
|
170
|
+
out.push(...lines.slice(at, start));
|
|
171
|
+
out.push(`(${rows.length} row${rows.length === 1 ? "" : "s"} omitted — ` +
|
|
172
|
+
`run \`loam explain <code>\` on any code this run reports.)`);
|
|
173
|
+
at = end;
|
|
174
|
+
}
|
|
175
|
+
out.push(...lines.slice(at));
|
|
176
|
+
return out.join("\n");
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=fix-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix-tables.js","sourceRoot":"","sources":["../../../src/core/explain/fix-tables.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The fix-table parser: `loam explain`'s finding-code content, read at runtime\n * out of the workflow bodies the binary ships. Every protocol body in\n * `COMMANDS` is walked, so a table added to any workflow is picked up without\n * touching this parser — today the tables live in the /loam-check body\n * (src/core/agent/workflows/check.ts) and the /loam-verify body's notice\n * table (src/core/agent/workflows/closing.ts).\n *\n * A PARSER rather than a table of its own, deliberately: the /loam-check fix\n * tables are already the documentation corpus test/codes-drift.test.ts holds\n * every emitted finding code against, so they are the one place the\n * meaning-and-fix prose is guaranteed to exist and to stay current. A second\n * copy inside an `explain` registry would be exactly the hand-maintained map\n * that silently trails the binary — worse than no command. Reading the shipped\n * constant instead means `loam explain spine.op-undefined` and the /loam-check\n * page cannot disagree, because they are the same bytes.\n *\n * The same walk also STRIPS those tables (`withoutFixTables`), which is what\n * `loam instructions <workflow> --no-fix-tables` prints. One walk and not two,\n * deliberately: a stripper carrying a regex of its own would be free to\n * disagree with the parser about where a table begins and ends, and the failure\n * that produces is both silent and precisely the wrong one — a narrowed\n * protocol whose omitted rows `loam explain` cannot answer, telling an agent to\n * look up a code nothing explains. Sharing the block detection makes \"what was\n * dropped\" and \"what can be explained\" the same computation rather than two\n * that agree today.\n *\n * The row grammar this depends on (test/explain.test.ts pins it with probes\n * and a count floor, so a table reformat fails loudly instead of leaving the\n * lookup silently empty):\n *\n * | `a.code` / `b.code` (severity note) | what it means | what to do |\n *\n * - the first cell holds one or more backticked codes and an optional trailing\n * parenthetical severity note, printed verbatim (`(warn)`, `(error, or\n * warn)`, `(warn, gates archive; one per service)`, `(ok)`); a row with no\n * note is an error, the tables' own default;\n * - cells never contain the ` | ` separator today; if a meaning cell ever\n * grows one, the probes convict the mis-split rather than letting it ship;\n * - the paragraph introducing each table (`` `--service <id>` — one service's\n * own axes… ``) names the scope its rows are graded in, so a code that\n * appears in two tables (`spec.merge-conflict`) explains both contexts.\n */\n\nexport interface FixRow {\n /** The backticked code(s) of the row's first cell — multi-code rows share one meaning. */\n readonly codes: readonly string[];\n /** The verbatim parenthetical from the first cell, or \"error\" — the tables' default. */\n readonly severityNote: string;\n /** The \"what it means\" cell, verbatim. */\n readonly meaning: string;\n /** The \"what to do\" cell, verbatim. */\n readonly fix: string;\n /** The short label of the table's introducing paragraph (`--service <id>`, `loam archive`, …). */\n readonly scope: string;\n}\n\nconst CODE_SPAN = /`([a-z][a-z0-9.-]*)`/g;\nconst SEVERITY_NOTE = /\\(([^)]+)\\)\\s*$/;\n\n/**\n * The scope label: the introducing paragraph's first line up to its ` — `\n * dash, backticks stripped — \"`--feature <FEAT-id>` — a change's three axes…\"\n * labels its rows `--feature <FEAT-id>`. A paragraph with no dash (none exist\n * today) falls back to its whole first line minus the trailing colon.\n */\nfunction scopeLabel(firstLine: string): string {\n const head = firstLine.split(\" — \")[0] ?? firstLine;\n return head.replace(/`/g, \"\").replace(/:$/, \"\").trim();\n}\n\n/**\n * Split one table row into its cells, or null for a line that is not a\n * three-cell row (the `|---|---|---|` separator has no ` | ` and yields one\n * cell). More than three cells re-joins the tail into the fix column — the\n * meaning cell is the split's second field either way, and the probe tests\n * are what convict a cell that ever grows a ` | ` of its own.\n */\nfunction splitRow(line: string): string[] | null {\n if (!line.startsWith(\"|\") || !line.endsWith(\"|\")) return null;\n const cells = line.slice(1, -1).split(\" | \").map((cell) => cell.trim());\n return cells.length >= 3 ? cells : null;\n}\n\n/**\n * One fix table as it sits in a body: which lines it occupies, and the rows\n * read out of them.\n *\n * The line span is what makes the stripper possible without a second notion of\n * where a table is. `start` is the header row (`| code | what it means | …`)\n * and `end` is one PAST the last table line, so `lines.slice(start, end)` is\n * exactly the block and `lines.slice(end)` is exactly what follows it — the\n * blank line and the next paragraph included, which is why the introducing\n * paragraph survives a strip.\n */\ninterface TableBlock {\n readonly start: number;\n readonly end: number;\n readonly rows: readonly FixRow[];\n}\n\n/**\n * Every fix table of one workflow body, in document order, each with its rows.\n *\n * The scope tracking is why this walks lines rather than matching rows\n * globally: each table's introducing paragraph ends one blank line above the\n * header row, so the label is the most recently COMPLETED paragraph when a\n * table opens (or the one still being built, for a table glued directly under\n * its intro).\n *\n * A run of consecutive `|` lines is one block, and the first line that is not\n * one closes it. That is the whole grammar — markdown gives a table no other\n * terminator — and it is why the blank line after a table belongs to what\n * follows rather than to the block.\n */\nfunction fixTableBlocks(body: string): TableBlock[] {\n const lines = body.split(\"\\n\");\n const blocks: TableBlock[] = [];\n let paragraph: string[] = [];\n let lastParagraph: string[] = [];\n let scope = \"\";\n let open: { start: number; rows: FixRow[] } | null = null;\n for (const [index, raw] of lines.entries()) {\n const line = raw.trimEnd();\n if (!line.startsWith(\"|\")) {\n if (open !== null) {\n blocks.push({ start: open.start, end: index, rows: open.rows });\n open = null;\n }\n if (line === \"\") {\n if (paragraph.length > 0) lastParagraph = paragraph;\n paragraph = [];\n } else {\n paragraph.push(line);\n }\n continue;\n }\n const intro = paragraph.length > 0 ? paragraph : lastParagraph;\n if (intro.length > 0) {\n scope = scopeLabel(intro[0]!);\n // Consumed: the next table needs its own intro, not this one again.\n lastParagraph = [];\n paragraph = [];\n }\n if (open === null) open = { start: index, rows: [] };\n const cells = splitRow(line);\n if (cells === null) continue;\n const codeCell = cells[0]!;\n const codes = [...codeCell.matchAll(CODE_SPAN)].map((m) => m[1]!);\n // The `| code | what it means | …` header row has no backticked code.\n if (codes.length === 0) continue;\n open.rows.push({\n codes,\n severityNote: SEVERITY_NOTE.exec(codeCell)?.[1] ?? \"error\",\n meaning: cells[1]!,\n fix: cells.slice(2).join(\" | \"),\n scope,\n });\n }\n // A body ending mid-table has no closing line to end the block; today every\n // body ends in prose, and a table that is the last thing in one must still\n // be seen rather than silently dropped from the lookup.\n if (open !== null) blocks.push({ start: open.start, end: lines.length, rows: open.rows });\n return blocks;\n}\n\n/** Every fix-table row of one workflow body, in document order. */\nexport function parseFixRows(body: string): FixRow[] {\n return fixTableBlocks(body).flatMap((block) => [...block.rows]);\n}\n\n/**\n * The same body with every fix table collapsed to one line naming what was\n * dropped and how to get it back.\n *\n * What this is FOR: /loam-check's body is 83 KB, about a fifth of a 100k-token\n * window, and every generated command and skill file opens by telling an agent\n * to run it. The rows are the whole of that weight and almost none of them are\n * about the run in hand — `loam explain <code>` answers one row in 473 bytes,\n * which is the lazy path this makes payable.\n *\n * The introducing PARAGRAPH stays, and that is not a formatting nicety. It is\n * the sentence that says which scope a code was graded in (`--service <id>`,\n * `--feature <FEAT-id>`, `loam archive`), and the same code means different\n * things in two of them — `spec.merge-conflict` is graded on a living document\n * and on a delta of it. Drop the intro and the remaining prose stops saying\n * which run it is describing.\n */\nexport function withoutFixTables(body: string): string {\n const lines = body.split(\"\\n\");\n const out: string[] = [];\n let at = 0;\n for (const { start, end, rows } of fixTableBlocks(body)) {\n // A block with no parsed rows is not a fix table — a two-column table, or\n // a row grammar that has moved. Left standing rather than replaced by a\n // line claiming rows nobody can look up.\n if (rows.length === 0) continue;\n out.push(...lines.slice(at, start));\n out.push(\n `(${rows.length} row${rows.length === 1 ? \"\" : \"s\"} omitted — ` +\n `run \\`loam explain <code>\\` on any code this run reports.)`,\n );\n at = end;\n }\n out.push(...lines.slice(at));\n return out.join(\"\\n\");\n}\n"]}
|