@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,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which service owns which capability, and which feature owns which change —
|
|
3
|
+
* the two decisions a human has to make, graded against what the scan found.
|
|
4
|
+
*
|
|
5
|
+
* The routing this produces is what everything downstream selects with, which
|
|
6
|
+
* is why `servicesForRequirement` is returned as a function rather than as a
|
|
7
|
+
* map: a split capability routes per REQUIREMENT and a single-service one
|
|
8
|
+
* routes wholesale, and a caller that reimplemented that choice would put a
|
|
9
|
+
* living requirement and its own delta in different services.
|
|
10
|
+
*/
|
|
11
|
+
import { resolve } from "node:path";
|
|
12
|
+
import { dictionary, ownValue } from "../../kernel/records.js";
|
|
13
|
+
import { FEATURE_ID_RULE, isFeatureId } from "../../kernel/ids/feature.js";
|
|
14
|
+
import { compareIds } from "../../repo/entries.js";
|
|
15
|
+
import { parseRequirements } from "../../document/parse.js";
|
|
16
|
+
import {} from "../../document/spec.js";
|
|
17
|
+
import {} from "../model/mapping.js";
|
|
18
|
+
import {} from "../model/model.js";
|
|
19
|
+
import { titleFromChangeId } from "../scan/changes.js";
|
|
20
|
+
export function capabilityDecisions(scan) {
|
|
21
|
+
const { root, mapping, bound, inventoryDigest, livingRequirements, active, renamed } = scan;
|
|
22
|
+
// Capability ownership must cover the active horizon too: a brand-new
|
|
23
|
+
// capability may exist only under changes/<id>/specs until archive.
|
|
24
|
+
//
|
|
25
|
+
// `routedNames` is the subset a split capability must actually allocate. A
|
|
26
|
+
// renamed requirement is routed by its FROM — that is what keeps the delta in
|
|
27
|
+
// the same services as the living text it rewrites — so demanding an
|
|
28
|
+
// allocation for its TO as well asked a reviewer for a decision apply ignores.
|
|
29
|
+
const requirementNamesByCapability = new Map();
|
|
30
|
+
const routedNamesByCapability = new Map();
|
|
31
|
+
const activeChangesByCapability = new Map();
|
|
32
|
+
const activeRenamePairs = renamed.filter((rename) => rename.scope === "active"
|
|
33
|
+
&& rename.from !== null && rename.from !== ""
|
|
34
|
+
&& rename.to !== null && rename.to !== "");
|
|
35
|
+
for (const [capability, requirements] of livingRequirements) {
|
|
36
|
+
requirementNamesByCapability.set(capability, new Set(requirements.map((item) => item.name)));
|
|
37
|
+
routedNamesByCapability.set(capability, new Set(requirements.map((item) => item.name)));
|
|
38
|
+
}
|
|
39
|
+
for (const change of active) {
|
|
40
|
+
for (const spec of change.specs) {
|
|
41
|
+
const names = requirementNamesByCapability.get(spec.capability) ?? new Set();
|
|
42
|
+
const routed = routedNamesByCapability.get(spec.capability) ?? new Set();
|
|
43
|
+
for (const name of spec.requirementNames) {
|
|
44
|
+
names.add(name);
|
|
45
|
+
const pairs = activeRenamePairs.filter((rename) => rename.changeId === change.id
|
|
46
|
+
&& rename.capability === spec.capability
|
|
47
|
+
&& (name === rename.from || name === rename.to));
|
|
48
|
+
routed.add(pairs.length === 1 ? pairs[0].from : name);
|
|
49
|
+
}
|
|
50
|
+
requirementNamesByCapability.set(spec.capability, names);
|
|
51
|
+
routedNamesByCapability.set(spec.capability, routed);
|
|
52
|
+
const changes = activeChangesByCapability.get(spec.capability) ?? new Set();
|
|
53
|
+
changes.add(change.id);
|
|
54
|
+
activeChangesByCapability.set(spec.capability, changes);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const allCapabilityIds = [...requirementNamesByCapability.keys()].sort(compareIds);
|
|
58
|
+
const mappingIssues = [];
|
|
59
|
+
if (bound) {
|
|
60
|
+
if (mapping.source === null) {
|
|
61
|
+
mappingIssues.push({
|
|
62
|
+
code: "mapping.source-missing",
|
|
63
|
+
key: "source",
|
|
64
|
+
message: "Mapping is not bound to an audited source root and inventory digest.",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (resolve(mapping.source.root) !== root) {
|
|
69
|
+
mappingIssues.push({
|
|
70
|
+
code: "mapping.source-root-mismatch",
|
|
71
|
+
key: "source.root",
|
|
72
|
+
message: `Mapping was created for ${mapping.source.root}, not ${root}.`,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (mapping.source.inventoryDigest !== inventoryDigest) {
|
|
76
|
+
mappingIssues.push({
|
|
77
|
+
code: "mapping.source-digest-mismatch",
|
|
78
|
+
key: "source.inventoryDigest",
|
|
79
|
+
message: `OpenSpec source changed after audit (${mapping.source.inventoryDigest} != ${inventoryDigest}).`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const capabilityIds = new Set(allCapabilityIds);
|
|
85
|
+
for (const capability of Object.keys(mapping.capabilities)) {
|
|
86
|
+
if (!capabilityIds.has(capability)) {
|
|
87
|
+
mappingIssues.push({
|
|
88
|
+
code: "mapping.unknown-capability",
|
|
89
|
+
key: capability,
|
|
90
|
+
message: `Mapping names unknown capability '${capability}'.`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const mappingDecisions = allCapabilityIds.map((capability) => {
|
|
95
|
+
const capabilityMapping = ownValue(mapping.capabilities, capability)
|
|
96
|
+
?? { services: [], requirementServices: dictionary() };
|
|
97
|
+
const services = [...new Set(capabilityMapping.services)]
|
|
98
|
+
.filter((service) => service.trim() !== "")
|
|
99
|
+
.sort(compareIds);
|
|
100
|
+
const requirementNames = [...(requirementNamesByCapability.get(capability) ?? [])].sort(compareIds);
|
|
101
|
+
const requirementNameSet = new Set(requirementNames);
|
|
102
|
+
const routedNames = [...(routedNamesByCapability.get(capability) ?? [])].sort(compareIds);
|
|
103
|
+
const requirementServices = dictionary();
|
|
104
|
+
for (const [requirement, allocated] of Object.entries(capabilityMapping.requirementServices)) {
|
|
105
|
+
if (!requirementNameSet.has(requirement)) {
|
|
106
|
+
mappingIssues.push({
|
|
107
|
+
code: "mapping.unknown-requirement",
|
|
108
|
+
key: `${capability}:${requirement}`,
|
|
109
|
+
message: `Capability '${capability}' mapping names unknown requirement '${requirement}'.`,
|
|
110
|
+
});
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const selected = [...new Set(allocated)].filter(Boolean).sort(compareIds);
|
|
114
|
+
requirementServices[requirement] = selected;
|
|
115
|
+
for (const service of selected) {
|
|
116
|
+
if (!services.includes(service)) {
|
|
117
|
+
mappingIssues.push({
|
|
118
|
+
code: "mapping.requirement-service-unknown",
|
|
119
|
+
key: `${capability}:${requirement}`,
|
|
120
|
+
message: `Requirement '${requirement}' is allocated to '${service}', which is not in capability '${capability}' services.`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Only routed names get an empty slot in the skeleton: an unroutable name
|
|
126
|
+
// offered for allocation is a decision that changes nothing.
|
|
127
|
+
for (const requirement of routedNames) {
|
|
128
|
+
if (ownValue(requirementServices, requirement) === undefined)
|
|
129
|
+
requirementServices[requirement] = [];
|
|
130
|
+
}
|
|
131
|
+
if (services.length > 1) {
|
|
132
|
+
for (const requirement of routedNames) {
|
|
133
|
+
if ((ownValue(requirementServices, requirement) ?? []).length === 0) {
|
|
134
|
+
mappingIssues.push({
|
|
135
|
+
code: "mapping.requirement-allocation-missing",
|
|
136
|
+
key: `${capability}:${requirement}`,
|
|
137
|
+
message: `Split capability '${capability}' must allocate requirement '${requirement}' to at least one selected service.`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
for (const service of services) {
|
|
142
|
+
if (!Object.values(requirementServices).some((selected) => selected.includes(service))) {
|
|
143
|
+
mappingIssues.push({
|
|
144
|
+
code: "mapping.service-allocation-empty",
|
|
145
|
+
key: `${capability}:${service}`,
|
|
146
|
+
message: `Split capability '${capability}' selects service '${service}' but allocates no requirement to it.`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
capability,
|
|
153
|
+
service: services.length === 1 ? services[0] : null,
|
|
154
|
+
services,
|
|
155
|
+
requirementServices,
|
|
156
|
+
suggestedService: capability.split("/").at(-1) ?? capability,
|
|
157
|
+
hasLivingSpec: livingRequirements.has(capability),
|
|
158
|
+
activeChanges: [...(activeChangesByCapability.get(capability) ?? [])].sort(compareIds),
|
|
159
|
+
status: services.length === 0 ? "needsMapping" : "mapped",
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
const decisionsByCapability = new Map(mappingDecisions.map((decision) => [decision.capability, decision]));
|
|
163
|
+
const servicesForRequirement = (capability, requirement) => {
|
|
164
|
+
const decision = decisionsByCapability.get(capability);
|
|
165
|
+
if (decision === undefined)
|
|
166
|
+
return [];
|
|
167
|
+
return decision.services.length === 1
|
|
168
|
+
? decision.services
|
|
169
|
+
: ownValue(decision.requirementServices, requirement) ?? [];
|
|
170
|
+
};
|
|
171
|
+
const livingByService = new Map();
|
|
172
|
+
for (const [capability, requirements] of livingRequirements) {
|
|
173
|
+
for (const requirement of requirements) {
|
|
174
|
+
for (const service of servicesForRequirement(capability, requirement.name)) {
|
|
175
|
+
const routed = livingByService.get(service) ?? [];
|
|
176
|
+
routed.push({ capability, requirement });
|
|
177
|
+
livingByService.set(service, routed);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const activeChangeIds = new Set(active.map((change) => change.id));
|
|
182
|
+
for (const change of Object.keys(mapping.changes)) {
|
|
183
|
+
if (!activeChangeIds.has(change)) {
|
|
184
|
+
mappingIssues.push({
|
|
185
|
+
code: "mapping.unknown-change",
|
|
186
|
+
key: change,
|
|
187
|
+
message: `Mapping names unknown active change '${change}'.`,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const changeDecisions = active.map((change, index) => {
|
|
192
|
+
const suggestedTitle = titleFromChangeId(change.id);
|
|
193
|
+
const selected = ownValue(mapping.changes, change.id);
|
|
194
|
+
const feature = selected?.feature ?? null;
|
|
195
|
+
const title = selected?.title?.trim() ?? suggestedTitle;
|
|
196
|
+
if (selected !== undefined && title === "") {
|
|
197
|
+
mappingIssues.push({
|
|
198
|
+
code: "mapping.change-title-missing",
|
|
199
|
+
key: change.id,
|
|
200
|
+
message: `Active change '${change.id}' needs a non-empty title.`,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (feature !== null && !isFeatureId(feature)) {
|
|
204
|
+
mappingIssues.push({
|
|
205
|
+
code: "mapping.feature-id-invalid",
|
|
206
|
+
key: change.id,
|
|
207
|
+
message: `Active change '${change.id}' maps to invalid loam feature id '${feature}'. ${FEATURE_ID_RULE}`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
change: change.id,
|
|
212
|
+
feature,
|
|
213
|
+
title,
|
|
214
|
+
suggestedFeature: `FEAT-${index + 1}`,
|
|
215
|
+
suggestedTitle,
|
|
216
|
+
status: feature === null || title === "" ? "needsFeature" : "mapped",
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
const featureOwners = new Map();
|
|
220
|
+
for (const decision of changeDecisions) {
|
|
221
|
+
if (decision.feature === null || !isFeatureId(decision.feature))
|
|
222
|
+
continue;
|
|
223
|
+
const key = decision.feature.toLowerCase();
|
|
224
|
+
const owners = featureOwners.get(key) ?? [];
|
|
225
|
+
owners.push(decision.change);
|
|
226
|
+
featureOwners.set(key, owners);
|
|
227
|
+
}
|
|
228
|
+
for (const [feature, owners] of featureOwners) {
|
|
229
|
+
if (owners.length > 1) {
|
|
230
|
+
mappingIssues.push({
|
|
231
|
+
code: "mapping.feature-id-duplicate",
|
|
232
|
+
key: feature,
|
|
233
|
+
message: `Loam feature id '${feature}' is assigned to multiple OpenSpec changes: ${owners.join(", ")}.`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
mappingIssues,
|
|
239
|
+
mappingDecisions,
|
|
240
|
+
changeDecisions,
|
|
241
|
+
routing: { servicesForRequirement, livingByService },
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../../../src/core/openspec/decide/capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Which service owns which capability, and which feature owns which change —\n * the two decisions a human has to make, graded against what the scan found.\n *\n * The routing this produces is what everything downstream selects with, which\n * is why `servicesForRequirement` is returned as a function rather than as a\n * map: a split capability routes per REQUIREMENT and a single-service one\n * routes wholesale, and a caller that reimplemented that choice would put a\n * living requirement and its own delta in different services.\n */\nimport { resolve } from \"node:path\";\nimport { dictionary, ownValue } from \"../../kernel/records.js\";\nimport { FEATURE_ID_RULE, isFeatureId } from \"../../kernel/ids/feature.js\";\nimport { compareIds } from \"../../repo/entries.js\";\nimport { parseRequirements } from \"../../document/parse.js\";\nimport { type Requirement } from \"../../document/spec.js\";\nimport {\n type OpenSpecMapping,\n type CapabilityMappingDecision,\n type OpenSpecChangeDecision,\n type OpenSpecMappingIssue,\n} from \"../model/mapping.js\";\nimport { type OpenSpecChange, type OpenSpecRenamedUsage } from \"../model/model.js\";\nimport { titleFromChangeId } from \"../scan/changes.js\";\n\n/** Everything the workspace scan found, before any decision is graded. */\nexport interface Scan {\n root: string;\n mapping: OpenSpecMapping;\n /** Whether a mapping was SUPPLIED — an audit grades no source binding. */\n bound: boolean;\n inventoryDigest: string;\n livingRequirements: Map<string, Requirement[]>;\n active: OpenSpecChange[];\n renamed: OpenSpecRenamedUsage[];\n}\n\n/** How a requirement reaches a service, once the capability decisions are in. */\nexport interface Routing {\n servicesForRequirement(capability: string, requirement: string): string[];\n livingByService: Map<string, Array<{ capability: string; requirement: Requirement }>>;\n}\n\nexport interface Decisions {\n mappingIssues: OpenSpecMappingIssue[];\n mappingDecisions: CapabilityMappingDecision[];\n changeDecisions: OpenSpecChangeDecision[];\n routing: Routing;\n}\n\nexport function capabilityDecisions(scan: Scan): Decisions {\n const { root, mapping, bound, inventoryDigest, livingRequirements, active, renamed } = scan;\n // Capability ownership must cover the active horizon too: a brand-new\n // capability may exist only under changes/<id>/specs until archive.\n //\n // `routedNames` is the subset a split capability must actually allocate. A\n // renamed requirement is routed by its FROM — that is what keeps the delta in\n // the same services as the living text it rewrites — so demanding an\n // allocation for its TO as well asked a reviewer for a decision apply ignores.\n const requirementNamesByCapability = new Map<string, Set<string>>();\n const routedNamesByCapability = new Map<string, Set<string>>();\n const activeChangesByCapability = new Map<string, Set<string>>();\n const activeRenamePairs = renamed.filter((rename) =>\n rename.scope === \"active\"\n && rename.from !== null && rename.from !== \"\"\n && rename.to !== null && rename.to !== \"\");\n for (const [capability, requirements] of livingRequirements) {\n requirementNamesByCapability.set(capability, new Set(requirements.map((item) => item.name)));\n routedNamesByCapability.set(capability, new Set(requirements.map((item) => item.name)));\n }\n for (const change of active) {\n for (const spec of change.specs) {\n const names = requirementNamesByCapability.get(spec.capability) ?? new Set<string>();\n const routed = routedNamesByCapability.get(spec.capability) ?? new Set<string>();\n for (const name of spec.requirementNames) {\n names.add(name);\n const pairs = activeRenamePairs.filter((rename) =>\n rename.changeId === change.id\n && rename.capability === spec.capability\n && (name === rename.from || name === rename.to));\n routed.add(pairs.length === 1 ? pairs[0]!.from! : name);\n }\n requirementNamesByCapability.set(spec.capability, names);\n routedNamesByCapability.set(spec.capability, routed);\n const changes = activeChangesByCapability.get(spec.capability) ?? new Set<string>();\n changes.add(change.id);\n activeChangesByCapability.set(spec.capability, changes);\n }\n }\n const allCapabilityIds = [...requirementNamesByCapability.keys()].sort(compareIds);\n\n const mappingIssues: OpenSpecMappingIssue[] = [];\n if (bound) {\n if (mapping.source === null) {\n mappingIssues.push({\n code: \"mapping.source-missing\",\n key: \"source\",\n message: \"Mapping is not bound to an audited source root and inventory digest.\",\n });\n } else {\n if (resolve(mapping.source.root) !== root) {\n mappingIssues.push({\n code: \"mapping.source-root-mismatch\",\n key: \"source.root\",\n message: `Mapping was created for ${mapping.source.root}, not ${root}.`,\n });\n }\n if (mapping.source.inventoryDigest !== inventoryDigest) {\n mappingIssues.push({\n code: \"mapping.source-digest-mismatch\",\n key: \"source.inventoryDigest\",\n message: `OpenSpec source changed after audit (${mapping.source.inventoryDigest} != ${inventoryDigest}).`,\n });\n }\n }\n }\n const capabilityIds = new Set(allCapabilityIds);\n for (const capability of Object.keys(mapping.capabilities)) {\n if (!capabilityIds.has(capability)) {\n mappingIssues.push({\n code: \"mapping.unknown-capability\",\n key: capability,\n message: `Mapping names unknown capability '${capability}'.`,\n });\n }\n }\n const mappingDecisions: CapabilityMappingDecision[] = allCapabilityIds.map((capability) => {\n const capabilityMapping = ownValue(mapping.capabilities, capability)\n ?? { services: [], requirementServices: dictionary<string[]>() };\n const services = [...new Set(capabilityMapping.services)]\n .filter((service) => service.trim() !== \"\")\n .sort(compareIds);\n const requirementNames = [...(requirementNamesByCapability.get(capability) ?? [])].sort(compareIds);\n const requirementNameSet = new Set(requirementNames);\n const routedNames = [...(routedNamesByCapability.get(capability) ?? [])].sort(compareIds);\n const requirementServices = dictionary<string[]>();\n for (const [requirement, allocated] of Object.entries(capabilityMapping.requirementServices)) {\n if (!requirementNameSet.has(requirement)) {\n mappingIssues.push({\n code: \"mapping.unknown-requirement\",\n key: `${capability}:${requirement}`,\n message: `Capability '${capability}' mapping names unknown requirement '${requirement}'.`,\n });\n continue;\n }\n const selected = [...new Set(allocated)].filter(Boolean).sort(compareIds);\n requirementServices[requirement] = selected;\n for (const service of selected) {\n if (!services.includes(service)) {\n mappingIssues.push({\n code: \"mapping.requirement-service-unknown\",\n key: `${capability}:${requirement}`,\n message: `Requirement '${requirement}' is allocated to '${service}', which is not in capability '${capability}' services.`,\n });\n }\n }\n }\n // Only routed names get an empty slot in the skeleton: an unroutable name\n // offered for allocation is a decision that changes nothing.\n for (const requirement of routedNames) {\n if (ownValue(requirementServices, requirement) === undefined) requirementServices[requirement] = [];\n }\n if (services.length > 1) {\n for (const requirement of routedNames) {\n if ((ownValue(requirementServices, requirement) ?? []).length === 0) {\n mappingIssues.push({\n code: \"mapping.requirement-allocation-missing\",\n key: `${capability}:${requirement}`,\n message: `Split capability '${capability}' must allocate requirement '${requirement}' to at least one selected service.`,\n });\n }\n }\n for (const service of services) {\n if (!Object.values(requirementServices).some((selected) => selected.includes(service))) {\n mappingIssues.push({\n code: \"mapping.service-allocation-empty\",\n key: `${capability}:${service}`,\n message: `Split capability '${capability}' selects service '${service}' but allocates no requirement to it.`,\n });\n }\n }\n }\n return {\n capability,\n service: services.length === 1 ? services[0]! : null,\n services,\n requirementServices,\n suggestedService: capability.split(\"/\").at(-1) ?? capability,\n hasLivingSpec: livingRequirements.has(capability),\n activeChanges: [...(activeChangesByCapability.get(capability) ?? [])].sort(compareIds),\n status: services.length === 0 ? \"needsMapping\" : \"mapped\",\n };\n });\n const decisionsByCapability = new Map(mappingDecisions.map((decision) => [decision.capability, decision]));\n const servicesForRequirement = (capability: string, requirement: string): string[] => {\n const decision = decisionsByCapability.get(capability);\n if (decision === undefined) return [];\n return decision.services.length === 1\n ? decision.services\n : ownValue(decision.requirementServices, requirement) ?? [];\n };\n const livingByService = new Map<string, Array<{ capability: string; requirement: ReturnType<typeof parseRequirements>[number] }>>();\n for (const [capability, requirements] of livingRequirements) {\n for (const requirement of requirements) {\n for (const service of servicesForRequirement(capability, requirement.name)) {\n const routed = livingByService.get(service) ?? [];\n routed.push({ capability, requirement });\n livingByService.set(service, routed);\n }\n }\n }\n\n const activeChangeIds = new Set(active.map((change) => change.id));\n for (const change of Object.keys(mapping.changes)) {\n if (!activeChangeIds.has(change)) {\n mappingIssues.push({\n code: \"mapping.unknown-change\",\n key: change,\n message: `Mapping names unknown active change '${change}'.`,\n });\n }\n }\n const changeDecisions: OpenSpecChangeDecision[] = active.map((change, index) => {\n const suggestedTitle = titleFromChangeId(change.id);\n const selected = ownValue(mapping.changes, change.id);\n const feature = selected?.feature ?? null;\n const title = selected?.title?.trim() ?? suggestedTitle;\n if (selected !== undefined && title === \"\") {\n mappingIssues.push({\n code: \"mapping.change-title-missing\",\n key: change.id,\n message: `Active change '${change.id}' needs a non-empty title.`,\n });\n }\n if (feature !== null && !isFeatureId(feature)) {\n mappingIssues.push({\n code: \"mapping.feature-id-invalid\",\n key: change.id,\n message: `Active change '${change.id}' maps to invalid loam feature id '${feature}'. ${FEATURE_ID_RULE}`,\n });\n }\n return {\n change: change.id,\n feature,\n title,\n suggestedFeature: `FEAT-${index + 1}`,\n suggestedTitle,\n status: feature === null || title === \"\" ? \"needsFeature\" : \"mapped\",\n };\n });\n const featureOwners = new Map<string, string[]>();\n for (const decision of changeDecisions) {\n if (decision.feature === null || !isFeatureId(decision.feature)) continue;\n const key = decision.feature.toLowerCase();\n const owners = featureOwners.get(key) ?? [];\n owners.push(decision.change);\n featureOwners.set(key, owners);\n }\n for (const [feature, owners] of featureOwners) {\n if (owners.length > 1) {\n mappingIssues.push({\n code: \"mapping.feature-id-duplicate\",\n key: feature,\n message: `Loam feature id '${feature}' is assigned to multiple OpenSpec changes: ${owners.join(\", \")}.`,\n });\n }\n }\n return {\n mappingIssues,\n mappingDecisions,\n changeDecisions,\n routing: { servicesForRequirement, livingByService },\n };\n}\n"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What happens to each authored artifact loam has no equivalent for: a
|
|
3
|
+
* proposal, a task list, a design note.
|
|
4
|
+
*
|
|
5
|
+
* Every one of them is a decision rather than a default, because the honest
|
|
6
|
+
* answers differ per corpus — one team's `design.md` is an ADR, another's is a
|
|
7
|
+
* scratchpad. A disposition nobody chose is the one way this migration could
|
|
8
|
+
* quietly drop authored work, so an unset one blocks readiness.
|
|
9
|
+
*/
|
|
10
|
+
import { ownValue } from "../../kernel/records.js";
|
|
11
|
+
import {} from "../model/mapping.js";
|
|
12
|
+
import {} from "../model/model.js";
|
|
13
|
+
export function artifactDispositions(artifacts, mapping, activeChangeIds, mappingIssues) {
|
|
14
|
+
const decisionKinds = new Set(["proposal", "tasks", "change-design"]);
|
|
15
|
+
const artifactDecisions = artifacts
|
|
16
|
+
// Never offer a disposition for an artifact no enumerated change owns —
|
|
17
|
+
// dot-prefixed change directories are refused, not migrated, and a
|
|
18
|
+
// `selectedDisposition` recorded for one is a decision about nothing.
|
|
19
|
+
.filter((artifact) => artifact.scope === "active"
|
|
20
|
+
&& decisionKinds.has(artifact.kind)
|
|
21
|
+
&& artifact.changeId !== undefined
|
|
22
|
+
&& activeChangeIds.has(artifact.changeId))
|
|
23
|
+
.map((artifact) => {
|
|
24
|
+
const selected = ownValue(mapping.artifacts, artifact.path) ?? null;
|
|
25
|
+
return {
|
|
26
|
+
path: artifact.path,
|
|
27
|
+
kind: artifact.kind,
|
|
28
|
+
suggestedDisposition: artifact.disposition,
|
|
29
|
+
disposition: selected,
|
|
30
|
+
status: selected === null ? "needsDisposition" : "mapped",
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
const artifactPaths = new Set(artifactDecisions.map((decision) => decision.path));
|
|
34
|
+
// Sets of plain strings: the question being asked is "is this authored value
|
|
35
|
+
// one of the ones this kind accepts", and a set of the union could not be
|
|
36
|
+
// asked it without an assertion putting the answer back where it started.
|
|
37
|
+
const dispositionsByKind = {
|
|
38
|
+
proposal: new Set(["convert-to-intent", "retain-read-only", "manual-review"]),
|
|
39
|
+
tasks: new Set(["preserve-as-legacy-checklist", "retain-read-only", "manual-review"]),
|
|
40
|
+
"change-design": new Set(["review-as-feature-adr", "retain-read-only", "manual-review"]),
|
|
41
|
+
};
|
|
42
|
+
for (const [path, disposition] of Object.entries(mapping.artifacts)) {
|
|
43
|
+
if (!artifactPaths.has(path)) {
|
|
44
|
+
mappingIssues.push({
|
|
45
|
+
code: "mapping.unknown-artifact",
|
|
46
|
+
key: path,
|
|
47
|
+
message: `Mapping names unknown active authored artifact '${path}'.`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const decision = artifactDecisions.find((item) => item.path === path);
|
|
52
|
+
if (dispositionsByKind[decision.kind].has(disposition))
|
|
53
|
+
continue;
|
|
54
|
+
mappingIssues.push({
|
|
55
|
+
code: "mapping.invalid-artifact-disposition",
|
|
56
|
+
key: path,
|
|
57
|
+
message: `${decision.kind} artifact '${path}' has unsupported disposition '${disposition}'.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return artifactDecisions;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=dispositions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispositions.js","sourceRoot":"","sources":["../../../../src/core/openspec/decide/dispositions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAmD,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAmF,MAAM,mBAAmB,CAAC;AAEpH,MAAM,UAAU,oBAAoB,CAClC,SAA6B,EAC7B,OAAwB,EACxB,eAAoC,EACpC,aAAqC;IAEnC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAuB,CAAC,UAAU,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;IAC5F,MAAM,iBAAiB,GAA+B,SAAS;QAC7D,wEAAwE;QACxE,mEAAmE;QACnE,sEAAsE;SACrE,MAAM,CAAC,CAAC,QAAQ,EAAmF,EAAE,CACpG,QAAQ,CAAC,KAAK,KAAK,QAAQ;WACxB,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;WAChC,QAAQ,CAAC,QAAQ,KAAK,SAAS;WAC/B,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SAC3C,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;QACpE,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,oBAAoB,EAAE,QAAQ,CAAC,WAAW;YAC1C,WAAW,EAAE,QAAQ;YACrB,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,kBAA2B,CAAC,CAAC,CAAC,QAAiB;SAC5E,CAAC;IACJ,CAAC,CAAC,CAAC;IACL,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,6EAA6E;IAC7E,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,kBAAkB,GAAkE;QACxF,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;QAC7E,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,8BAA8B,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;QACrF,eAAe,EAAE,IAAI,GAAG,CAAC,CAAC,uBAAuB,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;KACzF,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,aAAa,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,0BAA0B;gBAChC,GAAG,EAAE,IAAI;gBACT,OAAO,EAAE,mDAAmD,IAAI,IAAI;aACrE,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC;YACvE,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;gBAAE,SAAS;YACjE,aAAa,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,sCAAsC;gBAC5C,GAAG,EAAE,IAAI;gBACT,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,cAAc,IAAI,kCAAkC,WAAW,IAAI;aAC7F,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACH,OAAO,iBAAiB,CAAC;AAC3B,CAAC","sourcesContent":["/**\n * What happens to each authored artifact loam has no equivalent for: a\n * proposal, a task list, a design note.\n *\n * Every one of them is a decision rather than a default, because the honest\n * answers differ per corpus — one team's `design.md` is an ADR, another's is a\n * scratchpad. A disposition nobody chose is the one way this migration could\n * quietly drop authored work, so an unset one blocks readiness.\n */\nimport { ownValue } from \"../../kernel/records.js\";\nimport { type OpenSpecMapping, type OpenSpecMappingIssue } from \"../model/mapping.js\";\nimport { type OpenSpecArtifact, type OpenSpecArtifactDecision, type OpenSpecArtifactKind } from \"../model/model.js\";\n\nexport function artifactDispositions(\n artifacts: OpenSpecArtifact[],\n mapping: OpenSpecMapping,\n activeChangeIds: ReadonlySet<string>,\n mappingIssues: OpenSpecMappingIssue[],\n): OpenSpecArtifactDecision[] {\n const decisionKinds = new Set<OpenSpecArtifactKind>([\"proposal\", \"tasks\", \"change-design\"]);\n const artifactDecisions: OpenSpecArtifactDecision[] = artifacts\n // Never offer a disposition for an artifact no enumerated change owns —\n // dot-prefixed change directories are refused, not migrated, and a\n // `selectedDisposition` recorded for one is a decision about nothing.\n .filter((artifact): artifact is OpenSpecArtifact & { kind: \"proposal\" | \"tasks\" | \"change-design\" } =>\n artifact.scope === \"active\"\n && decisionKinds.has(artifact.kind)\n && artifact.changeId !== undefined\n && activeChangeIds.has(artifact.changeId))\n .map((artifact) => {\n const selected = ownValue(mapping.artifacts, artifact.path) ?? null;\n return {\n path: artifact.path,\n kind: artifact.kind,\n suggestedDisposition: artifact.disposition,\n disposition: selected,\n status: selected === null ? \"needsDisposition\" as const : \"mapped\" as const,\n };\n });\n const artifactPaths = new Set(artifactDecisions.map((decision) => decision.path));\n // Sets of plain strings: the question being asked is \"is this authored value\n // one of the ones this kind accepts\", and a set of the union could not be\n // asked it without an assertion putting the answer back where it started.\n const dispositionsByKind: Record<OpenSpecArtifactDecision[\"kind\"], ReadonlySet<string>> = {\n proposal: new Set([\"convert-to-intent\", \"retain-read-only\", \"manual-review\"]),\n tasks: new Set([\"preserve-as-legacy-checklist\", \"retain-read-only\", \"manual-review\"]),\n \"change-design\": new Set([\"review-as-feature-adr\", \"retain-read-only\", \"manual-review\"]),\n };\n for (const [path, disposition] of Object.entries(mapping.artifacts)) {\n if (!artifactPaths.has(path)) {\n mappingIssues.push({\n code: \"mapping.unknown-artifact\",\n key: path,\n message: `Mapping names unknown active authored artifact '${path}'.`,\n });\n } else {\n const decision = artifactDecisions.find((item) => item.path === path)!;\n if (dispositionsByKind[decision.kind].has(disposition)) continue;\n mappingIssues.push({\n code: \"mapping.invalid-artifact-disposition\",\n key: path,\n message: `${decision.kind} artifact '${path}' has unsupported disposition '${disposition}'.`,\n });\n }\n }\n return artifactDecisions;\n}\n"]}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every active RENAMED pair resolved against the living source of truth.
|
|
3
|
+
*
|
|
4
|
+
* This is the identity problem the whole package exists for: OpenSpec renames
|
|
5
|
+
* by writing FROM/TO bullets, loam renames by carrying one stable
|
|
6
|
+
* `Requirement-ID` through a MODIFIED requirement, and nothing mechanical
|
|
7
|
+
* bridges the two. So each pair is either resolved to an id the living text
|
|
8
|
+
* already carries, or it becomes a decision a human has to make — never a
|
|
9
|
+
* guess, because a wrong identity silently merges one requirement's text over
|
|
10
|
+
* another's.
|
|
11
|
+
*
|
|
12
|
+
* It MUTATES the usages it resolves rather than returning new ones: a rename is
|
|
13
|
+
* one fact seen in one file, and two copies of it — one resolved, one not — is
|
|
14
|
+
* exactly the bug this resolution exists to prevent.
|
|
15
|
+
*/
|
|
16
|
+
import { ownValue } from "../../kernel/records.js";
|
|
17
|
+
import { REQUIREMENT_ID_RE, requirementIdDeclarations } from "../../document/spec.js";
|
|
18
|
+
import {} from "../model/mapping.js";
|
|
19
|
+
import {} from "../model/model.js";
|
|
20
|
+
import {} from "./capabilities.js";
|
|
21
|
+
export function resolveRenames(scan, routing, mappingIssues) {
|
|
22
|
+
const { mapping, livingRequirements, renamed } = scan;
|
|
23
|
+
const { livingByService, servicesForRequirement } = routing;
|
|
24
|
+
const activeRenames = renamed.filter((rename) => rename.scope === "active");
|
|
25
|
+
const renameKeys = new Set(activeRenames.map((rename) => rename.key));
|
|
26
|
+
for (const [key, requirementId] of Object.entries(mapping.renames)) {
|
|
27
|
+
if (!renameKeys.has(key)) {
|
|
28
|
+
mappingIssues.push({
|
|
29
|
+
code: "mapping.unknown-rename",
|
|
30
|
+
key,
|
|
31
|
+
message: `Mapping names unknown RENAMED pair '${key}'.`,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else if (!REQUIREMENT_ID_RE.test(requirementId)) {
|
|
35
|
+
mappingIssues.push({
|
|
36
|
+
code: "mapping.invalid-requirement-id",
|
|
37
|
+
key,
|
|
38
|
+
message: `RENAMED pair '${key}' has invalid Requirement-ID '${requirementId}'.`,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Resolve every rename against the living source of truth. A mapped id is
|
|
43
|
+
// only needed when the source requirement does not already carry one.
|
|
44
|
+
for (const rename of activeRenames) {
|
|
45
|
+
if (rename.from === null || rename.from === "" || rename.to === null || rename.to === "")
|
|
46
|
+
continue;
|
|
47
|
+
const living = livingRequirements.get(rename.capability) ?? [];
|
|
48
|
+
const matches = living.filter((requirement) => requirement.name === rename.from);
|
|
49
|
+
if (matches.length === 0) {
|
|
50
|
+
mappingIssues.push({
|
|
51
|
+
code: "mapping.rename-source-missing",
|
|
52
|
+
key: rename.key,
|
|
53
|
+
message: `RENAMED source '${rename.from}' does not exist in living capability '${rename.capability}'.`,
|
|
54
|
+
});
|
|
55
|
+
rename.requirementId = null;
|
|
56
|
+
rename.status = "needsIdentity";
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (matches.length > 1) {
|
|
60
|
+
mappingIssues.push({
|
|
61
|
+
code: "mapping.rename-source-ambiguous",
|
|
62
|
+
key: rename.key,
|
|
63
|
+
message: `RENAMED source '${rename.from}' matches ${matches.length} living requirements in '${rename.capability}'.`,
|
|
64
|
+
});
|
|
65
|
+
rename.requirementId = null;
|
|
66
|
+
rename.status = "needsIdentity";
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const source = matches[0];
|
|
70
|
+
const declarations = requirementIdDeclarations(source);
|
|
71
|
+
if (declarations.length > 0
|
|
72
|
+
&& (declarations.length !== 1 || !REQUIREMENT_ID_RE.test(declarations[0]))) {
|
|
73
|
+
rename.existingRequirementId = source.id ?? null;
|
|
74
|
+
rename.requirementId = null;
|
|
75
|
+
rename.status = "needsIdentity";
|
|
76
|
+
mappingIssues.push({
|
|
77
|
+
code: "mapping.rename-source-id-invalid",
|
|
78
|
+
key: rename.key,
|
|
79
|
+
message: `RENAMED source '${rename.from}' has ${declarations.length === 1 ? "an invalid" : "repeated"} Requirement-ID declaration; repair the living source before migration.`,
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
rename.existingRequirementId = source.id ?? null;
|
|
84
|
+
const requestedId = ownValue(mapping.renames, rename.key) ?? null;
|
|
85
|
+
if (source.id !== undefined && requestedId !== null && requestedId !== source.id) {
|
|
86
|
+
mappingIssues.push({
|
|
87
|
+
code: "mapping.rename-existing-id-conflict",
|
|
88
|
+
key: rename.key,
|
|
89
|
+
message: `RENAMED source '${rename.from}' already has Requirement-ID '${source.id}'; mapping cannot replace it with '${requestedId}'.`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
rename.requirementId = source.id ?? requestedId;
|
|
93
|
+
rename.status = rename.requirementId === null ? "needsIdentity" : "mapped";
|
|
94
|
+
const routedServices = servicesForRequirement(rename.capability, rename.from);
|
|
95
|
+
if (rename.requirementId !== null) {
|
|
96
|
+
const collisionServices = routedServices.filter((service) => (livingByService.get(service) ?? []).some((entry) => entry.requirement !== source && entry.requirement.id === rename.requirementId));
|
|
97
|
+
if (collisionServices.length > 0) {
|
|
98
|
+
mappingIssues.push({
|
|
99
|
+
code: "mapping.rename-id-conflict",
|
|
100
|
+
key: rename.key,
|
|
101
|
+
message: `RENAMED identity '${rename.requirementId}' already belongs to another living requirement in mapped service(s): ${collisionServices.join(", ")}.`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const targetCollisionServices = routedServices.filter((service) => (livingByService.get(service) ?? []).some((entry) => entry.requirement !== source && entry.requirement.name === rename.to));
|
|
106
|
+
if (rename.to === rename.from || targetCollisionServices.length > 0) {
|
|
107
|
+
mappingIssues.push({
|
|
108
|
+
code: "mapping.rename-target-conflict",
|
|
109
|
+
key: rename.key,
|
|
110
|
+
message: rename.to === rename.from
|
|
111
|
+
? `RENAMED target '${rename.to}' is the same as its living source.`
|
|
112
|
+
: `RENAMED target '${rename.to}' conflicts in mapped service(s): ${targetCollisionServices.join(", ")}.`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const renameSources = new Map();
|
|
117
|
+
const renameTargets = new Map();
|
|
118
|
+
for (const rename of activeRenames) {
|
|
119
|
+
if (rename.from === null || rename.to === null)
|
|
120
|
+
continue;
|
|
121
|
+
for (const service of servicesForRequirement(rename.capability, rename.from)) {
|
|
122
|
+
const sourceKey = `${service}\0${rename.from}`;
|
|
123
|
+
const targetKey = `${service}\0${rename.to}`;
|
|
124
|
+
const sources = renameSources.get(sourceKey) ?? [];
|
|
125
|
+
sources.push(rename);
|
|
126
|
+
renameSources.set(sourceKey, sources);
|
|
127
|
+
const targets = renameTargets.get(targetKey) ?? [];
|
|
128
|
+
targets.push(rename);
|
|
129
|
+
renameTargets.set(targetKey, targets);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const [key, uses] of renameSources) {
|
|
133
|
+
if (uses.length > 1) {
|
|
134
|
+
mappingIssues.push({
|
|
135
|
+
code: "mapping.rename-double-source",
|
|
136
|
+
key: key.replace("\0", ":"),
|
|
137
|
+
message: `Living requirement '${uses[0].from}' is renamed by multiple active changes: ${uses.map((item) => item.changeId).join(", ")}.`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
for (const [key, uses] of renameTargets) {
|
|
142
|
+
if (uses.length > 1) {
|
|
143
|
+
mappingIssues.push({
|
|
144
|
+
code: "mapping.rename-double-target",
|
|
145
|
+
key: key.replace("\0", ":"),
|
|
146
|
+
message: `Multiple active renames target '${uses[0].to}' in mapped service '${key.split("\0")[0]}'.`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (renameSources.has(key)) {
|
|
150
|
+
mappingIssues.push({
|
|
151
|
+
code: "mapping.rename-chain",
|
|
152
|
+
key: key.replace("\0", ":"),
|
|
153
|
+
message: `Active rename chain through '${uses[0].to}' must be collapsed into one reviewed rename.`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const renameIdOwners = new Map();
|
|
158
|
+
for (const rename of activeRenames) {
|
|
159
|
+
if (rename.requirementId === null || rename.from === null)
|
|
160
|
+
continue;
|
|
161
|
+
for (const service of servicesForRequirement(rename.capability, rename.from)) {
|
|
162
|
+
const key = `${service}\0${rename.requirementId}`;
|
|
163
|
+
const owners = renameIdOwners.get(key) ?? new Set();
|
|
164
|
+
owners.add(`${rename.capability}:${rename.from}`);
|
|
165
|
+
renameIdOwners.set(key, owners);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const [key, owners] of renameIdOwners) {
|
|
169
|
+
if (owners.size > 1) {
|
|
170
|
+
const [service, requirementId] = key.split("\0");
|
|
171
|
+
mappingIssues.push({
|
|
172
|
+
code: "mapping.rename-id-conflict",
|
|
173
|
+
key,
|
|
174
|
+
message: `Requirement-ID '${requirementId}' is assigned to different RENAMED sources in mapped service '${service}': ${[...owners].join(", ")}.`,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=renames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renames.js","sourceRoot":"","sources":["../../../../src/core/openspec/decide/renames.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Every active RENAMED pair resolved against the living source of truth.\n *\n * This is the identity problem the whole package exists for: OpenSpec renames\n * by writing FROM/TO bullets, loam renames by carrying one stable\n * `Requirement-ID` through a MODIFIED requirement, and nothing mechanical\n * bridges the two. So each pair is either resolved to an id the living text\n * already carries, or it becomes a decision a human has to make — never a\n * guess, because a wrong identity silently merges one requirement's text over\n * another's.\n *\n * It MUTATES the usages it resolves rather than returning new ones: a rename is\n * one fact seen in one file, and two copies of it — one resolved, one not — is\n * exactly the bug this resolution exists to prevent.\n */\nimport { ownValue } from \"../../kernel/records.js\";\nimport { REQUIREMENT_ID_RE, requirementIdDeclarations } from \"../../document/spec.js\";\nimport { type OpenSpecMappingIssue } from \"../model/mapping.js\";\nimport { type OpenSpecRenamedUsage } from \"../model/model.js\";\nimport { type Scan, type Routing } from \"./capabilities.js\";\n\nexport function resolveRenames(scan: Scan, routing: Routing, mappingIssues: OpenSpecMappingIssue[]): void {\n const { mapping, livingRequirements, renamed } = scan;\n const { livingByService, servicesForRequirement } = routing;\n const activeRenames = renamed.filter((rename) => rename.scope === \"active\");\n const renameKeys = new Set(activeRenames.map((rename) => rename.key));\n for (const [key, requirementId] of Object.entries(mapping.renames)) {\n if (!renameKeys.has(key)) {\n mappingIssues.push({\n code: \"mapping.unknown-rename\",\n key,\n message: `Mapping names unknown RENAMED pair '${key}'.`,\n });\n } else if (!REQUIREMENT_ID_RE.test(requirementId)) {\n mappingIssues.push({\n code: \"mapping.invalid-requirement-id\",\n key,\n message: `RENAMED pair '${key}' has invalid Requirement-ID '${requirementId}'.`,\n });\n }\n }\n\n // Resolve every rename against the living source of truth. A mapped id is\n // only needed when the source requirement does not already carry one.\n for (const rename of activeRenames) {\n if (rename.from === null || rename.from === \"\" || rename.to === null || rename.to === \"\") continue;\n const living = livingRequirements.get(rename.capability) ?? [];\n const matches = living.filter((requirement) => requirement.name === rename.from);\n if (matches.length === 0) {\n mappingIssues.push({\n code: \"mapping.rename-source-missing\",\n key: rename.key,\n message: `RENAMED source '${rename.from}' does not exist in living capability '${rename.capability}'.`,\n });\n rename.requirementId = null;\n rename.status = \"needsIdentity\";\n continue;\n }\n if (matches.length > 1) {\n mappingIssues.push({\n code: \"mapping.rename-source-ambiguous\",\n key: rename.key,\n message: `RENAMED source '${rename.from}' matches ${matches.length} living requirements in '${rename.capability}'.`,\n });\n rename.requirementId = null;\n rename.status = \"needsIdentity\";\n continue;\n }\n const source = matches[0]!;\n const declarations = requirementIdDeclarations(source);\n if (declarations.length > 0\n && (declarations.length !== 1 || !REQUIREMENT_ID_RE.test(declarations[0]!))) {\n rename.existingRequirementId = source.id ?? null;\n rename.requirementId = null;\n rename.status = \"needsIdentity\";\n mappingIssues.push({\n code: \"mapping.rename-source-id-invalid\",\n key: rename.key,\n message: `RENAMED source '${rename.from}' has ${declarations.length === 1 ? \"an invalid\" : \"repeated\"} Requirement-ID declaration; repair the living source before migration.`,\n });\n continue;\n }\n rename.existingRequirementId = source.id ?? null;\n const requestedId = ownValue(mapping.renames, rename.key) ?? null;\n if (source.id !== undefined && requestedId !== null && requestedId !== source.id) {\n mappingIssues.push({\n code: \"mapping.rename-existing-id-conflict\",\n key: rename.key,\n message: `RENAMED source '${rename.from}' already has Requirement-ID '${source.id}'; mapping cannot replace it with '${requestedId}'.`,\n });\n }\n rename.requirementId = source.id ?? requestedId;\n rename.status = rename.requirementId === null ? \"needsIdentity\" : \"mapped\";\n const routedServices = servicesForRequirement(rename.capability, rename.from);\n if (rename.requirementId !== null) {\n const collisionServices = routedServices.filter((service) =>\n (livingByService.get(service) ?? []).some(\n (entry) => entry.requirement !== source && entry.requirement.id === rename.requirementId,\n ));\n if (collisionServices.length > 0) {\n mappingIssues.push({\n code: \"mapping.rename-id-conflict\",\n key: rename.key,\n message: `RENAMED identity '${rename.requirementId}' already belongs to another living requirement in mapped service(s): ${collisionServices.join(\", \")}.`,\n });\n }\n }\n const targetCollisionServices = routedServices.filter((service) =>\n (livingByService.get(service) ?? []).some(\n (entry) => entry.requirement !== source && entry.requirement.name === rename.to,\n ));\n if (rename.to === rename.from || targetCollisionServices.length > 0) {\n mappingIssues.push({\n code: \"mapping.rename-target-conflict\",\n key: rename.key,\n message: rename.to === rename.from\n ? `RENAMED target '${rename.to}' is the same as its living source.`\n : `RENAMED target '${rename.to}' conflicts in mapped service(s): ${targetCollisionServices.join(\", \")}.`,\n });\n }\n }\n\n const renameSources = new Map<string, OpenSpecRenamedUsage[]>();\n const renameTargets = new Map<string, OpenSpecRenamedUsage[]>();\n for (const rename of activeRenames) {\n if (rename.from === null || rename.to === null) continue;\n for (const service of servicesForRequirement(rename.capability, rename.from)) {\n const sourceKey = `${service}\\0${rename.from}`;\n const targetKey = `${service}\\0${rename.to}`;\n const sources = renameSources.get(sourceKey) ?? [];\n sources.push(rename);\n renameSources.set(sourceKey, sources);\n const targets = renameTargets.get(targetKey) ?? [];\n targets.push(rename);\n renameTargets.set(targetKey, targets);\n }\n }\n for (const [key, uses] of renameSources) {\n if (uses.length > 1) {\n mappingIssues.push({\n code: \"mapping.rename-double-source\",\n key: key.replace(\"\\0\", \":\"),\n message: `Living requirement '${uses[0]!.from}' is renamed by multiple active changes: ${uses.map((item) => item.changeId).join(\", \")}.`,\n });\n }\n }\n for (const [key, uses] of renameTargets) {\n if (uses.length > 1) {\n mappingIssues.push({\n code: \"mapping.rename-double-target\",\n key: key.replace(\"\\0\", \":\"),\n message: `Multiple active renames target '${uses[0]!.to}' in mapped service '${key.split(\"\\0\")[0]}'.`,\n });\n }\n if (renameSources.has(key)) {\n mappingIssues.push({\n code: \"mapping.rename-chain\",\n key: key.replace(\"\\0\", \":\"),\n message: `Active rename chain through '${uses[0]!.to}' must be collapsed into one reviewed rename.`,\n });\n }\n }\n const renameIdOwners = new Map<string, Set<string>>();\n for (const rename of activeRenames) {\n if (rename.requirementId === null || rename.from === null) continue;\n for (const service of servicesForRequirement(rename.capability, rename.from)) {\n const key = `${service}\\0${rename.requirementId}`;\n const owners = renameIdOwners.get(key) ?? new Set<string>();\n owners.add(`${rename.capability}:${rename.from}`);\n renameIdOwners.set(key, owners);\n }\n }\n for (const [key, owners] of renameIdOwners) {\n if (owners.size > 1) {\n const [service, requirementId] = key.split(\"\\0\");\n mappingIssues.push({\n code: \"mapping.rename-id-conflict\",\n key,\n message: `Requirement-ID '${requirementId}' is assigned to different RENAMED sources in mapped service '${service}': ${[...owners].join(\", \")}.`,\n });\n }\n }\n}\n"]}
|