@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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one (subject, axis) pass every delta check runs inside, and the living
|
|
3
|
+
* document indexed the way those checks ask about it.
|
|
4
|
+
*
|
|
5
|
+
* The scope exists because the checks that used to be one 400-line function all
|
|
6
|
+
* need the same five facts and none of them may take five parameters. It is a
|
|
7
|
+
* record of what is being graded, never of what was found — `Issue[]` stays a
|
|
8
|
+
* return value, so no check can quietly append to another's output.
|
|
9
|
+
*
|
|
10
|
+
* `indexLiving` builds all four lookups in one walk. Two of them answer the same
|
|
11
|
+
* question by different keys (heading, Requirement-ID) and the delta algebra
|
|
12
|
+
* requires them to agree; building one lazily beside the other is how they would
|
|
13
|
+
* eventually be built from different arrays.
|
|
14
|
+
*/
|
|
15
|
+
import {} from "../document/spec.js";
|
|
16
|
+
export function indexLiving(living) {
|
|
17
|
+
const byName = new Map();
|
|
18
|
+
const byId = new Map();
|
|
19
|
+
for (const requirement of living) {
|
|
20
|
+
const named = byName.get(requirement.name) ?? [];
|
|
21
|
+
named.push(requirement);
|
|
22
|
+
byName.set(requirement.name, named);
|
|
23
|
+
if (requirement.id !== undefined) {
|
|
24
|
+
const identified = byId.get(requirement.id) ?? [];
|
|
25
|
+
identified.push(requirement);
|
|
26
|
+
byId.set(requirement.id, identified);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
names: new Set(living.map((r) => r.name)),
|
|
31
|
+
byName,
|
|
32
|
+
byId,
|
|
33
|
+
folded: new Map(living.map((r) => [r.name.toLowerCase(), r.name])),
|
|
34
|
+
all: living,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Key for the (kind, subject, axis, requirement) tuple a feature claims. The
|
|
38
|
+
* axes are separate namespaces on purpose — an arch requirement cannot conflict
|
|
39
|
+
* with a business requirement of the same name, they merge into different files
|
|
40
|
+
* — and so are the kinds, for the reason `ClaimSubject` states above. */
|
|
41
|
+
export function key(claim, identity) {
|
|
42
|
+
return `${claim.kind}\0${claim.subject}\0${claim.axis.file}\0${identity}`;
|
|
43
|
+
}
|
|
44
|
+
/** Stable ID when present; exact heading for a legacy requirement. */
|
|
45
|
+
export function requirementKey(requirement) {
|
|
46
|
+
return requirement.id === undefined ? `name:${requirement.name}` : `id:${requirement.id}`;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../../src/core/delta/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAoB,MAAM,qBAAqB,CAAC;AA2DvD,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC9C,KAAK,MAAM,WAAW,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACpC,IAAI,WAAW,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YAClD,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO;QACL,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM;QACN,IAAI;QACJ,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,CAAU,CAAC,CAAC;QAC3E,GAAG,EAAE,MAAM;KACZ,CAAC;AACJ,CAAC;AAED;;;yEAGyE;AACzE,MAAM,UAAU,GAAG,CAAC,KAAmB,EAAE,QAAgB;IACvD,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;AAC5E,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAAC,WAA6C;IAC1E,OAAO,WAAW,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * The one (subject, axis) pass every delta check runs inside, and the living\n * document indexed the way those checks ask about it.\n *\n * The scope exists because the checks that used to be one 400-line function all\n * need the same five facts and none of them may take five parameters. It is a\n * record of what is being graded, never of what was found — `Issue[]` stays a\n * return value, so no check can quietly append to another's output.\n *\n * `indexLiving` builds all four lookups in one walk. Two of them answer the same\n * question by different keys (heading, Requirement-ID) and the delta algebra\n * requires them to agree; building one lazily beside the other is how they would\n * eventually be built from different arrays.\n */\nimport { type Requirement } from \"../document/spec.js\";\n\n/**\n * Which file an axis is, at the grain the delta checks need — the filename and\n * nothing else, because that is all any of them read (`key` below is the only\n * consumer). Structurally a `SPEC_AXES` entry with its other fields dropped, so\n * the two service axes keep travelling exactly as before while the CAPABILITY\n * axis — which indexes no `ServicePaths` and therefore has no `key` — travels\n * too. `label` is deliberately NOT carried: nothing here reads it, and a field\n * that exists only to look like the record it came from is a field the next\n * reader tries to use in a message.\n */\nexport interface DeltaAxis {\n file: string;\n}\n\n/**\n * WHAT a delta claims, at the grain the claim registry is keyed by: the kind of\n * document, its identity, and which of its axes.\n *\n * `kind` is not decoration. A fleet may hold a service called `billing` and a\n * capability called `billing`, and both write requirements into a `spec.md`; a\n * key built from the name and the filename alone would let one feature's\n * service claim answer another feature's capability question — reporting\n * `delta.added-conflict` against a document it has nothing to do with.\n */\nexport interface ClaimSubject {\n kind: \"service\" | \"capability\";\n /** The service id, or the capability id — whichever `kind` says. */\n subject: string;\n axis: DeltaAxis;\n}\n\nexport interface DeltaScope extends ClaimSubject {\n /** The feature being graded — named in the `loam rebase <FEAT>` advice. */\n featureId: string;\n docsDir: string;\n /** The delta document this pass reads, for the one message that names a path. */\n specPath: string;\n /**\n * How this axis's file is named in messages. The arch file says which document\n * it means so a finding cannot be chased into the wrong one; spec.md keeps its\n * historical spelling.\n */\n where: string;\n /** How the axis's LIVING document is named in messages, same reasoning. */\n livingDoc: string;\n}\n\n/** The living requirements, keyed every way a delta may select one. */\nexport interface LivingIndex {\n names: Set<string>;\n byName: Map<string, Requirement[]>;\n byId: Map<string, Requirement[]>;\n /** Lowercased living name -> its exact spelling, for the near-duplicate warning. */\n folded: Map<string, string>;\n all: Requirement[];\n}\n\nexport function indexLiving(living: Requirement[]): LivingIndex {\n const byName = new Map<string, Requirement[]>();\n const byId = new Map<string, Requirement[]>();\n for (const requirement of living) {\n const named = byName.get(requirement.name) ?? [];\n named.push(requirement);\n byName.set(requirement.name, named);\n if (requirement.id !== undefined) {\n const identified = byId.get(requirement.id) ?? [];\n identified.push(requirement);\n byId.set(requirement.id, identified);\n }\n }\n return {\n names: new Set(living.map((r) => r.name)),\n byName,\n byId,\n folded: new Map(living.map((r) => [r.name.toLowerCase(), r.name] as const)),\n all: living,\n };\n}\n\n/** Key for the (kind, subject, axis, requirement) tuple a feature claims. The\n * axes are separate namespaces on purpose — an arch requirement cannot conflict\n * with a business requirement of the same name, they merge into different files\n * — and so are the kinds, for the reason `ClaimSubject` states above. */\nexport function key(claim: ClaimSubject, identity: string): string {\n return `${claim.kind}\\0${claim.subject}\\0${claim.axis.file}\\0${identity}`;\n}\n\n/** Stable ID when present; exact heading for a legacy requirement. */\nexport function requirementKey(requirement: Pick<Requirement, \"id\" | \"name\">): string {\n return requirement.id === undefined ? `name:${requirement.name}` : `id:${requirement.id}`;\n}\n"]}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each delta requirement SELECTS in the living document, and whether the
|
|
3
|
+
* merge would do what its author meant.
|
|
4
|
+
*
|
|
5
|
+
* This is the half that needs both documents at once, which is why it is not in
|
|
6
|
+
* `./document.ts`. Every refusal here is a shape the merge would apply cleanly
|
|
7
|
+
* and silently: MODIFIED of a requirement that does not exist is merged as a
|
|
8
|
+
* creation, ADDED of one that does exist REPLACES it scenarios and all, and a
|
|
9
|
+
* stale `Based-On:` means someone landed a change in between that this delta
|
|
10
|
+
* would overwrite with text written against a document that no longer exists.
|
|
11
|
+
*/
|
|
12
|
+
import {} from "../vocabulary/issue.js";
|
|
13
|
+
import { isRequirementsHeading } from "../document/parse.js";
|
|
14
|
+
import { basedOnDeclarations, REQUIREMENT_DIGEST_RE, requirementDigest, } from "../document/spec.js";
|
|
15
|
+
import {} from "./claims.js";
|
|
16
|
+
import {} from "./scope.js";
|
|
17
|
+
export async function selectionIssues(scope, reqs, living, claims) {
|
|
18
|
+
const { featureId, subject, where, livingDoc } = scope;
|
|
19
|
+
const issues = [];
|
|
20
|
+
/**
|
|
21
|
+
* The pin, against the living requirement this delta actually selects.
|
|
22
|
+
*
|
|
23
|
+
* This is the check `delta.modified-conflict` cannot be: that one names
|
|
24
|
+
* the other feature while BOTH are in flight, and the collision that
|
|
25
|
+
* happens on a fleet outlives the window. A archives, leaves `features/`,
|
|
26
|
+
* and stops being an active claim; B revalidates GREEN, and its MODIFIED —
|
|
27
|
+
* carrying the full text it wrote against the pre-A document — replaces
|
|
28
|
+
* A's requirement wholesale, scenarios and all, with `+0 ~1 -0` and exit
|
|
29
|
+
* 0. Nothing downstream can even detect it afterwards: `unarchive A`
|
|
30
|
+
* refuses `snapshot-stale`, and `--force` takes B out with it.
|
|
31
|
+
*
|
|
32
|
+
* A digest of what the author read closes that by not depending on
|
|
33
|
+
* timing at all. Stale is an ERROR and gates, because there is no reading
|
|
34
|
+
* of a stale delta under which the merge is what its author meant.
|
|
35
|
+
* Missing is a warning that GATES: the document is legal — a delta
|
|
36
|
+
* adopted from OpenSpec never had the line — but an unpinned MODIFIED or
|
|
37
|
+
* REMOVED is exactly the timing hole the pin exists to close, and letting
|
|
38
|
+
* it through archived the silent rollback at exit 0. The migrated corpus
|
|
39
|
+
* is why this stays a warning rather than an error, and why the refusal
|
|
40
|
+
* is not an outage: `loam rebase <feat>` pins every delta in one command,
|
|
41
|
+
* and `--approve` remains the way to say the unpinned merge is meant.
|
|
42
|
+
*/
|
|
43
|
+
const checkBaseline = (r, selected) => {
|
|
44
|
+
// A pin the document pass already refused is not also stale: that would
|
|
45
|
+
// send its author to `loam rebase` for a problem rebase does not fix.
|
|
46
|
+
const declared = basedOnDeclarations(r);
|
|
47
|
+
if (declared.length > 1)
|
|
48
|
+
return;
|
|
49
|
+
if (r.basedOn !== undefined && !REQUIREMENT_DIGEST_RE.test(r.basedOn))
|
|
50
|
+
return;
|
|
51
|
+
const current = requirementDigest(selected);
|
|
52
|
+
if (r.basedOn === undefined) {
|
|
53
|
+
issues.push({
|
|
54
|
+
severity: "warn",
|
|
55
|
+
gates: true,
|
|
56
|
+
code: "delta.baseline-missing",
|
|
57
|
+
subject,
|
|
58
|
+
message: `${where}: ${r.kind} requirement '${r.name}' carries no Based-On, so nothing can say whether the living text moved since this delta was written — merging it would replace whatever landed in between. Run \`loam rebase ${featureId}\` to pin it (Based-On: ${current}), or archive with --approve to merge unpinned deliberately.`,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (r.basedOn === current)
|
|
63
|
+
return;
|
|
64
|
+
issues.push({
|
|
65
|
+
severity: "error",
|
|
66
|
+
code: "delta.baseline-stale",
|
|
67
|
+
subject,
|
|
68
|
+
message: `${where}: ${r.kind} requirement '${r.name}' was written against living version ${r.basedOn}, but the ${livingDoc} now holds ${current} — someone landed a change to it in between. ` +
|
|
69
|
+
(r.kind === "MODIFIED"
|
|
70
|
+
? `This MODIFIED carries its FULL new text, so merging it would replace theirs outright.`
|
|
71
|
+
: `Merging this REMOVED would delete what they landed.`) +
|
|
72
|
+
` Re-read the living requirement, fold in what you still mean, then run \`loam rebase ${featureId}\`.`,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
for (const r of reqs) {
|
|
76
|
+
// BASE in a delta file means the requirement is under no delta section, so
|
|
77
|
+
// the merge skips it. Reported rather than merged: deciding that `## Behavior`
|
|
78
|
+
// means ADDED would be archive guessing at intent, and it would guess wrong
|
|
79
|
+
// for every prose section that quotes a requirement as documentation. A
|
|
80
|
+
// requirement above every heading has no heading to name, and no claim to be
|
|
81
|
+
// written in the delta grammar at all — same judgement as `## Requirements`.
|
|
82
|
+
//
|
|
83
|
+
// A warning that GATES archive — the one check where the two axes
|
|
84
|
+
// diverge. Severity says whether the document is valid: this shape is
|
|
85
|
+
// legal OpenSpec, so an error would fail `loam validate` on every
|
|
86
|
+
// adopted repo whose active deltas still use it. Gating says whether
|
|
87
|
+
// the merge is safe: it is not — the merge would silently drop authored
|
|
88
|
+
// content, the exact loss this module exists to prevent — so archive
|
|
89
|
+
// refuses, and `--approve` remains the way to say the loss is meant.
|
|
90
|
+
if (r.kind === "BASE") {
|
|
91
|
+
if (r.section !== undefined && !isRequirementsHeading(r.section)) {
|
|
92
|
+
issues.push({
|
|
93
|
+
severity: "warn",
|
|
94
|
+
gates: true,
|
|
95
|
+
code: "delta.requirement-not-merged",
|
|
96
|
+
subject,
|
|
97
|
+
message: `${where}: requirement '${r.name}' sits under '${r.section}', which is not a delta section — archive will NOT merge it. Move it under '## ADDED Requirements' (or MODIFIED/REMOVED), or drop it if it is documentation.`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (r.kind === "ADDED") {
|
|
103
|
+
const idMatches = r.id === undefined ? [] : (living.byId.get(r.id) ?? []);
|
|
104
|
+
const nameMatches = living.byName.get(r.name) ?? [];
|
|
105
|
+
const nameSelectsOther = r.id !== undefined && nameMatches.some((candidate) => candidate.id !== r.id);
|
|
106
|
+
if (nameSelectsOther) {
|
|
107
|
+
issues.push({
|
|
108
|
+
severity: "error",
|
|
109
|
+
code: "delta.requirement-identity-collision",
|
|
110
|
+
subject,
|
|
111
|
+
message: `${where}: ADDED requirement '${r.name}' carries Requirement-ID '${r.id}', but that heading already identifies a different living requirement — ID and name cannot select different identities`,
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if ((r.id === undefined && living.names.has(r.name)) || idMatches.length > 0) {
|
|
116
|
+
issues.push({
|
|
117
|
+
severity: "error",
|
|
118
|
+
code: "delta.added-duplicate",
|
|
119
|
+
subject,
|
|
120
|
+
message: r.id === undefined
|
|
121
|
+
? `${where}: ADDED requirement '${r.name}' already exists in the ${livingDoc} — the merge would REPLACE it, scenarios and all. Use MODIFIED, or rename.`
|
|
122
|
+
: `${where}: ADDED requirement '${r.name}' uses Requirement-ID '${r.id}', which already exists in the ${livingDoc} — use MODIFIED to change that identity`,
|
|
123
|
+
});
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
// Merge identity is exact string equality (applyRequirementDelta), so a
|
|
127
|
+
// name that differs only in case slips past the duplicate check above and
|
|
128
|
+
// lands as a SECOND requirement next to the living one. A warning, not an
|
|
129
|
+
// error: the author may genuinely mean a distinct requirement, but with
|
|
130
|
+
// LLM authors the case drift is the likely story. Never fires together
|
|
131
|
+
// with added-duplicate — an exact match continues before this runs.
|
|
132
|
+
const near = living.folded.get(r.name.toLowerCase());
|
|
133
|
+
if (near !== undefined) {
|
|
134
|
+
issues.push({
|
|
135
|
+
severity: "warn",
|
|
136
|
+
code: "delta.added-near-duplicate",
|
|
137
|
+
subject,
|
|
138
|
+
message: `${where}: ADDED requirement '${r.name}' differs only in case from living requirement '${near}' — the merge matches names exactly, so both would coexist. Match the living spelling and use MODIFIED, or pick a distinct name.`,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const other = await claims.added(scope, r);
|
|
142
|
+
if (other !== undefined) {
|
|
143
|
+
issues.push({
|
|
144
|
+
severity: "warn",
|
|
145
|
+
code: "delta.added-conflict",
|
|
146
|
+
subject,
|
|
147
|
+
message: `${where}: requirement '${r.name}' is also added by ${other} — whichever archives first lands it, and the second archive is refused (delta.added-duplicate) unless --approve`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
// MODIFIED vs MODIFIED on ONE living requirement. The ADDED case has
|
|
153
|
+
// been caught since delta.added-conflict: two features adding the same
|
|
154
|
+
// name collide loudly, because the second archive is refused. Two
|
|
155
|
+
// features CHANGING the same requirement collide in total silence —
|
|
156
|
+
// both deltas apply cleanly, and whichever archives second replaces
|
|
157
|
+
// the first's text, scenarios and all, with a version written against
|
|
158
|
+
// a document that no longer exists. A warning, not a gate: the second
|
|
159
|
+
// author may well be rewriting on purpose, and only they can say.
|
|
160
|
+
const alsoChanged = await claims.changed(scope, r);
|
|
161
|
+
if (alsoChanged !== undefined) {
|
|
162
|
+
issues.push({
|
|
163
|
+
severity: "warn",
|
|
164
|
+
code: "delta.modified-conflict",
|
|
165
|
+
subject,
|
|
166
|
+
message: `${where}: ${r.kind} requirement '${r.name}' is also changed by ${alsoChanged} — both deltas apply cleanly, so whichever archives second REPLACES the other's text wholesale. Agree on one owner, or fold the two changes together.`,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (r.id !== undefined) {
|
|
170
|
+
const idMatches = living.byId.get(r.id) ?? [];
|
|
171
|
+
const nameMatches = living.byName.get(r.name) ?? [];
|
|
172
|
+
const nameSelectsOther = nameMatches.some((candidate) => candidate.id !== r.id);
|
|
173
|
+
// The second disjunct is defensive rather than reachable: a living
|
|
174
|
+
// requirement under this heading that the ID did NOT select must carry
|
|
175
|
+
// some other ID, which is what `nameSelectsOther` already says. It is
|
|
176
|
+
// kept because it states the rule the reader is being told — ID and
|
|
177
|
+
// heading must select the same identity — without depending on that
|
|
178
|
+
// derivation holding after the next edit.
|
|
179
|
+
if (nameSelectsOther || (idMatches.length === 0 && nameMatches.length > 0)) {
|
|
180
|
+
issues.push({
|
|
181
|
+
severity: "error",
|
|
182
|
+
code: "delta.requirement-identity-collision",
|
|
183
|
+
subject,
|
|
184
|
+
message: `${where}: ${r.kind} requirement '${r.name}' carries Requirement-ID '${r.id}', but its ID and heading select different living requirements — fix the ID or heading; archive will not guess`,
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
// A differing heading is the explicit loam rename mechanism: the
|
|
189
|
+
// stable ID selects the old requirement, MODIFIED supplies its new name.
|
|
190
|
+
//
|
|
191
|
+
// Total in the ID, deliberately: an ID that matches SEVERAL living
|
|
192
|
+
// requirements has already been refused as
|
|
193
|
+
// `delta.living-requirement-id-invalid` (severity error, so archive is
|
|
194
|
+
// gated either way), and the living document is where it gets fixed.
|
|
195
|
+
// Falling through instead added `delta.modified-unknown` — "does not
|
|
196
|
+
// exist … Did you mean ADDED?" — beside it, which is both false and
|
|
197
|
+
// the more actionable-sounding of the two, and it sends the author to
|
|
198
|
+
// edit the delta over a problem that is not in the delta. There is no
|
|
199
|
+
// baseline to check against an ambiguous selection, so the pin is
|
|
200
|
+
// simply not graded until the ambiguity is gone.
|
|
201
|
+
if (idMatches.length > 0) {
|
|
202
|
+
const selected = idMatches.length === 1 ? idMatches[0] : undefined;
|
|
203
|
+
if (selected !== undefined)
|
|
204
|
+
checkBaseline(r, selected);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else if (living.names.has(r.name)) {
|
|
209
|
+
// Twins under one heading are already refused
|
|
210
|
+
// (`delta.living-duplicate-requirement`), and applyRequirementDelta
|
|
211
|
+
// takes the first either way — so the pin is compared against the
|
|
212
|
+
// same requirement the merge would rewrite.
|
|
213
|
+
checkBaseline(r, living.byName.get(r.name)[0]);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const other = await claims.added(scope, r);
|
|
217
|
+
if (other !== undefined) {
|
|
218
|
+
issues.push({
|
|
219
|
+
severity: "warn",
|
|
220
|
+
code: r.kind === "MODIFIED" ? "delta.modified-pending" : "delta.removed-pending",
|
|
221
|
+
subject,
|
|
222
|
+
message: `${where}: ${r.kind} requirement '${r.name}' is not in the ${livingDoc} yet — ${other} introduces it. Archive ${other} first.`,
|
|
223
|
+
});
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
issues.push({
|
|
227
|
+
severity: "error",
|
|
228
|
+
code: r.kind === "MODIFIED" ? "delta.modified-unknown" : "delta.removed-unknown",
|
|
229
|
+
subject,
|
|
230
|
+
message: r.kind === "MODIFIED"
|
|
231
|
+
? `${where}: MODIFIED requirement '${r.name}' does not exist in the ${livingDoc} — the merge would create it. Did you mean ADDED?`
|
|
232
|
+
: `${where}: REMOVED requirement '${r.name}' does not exist in the ${livingDoc} — there is nothing to remove`,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return issues;
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/core/delta/select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What each delta requirement SELECTS in the living document, and whether the\n * merge would do what its author meant.\n *\n * This is the half that needs both documents at once, which is why it is not in\n * `./document.ts`. Every refusal here is a shape the merge would apply cleanly\n * and silently: MODIFIED of a requirement that does not exist is merged as a\n * creation, ADDED of one that does exist REPLACES it scenarios and all, and a\n * stale `Based-On:` means someone landed a change in between that this delta\n * would overwrite with text written against a document that no longer exists.\n */\nimport { type Issue } from \"../vocabulary/issue.js\";\nimport { isRequirementsHeading } from \"../document/parse.js\";\nimport {\n basedOnDeclarations,\n REQUIREMENT_DIGEST_RE,\n requirementDigest,\n type Requirement,\n} from \"../document/spec.js\";\nimport { type ClaimLookup } from \"./claims.js\";\nimport { type DeltaScope, type LivingIndex } from \"./scope.js\";\n\nexport async function selectionIssues(\n scope: DeltaScope,\n reqs: Requirement[],\n living: LivingIndex,\n claims: ClaimLookup,\n): Promise<Issue[]> {\n const { featureId, subject, where, livingDoc } = scope;\n const issues: Issue[] = [];\n /**\n * The pin, against the living requirement this delta actually selects.\n *\n * This is the check `delta.modified-conflict` cannot be: that one names\n * the other feature while BOTH are in flight, and the collision that\n * happens on a fleet outlives the window. A archives, leaves `features/`,\n * and stops being an active claim; B revalidates GREEN, and its MODIFIED —\n * carrying the full text it wrote against the pre-A document — replaces\n * A's requirement wholesale, scenarios and all, with `+0 ~1 -0` and exit\n * 0. Nothing downstream can even detect it afterwards: `unarchive A`\n * refuses `snapshot-stale`, and `--force` takes B out with it.\n *\n * A digest of what the author read closes that by not depending on\n * timing at all. Stale is an ERROR and gates, because there is no reading\n * of a stale delta under which the merge is what its author meant.\n * Missing is a warning that GATES: the document is legal — a delta\n * adopted from OpenSpec never had the line — but an unpinned MODIFIED or\n * REMOVED is exactly the timing hole the pin exists to close, and letting\n * it through archived the silent rollback at exit 0. The migrated corpus\n * is why this stays a warning rather than an error, and why the refusal\n * is not an outage: `loam rebase <feat>` pins every delta in one command,\n * and `--approve` remains the way to say the unpinned merge is meant.\n */\n const checkBaseline = (r: Requirement, selected: Requirement): void => {\n // A pin the document pass already refused is not also stale: that would\n // send its author to `loam rebase` for a problem rebase does not fix.\n const declared = basedOnDeclarations(r);\n if (declared.length > 1) return;\n if (r.basedOn !== undefined && !REQUIREMENT_DIGEST_RE.test(r.basedOn)) return;\n const current = requirementDigest(selected);\n if (r.basedOn === undefined) {\n issues.push({\n severity: \"warn\",\n gates: true,\n code: \"delta.baseline-missing\",\n subject,\n message: `${where}: ${r.kind} requirement '${r.name}' carries no Based-On, so nothing can say whether the living text moved since this delta was written — merging it would replace whatever landed in between. Run \\`loam rebase ${featureId}\\` to pin it (Based-On: ${current}), or archive with --approve to merge unpinned deliberately.`,\n });\n return;\n }\n if (r.basedOn === current) return;\n issues.push({\n severity: \"error\",\n code: \"delta.baseline-stale\",\n subject,\n message:\n `${where}: ${r.kind} requirement '${r.name}' was written against living version ${r.basedOn}, but the ${livingDoc} now holds ${current} — someone landed a change to it in between. ` +\n (r.kind === \"MODIFIED\"\n ? `This MODIFIED carries its FULL new text, so merging it would replace theirs outright.`\n : `Merging this REMOVED would delete what they landed.`) +\n ` Re-read the living requirement, fold in what you still mean, then run \\`loam rebase ${featureId}\\`.`,\n });\n };\n\n for (const r of reqs) {\n // BASE in a delta file means the requirement is under no delta section, so\n // the merge skips it. Reported rather than merged: deciding that `## Behavior`\n // means ADDED would be archive guessing at intent, and it would guess wrong\n // for every prose section that quotes a requirement as documentation. A\n // requirement above every heading has no heading to name, and no claim to be\n // written in the delta grammar at all — same judgement as `## Requirements`.\n //\n // A warning that GATES archive — the one check where the two axes\n // diverge. Severity says whether the document is valid: this shape is\n // legal OpenSpec, so an error would fail `loam validate` on every\n // adopted repo whose active deltas still use it. Gating says whether\n // the merge is safe: it is not — the merge would silently drop authored\n // content, the exact loss this module exists to prevent — so archive\n // refuses, and `--approve` remains the way to say the loss is meant.\n if (r.kind === \"BASE\") {\n if (r.section !== undefined && !isRequirementsHeading(r.section)) {\n issues.push({\n severity: \"warn\",\n gates: true,\n code: \"delta.requirement-not-merged\",\n subject,\n message: `${where}: requirement '${r.name}' sits under '${r.section}', which is not a delta section — archive will NOT merge it. Move it under '## ADDED Requirements' (or MODIFIED/REMOVED), or drop it if it is documentation.`,\n });\n }\n continue;\n }\n\n if (r.kind === \"ADDED\") {\n const idMatches = r.id === undefined ? [] : (living.byId.get(r.id) ?? []);\n const nameMatches = living.byName.get(r.name) ?? [];\n const nameSelectsOther = r.id !== undefined && nameMatches.some((candidate) => candidate.id !== r.id);\n if (nameSelectsOther) {\n issues.push({\n severity: \"error\",\n code: \"delta.requirement-identity-collision\",\n subject,\n message: `${where}: ADDED requirement '${r.name}' carries Requirement-ID '${r.id}', but that heading already identifies a different living requirement — ID and name cannot select different identities`,\n });\n continue;\n }\n if ((r.id === undefined && living.names.has(r.name)) || idMatches.length > 0) {\n issues.push({\n severity: \"error\",\n code: \"delta.added-duplicate\",\n subject,\n message: r.id === undefined\n ? `${where}: ADDED requirement '${r.name}' already exists in the ${livingDoc} — the merge would REPLACE it, scenarios and all. Use MODIFIED, or rename.`\n : `${where}: ADDED requirement '${r.name}' uses Requirement-ID '${r.id}', which already exists in the ${livingDoc} — use MODIFIED to change that identity`,\n });\n continue;\n }\n // Merge identity is exact string equality (applyRequirementDelta), so a\n // name that differs only in case slips past the duplicate check above and\n // lands as a SECOND requirement next to the living one. A warning, not an\n // error: the author may genuinely mean a distinct requirement, but with\n // LLM authors the case drift is the likely story. Never fires together\n // with added-duplicate — an exact match continues before this runs.\n const near = living.folded.get(r.name.toLowerCase());\n if (near !== undefined) {\n issues.push({\n severity: \"warn\",\n code: \"delta.added-near-duplicate\",\n subject,\n message: `${where}: ADDED requirement '${r.name}' differs only in case from living requirement '${near}' — the merge matches names exactly, so both would coexist. Match the living spelling and use MODIFIED, or pick a distinct name.`,\n });\n }\n const other = await claims.added(scope, r);\n if (other !== undefined) {\n issues.push({\n severity: \"warn\",\n code: \"delta.added-conflict\",\n subject,\n message: `${where}: requirement '${r.name}' is also added by ${other} — whichever archives first lands it, and the second archive is refused (delta.added-duplicate) unless --approve`,\n });\n }\n continue;\n }\n\n // MODIFIED vs MODIFIED on ONE living requirement. The ADDED case has\n // been caught since delta.added-conflict: two features adding the same\n // name collide loudly, because the second archive is refused. Two\n // features CHANGING the same requirement collide in total silence —\n // both deltas apply cleanly, and whichever archives second replaces\n // the first's text, scenarios and all, with a version written against\n // a document that no longer exists. A warning, not a gate: the second\n // author may well be rewriting on purpose, and only they can say.\n const alsoChanged = await claims.changed(scope, r);\n if (alsoChanged !== undefined) {\n issues.push({\n severity: \"warn\",\n code: \"delta.modified-conflict\",\n subject,\n message: `${where}: ${r.kind} requirement '${r.name}' is also changed by ${alsoChanged} — both deltas apply cleanly, so whichever archives second REPLACES the other's text wholesale. Agree on one owner, or fold the two changes together.`,\n });\n }\n\n if (r.id !== undefined) {\n const idMatches = living.byId.get(r.id) ?? [];\n const nameMatches = living.byName.get(r.name) ?? [];\n const nameSelectsOther = nameMatches.some((candidate) => candidate.id !== r.id);\n // The second disjunct is defensive rather than reachable: a living\n // requirement under this heading that the ID did NOT select must carry\n // some other ID, which is what `nameSelectsOther` already says. It is\n // kept because it states the rule the reader is being told — ID and\n // heading must select the same identity — without depending on that\n // derivation holding after the next edit.\n if (nameSelectsOther || (idMatches.length === 0 && nameMatches.length > 0)) {\n issues.push({\n severity: \"error\",\n code: \"delta.requirement-identity-collision\",\n subject,\n message: `${where}: ${r.kind} requirement '${r.name}' carries Requirement-ID '${r.id}', but its ID and heading select different living requirements — fix the ID or heading; archive will not guess`,\n });\n continue;\n }\n // A differing heading is the explicit loam rename mechanism: the\n // stable ID selects the old requirement, MODIFIED supplies its new name.\n //\n // Total in the ID, deliberately: an ID that matches SEVERAL living\n // requirements has already been refused as\n // `delta.living-requirement-id-invalid` (severity error, so archive is\n // gated either way), and the living document is where it gets fixed.\n // Falling through instead added `delta.modified-unknown` — \"does not\n // exist … Did you mean ADDED?\" — beside it, which is both false and\n // the more actionable-sounding of the two, and it sends the author to\n // edit the delta over a problem that is not in the delta. There is no\n // baseline to check against an ambiguous selection, so the pin is\n // simply not graded until the ambiguity is gone.\n if (idMatches.length > 0) {\n const selected = idMatches.length === 1 ? idMatches[0] : undefined;\n if (selected !== undefined) checkBaseline(r, selected);\n continue;\n }\n } else if (living.names.has(r.name)) {\n // Twins under one heading are already refused\n // (`delta.living-duplicate-requirement`), and applyRequirementDelta\n // takes the first either way — so the pin is compared against the\n // same requirement the merge would rewrite.\n checkBaseline(r, living.byName.get(r.name)![0]!);\n continue;\n }\n\n const other = await claims.added(scope, r);\n if (other !== undefined) {\n issues.push({\n severity: \"warn\",\n code: r.kind === \"MODIFIED\" ? \"delta.modified-pending\" : \"delta.removed-pending\",\n subject,\n message: `${where}: ${r.kind} requirement '${r.name}' is not in the ${livingDoc} yet — ${other} introduces it. Archive ${other} first.`,\n });\n continue;\n }\n issues.push({\n severity: \"error\",\n code: r.kind === \"MODIFIED\" ? \"delta.modified-unknown\" : \"delta.removed-unknown\",\n subject,\n message:\n r.kind === \"MODIFIED\"\n ? `${where}: MODIFIED requirement '${r.name}' does not exist in the ${livingDoc} — the merge would create it. Did you mean ADDED?`\n : `${where}: REMOVED requirement '${r.name}' does not exist in the ${livingDoc} — there is nothing to remove`,\n });\n }\n return issues;\n}\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The active-feature dependency graph: who has to archive before whom.
|
|
3
|
+
*
|
|
4
|
+
* A feature depends on another when it MODIFIES or REMOVES a requirement the
|
|
5
|
+
* other adds, or calls an operation the other introduces — the two ways one
|
|
6
|
+
* delta can only apply after another has landed. This module is the walk that
|
|
7
|
+
* puts `./facts.ts` and `./graph.ts` together; the reasons it attaches to each
|
|
8
|
+
* edge are what makes the answer explainable rather than merely true.
|
|
9
|
+
*/
|
|
10
|
+
import { inOrder } from "../kernel/concurrency.js";
|
|
11
|
+
import { FleetContext } from "../fleet-context.js";
|
|
12
|
+
import { compareIds } from "../repo/entries.js";
|
|
13
|
+
import { listFeatures } from "../repo/repo.js";
|
|
14
|
+
import { addOwner, opIndexKey, readFacts, reqIndexKey, reqKeys, } from "./facts.js";
|
|
15
|
+
import { appendReason, compareReasons, dependencyFirstOrder, stronglyConnected } from "./graph.js";
|
|
16
|
+
/** Derive the complete active-feature graph, or one feature and its transitive prerequisites. */
|
|
17
|
+
export async function analyzeDependencies(docsDir, featureId, context = new FleetContext()) {
|
|
18
|
+
const features = await listFeatures(docsDir, {}, context);
|
|
19
|
+
// Bounded, not `Promise.all`: `readFacts` loads the feature's delta.likec4,
|
|
20
|
+
// and each of those is a whole Langium workspace held open until the read
|
|
21
|
+
// finishes — the same resource `validate --all` rations for the same measured
|
|
22
|
+
// reason (see core/kernel/concurrency.ts). This module fanned out over every active
|
|
23
|
+
// feature at once, and it is not only `loam dependencies` that pays: the fleet
|
|
24
|
+
// form of `loam status` calls in here too. `inOrder` returns results in input
|
|
25
|
+
// order, so the graph, the conflict list and their ordering are unchanged.
|
|
26
|
+
const facts = await inOrder(features, (feature) => readFacts(docsDir, feature, context));
|
|
27
|
+
const requirementOwners = new Map();
|
|
28
|
+
// The second index over the SAME identity: who MODIFIES or REMOVES it. Only
|
|
29
|
+
// the first index existed, so the graph could see "two features add the same
|
|
30
|
+
// requirement" and was blind to "two features rewrite the same requirement" —
|
|
31
|
+
// the collision that actually happens on a fleet, and the one whose loser
|
|
32
|
+
// loses their whole authored text without a word from any command.
|
|
33
|
+
const changedOwners = new Map();
|
|
34
|
+
const operationOwners = new Map();
|
|
35
|
+
for (const fact of facts) {
|
|
36
|
+
for (const added of fact.addedRequirements) {
|
|
37
|
+
for (const identity of reqKeys(added.requirement)) {
|
|
38
|
+
const at = { service: added.service, axis: added.axis, identity };
|
|
39
|
+
addOwner(requirementOwners, reqIndexKey(at), at, fact.feature.id);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const changed of fact.changedRequirements) {
|
|
43
|
+
for (const identity of reqKeys(changed.requirement)) {
|
|
44
|
+
const at = { service: changed.service, axis: changed.axis, identity };
|
|
45
|
+
addOwner(changedOwners, reqIndexKey(at), at, fact.feature.id);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const operation of fact.introducedOperations) {
|
|
49
|
+
addOwner(operationOwners, opIndexKey(operation), operation, fact.feature.id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const edgeMap = new Map();
|
|
53
|
+
for (const fact of facts) {
|
|
54
|
+
for (const changed of fact.changedRequirements) {
|
|
55
|
+
for (const identity of reqKeys(changed.requirement)) {
|
|
56
|
+
const at = { service: changed.service, axis: changed.axis, identity };
|
|
57
|
+
for (const owner of requirementOwners.get(reqIndexKey(at))?.features ?? []) {
|
|
58
|
+
appendReason(edgeMap, fact.feature.id, owner, { kind: "requirement", ...at });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const required of fact.requiredOperations) {
|
|
63
|
+
for (const owner of operationOwners.get(opIndexKey(required))?.features ?? []) {
|
|
64
|
+
appendReason(edgeMap, fact.feature.id, owner, { kind: "operation", ...required });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let edges = [...edgeMap.values()]
|
|
69
|
+
.map((edge) => ({ ...edge, reasons: edge.reasons.sort(compareReasons) }))
|
|
70
|
+
.sort((a, b) => compareIds(a.from, b.from) || compareIds(a.to, b.to));
|
|
71
|
+
const conflicts = [];
|
|
72
|
+
for (const [index, change] of [
|
|
73
|
+
[requirementOwners, "added"],
|
|
74
|
+
[changedOwners, "changed"],
|
|
75
|
+
]) {
|
|
76
|
+
for (const { at, features } of index.values()) {
|
|
77
|
+
if (features.size < 2)
|
|
78
|
+
continue;
|
|
79
|
+
conflicts.push({
|
|
80
|
+
kind: "requirement",
|
|
81
|
+
change,
|
|
82
|
+
service: at.service,
|
|
83
|
+
axis: at.axis,
|
|
84
|
+
identity: at.identity,
|
|
85
|
+
features: [...features].sort(compareIds),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const { at, features } of operationOwners.values()) {
|
|
90
|
+
if (features.size < 2)
|
|
91
|
+
continue;
|
|
92
|
+
conflicts.push({
|
|
93
|
+
kind: "operation",
|
|
94
|
+
// Two features DEFINING the same operationId — the only way an operation
|
|
95
|
+
// collides, since removals address a living slot rather than claim one.
|
|
96
|
+
change: "added",
|
|
97
|
+
service: at.service,
|
|
98
|
+
identity: at.operationId,
|
|
99
|
+
features: [...features].sort(compareIds),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
conflicts.sort((a, b) => compareIds(a.kind, b.kind)
|
|
103
|
+
|| compareIds(a.change, b.change)
|
|
104
|
+
|| compareIds(a.service, b.service)
|
|
105
|
+
|| compareIds(a.axis ?? "", b.axis ?? "")
|
|
106
|
+
|| compareIds(a.identity, b.identity));
|
|
107
|
+
// `Set<string>`, not the ids' own brand: `DependencyEdge.from`/`to` are plain
|
|
108
|
+
// strings, and the reassignment below rebuilds the set from a caller's
|
|
109
|
+
// argument.
|
|
110
|
+
let selected = new Set(features.map((feature) => feature.id));
|
|
111
|
+
if (featureId !== undefined) {
|
|
112
|
+
selected = new Set([featureId]);
|
|
113
|
+
let changed = true;
|
|
114
|
+
while (changed) {
|
|
115
|
+
changed = false;
|
|
116
|
+
for (const edge of edges) {
|
|
117
|
+
if (selected.has(edge.from) && !selected.has(edge.to)) {
|
|
118
|
+
selected.add(edge.to);
|
|
119
|
+
changed = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
edges = edges.filter((edge) => selected.has(edge.from) && selected.has(edge.to));
|
|
124
|
+
}
|
|
125
|
+
const selectedFeatures = features.filter((feature) => selected.has(feature.id));
|
|
126
|
+
const ids = selectedFeatures.map((feature) => feature.id);
|
|
127
|
+
const nodes = selectedFeatures.map((feature) => ({
|
|
128
|
+
id: feature.id,
|
|
129
|
+
dirName: feature.dirName,
|
|
130
|
+
services: [...feature.services],
|
|
131
|
+
dependsOn: edges.filter((edge) => edge.from === feature.id).map((edge) => edge.to).sort(compareIds),
|
|
132
|
+
}));
|
|
133
|
+
return {
|
|
134
|
+
nodes,
|
|
135
|
+
edges,
|
|
136
|
+
conflicts: conflicts.filter((conflict) => conflict.features.some((id) => selected.has(id))),
|
|
137
|
+
order: dependencyFirstOrder(ids, edges),
|
|
138
|
+
cycles: stronglyConnected(ids, edges),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../src/core/dependencies/dependencies.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The active-feature dependency graph: who has to archive before whom.\n *\n * A feature depends on another when it MODIFIES or REMOVES a requirement the\n * other adds, or calls an operation the other introduces — the two ways one\n * delta can only apply after another has landed. This module is the walk that\n * puts `./facts.ts` and `./graph.ts` together; the reasons it attaches to each\n * edge are what makes the answer explainable rather than merely true.\n */\nimport { inOrder } from \"../kernel/concurrency.js\";\nimport { FleetContext } from \"../fleet-context.js\";\nimport { compareIds } from \"../repo/entries.js\";\nimport { listFeatures } from \"../repo/repo.js\";\nimport {\n addOwner,\n opIndexKey,\n readFacts,\n reqIndexKey,\n reqKeys,\n type DependencyEdge,\n type DependencyGraph,\n type DependencyNode,\n type FeatureConflict,\n type OpAt,\n type Owners,\n type ReqAt,\n} from \"./facts.js\";\nimport { appendReason, compareReasons, dependencyFirstOrder, stronglyConnected } from \"./graph.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\n\n/** Derive the complete active-feature graph, or one feature and its transitive prerequisites. */\nexport async function analyzeDependencies(\n docsDir: DocsDir,\n featureId?: string,\n context = new FleetContext(),\n): Promise<DependencyGraph> {\n const features = await listFeatures(docsDir, {}, context);\n // Bounded, not `Promise.all`: `readFacts` loads the feature's delta.likec4,\n // and each of those is a whole Langium workspace held open until the read\n // finishes — the same resource `validate --all` rations for the same measured\n // reason (see core/kernel/concurrency.ts). This module fanned out over every active\n // feature at once, and it is not only `loam dependencies` that pays: the fleet\n // form of `loam status` calls in here too. `inOrder` returns results in input\n // order, so the graph, the conflict list and their ordering are unchanged.\n const facts = await inOrder(features, (feature) => readFacts(docsDir, feature, context));\n const requirementOwners = new Map<string, Owners<ReqAt>>();\n // The second index over the SAME identity: who MODIFIES or REMOVES it. Only\n // the first index existed, so the graph could see \"two features add the same\n // requirement\" and was blind to \"two features rewrite the same requirement\" —\n // the collision that actually happens on a fleet, and the one whose loser\n // loses their whole authored text without a word from any command.\n const changedOwners = new Map<string, Owners<ReqAt>>();\n const operationOwners = new Map<string, Owners<OpAt>>();\n\n for (const fact of facts) {\n for (const added of fact.addedRequirements) {\n for (const identity of reqKeys(added.requirement)) {\n const at: ReqAt = { service: added.service, axis: added.axis, identity };\n addOwner(requirementOwners, reqIndexKey(at), at, fact.feature.id);\n }\n }\n for (const changed of fact.changedRequirements) {\n for (const identity of reqKeys(changed.requirement)) {\n const at: ReqAt = { service: changed.service, axis: changed.axis, identity };\n addOwner(changedOwners, reqIndexKey(at), at, fact.feature.id);\n }\n }\n for (const operation of fact.introducedOperations) {\n addOwner(operationOwners, opIndexKey(operation), operation, fact.feature.id);\n }\n }\n\n const edgeMap = new Map<string, DependencyEdge>();\n for (const fact of facts) {\n for (const changed of fact.changedRequirements) {\n for (const identity of reqKeys(changed.requirement)) {\n const at: ReqAt = { service: changed.service, axis: changed.axis, identity };\n for (const owner of requirementOwners.get(reqIndexKey(at))?.features ?? []) {\n appendReason(edgeMap, fact.feature.id, owner, { kind: \"requirement\", ...at });\n }\n }\n }\n for (const required of fact.requiredOperations) {\n for (const owner of operationOwners.get(opIndexKey(required))?.features ?? []) {\n appendReason(edgeMap, fact.feature.id, owner, { kind: \"operation\", ...required });\n }\n }\n }\n\n let edges = [...edgeMap.values()]\n .map((edge) => ({ ...edge, reasons: edge.reasons.sort(compareReasons) }))\n .sort((a, b) => compareIds(a.from, b.from) || compareIds(a.to, b.to));\n\n const conflicts: FeatureConflict[] = [];\n for (const [index, change] of [\n [requirementOwners, \"added\"],\n [changedOwners, \"changed\"],\n ] as const) {\n for (const { at, features } of index.values()) {\n if (features.size < 2) continue;\n conflicts.push({\n kind: \"requirement\",\n change,\n service: at.service,\n axis: at.axis,\n identity: at.identity,\n features: [...features].sort(compareIds),\n });\n }\n }\n for (const { at, features } of operationOwners.values()) {\n if (features.size < 2) continue;\n conflicts.push({\n kind: \"operation\",\n // Two features DEFINING the same operationId — the only way an operation\n // collides, since removals address a living slot rather than claim one.\n change: \"added\",\n service: at.service,\n identity: at.operationId,\n features: [...features].sort(compareIds),\n });\n }\n conflicts.sort((a, b) =>\n compareIds(a.kind, b.kind)\n || compareIds(a.change, b.change)\n || compareIds(a.service, b.service)\n || compareIds(a.axis ?? \"\", b.axis ?? \"\")\n || compareIds(a.identity, b.identity));\n\n // `Set<string>`, not the ids' own brand: `DependencyEdge.from`/`to` are plain\n // strings, and the reassignment below rebuilds the set from a caller's\n // argument.\n let selected = new Set<string>(features.map((feature) => feature.id));\n if (featureId !== undefined) {\n selected = new Set<string>([featureId]);\n let changed = true;\n while (changed) {\n changed = false;\n for (const edge of edges) {\n if (selected.has(edge.from) && !selected.has(edge.to)) {\n selected.add(edge.to);\n changed = true;\n }\n }\n }\n edges = edges.filter((edge) => selected.has(edge.from) && selected.has(edge.to));\n }\n\n const selectedFeatures = features.filter((feature) => selected.has(feature.id));\n const ids = selectedFeatures.map((feature) => feature.id);\n const nodes = selectedFeatures.map((feature): DependencyNode => ({\n id: feature.id,\n dirName: feature.dirName,\n services: [...feature.services],\n dependsOn: edges.filter((edge) => edge.from === feature.id).map((edge) => edge.to).sort(compareIds),\n }));\n\n return {\n nodes,\n edges,\n conflicts: conflicts.filter((conflict) => conflict.features.some((id) => selected.has(id))),\n order: dependencyFirstOrder(ids, edges),\n cycles: stronglyConnected(ids, edges),\n };\n}\n"]}
|