@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,75 @@
|
|
|
1
|
+
import { toolRunner } from "./dispatch.js";
|
|
2
|
+
import { serve } from "./serve.js";
|
|
3
|
+
import { MCP_TOOLS } from "../../core/mcp/tools.js";
|
|
4
|
+
import { MCP_AUTHOR_TOOLS } from "../../core/mcp/author-tools.js";
|
|
5
|
+
export function registerMcp(program) {
|
|
6
|
+
program
|
|
7
|
+
.command("mcp")
|
|
8
|
+
.description("Serve loam commands as MCP tools over stdio (JSON-RPC 2.0)")
|
|
9
|
+
.option("--author", "opt in to safe authoring tools; vouch and committing archive stay excluded")
|
|
10
|
+
// Declared for the uniform surface every command owes (`--json` is
|
|
11
|
+
// mandatory, test/agents.test.ts), and it is not inert: it governs the one
|
|
12
|
+
// pre-loop surface this command has — a usage error like `loam mcp --bogus`
|
|
13
|
+
// aborts before the action runs, and cli.ts's catch reads raw argv to
|
|
14
|
+
// decide whether that refusal is an envelope. Once the loop runs, stdout
|
|
15
|
+
// is JSON-RPC frames either way; there is no human rendering to switch off.
|
|
16
|
+
.option("--json", "emit the machine contract instead of the human view")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
await startMcp(mcpToolTable(opts.author === true), {
|
|
19
|
+
input: process.stdin,
|
|
20
|
+
output: process.stdout,
|
|
21
|
+
log: process.stderr,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The table `loam mcp` serves: the read surface, and the bounded writers after
|
|
27
|
+
* it only when the server was launched with `--author`.
|
|
28
|
+
*
|
|
29
|
+
* A function of its own, exported, because nothing pinned it inline. The
|
|
30
|
+
* in-process tests hand `startMcp` a table directly and the stdio smoke
|
|
31
|
+
* spawned `loam mcp` only without the flag, so this choice written as
|
|
32
|
+
* `MCP_TOOLS` alone left every test green — while every config `loam init
|
|
33
|
+
* --mcp-author` writes launches `loam mcp --author`, and those hosts would
|
|
34
|
+
* have lost the authoring tools without a word. test/mcp-serve.test.ts holds
|
|
35
|
+
* both values here; test/mcp-stdio.test.ts spawns `loam mcp --author` and holds
|
|
36
|
+
* the flag to it.
|
|
37
|
+
*/
|
|
38
|
+
export function mcpToolTable(author) {
|
|
39
|
+
return author ? [...MCP_TOOLS, ...MCP_AUTHOR_TOOLS] : MCP_TOOLS;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The action's body: serve `tools` on `io` until its input ends — or refuse
|
|
43
|
+
* before the first byte when the table itself is defective.
|
|
44
|
+
*
|
|
45
|
+
* Exported, with the stdio triple injected, so the startup refusal is pinned
|
|
46
|
+
* WHERE it happens. A test of `toolRunner` alone could not see the wiring
|
|
47
|
+
* here: rewritten as `(argv) => toolRunner(tools)(argv)`, every call would
|
|
48
|
+
* build its own runner, the refusal would move back to every `tools/call`, and
|
|
49
|
+
* a test that only called `toolRunner` would still pass.
|
|
50
|
+
*/
|
|
51
|
+
export function startMcp(tools, io) {
|
|
52
|
+
// No docs-repo gate at startup, deliberately (the add-command preamble
|
|
53
|
+
// decision): a launch-time refusal would print a non-JSON-RPC line into
|
|
54
|
+
// the client's protocol stream and kill the handshake with nothing a
|
|
55
|
+
// client can parse. Every tool call flows through the same command path
|
|
56
|
+
// the CLI uses, so a missing or broken loam.json arrives as the ordinary
|
|
57
|
+
// `no-config`/`config-invalid` envelope in a tool result — readable, and
|
|
58
|
+
// actionable, by the agent on the other end. The server serves the
|
|
59
|
+
// repository it was started in (each call resolves loam.json through
|
|
60
|
+
// process.cwd()) and never changes directory.
|
|
61
|
+
// One table decides both what `tools/list` advertises and which commands
|
|
62
|
+
// a `tools/call` can reach (`./dispatch.ts`'s `toolRunner`).
|
|
63
|
+
//
|
|
64
|
+
// `toolRunner` is the ONE launch-time refusal, and it is not the gate the
|
|
65
|
+
// paragraph above declines: it throws only when the table itself names a
|
|
66
|
+
// command with no registrar — a defect in the shipped binary that no
|
|
67
|
+
// repository state causes and no client can repair. Refusing here, before
|
|
68
|
+
// the first frame, costs the handshake; answering it per call instead
|
|
69
|
+
// turned every `tools/call` into an `internal` envelope, the correctly
|
|
70
|
+
// wired tools included. Without `--json` (how a client launches it) the
|
|
71
|
+
// message goes to stderr through cli.ts's catch, and stdout stays empty.
|
|
72
|
+
const run = toolRunner(tools);
|
|
73
|
+
return serve(io, run, tools);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/commands/mcp/mcp.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAgB,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAMlE,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,UAAU,EAAE,4EAA4E,CAAC;QACjG,mEAAmE;QACnE,2EAA2E;QAC3E,4EAA4E;QAC5E,sEAAsE;QACtE,yEAAyE;QACzE,4EAA4E;SAC3E,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,IAAgB,EAAE,EAAE;QACjC,MAAM,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,EAAE,OAAO,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAyB,EAAE,EAAW;IAC7D,uEAAuE;IACvE,wEAAwE;IACxE,qEAAqE;IACrE,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,mEAAmE;IACnE,qEAAqE;IACrE,8CAA8C;IAC9C,yEAAyE;IACzE,6DAA6D;IAC7D,EAAE;IACF,0EAA0E;IAC1E,yEAAyE;IACzE,qEAAqE;IACrE,0EAA0E;IAC1E,sEAAsE;IACtE,uEAAuE;IACvE,wEAAwE;IACxE,yEAAyE;IACzE,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * `loam mcp` — serve the read surface, plus bounded writers under `--author`.\n *\n * The action asks `mcpToolTable` which table its flag selects and hands it,\n * with the real stdio triple, to `startMcp`, which resolves the table once and\n * serves it until stdin EOF; everything else with a decision in it lives in\n * `./serve.ts`, `./dispatch.ts` and `src/core/mcp/`. This module carries the\n * one command registration of the package (test/agents.test.ts counts\n * registrations by their literal spelling, so the sibling modules must never\n * spell one).\n */\nimport type { Command } from \"commander\";\nimport { toolRunner } from \"./dispatch.js\";\nimport { serve, type ServeIo } from \"./serve.js\";\nimport { MCP_TOOLS, type McpTool } from \"../../core/mcp/tools.js\";\nimport { MCP_AUTHOR_TOOLS } from \"../../core/mcp/author-tools.js\";\n\ninterface McpOptions {\n author?: boolean;\n}\n\nexport function registerMcp(program: Command): void {\n program\n .command(\"mcp\")\n .description(\"Serve loam commands as MCP tools over stdio (JSON-RPC 2.0)\")\n .option(\"--author\", \"opt in to safe authoring tools; vouch and committing archive stay excluded\")\n // Declared for the uniform surface every command owes (`--json` is\n // mandatory, test/agents.test.ts), and it is not inert: it governs the one\n // pre-loop surface this command has — a usage error like `loam mcp --bogus`\n // aborts before the action runs, and cli.ts's catch reads raw argv to\n // decide whether that refusal is an envelope. Once the loop runs, stdout\n // is JSON-RPC frames either way; there is no human rendering to switch off.\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: McpOptions) => {\n await startMcp(mcpToolTable(opts.author === true), {\n input: process.stdin,\n output: process.stdout,\n log: process.stderr,\n });\n });\n}\n\n/**\n * The table `loam mcp` serves: the read surface, and the bounded writers after\n * it only when the server was launched with `--author`.\n *\n * A function of its own, exported, because nothing pinned it inline. The\n * in-process tests hand `startMcp` a table directly and the stdio smoke\n * spawned `loam mcp` only without the flag, so this choice written as\n * `MCP_TOOLS` alone left every test green — while every config `loam init\n * --mcp-author` writes launches `loam mcp --author`, and those hosts would\n * have lost the authoring tools without a word. test/mcp-serve.test.ts holds\n * both values here; test/mcp-stdio.test.ts spawns `loam mcp --author` and holds\n * the flag to it.\n */\nexport function mcpToolTable(author: boolean): readonly McpTool[] {\n return author ? [...MCP_TOOLS, ...MCP_AUTHOR_TOOLS] : MCP_TOOLS;\n}\n\n/**\n * The action's body: serve `tools` on `io` until its input ends — or refuse\n * before the first byte when the table itself is defective.\n *\n * Exported, with the stdio triple injected, so the startup refusal is pinned\n * WHERE it happens. A test of `toolRunner` alone could not see the wiring\n * here: rewritten as `(argv) => toolRunner(tools)(argv)`, every call would\n * build its own runner, the refusal would move back to every `tools/call`, and\n * a test that only called `toolRunner` would still pass.\n */\nexport function startMcp(tools: readonly McpTool[], io: ServeIo): Promise<void> {\n // No docs-repo gate at startup, deliberately (the add-command preamble\n // decision): a launch-time refusal would print a non-JSON-RPC line into\n // the client's protocol stream and kill the handshake with nothing a\n // client can parse. Every tool call flows through the same command path\n // the CLI uses, so a missing or broken loam.json arrives as the ordinary\n // `no-config`/`config-invalid` envelope in a tool result — readable, and\n // actionable, by the agent on the other end. The server serves the\n // repository it was started in (each call resolves loam.json through\n // process.cwd()) and never changes directory.\n // One table decides both what `tools/list` advertises and which commands\n // a `tools/call` can reach (`./dispatch.ts`'s `toolRunner`).\n //\n // `toolRunner` is the ONE launch-time refusal, and it is not the gate the\n // paragraph above declines: it throws only when the table itself names a\n // command with no registrar — a defect in the shipped binary that no\n // repository state causes and no client can repair. Refusing here, before\n // the first frame, costs the handshake; answering it per call instead\n // turned every `tools/call` into an `internal` envelope, the correctly\n // wired tools included. Without `--json` (how a client launches it) the\n // message goes to stderr through cli.ts's catch, and stdout stays empty.\n const run = toolRunner(tools);\n return serve(io, run, tools);\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { frame, splitFrames } from "../../core/mcp/framing.js";
|
|
2
|
+
import { INTERNAL_ERROR, errorResponse, resultResponse, routeLine, toolReply, } from "../../core/mcp/protocol.js";
|
|
3
|
+
import { MCP_TOOLS } from "../../core/mcp/tools.js";
|
|
4
|
+
export async function serve(io, runTool, tools = MCP_TOOLS) {
|
|
5
|
+
// One startup line, to stderr only — a client is entitled to a stdout that
|
|
6
|
+
// has never carried anything but frames, from the very first byte.
|
|
7
|
+
io.log.write(`loam mcp: serving ${process.cwd()} over stdio\n`);
|
|
8
|
+
// Decode at the stream, not per chunk: a UTF-8 code point split across two
|
|
9
|
+
// chunks would corrupt if each chunk were stringified on its own.
|
|
10
|
+
io.input.setEncoding("utf8");
|
|
11
|
+
let rest = "";
|
|
12
|
+
for await (const chunk of io.input) {
|
|
13
|
+
const split = splitFrames(rest + String(chunk));
|
|
14
|
+
rest = split.rest;
|
|
15
|
+
for (const line of split.lines)
|
|
16
|
+
await handleLine(line, io, runTool, tools);
|
|
17
|
+
}
|
|
18
|
+
// A final frame the client sent without a trailing newline is still a frame:
|
|
19
|
+
// EOF terminates it exactly as the delimiter would have.
|
|
20
|
+
if (rest.trim() !== "")
|
|
21
|
+
await handleLine(rest, io, runTool, tools);
|
|
22
|
+
}
|
|
23
|
+
async function handleLine(line, io, runTool, tools) {
|
|
24
|
+
const outcome = routeLine(line, tools);
|
|
25
|
+
if (outcome.kind === "ignore")
|
|
26
|
+
return;
|
|
27
|
+
if (outcome.kind === "reply") {
|
|
28
|
+
io.output.write(frame(outcome.response));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
await handleCall(outcome, io, runTool);
|
|
32
|
+
}
|
|
33
|
+
/** One tools/call, contained: whatever this call does, the loop survives it. */
|
|
34
|
+
async function handleCall(call, io, runTool) {
|
|
35
|
+
try {
|
|
36
|
+
const run = await runTool(call.argv);
|
|
37
|
+
if (run.stderr.trim() !== "") {
|
|
38
|
+
// A command's diagnostics are server-side logging, never protocol bytes.
|
|
39
|
+
io.log.write(`loam mcp: ${call.toolName} stderr: ${run.stderr.trim()}\n`);
|
|
40
|
+
}
|
|
41
|
+
const reply = toolReply(run);
|
|
42
|
+
io.output.write(frame(reply.kind === "result"
|
|
43
|
+
? resultResponse(call.id, reply.result)
|
|
44
|
+
: errorResponse(call.id, reply.code, reply.message)));
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
// The dispatcher already converts everything it can into an envelope, so
|
|
48
|
+
// reaching here means the failure was outside it (or in the wrapping
|
|
49
|
+
// itself). It becomes a JSON-RPC error for THIS id — the caller learns
|
|
50
|
+
// which call died, with the reason — and the loop reads the next frame.
|
|
51
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
52
|
+
io.output.write(frame(errorResponse(call.id, INTERNAL_ERROR, `${call.toolName} failed: ${detail}`)));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/commands/mcp/serve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The MCP stdio loop: read newline-delimited JSON-RPC frames from `input`,\n * answer on `output`, log on `log`. Streams are injected so the tests drive\n * a whole session in-process with PassThrough pairs; `loam mcp` passes the\n * real stdio triple.\n *\n * Two invariants everything else leans on:\n *\n * - `output` carries protocol frames and NOTHING else — every byte goes\n * through `frame()`. Command output cannot leak here: the dispatcher hooks\n * console and commander's own writers, and no command in src/ writes to\n * process.stdout directly (verified at implementation time; the dispatcher\n * comment records the guarantee it needs). Logging — the startup line, a\n * tool's captured stderr — goes to `log`, which MCP permits.\n *\n * - Frames are handled STRICTLY SEQUENTIALLY: each one is awaited before the\n * next is looked at. This is not an optimization opportunity — the\n * dispatcher's console capture is process-global, so two overlapping calls\n * would interleave their captured output into each other's envelopes.\n *\n * The loop ends when `input` ends: per the MCP stdio lifecycle the client\n * closes stdin to shut the server down, so EOF resolves this promise, the\n * action resolves, and cli.ts — the only process-exit decider — lets the\n * process drain to exit 0. No signal handling, no exit call here.\n */\nimport type { Readable, Writable } from \"node:stream\";\nimport { frame, splitFrames } from \"../../core/mcp/framing.js\";\nimport {\n INTERNAL_ERROR,\n errorResponse,\n resultResponse,\n routeLine,\n toolReply,\n} from \"../../core/mcp/protocol.js\";\nimport type { RouteOutcome, ToolRunOutcome } from \"../../core/mcp/protocol.js\";\nimport { MCP_TOOLS, type McpTool } from \"../../core/mcp/tools.js\";\n\nexport interface ServeIo {\n readonly input: Readable;\n readonly output: Writable;\n readonly log: Writable;\n}\n\n/** The dispatcher, as a parameter: serve() stays testable with a stub and owns no registration. */\nexport type ToolRunner = (argv: readonly string[]) => Promise<ToolRunOutcome>;\n\nexport async function serve(\n io: ServeIo,\n runTool: ToolRunner,\n tools: readonly McpTool[] = MCP_TOOLS,\n): Promise<void> {\n // One startup line, to stderr only — a client is entitled to a stdout that\n // has never carried anything but frames, from the very first byte.\n io.log.write(`loam mcp: serving ${process.cwd()} over stdio\\n`);\n // Decode at the stream, not per chunk: a UTF-8 code point split across two\n // chunks would corrupt if each chunk were stringified on its own.\n io.input.setEncoding(\"utf8\");\n let rest = \"\";\n for await (const chunk of io.input) {\n const split = splitFrames(rest + String(chunk));\n rest = split.rest;\n for (const line of split.lines) await handleLine(line, io, runTool, tools);\n }\n // A final frame the client sent without a trailing newline is still a frame:\n // EOF terminates it exactly as the delimiter would have.\n if (rest.trim() !== \"\") await handleLine(rest, io, runTool, tools);\n}\n\nasync function handleLine(\n line: string,\n io: ServeIo,\n runTool: ToolRunner,\n tools: readonly McpTool[],\n): Promise<void> {\n const outcome: RouteOutcome = routeLine(line, tools);\n if (outcome.kind === \"ignore\") return;\n if (outcome.kind === \"reply\") {\n io.output.write(frame(outcome.response));\n return;\n }\n await handleCall(outcome, io, runTool);\n}\n\n/** One tools/call, contained: whatever this call does, the loop survives it. */\nasync function handleCall(\n call: Extract<RouteOutcome, { kind: \"call\" }>,\n io: ServeIo,\n runTool: ToolRunner,\n): Promise<void> {\n try {\n const run = await runTool(call.argv);\n if (run.stderr.trim() !== \"\") {\n // A command's diagnostics are server-side logging, never protocol bytes.\n io.log.write(`loam mcp: ${call.toolName} stderr: ${run.stderr.trim()}\\n`);\n }\n const reply = toolReply(run);\n io.output.write(frame(\n reply.kind === \"result\"\n ? resultResponse(call.id, reply.result)\n : errorResponse(call.id, reply.code, reply.message),\n ));\n } catch (err) {\n // The dispatcher already converts everything it can into an envelope, so\n // reaching here means the failure was outside it (or in the wrapping\n // itself). It becomes a JSON-RPC error for THIS id — the caller learns\n // which call died, with the reason — and the loop reads the next frame.\n const detail = err instanceof Error ? err.message : String(err);\n io.output.write(frame(errorResponse(call.id, INTERNAL_ERROR, `${call.toolName} failed: ${detail}`)));\n }\n}\n"]}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Each active OpenSpec change as a staged loam feature: its intent, the
|
|
3
|
+
* authored artifacts a disposition kept, a verbatim copy of the source change
|
|
4
|
+
* tree, and one delta `spec.md` per service its requirements routed to.
|
|
5
|
+
*
|
|
6
|
+
* This is the phase that resolves RENAMED pairs, and the reason it is the
|
|
7
|
+
* longest: a rename is the only place where the living corpus, the delta and
|
|
8
|
+
* the human's identity decision all have to agree, and every disagreement
|
|
9
|
+
* between them is a refusal rather than a guess. `./feature.js` holds the file
|
|
10
|
+
* shapes this emits; `./living.js` is the same corpus read for the other half.
|
|
11
|
+
*/
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { openspecRequirements } from "../../../core/openspec/scan/shape.js";
|
|
14
|
+
import {} from "../../../core/document/spec.js";
|
|
15
|
+
import { ownValue } from "../../../core/kernel/records.js";
|
|
16
|
+
import {} from "../../../core/openspec/model/mapping.js";
|
|
17
|
+
import { isOpenSpecArtifactDisposition } from "../../../core/openspec/model/model.js";
|
|
18
|
+
import { planWrite } from "../../../core/staging/writes.js";
|
|
19
|
+
import { selectedServices } from "../openspec/decisions.js";
|
|
20
|
+
import { OpenSpecCommandError } from "../openspec/error.js";
|
|
21
|
+
import { safeArtifactRelative } from "../openspec/paths.js";
|
|
22
|
+
import { readSourceArtifact } from "../openspec/read.js";
|
|
23
|
+
import { featureSlug, migrationFrontmatter, renderAuthoredBundle, serializeDeltaRequirements, } from "./feature.js";
|
|
24
|
+
import { assertMaterializedRequirementIds, requirementWithCapability } from "./stage.js";
|
|
25
|
+
function isSettled(rename) {
|
|
26
|
+
return rename.from !== null && rename.to !== null && rename.requirementId !== null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A settled rename staged as the MODIFIED requirement it becomes: the new
|
|
30
|
+
* heading under the settled id, annotated once with the living requirement it
|
|
31
|
+
* renames. One construction for both places a rename materializes — over the
|
|
32
|
+
* delta's own MODIFIED body (already that kind, so the `kind` here changes
|
|
33
|
+
* nothing), and over the living requirement when the delta restates none.
|
|
34
|
+
*/
|
|
35
|
+
function renamedAsModified(base, rename) {
|
|
36
|
+
const annotation = `OpenSpec-Living-Source: ${rename.capability} :: ${rename.from}`;
|
|
37
|
+
return {
|
|
38
|
+
...base,
|
|
39
|
+
kind: "MODIFIED",
|
|
40
|
+
id: rename.requirementId,
|
|
41
|
+
name: rename.to,
|
|
42
|
+
text: base.text.includes(annotation) ? base.text : [...base.text, "", annotation],
|
|
43
|
+
section: "## MODIFIED Requirements",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export async function materializeActiveChanges(inventory, mapping, target, livingByCapability) {
|
|
47
|
+
const writes = [];
|
|
48
|
+
const inventoryArtifactsByPath = new Map(inventory.artifacts.map((artifact) => [artifact.path, artifact]));
|
|
49
|
+
for (const change of inventory.changes.active) {
|
|
50
|
+
const decision = inventory.changeDecisions.find((item) => item.change === change.id);
|
|
51
|
+
const feature = ownValue(mapping.changes, change.id)?.feature ?? null;
|
|
52
|
+
if (decision === undefined || feature === null)
|
|
53
|
+
continue; // readiness prevents this on --apply
|
|
54
|
+
const featureDir = join(target, "features", `${feature}-${featureSlug(decision.title, change.id)}`);
|
|
55
|
+
// Preserve the complete authored source change tree, including metadata,
|
|
56
|
+
// rename syntax, custom artifacts, and original delta section ordering.
|
|
57
|
+
for (const artifactPath of change.artifacts) {
|
|
58
|
+
const segments = safeArtifactRelative(artifactPath, `changes/${change.id}/`, `OpenSpec change '${change.id}'`);
|
|
59
|
+
writes.push(planWrite(join(featureDir, "legacy", "openspec", ...segments), await readSourceArtifact(inventory.root, artifactPath)));
|
|
60
|
+
}
|
|
61
|
+
const authored = [];
|
|
62
|
+
for (const artifactDecision of inventory.artifactDecisions) {
|
|
63
|
+
const artifact = inventoryArtifactsByPath.get(artifactDecision.path);
|
|
64
|
+
if (artifact?.changeId !== change.id)
|
|
65
|
+
continue;
|
|
66
|
+
const disposition = ownValue(mapping.artifacts, artifactDecision.path);
|
|
67
|
+
if (disposition === undefined)
|
|
68
|
+
continue; // readiness prevents this on --apply
|
|
69
|
+
// The mapping holds the authored string; everything below compares it
|
|
70
|
+
// against disposition literals, so this is where the value has to become
|
|
71
|
+
// one of them or stop being routed. `mapping.invalid-artifact-disposition`
|
|
72
|
+
// already refuses an unknown one, so readiness prevents this too — but a
|
|
73
|
+
// silent skip is the right failure for a value nothing here can act on.
|
|
74
|
+
if (!isOpenSpecArtifactDisposition(disposition))
|
|
75
|
+
continue;
|
|
76
|
+
authored.push({
|
|
77
|
+
path: artifactDecision.path,
|
|
78
|
+
kind: artifactDecision.kind,
|
|
79
|
+
disposition,
|
|
80
|
+
raw: await readSourceArtifact(inventory.root, artifactDecision.path),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const convertedProposals = authored.filter((artifact) => artifact.kind === "proposal" && artifact.disposition === "convert-to-intent");
|
|
84
|
+
const retainedProposals = authored.filter((artifact) => artifact.kind === "proposal" && artifact.disposition !== "convert-to-intent");
|
|
85
|
+
const intentBody = convertedProposals.length > 0
|
|
86
|
+
? renderAuthoredBundle("## Migrated OpenSpec proposal", convertedProposals)
|
|
87
|
+
: "No proposal was converted into this intent. Review the retained OpenSpec artifacts and migration-plan.json before promotion.\n";
|
|
88
|
+
writes.push(planWrite(join(featureDir, "intent.md"), `${migrationFrontmatter(feature, decision.title)}\n\n# ${decision.title}\n\n<!-- Staged from OpenSpec change '${change.id}'. This feature is deliberately not validation-green yet. -->\n\n${intentBody}`));
|
|
89
|
+
if (retainedProposals.length > 0) {
|
|
90
|
+
writes.push(planWrite(join(featureDir, "legacy", "proposal.md"), renderAuthoredBundle("# Retained OpenSpec proposal", retainedProposals)));
|
|
91
|
+
}
|
|
92
|
+
const tasks = authored.filter((artifact) => artifact.kind === "tasks");
|
|
93
|
+
if (tasks.length > 0) {
|
|
94
|
+
writes.push(planWrite(join(featureDir, "legacy", "tasks.md"), renderAuthoredBundle("# OpenSpec task checklist", tasks)));
|
|
95
|
+
}
|
|
96
|
+
const reviewedDesigns = authored.filter((artifact) => artifact.kind === "change-design" && artifact.disposition === "review-as-feature-adr");
|
|
97
|
+
if (reviewedDesigns.length > 0) {
|
|
98
|
+
writes.push(planWrite(join(featureDir, "adrs", "openspec-design.md"), renderAuthoredBundle("# OpenSpec design (review required)", reviewedDesigns)));
|
|
99
|
+
}
|
|
100
|
+
const retainedDesigns = authored.filter((artifact) => artifact.kind === "change-design" && artifact.disposition !== "review-as-feature-adr");
|
|
101
|
+
if (retainedDesigns.length > 0) {
|
|
102
|
+
writes.push(planWrite(join(featureDir, "legacy", "design.md"), renderAuthoredBundle("# Retained OpenSpec design", retainedDesigns)));
|
|
103
|
+
}
|
|
104
|
+
if (change.metadata.skipSpecs)
|
|
105
|
+
continue;
|
|
106
|
+
const deltaByService = new Map();
|
|
107
|
+
const changeRenames = inventory.renamed.filter((item) => item.scope === "active" && item.changeId === change.id);
|
|
108
|
+
const materializedRenameKeys = new Set();
|
|
109
|
+
const addDelta = (service, requirement, origin) => {
|
|
110
|
+
const existing = deltaByService.get(service) ?? [];
|
|
111
|
+
const collision = existing.find((item) => item.name === requirement.name
|
|
112
|
+
|| (item.id !== undefined && requirement.id !== undefined && item.id === requirement.id));
|
|
113
|
+
if (collision !== undefined) {
|
|
114
|
+
const identity = requirement.id === undefined ? requirement.name : requirement.id;
|
|
115
|
+
throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' produces colliding requirement '${identity}' in service '${service}' while materializing ${origin}.`);
|
|
116
|
+
}
|
|
117
|
+
existing.push(requirement);
|
|
118
|
+
deltaByService.set(service, existing);
|
|
119
|
+
};
|
|
120
|
+
for (const spec of change.specs) {
|
|
121
|
+
const requirements = openspecRequirements(await readSourceArtifact(inventory.root, spec.path))
|
|
122
|
+
.filter((requirement) => requirement.kind !== "BASE");
|
|
123
|
+
for (const parsed of requirements) {
|
|
124
|
+
const matchingRenames = changeRenames.filter((rename) => rename.capability === spec.capability
|
|
125
|
+
&& rename.from !== null
|
|
126
|
+
&& rename.to !== null
|
|
127
|
+
&& (parsed.name === rename.from || parsed.name === rename.to));
|
|
128
|
+
if (matchingRenames.length > 1) {
|
|
129
|
+
throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' requirement '${parsed.name}' matches multiple RENAMED pairs.`);
|
|
130
|
+
}
|
|
131
|
+
const rename = matchingRenames[0];
|
|
132
|
+
let requirement = parsed;
|
|
133
|
+
let routingName = parsed.name;
|
|
134
|
+
if (rename !== undefined && isSettled(rename)) {
|
|
135
|
+
if (parsed.kind !== "MODIFIED") {
|
|
136
|
+
throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' combines RENAMED '${rename.from}' → '${rename.to}' with ${parsed.kind} '${parsed.name}'; review the conflicting delta before --apply.`);
|
|
137
|
+
}
|
|
138
|
+
if (parsed.id !== undefined && parsed.id !== rename.requirementId) {
|
|
139
|
+
throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' MODIFIED requirement '${parsed.name}' has Requirement-ID '${parsed.id}', but its RENAMED source resolves to '${rename.requirementId}'.`);
|
|
140
|
+
}
|
|
141
|
+
requirement = renamedAsModified(parsed, rename);
|
|
142
|
+
routingName = rename.from;
|
|
143
|
+
materializedRenameKeys.add(rename.key);
|
|
144
|
+
}
|
|
145
|
+
// Every delta kind uniformly: REMOVED is harmless (every check exempts
|
|
146
|
+
// it), and a MODIFIED body MUST carry the line or its wholesale
|
|
147
|
+
// replace would strip the one the living side was staged with.
|
|
148
|
+
const withCapability = requirementWithCapability(requirement, spec.capability);
|
|
149
|
+
for (const service of selectedServices(mapping, spec.capability, routingName)) {
|
|
150
|
+
addDelta(service, withCapability, spec.path);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const rename of changeRenames) {
|
|
155
|
+
if (materializedRenameKeys.has(rename.key))
|
|
156
|
+
continue;
|
|
157
|
+
if (!isSettled(rename))
|
|
158
|
+
continue;
|
|
159
|
+
const source = (livingByCapability.get(rename.capability) ?? [])
|
|
160
|
+
.filter((requirement) => requirement.name === rename.from)[0];
|
|
161
|
+
if (source === undefined)
|
|
162
|
+
continue; // readiness prevents this on --apply
|
|
163
|
+
const modified = renamedAsModified(source, rename);
|
|
164
|
+
for (const service of selectedServices(mapping, rename.capability, rename.from)) {
|
|
165
|
+
addDelta(service, requirementWithCapability(modified, rename.capability), rename.path);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const [service, requirements] of [...deltaByService].sort(([a], [b]) => a.localeCompare(b))) {
|
|
169
|
+
assertMaterializedRequirementIds(`Active change '${change.id}' mapped to service '${service}'`, requirements);
|
|
170
|
+
writes.push(planWrite(join(featureDir, "specs", service, "spec.md"), serializeDeltaRequirements(requirements)));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return writes;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=active.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active.js","sourceRoot":"","sources":["../../../../src/commands/migrate-openspec/materialize/active.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Each active OpenSpec change as a staged loam feature: its intent, the\n * authored artifacts a disposition kept, a verbatim copy of the source change\n * tree, and one delta `spec.md` per service its requirements routed to.\n *\n * This is the phase that resolves RENAMED pairs, and the reason it is the\n * longest: a rename is the only place where the living corpus, the delta and\n * the human's identity decision all have to agree, and every disagreement\n * between them is a refusal rather than a guess. `./feature.js` holds the file\n * shapes this emits; `./living.js` is the same corpus read for the other half.\n */\nimport { join } from \"node:path\";\nimport { openspecRequirements } from \"../../../core/openspec/scan/shape.js\";\nimport { type Requirement } from \"../../../core/document/spec.js\";\nimport { ownValue } from \"../../../core/kernel/records.js\";\nimport { type OpenSpecMapping } from \"../../../core/openspec/model/mapping.js\";\nimport { isOpenSpecArtifactDisposition, type OpenSpecInventory, type OpenSpecRenamedUsage } from \"../../../core/openspec/model/model.js\";\nimport { planWrite, type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport { selectedServices } from \"../openspec/decisions.js\";\nimport { OpenSpecCommandError } from \"../openspec/error.js\";\nimport { safeArtifactRelative } from \"../openspec/paths.js\";\nimport { readSourceArtifact } from \"../openspec/read.js\";\nimport {\n featureSlug,\n migrationFrontmatter,\n renderAuthoredBundle,\n serializeDeltaRequirements,\n type AuthoredArtifactCopy,\n} from \"./feature.js\";\nimport { assertMaterializedRequirementIds, requirementWithCapability } from \"./stage.js\";\n\n/** A RENAMED pair whose two headings and settled identity are all known — the only kind that materializes. */\ntype SettledRename = OpenSpecRenamedUsage & { from: string; to: string; requirementId: string };\n\nfunction isSettled(rename: OpenSpecRenamedUsage): rename is SettledRename {\n return rename.from !== null && rename.to !== null && rename.requirementId !== null;\n}\n\n/**\n * A settled rename staged as the MODIFIED requirement it becomes: the new\n * heading under the settled id, annotated once with the living requirement it\n * renames. One construction for both places a rename materializes — over the\n * delta's own MODIFIED body (already that kind, so the `kind` here changes\n * nothing), and over the living requirement when the delta restates none.\n */\nfunction renamedAsModified(base: Requirement, rename: SettledRename): Requirement {\n const annotation = `OpenSpec-Living-Source: ${rename.capability} :: ${rename.from}`;\n return {\n ...base,\n kind: \"MODIFIED\",\n id: rename.requirementId,\n name: rename.to,\n text: base.text.includes(annotation) ? base.text : [...base.text, \"\", annotation],\n section: \"## MODIFIED Requirements\",\n };\n}\n\nexport async function materializeActiveChanges(\n inventory: OpenSpecInventory,\n mapping: OpenSpecMapping,\n target: string,\n livingByCapability: ReadonlyMap<string, Requirement[]>,\n): Promise<PlannedWrite[]> {\n const writes: PlannedWrite[] = [];\n const inventoryArtifactsByPath = new Map(inventory.artifacts.map((artifact) => [artifact.path, artifact]));\n\n for (const change of inventory.changes.active) {\n const decision = inventory.changeDecisions.find((item) => item.change === change.id);\n const feature = ownValue(mapping.changes, change.id)?.feature ?? null;\n if (decision === undefined || feature === null) continue; // readiness prevents this on --apply\n const featureDir = join(target, \"features\", `${feature}-${featureSlug(decision.title, change.id)}`);\n\n // Preserve the complete authored source change tree, including metadata,\n // rename syntax, custom artifacts, and original delta section ordering.\n for (const artifactPath of change.artifacts) {\n const segments = safeArtifactRelative(artifactPath, `changes/${change.id}/`, `OpenSpec change '${change.id}'`);\n writes.push(planWrite(\n join(featureDir, \"legacy\", \"openspec\", ...segments),\n await readSourceArtifact(inventory.root, artifactPath),\n ));\n }\n\n const authored: Array<AuthoredArtifactCopy & { kind: \"proposal\" | \"tasks\" | \"change-design\" }> = [];\n for (const artifactDecision of inventory.artifactDecisions) {\n const artifact = inventoryArtifactsByPath.get(artifactDecision.path);\n if (artifact?.changeId !== change.id) continue;\n const disposition = ownValue(mapping.artifacts, artifactDecision.path);\n if (disposition === undefined) continue; // readiness prevents this on --apply\n // The mapping holds the authored string; everything below compares it\n // against disposition literals, so this is where the value has to become\n // one of them or stop being routed. `mapping.invalid-artifact-disposition`\n // already refuses an unknown one, so readiness prevents this too — but a\n // silent skip is the right failure for a value nothing here can act on.\n if (!isOpenSpecArtifactDisposition(disposition)) continue;\n authored.push({\n path: artifactDecision.path,\n kind: artifactDecision.kind,\n disposition,\n raw: await readSourceArtifact(inventory.root, artifactDecision.path),\n });\n }\n\n const convertedProposals = authored.filter(\n (artifact) => artifact.kind === \"proposal\" && artifact.disposition === \"convert-to-intent\",\n );\n const retainedProposals = authored.filter(\n (artifact) => artifact.kind === \"proposal\" && artifact.disposition !== \"convert-to-intent\",\n );\n const intentBody = convertedProposals.length > 0\n ? renderAuthoredBundle(\"## Migrated OpenSpec proposal\", convertedProposals)\n : \"No proposal was converted into this intent. Review the retained OpenSpec artifacts and migration-plan.json before promotion.\\n\";\n writes.push(planWrite(\n join(featureDir, \"intent.md\"),\n `${migrationFrontmatter(feature, decision.title)}\\n\\n# ${decision.title}\\n\\n<!-- Staged from OpenSpec change '${change.id}'. This feature is deliberately not validation-green yet. -->\\n\\n${intentBody}`,\n ));\n if (retainedProposals.length > 0) {\n writes.push(planWrite(\n join(featureDir, \"legacy\", \"proposal.md\"),\n renderAuthoredBundle(\"# Retained OpenSpec proposal\", retainedProposals),\n ));\n }\n\n const tasks = authored.filter((artifact) => artifact.kind === \"tasks\");\n if (tasks.length > 0) {\n writes.push(planWrite(\n join(featureDir, \"legacy\", \"tasks.md\"),\n renderAuthoredBundle(\"# OpenSpec task checklist\", tasks),\n ));\n }\n const reviewedDesigns = authored.filter(\n (artifact) => artifact.kind === \"change-design\" && artifact.disposition === \"review-as-feature-adr\",\n );\n if (reviewedDesigns.length > 0) {\n writes.push(planWrite(\n join(featureDir, \"adrs\", \"openspec-design.md\"),\n renderAuthoredBundle(\"# OpenSpec design (review required)\", reviewedDesigns),\n ));\n }\n const retainedDesigns = authored.filter(\n (artifact) => artifact.kind === \"change-design\" && artifact.disposition !== \"review-as-feature-adr\",\n );\n if (retainedDesigns.length > 0) {\n writes.push(planWrite(\n join(featureDir, \"legacy\", \"design.md\"),\n renderAuthoredBundle(\"# Retained OpenSpec design\", retainedDesigns),\n ));\n }\n\n if (change.metadata.skipSpecs) continue;\n const deltaByService = new Map<string, Requirement[]>();\n const changeRenames = inventory.renamed.filter(\n (item) => item.scope === \"active\" && item.changeId === change.id,\n );\n const materializedRenameKeys = new Set<string>();\n const addDelta = (service: string, requirement: Requirement, origin: string): void => {\n const existing = deltaByService.get(service) ?? [];\n const collision = existing.find((item) =>\n item.name === requirement.name\n || (item.id !== undefined && requirement.id !== undefined && item.id === requirement.id));\n if (collision !== undefined) {\n const identity = requirement.id === undefined ? requirement.name : requirement.id;\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Active change '${change.id}' produces colliding requirement '${identity}' in service '${service}' while materializing ${origin}.`,\n );\n }\n existing.push(requirement);\n deltaByService.set(service, existing);\n };\n\n for (const spec of change.specs) {\n const requirements = openspecRequirements(await readSourceArtifact(inventory.root, spec.path))\n .filter((requirement) => requirement.kind !== \"BASE\");\n for (const parsed of requirements) {\n const matchingRenames = changeRenames.filter((rename) =>\n rename.capability === spec.capability\n && rename.from !== null\n && rename.to !== null\n && (parsed.name === rename.from || parsed.name === rename.to));\n if (matchingRenames.length > 1) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Active change '${change.id}' requirement '${parsed.name}' matches multiple RENAMED pairs.`,\n );\n }\n const rename = matchingRenames[0];\n let requirement = parsed;\n let routingName = parsed.name;\n if (rename !== undefined && isSettled(rename)) {\n if (parsed.kind !== \"MODIFIED\") {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Active change '${change.id}' combines RENAMED '${rename.from}' → '${rename.to}' with ${parsed.kind} '${parsed.name}'; review the conflicting delta before --apply.`,\n );\n }\n if (parsed.id !== undefined && parsed.id !== rename.requirementId) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Active change '${change.id}' MODIFIED requirement '${parsed.name}' has Requirement-ID '${parsed.id}', but its RENAMED source resolves to '${rename.requirementId}'.`,\n );\n }\n requirement = renamedAsModified(parsed, rename);\n routingName = rename.from;\n materializedRenameKeys.add(rename.key);\n }\n // Every delta kind uniformly: REMOVED is harmless (every check exempts\n // it), and a MODIFIED body MUST carry the line or its wholesale\n // replace would strip the one the living side was staged with.\n const withCapability = requirementWithCapability(requirement, spec.capability);\n for (const service of selectedServices(mapping, spec.capability, routingName)) {\n addDelta(service, withCapability, spec.path);\n }\n }\n }\n for (const rename of changeRenames) {\n if (materializedRenameKeys.has(rename.key)) continue;\n if (!isSettled(rename)) continue;\n const source = (livingByCapability.get(rename.capability) ?? [])\n .filter((requirement) => requirement.name === rename.from)[0];\n if (source === undefined) continue; // readiness prevents this on --apply\n const modified = renamedAsModified(source, rename);\n for (const service of selectedServices(mapping, rename.capability, rename.from)) {\n addDelta(service, requirementWithCapability(modified, rename.capability), rename.path);\n }\n }\n for (const [service, requirements] of [...deltaByService].sort(([a], [b]) => a.localeCompare(b))) {\n assertMaterializedRequirementIds(\n `Active change '${change.id}' mapped to service '${service}'`,\n requirements,\n );\n writes.push(planWrite(\n join(featureDir, \"specs\", service, \"spec.md\"),\n serializeDeltaRequirements(requirements),\n ));\n }\n }\n return writes;\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes a staged feature is written in: its directory slug, its
|
|
3
|
+
* frontmatter, the delta spec body, and the bundle an authored OpenSpec
|
|
4
|
+
* artifact is copied into.
|
|
5
|
+
*
|
|
6
|
+
* All four are used by `./active.js` alone, and they are here rather than
|
|
7
|
+
* inside it because they are the part a reviewer compares against the migrated
|
|
8
|
+
* repository by eye. What routes a requirement to a service is a decision;
|
|
9
|
+
* these are the file formats that decision comes out as, and the two answer to
|
|
10
|
+
* different questions when a migration reads wrong.
|
|
11
|
+
*/
|
|
12
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
13
|
+
import { serializeRequirements } from "../../../core/document/spec.js";
|
|
14
|
+
import {} from "../../../core/document/spec.js";
|
|
15
|
+
import {} from "../../../core/openspec/model/model.js";
|
|
16
|
+
export function featureSlug(title, changeId) {
|
|
17
|
+
const slug = (text) => text
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
20
|
+
.replace(/^-+|-+$/g, "");
|
|
21
|
+
return slug(title) || slug(changeId) || "openspec-change";
|
|
22
|
+
}
|
|
23
|
+
export function serializeDeltaRequirements(requirements) {
|
|
24
|
+
const sections = [];
|
|
25
|
+
for (const kind of ["ADDED", "MODIFIED", "REMOVED"]) {
|
|
26
|
+
const group = requirements.filter((requirement) => requirement.kind === kind);
|
|
27
|
+
if (group.length > 0)
|
|
28
|
+
sections.push(`## ${kind} Requirements\n\n${serializeRequirements(group).trimEnd()}`);
|
|
29
|
+
}
|
|
30
|
+
return `${sections.join("\n\n")}\n`;
|
|
31
|
+
}
|
|
32
|
+
export function migrationFrontmatter(feature, title) {
|
|
33
|
+
return `---\n${stringifyYaml({ feature, title, status: "proposed" }, { lineWidth: 0 }).trimEnd()}\n---`;
|
|
34
|
+
}
|
|
35
|
+
export function renderAuthoredBundle(heading, artifacts) {
|
|
36
|
+
return `${heading}\n\n${artifacts.map((artifact) => [
|
|
37
|
+
`<!-- OpenSpec source: ${artifact.path}; disposition: ${artifact.disposition}. -->`,
|
|
38
|
+
artifact.raw.trimEnd(),
|
|
39
|
+
].join("\n\n")).join("\n\n---\n\n")}\n`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../../src/commands/migrate-openspec/materialize/feature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAoB,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAoC,MAAM,uCAAuC,CAAC;AAEzF,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,QAAgB;IACzD,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI;SACxC,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,YAA2B;IACpE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC9E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,oBAAoB,qBAAqB,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9G,CAAC;IACD,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,KAAa;IACjE,OAAO,QAAQ,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;AAC1G,CAAC;AAQD,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,SAAiC;IACrF,OAAO,GAAG,OAAO,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;QAClD,yBAAyB,QAAQ,CAAC,IAAI,kBAAkB,QAAQ,CAAC,WAAW,OAAO;QACnF,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;KACvB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * The shapes a staged feature is written in: its directory slug, its\n * frontmatter, the delta spec body, and the bundle an authored OpenSpec\n * artifact is copied into.\n *\n * All four are used by `./active.js` alone, and they are here rather than\n * inside it because they are the part a reviewer compares against the migrated\n * repository by eye. What routes a requirement to a service is a decision;\n * these are the file formats that decision comes out as, and the two answer to\n * different questions when a migration reads wrong.\n */\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { serializeRequirements } from \"../../../core/document/spec.js\";\nimport { type Requirement } from \"../../../core/document/spec.js\";\nimport { type OpenSpecArtifactDisposition } from \"../../../core/openspec/model/model.js\";\n\nexport function featureSlug(title: string, changeId: string): string {\n const slug = (text: string): string => text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return slug(title) || slug(changeId) || \"openspec-change\";\n}\n\nexport function serializeDeltaRequirements(requirements: Requirement[]): string {\n const sections: string[] = [];\n for (const kind of [\"ADDED\", \"MODIFIED\", \"REMOVED\"] as const) {\n const group = requirements.filter((requirement) => requirement.kind === kind);\n if (group.length > 0) sections.push(`## ${kind} Requirements\\n\\n${serializeRequirements(group).trimEnd()}`);\n }\n return `${sections.join(\"\\n\\n\")}\\n`;\n}\n\nexport function migrationFrontmatter(feature: string, title: string): string {\n return `---\\n${stringifyYaml({ feature, title, status: \"proposed\" }, { lineWidth: 0 }).trimEnd()}\\n---`;\n}\n\nexport interface AuthoredArtifactCopy {\n path: string;\n disposition: OpenSpecArtifactDisposition;\n raw: string;\n}\n\nexport function renderAuthoredBundle(heading: string, artifacts: AuthoredArtifactCopy[]): string {\n return `${heading}\\n\\n${artifacts.map((artifact) => [\n `<!-- OpenSpec source: ${artifact.path}; disposition: ${artifact.disposition}. -->`,\n artifact.raw.trimEnd(),\n ].join(\"\\n\\n\")).join(\"\\n\\n---\\n\\n\")}\\n`;\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The living OpenSpec corpus as draft loam service specs — one `spec.md` per
|
|
3
|
+
* service a capability was routed to.
|
|
4
|
+
*
|
|
5
|
+
* Separate from `./active.js` because the two materialize different documents
|
|
6
|
+
* from the same corpus: this one emits BASE requirements a service owns, that
|
|
7
|
+
* one emits the ADDED/MODIFIED/REMOVED deltas a feature proposes. They share
|
|
8
|
+
* the routing rule (`../openspec/decisions.js`) and the spec guard
|
|
9
|
+
* (`./stage.js`) and nothing else, and keeping them apart is what stopped a
|
|
10
|
+
* rename resolved on one side from being written beside a spec built on the
|
|
11
|
+
* other.
|
|
12
|
+
*/
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
15
|
+
import { serializeRequirements } from "../../../core/document/spec.js";
|
|
16
|
+
import {} from "../../../core/document/spec.js";
|
|
17
|
+
import { ownValue } from "../../../core/kernel/records.js";
|
|
18
|
+
import {} from "../../../core/openspec/model/mapping.js";
|
|
19
|
+
import {} from "../../../core/openspec/model/model.js";
|
|
20
|
+
import { planWrite } from "../../../core/staging/writes.js";
|
|
21
|
+
import { selectedServices } from "../openspec/decisions.js";
|
|
22
|
+
import { OpenSpecCommandError } from "../openspec/error.js";
|
|
23
|
+
import { assertMaterializedRequirementIds, requirementWithCapability } from "./stage.js";
|
|
24
|
+
export async function materializeLivingSpecs(inventory, mapping, target, livingByCapability) {
|
|
25
|
+
const byService = new Map();
|
|
26
|
+
const renameIds = new Map(inventory.renamed
|
|
27
|
+
.filter((rename) => rename.scope === "active" && rename.from !== null && rename.requirementId !== null)
|
|
28
|
+
.map((rename) => [`${rename.capability}\0${rename.from}`, rename.requirementId]));
|
|
29
|
+
for (const capability of inventory.living.capabilities) {
|
|
30
|
+
const selected = ownValue(mapping.capabilities, capability.id);
|
|
31
|
+
if (selected === undefined)
|
|
32
|
+
continue; // readiness prevents this on --apply
|
|
33
|
+
for (const parsed of livingByCapability.get(capability.id) ?? []) {
|
|
34
|
+
const renamedId = renameIds.get(`${capability.id}\0${parsed.name}`);
|
|
35
|
+
const requirement = renamedId === undefined ? parsed : { ...parsed, id: renamedId };
|
|
36
|
+
// The one spelling of the routing rule, and the reason it lives in
|
|
37
|
+
// `../openspec/decisions.js` rather than here. Written out again here, it
|
|
38
|
+
// drifted from the copy the delta side uses, so a split capability could
|
|
39
|
+
// route a living requirement and its own delta to different services.
|
|
40
|
+
const services = selectedServices(mapping, capability.id, requirement.name);
|
|
41
|
+
for (const service of services) {
|
|
42
|
+
const existing = byService.get(service) ?? [];
|
|
43
|
+
const identity = requirement.id === undefined ? `heading '${requirement.name}'` : `Requirement-ID '${requirement.id}'`;
|
|
44
|
+
if (existing.some((item) => item.name === requirement.name
|
|
45
|
+
|| (item.id !== undefined && requirement.id !== undefined && item.id === requirement.id))) {
|
|
46
|
+
throw new OpenSpecCommandError("invalid-option", `Mapped living specs collide in service '${service}' on ${identity}; refine the capability/requirement allocation before --apply.`);
|
|
47
|
+
}
|
|
48
|
+
// The capability id rides every routed requirement as a `Capability:`
|
|
49
|
+
// line, declared in the staged architecture/capabilities.yaml (target.ts).
|
|
50
|
+
existing.push(requirementWithCapability({ ...requirement, kind: "BASE" }, capability.id));
|
|
51
|
+
byService.set(service, existing);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [...byService.entries()]
|
|
56
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
57
|
+
.map(([service, requirements]) => {
|
|
58
|
+
assertMaterializedRequirementIds(`Mapped living service '${service}'`, requirements);
|
|
59
|
+
return planWrite(join(target, "services", service, "spec.md"), `---\n${stringifyYaml({ service, status: "draft" }, { lineWidth: 0 }).trimEnd()}\n---\n\n# ${service}\n\n<!-- Staged from OpenSpec. Purpose/section prose and capability design.md are preserved verbatim under legacy/openspec/specs/. Add truthful sources and complete C4/OpenAPI links before validation/vouch. -->\n\n## Requirements\n\n${serializeRequirements(requirements)}`);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=living.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"living.js","sourceRoot":"","sources":["../../../../src/commands/migrate-openspec/materialize/living.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The living OpenSpec corpus as draft loam service specs — one `spec.md` per\n * service a capability was routed to.\n *\n * Separate from `./active.js` because the two materialize different documents\n * from the same corpus: this one emits BASE requirements a service owns, that\n * one emits the ADDED/MODIFIED/REMOVED deltas a feature proposes. They share\n * the routing rule (`../openspec/decisions.js`) and the spec guard\n * (`./stage.js`) and nothing else, and keeping them apart is what stopped a\n * rename resolved on one side from being written beside a spec built on the\n * other.\n */\nimport { join } from \"node:path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { serializeRequirements } from \"../../../core/document/spec.js\";\nimport { type Requirement } from \"../../../core/document/spec.js\";\nimport { ownValue } from \"../../../core/kernel/records.js\";\nimport { type OpenSpecMapping } from \"../../../core/openspec/model/mapping.js\";\nimport { type OpenSpecInventory } from \"../../../core/openspec/model/model.js\";\nimport { planWrite, type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport { selectedServices } from \"../openspec/decisions.js\";\nimport { OpenSpecCommandError } from \"../openspec/error.js\";\nimport { assertMaterializedRequirementIds, requirementWithCapability } from \"./stage.js\";\n\nexport async function materializeLivingSpecs(\n inventory: OpenSpecInventory,\n mapping: OpenSpecMapping,\n target: string,\n livingByCapability: ReadonlyMap<string, Requirement[]>,\n): Promise<PlannedWrite[]> {\n const byService = new Map<string, Requirement[]>();\n const renameIds = new Map(\n inventory.renamed\n .filter((rename) => rename.scope === \"active\" && rename.from !== null && rename.requirementId !== null)\n .map((rename) => [`${rename.capability}\\0${rename.from}`, rename.requirementId!] as const),\n );\n for (const capability of inventory.living.capabilities) {\n const selected = ownValue(mapping.capabilities, capability.id);\n if (selected === undefined) continue; // readiness prevents this on --apply\n for (const parsed of livingByCapability.get(capability.id) ?? []) {\n const renamedId = renameIds.get(`${capability.id}\\0${parsed.name}`);\n const requirement = renamedId === undefined ? parsed : { ...parsed, id: renamedId };\n // The one spelling of the routing rule, and the reason it lives in\n // `../openspec/decisions.js` rather than here. Written out again here, it\n // drifted from the copy the delta side uses, so a split capability could\n // route a living requirement and its own delta to different services.\n const services = selectedServices(mapping, capability.id, requirement.name);\n for (const service of services) {\n const existing = byService.get(service) ?? [];\n const identity = requirement.id === undefined ? `heading '${requirement.name}'` : `Requirement-ID '${requirement.id}'`;\n if (existing.some((item) =>\n item.name === requirement.name\n || (item.id !== undefined && requirement.id !== undefined && item.id === requirement.id))) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Mapped living specs collide in service '${service}' on ${identity}; refine the capability/requirement allocation before --apply.`,\n );\n }\n // The capability id rides every routed requirement as a `Capability:`\n // line, declared in the staged architecture/capabilities.yaml (target.ts).\n existing.push(requirementWithCapability({ ...requirement, kind: \"BASE\" }, capability.id));\n byService.set(service, existing);\n }\n }\n }\n return [...byService.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([service, requirements]) => {\n assertMaterializedRequirementIds(`Mapped living service '${service}'`, requirements);\n return planWrite(\n join(target, \"services\", service, \"spec.md\"),\n `---\\n${stringifyYaml({ service, status: \"draft\" }, { lineWidth: 0 }).trimEnd()}\\n---\\n\\n# ${service}\\n\\n<!-- Staged from OpenSpec. Purpose/section prose and capability design.md are preserved verbatim under legacy/openspec/specs/. Add truthful sources and complete C4/OpenAPI links before validation/vouch. -->\\n\\n## Requirements\\n\\n${serializeRequirements(requirements)}`,\n );\n });\n}\n"]}
|