@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5992 -82
- package/COMPARISON.md +168 -63
- package/CONTRIBUTING.md +121 -0
- package/MIGRATING-from-OpenSpec.md +238 -55
- package/QUICKSTART.md +302 -0
- package/README.md +653 -144
- package/ROADMAP.md +1035 -0
- package/SCHEMA.md +3916 -263
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +927 -0
- package/dist/cli.js +133 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +204 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +309 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +74 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +193 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +319 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +298 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +106 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +318 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +30 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +355 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +166 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +305 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +367 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +221 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +6 -8
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +86 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +65 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +227 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +39 -28
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +152 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +66 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +105 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +262 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +146 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +72 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +142 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +63 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +155 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +358 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +344 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +108 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +238 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +75 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +175 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +18 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +62 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +328 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +279 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +199 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +300 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +221 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +278 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +174 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +182 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +53 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/show/service.js +239 -0
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +87 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +47 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +209 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +115 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +269 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +325 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +113 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +98 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +318 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +196 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +249 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +176 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/unarchive/restore.js +254 -0
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +59 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +245 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +204 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +58 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +264 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +85 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +222 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +93 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +371 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +118 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +266 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +71 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +75 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +52 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +89 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +145 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +252 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +241 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +177 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +310 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +279 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +148 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +363 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +178 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +81 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +263 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +278 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +206 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +328 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +220 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +266 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +141 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +230 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +111 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +155 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +169 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +299 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +46 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +44 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +78 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +104 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +138 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +273 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md.js +203 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +254 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +144 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +151 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +193 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +280 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +373 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +323 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +220 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +188 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +311 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +67 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +210 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +19 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +338 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +43 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +146 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +92 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +38 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +290 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +195 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +83 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/asyncapi/read.js +263 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +285 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +385 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +273 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +304 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +58 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +190 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +243 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +110 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +113 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +161 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +89 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +219 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +174 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +173 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +369 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +308 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +167 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +30 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +73 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +337 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +298 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +166 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +47 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +338 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +174 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +123 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +205 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +104 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +267 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +185 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +75 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +332 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +295 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +191 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +335 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +189 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +63 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +95 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +341 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +230 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +237 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +204 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +312 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/docs.js +37 -85
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +238 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +139 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +355 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +224 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +286 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +238 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +234 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +89 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +209 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +180 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +194 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +103 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/explore/explore.js +204 -0
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +174 -146
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +208 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +246 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +176 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +210 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +109 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +73 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/{records.js → kernel/records.js} +11 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +66 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +118 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +265 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +212 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +73 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +324 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +207 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +142 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +174 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +136 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +239 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +54 -108
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +199 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +16 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +204 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +232 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +110 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +220 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +78 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +70 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +241 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +191 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +304 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +116 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +157 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +120 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +244 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +201 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +139 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +280 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +220 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +322 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +308 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +61 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +90 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +255 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +146 -14
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +239 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +252 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +268 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +95 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +204 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/snapshot/snapshot.js +196 -0
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +181 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +60 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +126 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +214 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +163 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +216 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +302 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +216 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +166 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +140 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +101 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +76 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +296 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/grade/capability-tag.js +93 -0
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/core/usecases/grade/requirement-tag.js +94 -0
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/core/usecases/grade/steps.js +266 -0
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/core/usecases/grade/usecases.js +112 -0
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +123 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +180 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +170 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +259 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +158 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/read/shape.js +169 -0
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +165 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +99 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +61 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +59 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +216 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/vocabulary/report.js +90 -0
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +232 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +336 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +18 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +8 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +92 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +134 -0
- package/examples/docs/services/order-service/asyncapi.yaml +109 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +126 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +76 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +68 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
- package/examples/docs/services/platform/notification-service/health.yaml +40 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js +0 -320
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js +0 -317
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js +0 -253
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js +0 -225
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js +0 -47
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fleet's capability vocabulary AS THIS FEATURE'S MERGE WOULD LEAVE IT —
|
|
3
|
+
* the living declarations unioned with what the feature's own capability deltas
|
|
4
|
+
* add.
|
|
5
|
+
*
|
|
6
|
+
* WHY THIS EXISTS AT ALL. Without it the axis's headline flow is refused by an
|
|
7
|
+
* error code of its own making. `capabilityRequirementIndex` builds from
|
|
8
|
+
* `vocab.tree.docs`, the LIVING tree, and `realizesUnknownIssues` runs against
|
|
9
|
+
* it inside a feature delta as an ERROR that gates archive. So an author who
|
|
10
|
+
* writes `CHECKOUT-REFUND-ONCE` into
|
|
11
|
+
* `features/FEAT-9/capabilities/checkout/spec.md` and
|
|
12
|
+
* `Realizes: checkout#CHECKOUT-REFUND-ONCE` into
|
|
13
|
+
* `features/FEAT-9/specs/billing/spec.md` — the two halves of one change, in one
|
|
14
|
+
* feature — is told the target does not exist. It does not exist YET, and the
|
|
15
|
+
* same archive that would land the pointer lands the promise it points at.
|
|
16
|
+
*
|
|
17
|
+
* THE GRADE IS TAKEN AGAINST THE POST-MERGE FLEET, which is the only reading
|
|
18
|
+
* under which both directions of the join mean anything inside a feature. It is
|
|
19
|
+
* the same judgement the contract axis already makes one axis over, where
|
|
20
|
+
* `spec-api.op-undefined` is graded against feature ∪ living rather than living
|
|
21
|
+
* alone.
|
|
22
|
+
*
|
|
23
|
+
* IT WIDENS; IT MUST NOT BLIND. Every entry naming something neither side
|
|
24
|
+
* declares still fails, with the same message and the same close-name
|
|
25
|
+
* candidates — now drawn from the widened set, so a typo against a requirement
|
|
26
|
+
* the same feature is adding gets the useful suggestion rather than a list of
|
|
27
|
+
* ids the author was not writing about.
|
|
28
|
+
*
|
|
29
|
+
* THE LADDER SURVIVES. An unreadable `architecture/capabilities.yaml` is still
|
|
30
|
+
* `invalid`, and `declared: null` still suspends the whole family: a feature
|
|
31
|
+
* delta cannot make an unreadable vocabulary readable, and grading a hundred
|
|
32
|
+
* entries against a file nobody can parse is the cascade `../findings.ts`
|
|
33
|
+
* suppresses.
|
|
34
|
+
*/
|
|
35
|
+
import { requirementDigest } from "../../document/spec.js";
|
|
36
|
+
/**
|
|
37
|
+
* The vocabulary a feature's deltas would leave behind: every living
|
|
38
|
+
* declaration, plus every capability id this feature introduces.
|
|
39
|
+
*
|
|
40
|
+
* `present` widens too, and that is the point rather than a side effect: a
|
|
41
|
+
* feature writing the fleet's FIRST capability document is what creates
|
|
42
|
+
* `capabilities/`, so it is the act of opting in. Grading its own joins against
|
|
43
|
+
* the vocabulary it is about to create catches the typo before the merge; the
|
|
44
|
+
* alternative — silence until the document is living — reports the same typo on
|
|
45
|
+
* somebody else's next `validate --all`, against a document they did not write.
|
|
46
|
+
*
|
|
47
|
+
* `tree` is deliberately NOT widened. It lists the LIVING documents under
|
|
48
|
+
* `capabilities/`, and `capabilityRequirementIndex` reads every one of them and
|
|
49
|
+
* declares every non-REMOVED requirement it finds. Splicing a feature's delta
|
|
50
|
+
* path into that list would apply the living rule to a delta — which is right
|
|
51
|
+
* for ADDED and wrong for BASE, the kind a delta uses to QUOTE living context
|
|
52
|
+
* and that the merge never writes. The feature side arrives through
|
|
53
|
+
* `withFeatureRequirements` below instead, where the delta kinds decide.
|
|
54
|
+
*
|
|
55
|
+
* An id a feature introduces is recorded `source: "tree"` with no `spec`: the
|
|
56
|
+
* tree is the side that will declare it once the merge lands, and there is no
|
|
57
|
+
* living document to name yet. Nothing in the feature-grading path reads either
|
|
58
|
+
* field — they exist for the fleet-scope messages, which never see this value.
|
|
59
|
+
*/
|
|
60
|
+
export function withFeatureCapabilities(vocab, ids) {
|
|
61
|
+
if (ids.length === 0)
|
|
62
|
+
return vocab;
|
|
63
|
+
const byId = new Map(vocab.byId);
|
|
64
|
+
for (const id of ids) {
|
|
65
|
+
if (byId.has(id))
|
|
66
|
+
continue;
|
|
67
|
+
byId.set(id, { id, source: "tree" });
|
|
68
|
+
}
|
|
69
|
+
return { ...vocab, present: true, byId };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The `Realizes:` index a feature's deltas would leave behind: the living
|
|
73
|
+
* requirement ids per capability, plus the ids this feature ADDS or MODIFIES.
|
|
74
|
+
*
|
|
75
|
+
* ADDED and MODIFIED, never REMOVED and never BASE.
|
|
76
|
+
*
|
|
77
|
+
* BASE is where the exclusion earns its keep: a `## Requirements` section
|
|
78
|
+
* inside a delta QUOTES living context for a reader, and the merge never writes
|
|
79
|
+
* it — so an id appearing only there will not exist after the archive either,
|
|
80
|
+
* and widening on it would resolve a `Realizes:` in silence and leave the fleet
|
|
81
|
+
* holding a pointer at a promise nobody ever wrote.
|
|
82
|
+
*
|
|
83
|
+
* REMOVED is excluded for honesty rather than for effect. A REMOVED requirement
|
|
84
|
+
* that names something living is already in the index through the LIVING half,
|
|
85
|
+
* so leaving it out changes no answer; what it must not do is make a delta that
|
|
86
|
+
* removes something absent — already `delta.removed-unknown` — look resolvable
|
|
87
|
+
* on top of that.
|
|
88
|
+
*
|
|
89
|
+
* WHAT THIS DOES NOT CLOSE, stated because the shape invites the assumption: a
|
|
90
|
+
* feature that REMOVES a capability requirement a LIVING service requirement
|
|
91
|
+
* realizes archives clean, and the next `validate --all` reports
|
|
92
|
+
* `capability.realizes-unknown` against a service document nobody touched.
|
|
93
|
+
* Catching that needs the join taken in the other direction — the living
|
|
94
|
+
* `Realizes:` corpus against this feature's removals — which is the mirror of
|
|
95
|
+
* the ROADMAP's `capability.uncovered` and belongs with it, not here.
|
|
96
|
+
*
|
|
97
|
+
* A capability the feature introduces gets an entry even when its delta adds no
|
|
98
|
+
* requirements, and the empty set is a real answer rather than a filler: it is
|
|
99
|
+
* what tells `resolveRealizes` to say "declares no requirements yet" instead of
|
|
100
|
+
* "has no document at all", which are two different fixes.
|
|
101
|
+
*
|
|
102
|
+
* `declared === null` returns the index untouched — the ladder, one level down.
|
|
103
|
+
*/
|
|
104
|
+
export function withFeatureRequirements(index, deltas) {
|
|
105
|
+
if (index.declared === null || deltas.length === 0)
|
|
106
|
+
return index;
|
|
107
|
+
const byCapability = new Map(index.byCapability);
|
|
108
|
+
const digests = new Map(index.digests);
|
|
109
|
+
for (const delta of deltas) {
|
|
110
|
+
const ids = new Set(byCapability.get(delta.id) ?? []);
|
|
111
|
+
// The delta's OWN digest wins for a MODIFIED id: inside a feature window,
|
|
112
|
+
// the version a `Realizes:` pin should agree with is the one this feature
|
|
113
|
+
// is about to merge, not the living one it is replacing. Overwriting is
|
|
114
|
+
// therefore the point, not a collision.
|
|
115
|
+
const withDigests = new Map(digests.get(delta.id) ?? []);
|
|
116
|
+
for (const r of delta.reqs) {
|
|
117
|
+
if (r.kind !== "ADDED" && r.kind !== "MODIFIED")
|
|
118
|
+
continue;
|
|
119
|
+
if (r.id === undefined)
|
|
120
|
+
continue;
|
|
121
|
+
ids.add(r.id);
|
|
122
|
+
withDigests.set(r.id, requirementDigest(r));
|
|
123
|
+
}
|
|
124
|
+
byCapability.set(delta.id, ids);
|
|
125
|
+
digests.set(delta.id, withDigests);
|
|
126
|
+
}
|
|
127
|
+
return { declared: index.declared, byCapability, digests };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../../src/core/capabilities/delta/overlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAY7E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAA2B,EAC3B,GAAsB;IAEtB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAqB,KAAK,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAiC,EACjC,MAAyC;IAEzC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,MAAM,YAAY,GAAG,IAAI,GAAG,CAA8B,KAAK,CAAC,YAAY,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAsC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAiB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACzE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YAC1D,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS;gBAAE,SAAS;YACjC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACd,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * The fleet's capability vocabulary AS THIS FEATURE'S MERGE WOULD LEAVE IT —\n * the living declarations unioned with what the feature's own capability deltas\n * add.\n *\n * WHY THIS EXISTS AT ALL. Without it the axis's headline flow is refused by an\n * error code of its own making. `capabilityRequirementIndex` builds from\n * `vocab.tree.docs`, the LIVING tree, and `realizesUnknownIssues` runs against\n * it inside a feature delta as an ERROR that gates archive. So an author who\n * writes `CHECKOUT-REFUND-ONCE` into\n * `features/FEAT-9/capabilities/checkout/spec.md` and\n * `Realizes: checkout#CHECKOUT-REFUND-ONCE` into\n * `features/FEAT-9/specs/billing/spec.md` — the two halves of one change, in one\n * feature — is told the target does not exist. It does not exist YET, and the\n * same archive that would land the pointer lands the promise it points at.\n *\n * THE GRADE IS TAKEN AGAINST THE POST-MERGE FLEET, which is the only reading\n * under which both directions of the join mean anything inside a feature. It is\n * the same judgement the contract axis already makes one axis over, where\n * `spec-api.op-undefined` is graded against feature ∪ living rather than living\n * alone.\n *\n * IT WIDENS; IT MUST NOT BLIND. Every entry naming something neither side\n * declares still fails, with the same message and the same close-name\n * candidates — now drawn from the widened set, so a typo against a requirement\n * the same feature is adding gets the useful suggestion rather than a list of\n * ids the author was not writing about.\n *\n * THE LADDER SURVIVES. An unreadable `architecture/capabilities.yaml` is still\n * `invalid`, and `declared: null` still suspends the whole family: a feature\n * delta cannot make an unreadable vocabulary readable, and grading a hundred\n * entries against a file nobody can parse is the cascade `../findings.ts`\n * suppresses.\n */\nimport { requirementDigest, type Requirement } from \"../../document/spec.js\";\nimport type { Capability, CapabilityVocabulary } from \"../capabilities.js\";\nimport type { CapabilityRequirementIndex } from \"../realizes/join.js\";\n\n/** One capability document a feature's delta carries, already parsed. */\nexport interface FeatureCapabilityDelta {\n /** The capability id — the directory chain under `features/<FEAT>/capabilities/`. */\n id: string;\n /** The delta document's requirements, kinds and all. */\n reqs: Requirement[];\n}\n\n/**\n * The vocabulary a feature's deltas would leave behind: every living\n * declaration, plus every capability id this feature introduces.\n *\n * `present` widens too, and that is the point rather than a side effect: a\n * feature writing the fleet's FIRST capability document is what creates\n * `capabilities/`, so it is the act of opting in. Grading its own joins against\n * the vocabulary it is about to create catches the typo before the merge; the\n * alternative — silence until the document is living — reports the same typo on\n * somebody else's next `validate --all`, against a document they did not write.\n *\n * `tree` is deliberately NOT widened. It lists the LIVING documents under\n * `capabilities/`, and `capabilityRequirementIndex` reads every one of them and\n * declares every non-REMOVED requirement it finds. Splicing a feature's delta\n * path into that list would apply the living rule to a delta — which is right\n * for ADDED and wrong for BASE, the kind a delta uses to QUOTE living context\n * and that the merge never writes. The feature side arrives through\n * `withFeatureRequirements` below instead, where the delta kinds decide.\n *\n * An id a feature introduces is recorded `source: \"tree\"` with no `spec`: the\n * tree is the side that will declare it once the merge lands, and there is no\n * living document to name yet. Nothing in the feature-grading path reads either\n * field — they exist for the fleet-scope messages, which never see this value.\n */\nexport function withFeatureCapabilities(\n vocab: CapabilityVocabulary,\n ids: readonly string[],\n): CapabilityVocabulary {\n if (ids.length === 0) return vocab;\n const byId = new Map<string, Capability>(vocab.byId);\n for (const id of ids) {\n if (byId.has(id)) continue;\n byId.set(id, { id, source: \"tree\" });\n }\n return { ...vocab, present: true, byId };\n}\n\n/**\n * The `Realizes:` index a feature's deltas would leave behind: the living\n * requirement ids per capability, plus the ids this feature ADDS or MODIFIES.\n *\n * ADDED and MODIFIED, never REMOVED and never BASE.\n *\n * BASE is where the exclusion earns its keep: a `## Requirements` section\n * inside a delta QUOTES living context for a reader, and the merge never writes\n * it — so an id appearing only there will not exist after the archive either,\n * and widening on it would resolve a `Realizes:` in silence and leave the fleet\n * holding a pointer at a promise nobody ever wrote.\n *\n * REMOVED is excluded for honesty rather than for effect. A REMOVED requirement\n * that names something living is already in the index through the LIVING half,\n * so leaving it out changes no answer; what it must not do is make a delta that\n * removes something absent — already `delta.removed-unknown` — look resolvable\n * on top of that.\n *\n * WHAT THIS DOES NOT CLOSE, stated because the shape invites the assumption: a\n * feature that REMOVES a capability requirement a LIVING service requirement\n * realizes archives clean, and the next `validate --all` reports\n * `capability.realizes-unknown` against a service document nobody touched.\n * Catching that needs the join taken in the other direction — the living\n * `Realizes:` corpus against this feature's removals — which is the mirror of\n * the ROADMAP's `capability.uncovered` and belongs with it, not here.\n *\n * A capability the feature introduces gets an entry even when its delta adds no\n * requirements, and the empty set is a real answer rather than a filler: it is\n * what tells `resolveRealizes` to say \"declares no requirements yet\" instead of\n * \"has no document at all\", which are two different fixes.\n *\n * `declared === null` returns the index untouched — the ladder, one level down.\n */\nexport function withFeatureRequirements(\n index: CapabilityRequirementIndex,\n deltas: readonly FeatureCapabilityDelta[],\n): CapabilityRequirementIndex {\n if (index.declared === null || deltas.length === 0) return index;\n const byCapability = new Map<string, ReadonlySet<string>>(index.byCapability);\n const digests = new Map<string, ReadonlyMap<string, string>>(index.digests);\n for (const delta of deltas) {\n const ids = new Set(byCapability.get(delta.id) ?? []);\n // The delta's OWN digest wins for a MODIFIED id: inside a feature window,\n // the version a `Realizes:` pin should agree with is the one this feature\n // is about to merge, not the living one it is replacing. Overwriting is\n // therefore the point, not a collision.\n const withDigests = new Map<string, string>(digests.get(delta.id) ?? []);\n for (const r of delta.reqs) {\n if (r.kind !== \"ADDED\" && r.kind !== \"MODIFIED\") continue;\n if (r.id === undefined) continue;\n ids.add(r.id);\n withDigests.set(r.id, requirementDigest(r));\n }\n byCapability.set(delta.id, ids);\n digests.set(delta.id, withDigests);\n }\n return { declared: index.declared, byCapability, digests };\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one feature's capability deltas CHANGE, summarized once for the two
|
|
3
|
+
* commands a person reads before an archive.
|
|
4
|
+
*
|
|
5
|
+
* `loam show <FEAT>` and `loam delta <FEAT>` mentioned the business corpus
|
|
6
|
+
* nowhere, and the consequence was the worst shape an informational surface can
|
|
7
|
+
* have: a feature carrying ONLY a capability delta — which is the first thing an
|
|
8
|
+
* analyst writes, and exactly what `loam new --capability` now scaffolds —
|
|
9
|
+
* displayed as a feature that carries nothing. The two surfaces a reader
|
|
10
|
+
* consults before running `loam archive` therefore disagreed with the archive
|
|
11
|
+
* that would refuse it.
|
|
12
|
+
*
|
|
13
|
+
* ONE SHAPE FOR BOTH, and that is the reason this lives in core rather than in
|
|
14
|
+
* either command. `show` needs the counts (its service rows are `+N ~N -N`) and
|
|
15
|
+
* `delta` needs the promises themselves (it is a task brief, and the id in
|
|
16
|
+
* `Realizes: <capability>#<id>` is the one thing the implementer has to copy
|
|
17
|
+
* exactly). Two derivations would be two answers to "what does this feature
|
|
18
|
+
* change here", from the two commands most likely to be read side by side.
|
|
19
|
+
*
|
|
20
|
+
* THE READER IS INJECTED, exactly as `../rollup.ts`'s is and for the same
|
|
21
|
+
* package-graph reason: `core/fleet-context.ts` imports this package for its
|
|
22
|
+
* memo, so nothing under `src/core/capabilities/` may import it back.
|
|
23
|
+
*
|
|
24
|
+
* BASE requirements are counted by neither. A delta's `## Requirements` section
|
|
25
|
+
* QUOTES living context for a reader and the merge never writes it, so counting
|
|
26
|
+
* one as a change would report a feature as touching a promise it only cites.
|
|
27
|
+
* `delta.requirement-not-merged` is the grade for BASE requirements the author
|
|
28
|
+
* did NOT mean to quote — it exempts `## Requirements` precisely because that
|
|
29
|
+
* heading is the deliberate quotation — and this module owes the same reading:
|
|
30
|
+
* quoted or stranded, a BASE requirement merges nothing, so it is no part of
|
|
31
|
+
* what this feature changes.
|
|
32
|
+
*/
|
|
33
|
+
import { compareIds } from "../../repo/entries.js";
|
|
34
|
+
/**
|
|
35
|
+
* Summarize each capability delta, ordered by capability id.
|
|
36
|
+
*
|
|
37
|
+
* `docs` comes from `featureCapabilityDeltas` (or a `FleetContext`'s memo of
|
|
38
|
+
* it), so it is already `compareIds`-ordered by the walk; the sort here is the
|
|
39
|
+
* statement that the order is part of the answer rather than a property of
|
|
40
|
+
* whoever happened to call.
|
|
41
|
+
*/
|
|
42
|
+
export async function capabilityDeltaSummaries(docs, read) {
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const doc of docs) {
|
|
45
|
+
const reqs = await read(doc.spec);
|
|
46
|
+
out.push({
|
|
47
|
+
id: doc.id,
|
|
48
|
+
spec: doc.spec,
|
|
49
|
+
added: reqs.filter((r) => r.kind === "ADDED").length,
|
|
50
|
+
modified: reqs.filter((r) => r.kind === "MODIFIED").length,
|
|
51
|
+
removed: reqs.filter((r) => r.kind === "REMOVED").length,
|
|
52
|
+
promises: reqs.flatMap((r) => r.kind === "BASE" ? [] : [{ kind: r.kind, id: r.id ?? null, name: r.name }]),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return out.sort((a, b) => compareIds(a.id, b.id));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../../src/core/capabilities/delta/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAgCnD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,IAA8B,EAC9B,IAA8C;IAE9C,MAAM,GAAG,GAA6B,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC;YACP,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,MAAM;YACpD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,MAAM;YAC1D,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM;YACxD,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3B,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAC5E;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC","sourcesContent":["/**\n * What one feature's capability deltas CHANGE, summarized once for the two\n * commands a person reads before an archive.\n *\n * `loam show <FEAT>` and `loam delta <FEAT>` mentioned the business corpus\n * nowhere, and the consequence was the worst shape an informational surface can\n * have: a feature carrying ONLY a capability delta — which is the first thing an\n * analyst writes, and exactly what `loam new --capability` now scaffolds —\n * displayed as a feature that carries nothing. The two surfaces a reader\n * consults before running `loam archive` therefore disagreed with the archive\n * that would refuse it.\n *\n * ONE SHAPE FOR BOTH, and that is the reason this lives in core rather than in\n * either command. `show` needs the counts (its service rows are `+N ~N -N`) and\n * `delta` needs the promises themselves (it is a task brief, and the id in\n * `Realizes: <capability>#<id>` is the one thing the implementer has to copy\n * exactly). Two derivations would be two answers to \"what does this feature\n * change here\", from the two commands most likely to be read side by side.\n *\n * THE READER IS INJECTED, exactly as `../rollup.ts`'s is and for the same\n * package-graph reason: `core/fleet-context.ts` imports this package for its\n * memo, so nothing under `src/core/capabilities/` may import it back.\n *\n * BASE requirements are counted by neither. A delta's `## Requirements` section\n * QUOTES living context for a reader and the merge never writes it, so counting\n * one as a change would report a feature as touching a promise it only cites.\n * `delta.requirement-not-merged` is the grade for BASE requirements the author\n * did NOT mean to quote — it exempts `## Requirements` precisely because that\n * heading is the deliberate quotation — and this module owes the same reading:\n * quoted or stranded, a BASE requirement merges nothing, so it is no part of\n * what this feature changes.\n */\nimport { compareIds } from \"../../repo/entries.js\";\nimport type { Requirement } from \"../../document/spec.js\";\nimport type { CapabilityDoc } from \"../tree.js\";\n\n/** One promise a delta adds, restates or retires — the `Realizes:` target it creates or removes. */\nexport interface CapabilityDeltaPromise {\n kind: \"ADDED\" | \"MODIFIED\" | \"REMOVED\";\n /**\n * Its `Requirement-ID:`, or null when the delta wrote none. Null rather than\n * absent because it is a real and reportable state, not a missing field: an\n * unidentified capability requirement is an ERROR\n * (`capability.requirement-unidentified`) that gates the archive, and a brief\n * that silently dropped the row would hide the requirement the author has to\n * fix.\n */\n id: string | null;\n /** Its `### Requirement:` heading. */\n name: string;\n}\n\n/** One capability document a feature's delta carries, and what it would merge. */\nexport interface CapabilityDeltaSummary {\n id: string;\n /** The delta document, absolute. Callers make it repo-relative for their own payload. */\n spec: string;\n added: number;\n modified: number;\n removed: number;\n /** Every non-BASE requirement, in document order — the promises this delta moves. */\n promises: CapabilityDeltaPromise[];\n}\n\n/**\n * Summarize each capability delta, ordered by capability id.\n *\n * `docs` comes from `featureCapabilityDeltas` (or a `FleetContext`'s memo of\n * it), so it is already `compareIds`-ordered by the walk; the sort here is the\n * statement that the order is part of the answer rather than a property of\n * whoever happened to call.\n */\nexport async function capabilityDeltaSummaries(\n docs: readonly CapabilityDoc[],\n read: (path: string) => Promise<Requirement[]>,\n): Promise<CapabilityDeltaSummary[]> {\n const out: CapabilityDeltaSummary[] = [];\n for (const doc of docs) {\n const reqs = await read(doc.spec);\n out.push({\n id: doc.id,\n spec: doc.spec,\n added: reqs.filter((r) => r.kind === \"ADDED\").length,\n modified: reqs.filter((r) => r.kind === \"MODIFIED\").length,\n removed: reqs.filter((r) => r.kind === \"REMOVED\").length,\n promises: reqs.flatMap((r) =>\n r.kind === \"BASE\" ? [] : [{ kind: r.kind, id: r.id ?? null, name: r.name }],\n ),\n });\n }\n return out.sort((a, b) => compareIds(a.id, b.id));\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A feature's own capability deltas: `features/<FEAT>/capabilities/<id>/spec.md`.
|
|
3
|
+
*
|
|
4
|
+
* The business axis's answer to `specs/<svc>/spec.md`. A capability document is
|
|
5
|
+
* a requirements document like any other, so a feature that changes one writes
|
|
6
|
+
* a DELTA against it rather than editing the living text in place — which buys
|
|
7
|
+
* the three things the living tree has never had: a `Based-On:` pin, so two PRs
|
|
8
|
+
* touching one capability collide loudly instead of silently overwriting each
|
|
9
|
+
* other; the delta algebra's refusals (`delta.added-duplicate`,
|
|
10
|
+
* `delta.modified-unknown`, …), so a diff that lands nothing says so; and a
|
|
11
|
+
* business change that ships and unships with the feature that made it.
|
|
12
|
+
*
|
|
13
|
+
* BOTH LIFECYCLES COEXIST AND MUST. Nothing here makes a direct edit of
|
|
14
|
+
* `capabilities/<id>/spec.md` illegal — a fleet mid-adoption edits the document
|
|
15
|
+
* and always has. What a feature-local delta adds is a second, safer route, and
|
|
16
|
+
* a direct edit racing one surfaces as `delta.baseline-stale` instead of as
|
|
17
|
+
* today's silent loss.
|
|
18
|
+
*
|
|
19
|
+
* ONE CALL, because the walk is already written: `readCapabilityTree`
|
|
20
|
+
* implements the presence-classifies rule, the symlink-cycle guard and the
|
|
21
|
+
* `compareIds` ordering over any root. Re-deriving it here for the feature side
|
|
22
|
+
* would be two walks free to disagree about what a capability directory is.
|
|
23
|
+
*
|
|
24
|
+
* NO `FleetContext` PARAMETER, and that is load-bearing rather than stylistic:
|
|
25
|
+
* `core/fleet-context.ts` imports `../capabilities.js`, so nothing under
|
|
26
|
+
* `src/core/capabilities/` may import it back — a core-root↔capabilities
|
|
27
|
+
* package cycle `import/no-cycle` cannot see. The memo lives on the class and
|
|
28
|
+
* calls this; callers holding a context use `context.featureCapabilityDeltas`.
|
|
29
|
+
*/
|
|
30
|
+
import { readCapabilityTree } from "../tree.js";
|
|
31
|
+
import { featureCapabilityDeltasDir } from "../../repo/authored/paths.js";
|
|
32
|
+
/**
|
|
33
|
+
* The capability documents one feature's delta carries, ordered by id.
|
|
34
|
+
*
|
|
35
|
+
* `present: false` — and zero readdirs — when the feature has no
|
|
36
|
+
* `capabilities/` directory, which is every feature in a fleet that has not
|
|
37
|
+
* adopted the axis. That short-circuit is `readCapabilityTree`'s own
|
|
38
|
+
* `existsSync` and it is the whole cost such a fleet pays.
|
|
39
|
+
*/
|
|
40
|
+
export function featureCapabilityDeltas(featureDir) {
|
|
41
|
+
return readCapabilityTree(featureCapabilityDeltasDir(featureDir));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../../src/core/capabilities/delta/tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,kBAAkB,EAAuB,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAG1E;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAsB;IAC5D,OAAO,kBAAkB,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC,CAAC;AACpE,CAAC","sourcesContent":["/**\n * A feature's own capability deltas: `features/<FEAT>/capabilities/<id>/spec.md`.\n *\n * The business axis's answer to `specs/<svc>/spec.md`. A capability document is\n * a requirements document like any other, so a feature that changes one writes\n * a DELTA against it rather than editing the living text in place — which buys\n * the three things the living tree has never had: a `Based-On:` pin, so two PRs\n * touching one capability collide loudly instead of silently overwriting each\n * other; the delta algebra's refusals (`delta.added-duplicate`,\n * `delta.modified-unknown`, …), so a diff that lands nothing says so; and a\n * business change that ships and unships with the feature that made it.\n *\n * BOTH LIFECYCLES COEXIST AND MUST. Nothing here makes a direct edit of\n * `capabilities/<id>/spec.md` illegal — a fleet mid-adoption edits the document\n * and always has. What a feature-local delta adds is a second, safer route, and\n * a direct edit racing one surfaces as `delta.baseline-stale` instead of as\n * today's silent loss.\n *\n * ONE CALL, because the walk is already written: `readCapabilityTree`\n * implements the presence-classifies rule, the symlink-cycle guard and the\n * `compareIds` ordering over any root. Re-deriving it here for the feature side\n * would be two walks free to disagree about what a capability directory is.\n *\n * NO `FleetContext` PARAMETER, and that is load-bearing rather than stylistic:\n * `core/fleet-context.ts` imports `../capabilities.js`, so nothing under\n * `src/core/capabilities/` may import it back — a core-root↔capabilities\n * package cycle `import/no-cycle` cannot see. The memo lives on the class and\n * calls this; callers holding a context use `context.featureCapabilityDeltas`.\n */\nimport { readCapabilityTree, type CapabilityTree } from \"../tree.js\";\nimport { featureCapabilityDeltasDir } from \"../../repo/authored/paths.js\";\nimport type { FeatureDir } from \"../../kernel/ids/dirs.js\";\n\n/**\n * The capability documents one feature's delta carries, ordered by id.\n *\n * `present: false` — and zero readdirs — when the feature has no\n * `capabilities/` directory, which is every feature in a fleet that has not\n * adopted the axis. That short-circuit is `readCapabilityTree`'s own\n * `existsSync` and it is the whole cost such a fleet pays.\n */\nexport function featureCapabilityDeltas(featureDir: FeatureDir): Promise<CapabilityTree> {\n return readCapabilityTree(featureCapabilityDeltasDir(featureDir));\n}\n"]}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { splitRealizesEntry } from "../realizes/join.js";
|
|
2
|
+
import { tagSlug } from "../usecase-join.js";
|
|
3
|
+
/**
|
|
4
|
+
* The `(capability, requirement)` pair, keyed for a Set.
|
|
5
|
+
*
|
|
6
|
+
* NUL — the separator `core/delta/scope.ts`'s claim key already uses — rather
|
|
7
|
+
* than `#`, because a key's separator must be one its halves cannot contain and
|
|
8
|
+
* a capability id is a YAML key and a directory name, constrained nowhere.
|
|
9
|
+
* Re-joining with `#` would make `a#b` + `C` and `a` + `b#C` one key, and the
|
|
10
|
+
* second is unreachable only because the requirement grammar happens to exclude
|
|
11
|
+
* `#` today.
|
|
12
|
+
*/
|
|
13
|
+
function pairKey(capability, requirement) {
|
|
14
|
+
return `${capability}\0${requirement}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The pairs one requirement's `Realizes:` lines name.
|
|
18
|
+
*
|
|
19
|
+
* Through `splitRealizesEntry`, never a local split, and the LAST `#` is what
|
|
20
|
+
* makes it right: the requirement half has a grammar that excludes `#` and the
|
|
21
|
+
* capability half has none, so a first-`#` split mis-parses every id containing
|
|
22
|
+
* one — silently, which is the failure this axis exists to refuse.
|
|
23
|
+
*/
|
|
24
|
+
function realizedPairs(r) {
|
|
25
|
+
return r.realizes.flatMap((entry) => {
|
|
26
|
+
const target = splitRealizesEntry(entry);
|
|
27
|
+
return target === null ? [] : [pairKey(target.capability, target.requirement)];
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** How a service document is named in a message — the axis only where it is not the default one. */
|
|
31
|
+
function docLabel(doc) {
|
|
32
|
+
return doc.file === "spec.md" ? doc.service : `${doc.service} (${doc.file})`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* `capability.uncovered` — a capability requirement this feature ADDS that no
|
|
36
|
+
* `Realizes:` line in the same feature's service deltas names.
|
|
37
|
+
*
|
|
38
|
+
* ADDED ONLY. A MODIFIED changes a promise the living fleet may already
|
|
39
|
+
* realize, so demanding a re-declaration would force an edit with nothing to
|
|
40
|
+
* change — the same exemption `c4.uncovered` takes one axis over. A requirement
|
|
41
|
+
* with no `Requirement-ID:` is SKIPPED rather than reported: it is already
|
|
42
|
+
* `capability.requirement-unidentified`, and there is nothing for a `Realizes:`
|
|
43
|
+
* line to address, so two findings for one mistake is the failure to avoid.
|
|
44
|
+
*
|
|
45
|
+
* The covering side is ADDED or MODIFIED, never BASE and never REMOVED. A BASE
|
|
46
|
+
* requirement in a delta quotes living context and the merge never writes it,
|
|
47
|
+
* so a `Realizes:` line there lands nowhere; a REMOVED one is on its way out and
|
|
48
|
+
* cannot keep a promise after it is gone.
|
|
49
|
+
*
|
|
50
|
+
* Feature scope, deliberately. The fleet-scope version already ships as
|
|
51
|
+
* `capability.requirement-unrealized`, and grading a feature-ADDED requirement
|
|
52
|
+
* against the LIVING fleet is vacuous — no living `Realizes:` can name it
|
|
53
|
+
* without being `capability.realizes-unknown` today.
|
|
54
|
+
*/
|
|
55
|
+
export function uncoveredIssues(capabilities, services,
|
|
56
|
+
// REQUIRED, with no default. A default would have to be one of the two arms,
|
|
57
|
+
// and either choice is wrong for a caller that forgot: `graded: true` with an
|
|
58
|
+
// empty list makes the message assert a negative, and `graded: false` makes it
|
|
59
|
+
// quietly stop checking a corpus the caller does have. The compiler asking is
|
|
60
|
+
// cheaper than either.
|
|
61
|
+
flows) {
|
|
62
|
+
if (capabilities.length === 0)
|
|
63
|
+
return [];
|
|
64
|
+
const kept = new Set();
|
|
65
|
+
for (const doc of services) {
|
|
66
|
+
for (const r of doc.reqs) {
|
|
67
|
+
if (r.kind !== "ADDED" && r.kind !== "MODIFIED")
|
|
68
|
+
continue;
|
|
69
|
+
for (const pair of realizedPairs(r))
|
|
70
|
+
kept.add(pair);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// The other carrier, through the SAME `pairKey` as the `Realizes:` side: two
|
|
74
|
+
// corpora answering one question must not be able to disagree about which
|
|
75
|
+
// promise a claim addresses. The caller resolved these; a claim whose tags did
|
|
76
|
+
// not both resolve never reaches here, which is what stops a typo from
|
|
77
|
+
// silencing the gate.
|
|
78
|
+
if (flows.graded)
|
|
79
|
+
for (const flow of flows.kept)
|
|
80
|
+
kept.add(pairKey(flow.capability, flow.requirement));
|
|
81
|
+
// What the message may CLAIM about the flow half. Ungraded, it claims nothing
|
|
82
|
+
// and says so — the `Realizes:` half was still checked and is still worth
|
|
83
|
+
// gating on, so the finding stands; what must not stand is a sentence
|
|
84
|
+
// convicting a flow nobody resolved.
|
|
85
|
+
const flowClause = flows.graded
|
|
86
|
+
? "and no `dynamic view` under this feature's usecases/ resolves a `#req-` tag to it. "
|
|
87
|
+
: `and the flow half of the join was NOT checked — ${flows.why}, so a \`#req-\` claim could not be resolved either way. `;
|
|
88
|
+
const issues = [];
|
|
89
|
+
for (const doc of capabilities) {
|
|
90
|
+
for (const r of doc.reqs) {
|
|
91
|
+
if (r.kind !== "ADDED" || r.id === undefined)
|
|
92
|
+
continue;
|
|
93
|
+
if (kept.has(pairKey(doc.id, r.id)))
|
|
94
|
+
continue;
|
|
95
|
+
const entry = `${doc.id}#${r.id}`;
|
|
96
|
+
issues.push({
|
|
97
|
+
severity: "warn",
|
|
98
|
+
gates: true,
|
|
99
|
+
code: "capability.uncovered",
|
|
100
|
+
subject: doc.id,
|
|
101
|
+
message: `capability ${doc.id}: ADDED requirement '${r.name}' (${r.id}) is realized by nothing this feature changes — ` +
|
|
102
|
+
`no ADDED or MODIFIED requirement in its specs/ deltas carries \`Realizes: ${entry}\`, ` +
|
|
103
|
+
flowClause +
|
|
104
|
+
"The document is legal; the MERGE is what is unsafe: once it lands, the only thing that will ever mention " +
|
|
105
|
+
"this promise again is a fleet-scope warning (capability.requirement-unrealized) nobody reads. " +
|
|
106
|
+
`Three ways on: add \`Realizes: ${entry}\` to the service requirement that carries part of it; ` +
|
|
107
|
+
`if the promise CROSSES services, write the flow that keeps it as features/<FEAT>/usecases/<name>.likec4 and ` +
|
|
108
|
+
`tag its \`dynamic view\` \`#cap-${tagSlug(doc.id)}\` and \`#req-${tagSlug(r.id)}\` — the archive merges it into ` +
|
|
109
|
+
"architecture/usecases/ with everything else this feature lands; or archive with --approve to land the promise " +
|
|
110
|
+
"ahead of the fleet and let capability.requirement-unrealized carry it.",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return issues;
|
|
115
|
+
}
|
|
116
|
+
/** The living requirements a delta document supersedes — MODIFIED and REMOVED both restate or delete. */
|
|
117
|
+
function supersedes(delta, living) {
|
|
118
|
+
if (delta === undefined)
|
|
119
|
+
return false;
|
|
120
|
+
return delta.reqs.some((r) => {
|
|
121
|
+
if (r.kind !== "MODIFIED" && r.kind !== "REMOVED")
|
|
122
|
+
return false;
|
|
123
|
+
return r.id === undefined ? r.name === living.name : r.id === living.id;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* `capability.remove-requirement-realized` — this feature retires a capability
|
|
128
|
+
* requirement that something the merge LEAVES BEHIND still realizes.
|
|
129
|
+
*
|
|
130
|
+
* The hole the forward direction does not close, and the one this whole module
|
|
131
|
+
* exists to make impossible: a feature that REMOVES a capability requirement a
|
|
132
|
+
* living service requirement realizes used to archive at exit 0, and the next
|
|
133
|
+
* `loam validate --all` then failed with `capability.realizes-unknown` against a
|
|
134
|
+
* service document nobody had touched. An archive that leaves the fleet red
|
|
135
|
+
* against an untouched document is the exact class of silent damage the product
|
|
136
|
+
* exists to refuse.
|
|
137
|
+
*
|
|
138
|
+
* GRADED AGAINST THE POST-MERGE FLEET, which is the only reading under which
|
|
139
|
+
* the two escape hatches fall out instead of being special-cased. A living
|
|
140
|
+
* requirement that this feature's own delta MODIFIES or REMOVES is gone as
|
|
141
|
+
* written — a MODIFIED carries its FULL new text, so restating the requirement
|
|
142
|
+
* without its `Realizes:` line IS how an author drops the join — and the delta's
|
|
143
|
+
* own ADDED/MODIFIED requirements are what stands in its place. So: retire the
|
|
144
|
+
* realizer in the same change and there is no breach; keep the line and there
|
|
145
|
+
* is.
|
|
146
|
+
*
|
|
147
|
+
* A `#req-` tagged flow realizing the promise is NOT consulted, and that is the
|
|
148
|
+
* other subject rather than a gap: the tag names the requirement directly, so a
|
|
149
|
+
* removal turns it into `usecase.requirement-unresolved` on the living view —
|
|
150
|
+
* an error the delta walk raises before the archive, naming that view
|
|
151
|
+
* (`core/usecases/delta/modified.ts`), and nothing here would make it louder.
|
|
152
|
+
*
|
|
153
|
+
* A REMOVED spelled by heading resolves through the living document, so it
|
|
154
|
+
* grades exactly what the merge would delete. One that selects nothing is
|
|
155
|
+
* already `delta.removed-unknown` and retires nothing, so it is skipped here —
|
|
156
|
+
* two findings for one mistake, again.
|
|
157
|
+
*/
|
|
158
|
+
export async function removedRealizedIssues(join) {
|
|
159
|
+
const retired = new Map();
|
|
160
|
+
for (const doc of join.capabilities) {
|
|
161
|
+
for (const r of doc.reqs) {
|
|
162
|
+
if (r.kind !== "REMOVED")
|
|
163
|
+
continue;
|
|
164
|
+
const selected = doc.living.filter((l) => (r.id === undefined ? l.name === r.name : l.id === r.id));
|
|
165
|
+
for (const l of selected) {
|
|
166
|
+
if (l.id === undefined)
|
|
167
|
+
continue;
|
|
168
|
+
retired.set(pairKey(doc.id, l.id), { capability: doc.id, id: l.id, name: l.name });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (retired.size === 0)
|
|
173
|
+
return [];
|
|
174
|
+
// Who still realizes each retired pair after the merge: the living
|
|
175
|
+
// requirements this feature does not supersede, plus the requirements its own
|
|
176
|
+
// deltas add or restate.
|
|
177
|
+
const realizers = new Map();
|
|
178
|
+
const record = (pair, who) => {
|
|
179
|
+
if (!retired.has(pair))
|
|
180
|
+
return;
|
|
181
|
+
const found = realizers.get(pair) ?? [];
|
|
182
|
+
found.push(who);
|
|
183
|
+
realizers.set(pair, found);
|
|
184
|
+
};
|
|
185
|
+
for (const doc of await join.living()) {
|
|
186
|
+
const delta = join.deltas.find((d) => d.service === doc.service && d.file === doc.file);
|
|
187
|
+
for (const r of doc.reqs) {
|
|
188
|
+
if (supersedes(delta, r))
|
|
189
|
+
continue;
|
|
190
|
+
for (const pair of realizedPairs(r))
|
|
191
|
+
record(pair, `${docLabel(doc)}'s living requirement '${r.name}'`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
for (const doc of join.deltas) {
|
|
195
|
+
for (const r of doc.reqs) {
|
|
196
|
+
if (r.kind !== "ADDED" && r.kind !== "MODIFIED")
|
|
197
|
+
continue;
|
|
198
|
+
for (const pair of realizedPairs(r))
|
|
199
|
+
record(pair, `this feature's ${docLabel(doc)} delta requirement '${r.name}'`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const issues = [];
|
|
203
|
+
for (const [pair, promise] of retired) {
|
|
204
|
+
const who = realizers.get(pair);
|
|
205
|
+
if (who === undefined)
|
|
206
|
+
continue;
|
|
207
|
+
const entry = `${promise.capability}#${promise.id}`;
|
|
208
|
+
issues.push({
|
|
209
|
+
severity: "error",
|
|
210
|
+
code: "capability.remove-requirement-realized",
|
|
211
|
+
subject: promise.capability,
|
|
212
|
+
message: `capability ${promise.capability}: this feature REMOVES '${promise.name}' (${promise.id}), but ${who.join("; ")} ` +
|
|
213
|
+
`still carries \`Realizes: ${entry}\`. After the merge that line points at a promise no document declares, and ` +
|
|
214
|
+
"the very next `loam validate --all` reports capability.realizes-unknown against whatever carries it — for a " +
|
|
215
|
+
"LIVING realizer, a service document this feature never touched. Retire the realizing requirement in the same " +
|
|
216
|
+
"feature, or drop its `Realizes:` line (a MODIFIED does that by restating the requirement without it), or " +
|
|
217
|
+
"archive with --approve to break the join deliberately.",
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return issues;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=uncovered.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uncovered.js","sourceRoot":"","sources":["../../../../src/core/capabilities/delta/uncovered.ts"],"names":[],"mappings":"AAmEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAqC7C;;;;;;;;;GASG;AACH,SAAS,OAAO,CAAC,UAAkB,EAAE,WAAmB;IACtD,OAAO,GAAG,UAAU,KAAK,WAAW,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,aAAa,CAAC,CAAc;IACnC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oGAAoG;AACpG,SAAS,QAAQ,CAAC,GAAiB;IACjC,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC;AAC/E,CAAC;AAwCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC7B,YAA2C,EAC3C,QAAiC;AACjC,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAC9E,uBAAuB;AACvB,KAAiB;IAEjB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YAC1D,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IACD,6EAA6E;IAC7E,0EAA0E;IAC1E,+EAA+E;IAC/E,uEAAuE;IACvE,sBAAsB;IACtB,IAAI,KAAK,CAAC,MAAM;QAAE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACtG,8EAA8E;IAC9E,0EAA0E;IAC1E,sEAAsE;IACtE,qCAAqC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM;QAC7B,CAAC,CAAC,qFAAqF;QACvF,CAAC,CAAC,mDAAmD,KAAK,CAAC,GAAG,2DAA2D,CAAC;IAC5H,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS;gBAAE,SAAS;YACvD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;gBAAE,SAAS;YAC9C,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,GAAG,CAAC,EAAE;gBACf,OAAO,EACL,cAAc,GAAG,CAAC,EAAE,wBAAwB,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,kDAAkD;oBAC9G,6EAA6E,KAAK,MAAM;oBACxF,UAAU;oBACV,2GAA2G;oBAC3G,gGAAgG;oBAChG,kCAAkC,KAAK,yDAAyD;oBAChG,8GAA8G;oBAC9G,mCAAmC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAiB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,kCAAkC;oBAClH,gHAAgH;oBAChH,wEAAwE;aAC3E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAiBD,yGAAyG;AACzG,SAAS,UAAU,CAAC,KAA+B,EAAE,MAAmB;IACtE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAChE,OAAO,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAiB;IAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4D,CAAC;IACpF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;gBAAE,SAAS;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpG,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS;oBAAE,SAAS;gBACjC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,mEAAmE;IACnE,8EAA8E;IAC9E,yBAAyB;IACzB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,GAAW,EAAQ,EAAE;QACjD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QACxF,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;gBAAE,SAAS;YACnC,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC;gBAAE,MAAM,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QACzG,CAAC;IACH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YAC1D,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC;gBAAE,MAAM,CAAC,IAAI,EAAE,kBAAkB,QAAQ,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC;YACV,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,wCAAwC;YAC9C,OAAO,EAAE,OAAO,CAAC,UAAU;YAC3B,OAAO,EACL,cAAc,OAAO,CAAC,UAAU,2BAA2B,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAClH,6BAA6B,KAAK,8EAA8E;gBAChH,8GAA8G;gBAC9G,+GAA+G;gBAC/G,2GAA2G;gBAC3G,wDAAwD;SAC3D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * The `Realizes:` join taken INSIDE ONE FEATURE, in both directions: a promise\n * this feature makes that nothing in it keeps, and a promise it retires that\n * something outside it still keeps.\n *\n * `../realizes/findings.ts` grades the same join at the two places it can be\n * WRONG — an entry that resolves to nothing, a living requirement nothing\n * realizes. This module grades it at the one place it can silently COME APART:\n * the merge. Both directions are about a change, both are answered from\n * documents the archive gate already has parsed, and neither has any meaning\n * outside a feature — which is why they live together here and not beside their\n * fleet-scope siblings.\n *\n * TWO CODES, NOT ONE, and the decision is worth the paragraph because the shape\n * invites the opposite:\n *\n * - The FIXES are different. `capability.uncovered` is fixed by writing the\n * `Realizes:` line the promise is missing; `capability.remove-requirement-realized`\n * is fixed by retiring the requirement that carries the line, or by dropping\n * the line from it. A code is what a machine branches on and the branch is\n * the fix, so a single code covering both would be a code neither caller can\n * act on.\n * - The SEVERITIES are different, and they are different for the reason\n * `../../vocabulary/issue.ts` draws the distinction at all. `capability.uncovered`\n * is a warning that GATES: the document is legal — writing a business promise\n * ahead of the fleet is the recorded intended use, which is exactly why\n * `capability.requirement-unrealized` warns and never gates — while the MERGE\n * is what is unsafe, because once it lands the only thing that will ever\n * mention the promise again is a fleet-scope warning nobody reads. The\n * removal direction has no such legal reading: after that merge a LIVING\n * service document nobody in the feature touched carries a pointer at\n * nothing, and `capability.realizes-unknown` is already an ERROR there. So it\n * is an error here, exactly as `openapi.remove-op-consumed` is one axis over\n * for the identical shape — this feature retires a thing the living fleet\n * still uses. One code carrying two severities is a code that says nothing.\n * - The family already spells every direction of every join as its own code:\n * `capability.unknown` / `capability.realizes-unknown` name the entry that\n * resolves to nothing, `capability.unrealized` /\n * `capability.requirement-unrealized` name the promise nobody keeps. A pair\n * here is the shape a reader of that list already expects.\n *\n * A `#req-` TAGGED FLOW COUNTS AS COVER, and the reason it did not is worth\n * recording because it was a consequence rather than a policy. A `dynamic view`\n * used to be a fleet document with no feature-delta path, so a `#req-` tag\n * naming a capability requirement that was not living yet was ALREADY\n * `usecase.requirement-unresolved` — an error on `validate --all` — for the\n * whole window before the archive. At the moment this ran, a legal flow claim on\n * a newly-ADDED requirement could not exist, and the message said so: archive\n * with `--approve` first, tag the flow afterwards. That advice lands a promise\n * kept by nothing and relies on somebody coming back.\n *\n * `features/<FEAT>/usecases/` closed that (`core/usecases/delta/flows.ts`), so\n * the claim can now be legal at the moment it is graded, and the third arm of\n * `flows` below is it. What has NOT changed is which claims count: both tags\n * must resolve, against the vocabulary and requirement index this feature's own\n * merge would leave behind. A broken tag of either kind is an error in its own\n * right and must never also mark a promise kept — a typo that silenced this gate\n * would turn a mistake into a green archive.\n *\n * NO FILESYSTEM, deliberately, exactly as `../realizes/join.ts` has none — and\n * that is why the flows arrive as resolved pairs rather than as a docsDir. The\n * living side of the removal direction arrives as a thunk the caller supplies,\n * so the fleet-wide read happens only when this feature retires something, and\n * this module stays testable without a tree.\n */\nimport type { Requirement } from \"../../document/spec.js\";\nimport type { Issue } from \"../../vocabulary/issue.js\";\nimport { splitRealizesEntry } from \"../realizes/join.js\";\nimport { tagSlug } from \"../usecase-join.js\";\n\n/**\n * One requirements document on the SERVICE side of the join, and the two facts\n * that address it: whose it is, and which axis. Both halves of the key are\n * needed because a feature's delta of `payment-service`'s `arch.spec.md`\n * supersedes the living `arch.spec.md` and says nothing at all about the living\n * `spec.md` beside it.\n */\nexport interface RealizingDoc {\n /** The service id. */\n service: string;\n /** The axis's filename — `spec.md` or `arch.spec.md`, as `SPEC_AXES` spells it. */\n file: string;\n reqs: readonly Requirement[];\n}\n\n/**\n * One capability document a feature's delta changes, with the living text that\n * delta applies to.\n *\n * `living` is here rather than derived because a REMOVED requirement is exempt\n * from `capability.requirement-unidentified` and so may be spelled by heading\n * alone — the id it retires is then a fact about the LIVING document, and\n * without it the removal direction would silently grade nothing for the\n * commonest way a removal is written. Requirements rather than the delta\n * package's `LivingIndex`: `core/delta` imports this package, so importing it\n * back would be a package cycle the file-level cycle check cannot see.\n */\nexport interface CapabilityDeltaDoc {\n /** The capability id — the directory chain under `features/<FEAT>/capabilities/`. */\n id: string;\n reqs: readonly Requirement[];\n /** The LIVING `capabilities/<id>/spec.md` requirements, or `[]` when this feature creates it. */\n living: readonly Requirement[];\n}\n\n/**\n * The `(capability, requirement)` pair, keyed for a Set.\n *\n * NUL — the separator `core/delta/scope.ts`'s claim key already uses — rather\n * than `#`, because a key's separator must be one its halves cannot contain and\n * a capability id is a YAML key and a directory name, constrained nowhere.\n * Re-joining with `#` would make `a#b` + `C` and `a` + `b#C` one key, and the\n * second is unreachable only because the requirement grammar happens to exclude\n * `#` today.\n */\nfunction pairKey(capability: string, requirement: string): string {\n return `${capability}\\0${requirement}`;\n}\n\n/**\n * The pairs one requirement's `Realizes:` lines name.\n *\n * Through `splitRealizesEntry`, never a local split, and the LAST `#` is what\n * makes it right: the requirement half has a grammar that excludes `#` and the\n * capability half has none, so a first-`#` split mis-parses every id containing\n * one — silently, which is the failure this axis exists to refuse.\n */\nfunction realizedPairs(r: Requirement): string[] {\n return r.realizes.flatMap((entry) => {\n const target = splitRealizesEntry(entry);\n return target === null ? [] : [pairKey(target.capability, target.requirement)];\n });\n}\n\n/** How a service document is named in a message — the axis only where it is not the default one. */\nfunction docLabel(doc: RealizingDoc): string {\n return doc.file === \"spec.md\" ? doc.service : `${doc.service} (${doc.file})`;\n}\n\n/**\n * One promise a `#req-` tagged flow in the SAME feature keeps.\n *\n * Structurally typed rather than imported from `core/usecases/delta/claims.ts`,\n * where the caller builds it, and the reason is the package graph rather than\n * taste: `core/usecases/` already imports this package, so importing it back\n * would be a cycle that `import/no-cycle` cannot see — the acyclicity obligation\n * `scripts/package-graph.mjs` exists to hold. The shape is three fields; the\n * RULE that produced them (both tags resolved, or the claim does not count) is\n * that module's, and this one grades what it is handed.\n */\nexport interface KeptByFlow {\n capability: string;\n requirement: string;\n /** The view ids keeping it. Carried for a caller's report; nothing here reads it. */\n flows: readonly string[];\n}\n\n/**\n * The flow corpus, or the honest statement that there was not one to read.\n *\n * A TRI-STATE and not a possibly-empty list, because the message says what was\n * checked and an empty list would make it say something loam never looked at.\n * \"No flow keeps this\" and \"the flows were not graded\" are different sentences\n * and only one of them is an accusation — the standing rule this axis states\n * everywhere else, applied to the message rather than to a severity.\n *\n * `why` is printed, so it names the cause an author can act on: an\n * `architecture/` that did not parse is one thing, a `capabilities.yaml` that\n * does not read as a vocabulary is another, and inside a feature gate NOTHING\n * ELSE reports the second — `core/coherence/declared.ts` keeps\n * `capability.invalid` for `validate --all`. Without the sentence the run\n * refuses, names the wrong cause, and points at nothing.\n */\nexport type FlowCorpus =\n | { graded: true; kept: readonly KeptByFlow[] }\n | { graded: false; why: string };\n\n/**\n * `capability.uncovered` — a capability requirement this feature ADDS that no\n * `Realizes:` line in the same feature's service deltas names.\n *\n * ADDED ONLY. A MODIFIED changes a promise the living fleet may already\n * realize, so demanding a re-declaration would force an edit with nothing to\n * change — the same exemption `c4.uncovered` takes one axis over. A requirement\n * with no `Requirement-ID:` is SKIPPED rather than reported: it is already\n * `capability.requirement-unidentified`, and there is nothing for a `Realizes:`\n * line to address, so two findings for one mistake is the failure to avoid.\n *\n * The covering side is ADDED or MODIFIED, never BASE and never REMOVED. A BASE\n * requirement in a delta quotes living context and the merge never writes it,\n * so a `Realizes:` line there lands nowhere; a REMOVED one is on its way out and\n * cannot keep a promise after it is gone.\n *\n * Feature scope, deliberately. The fleet-scope version already ships as\n * `capability.requirement-unrealized`, and grading a feature-ADDED requirement\n * against the LIVING fleet is vacuous — no living `Realizes:` can name it\n * without being `capability.realizes-unknown` today.\n */\nexport function uncoveredIssues(\n capabilities: readonly CapabilityDeltaDoc[],\n services: readonly RealizingDoc[],\n // REQUIRED, with no default. A default would have to be one of the two arms,\n // and either choice is wrong for a caller that forgot: `graded: true` with an\n // empty list makes the message assert a negative, and `graded: false` makes it\n // quietly stop checking a corpus the caller does have. The compiler asking is\n // cheaper than either.\n flows: FlowCorpus,\n): Issue[] {\n if (capabilities.length === 0) return [];\n const kept = new Set<string>();\n for (const doc of services) {\n for (const r of doc.reqs) {\n if (r.kind !== \"ADDED\" && r.kind !== \"MODIFIED\") continue;\n for (const pair of realizedPairs(r)) kept.add(pair);\n }\n }\n // The other carrier, through the SAME `pairKey` as the `Realizes:` side: two\n // corpora answering one question must not be able to disagree about which\n // promise a claim addresses. The caller resolved these; a claim whose tags did\n // not both resolve never reaches here, which is what stops a typo from\n // silencing the gate.\n if (flows.graded) for (const flow of flows.kept) kept.add(pairKey(flow.capability, flow.requirement));\n // What the message may CLAIM about the flow half. Ungraded, it claims nothing\n // and says so — the `Realizes:` half was still checked and is still worth\n // gating on, so the finding stands; what must not stand is a sentence\n // convicting a flow nobody resolved.\n const flowClause = flows.graded\n ? \"and no `dynamic view` under this feature's usecases/ resolves a `#req-` tag to it. \"\n : `and the flow half of the join was NOT checked — ${flows.why}, so a \\`#req-\\` claim could not be resolved either way. `;\n const issues: Issue[] = [];\n for (const doc of capabilities) {\n for (const r of doc.reqs) {\n if (r.kind !== \"ADDED\" || r.id === undefined) continue;\n if (kept.has(pairKey(doc.id, r.id))) continue;\n const entry = `${doc.id}#${r.id}`;\n issues.push({\n severity: \"warn\",\n gates: true,\n code: \"capability.uncovered\",\n subject: doc.id,\n message:\n `capability ${doc.id}: ADDED requirement '${r.name}' (${r.id}) is realized by nothing this feature changes — ` +\n `no ADDED or MODIFIED requirement in its specs/ deltas carries \\`Realizes: ${entry}\\`, ` +\n flowClause +\n \"The document is legal; the MERGE is what is unsafe: once it lands, the only thing that will ever mention \" +\n \"this promise again is a fleet-scope warning (capability.requirement-unrealized) nobody reads. \" +\n `Three ways on: add \\`Realizes: ${entry}\\` to the service requirement that carries part of it; ` +\n `if the promise CROSSES services, write the flow that keeps it as features/<FEAT>/usecases/<name>.likec4 and ` +\n `tag its \\`dynamic view\\` \\`#cap-${tagSlug(doc.id)}\\` and \\`#req-${tagSlug(r.id)}\\` — the archive merges it into ` +\n \"architecture/usecases/ with everything else this feature lands; or archive with --approve to land the promise \" +\n \"ahead of the fleet and let capability.requirement-unrealized carry it.\",\n });\n }\n }\n return issues;\n}\n\n/** Everything the removal direction needs, and nothing it would have to read twice. */\nexport interface RemovalJoin {\n /** This feature's capability deltas, each with the living document it applies to. */\n capabilities: readonly CapabilityDeltaDoc[];\n /** This feature's own service delta documents, already parsed by the same walk. */\n deltas: readonly RealizingDoc[];\n /**\n * Every LIVING service requirements document in the fleet. A thunk, called at\n * most once and only when this feature actually retires a capability\n * requirement — the overwhelming majority of features retire none, and this\n * read is the whole fleet's `spec.md` and `arch.spec.md`.\n */\n living: () => Promise<readonly RealizingDoc[]>;\n}\n\n/** The living requirements a delta document supersedes — MODIFIED and REMOVED both restate or delete. */\nfunction supersedes(delta: RealizingDoc | undefined, living: Requirement): boolean {\n if (delta === undefined) return false;\n return delta.reqs.some((r) => {\n if (r.kind !== \"MODIFIED\" && r.kind !== \"REMOVED\") return false;\n return r.id === undefined ? r.name === living.name : r.id === living.id;\n });\n}\n\n/**\n * `capability.remove-requirement-realized` — this feature retires a capability\n * requirement that something the merge LEAVES BEHIND still realizes.\n *\n * The hole the forward direction does not close, and the one this whole module\n * exists to make impossible: a feature that REMOVES a capability requirement a\n * living service requirement realizes used to archive at exit 0, and the next\n * `loam validate --all` then failed with `capability.realizes-unknown` against a\n * service document nobody had touched. An archive that leaves the fleet red\n * against an untouched document is the exact class of silent damage the product\n * exists to refuse.\n *\n * GRADED AGAINST THE POST-MERGE FLEET, which is the only reading under which\n * the two escape hatches fall out instead of being special-cased. A living\n * requirement that this feature's own delta MODIFIES or REMOVES is gone as\n * written — a MODIFIED carries its FULL new text, so restating the requirement\n * without its `Realizes:` line IS how an author drops the join — and the delta's\n * own ADDED/MODIFIED requirements are what stands in its place. So: retire the\n * realizer in the same change and there is no breach; keep the line and there\n * is.\n *\n * A `#req-` tagged flow realizing the promise is NOT consulted, and that is the\n * other subject rather than a gap: the tag names the requirement directly, so a\n * removal turns it into `usecase.requirement-unresolved` on the living view —\n * an error the delta walk raises before the archive, naming that view\n * (`core/usecases/delta/modified.ts`), and nothing here would make it louder.\n *\n * A REMOVED spelled by heading resolves through the living document, so it\n * grades exactly what the merge would delete. One that selects nothing is\n * already `delta.removed-unknown` and retires nothing, so it is skipped here —\n * two findings for one mistake, again.\n */\nexport async function removedRealizedIssues(join: RemovalJoin): Promise<Issue[]> {\n const retired = new Map<string, { capability: string; id: string; name: string }>();\n for (const doc of join.capabilities) {\n for (const r of doc.reqs) {\n if (r.kind !== \"REMOVED\") continue;\n const selected = doc.living.filter((l) => (r.id === undefined ? l.name === r.name : l.id === r.id));\n for (const l of selected) {\n if (l.id === undefined) continue;\n retired.set(pairKey(doc.id, l.id), { capability: doc.id, id: l.id, name: l.name });\n }\n }\n }\n if (retired.size === 0) return [];\n\n // Who still realizes each retired pair after the merge: the living\n // requirements this feature does not supersede, plus the requirements its own\n // deltas add or restate.\n const realizers = new Map<string, string[]>();\n const record = (pair: string, who: string): void => {\n if (!retired.has(pair)) return;\n const found = realizers.get(pair) ?? [];\n found.push(who);\n realizers.set(pair, found);\n };\n for (const doc of await join.living()) {\n const delta = join.deltas.find((d) => d.service === doc.service && d.file === doc.file);\n for (const r of doc.reqs) {\n if (supersedes(delta, r)) continue;\n for (const pair of realizedPairs(r)) record(pair, `${docLabel(doc)}'s living requirement '${r.name}'`);\n }\n }\n for (const doc of join.deltas) {\n for (const r of doc.reqs) {\n if (r.kind !== \"ADDED\" && r.kind !== \"MODIFIED\") continue;\n for (const pair of realizedPairs(r)) record(pair, `this feature's ${docLabel(doc)} delta requirement '${r.name}'`);\n }\n }\n\n const issues: Issue[] = [];\n for (const [pair, promise] of retired) {\n const who = realizers.get(pair);\n if (who === undefined) continue;\n const entry = `${promise.capability}#${promise.id}`;\n issues.push({\n severity: \"error\",\n code: \"capability.remove-requirement-realized\",\n subject: promise.capability,\n message:\n `capability ${promise.capability}: this feature REMOVES '${promise.name}' (${promise.id}), but ${who.join(\"; \")} ` +\n `still carries \\`Realizes: ${entry}\\`. After the merge that line points at a promise no document declares, and ` +\n \"the very next `loam validate --all` reports capability.realizes-unknown against whatever carries it — for a \" +\n \"LIVING realizer, a service document this feature never touched. Retire the realizing requirement in the same \" +\n \"feature, or drop its `Realizes:` line (a MODIFIED does that by restating the requirement without it), or \" +\n \"archive with --approve to break the join deliberately.\",\n });\n }\n return issues;\n}\n"]}
|