@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,337 @@
|
|
|
1
|
+
import { parentIdOf } from "../../kernel/ids/fqn/ancestors.js";
|
|
2
|
+
import { errorText, loadSource } from "../likec4.js";
|
|
3
|
+
import { firstUnlocated, unlocatedReason } from "../locate/unlocated.js";
|
|
4
|
+
import { elementService, serviceOf } from "../resolve/service.js";
|
|
5
|
+
import { kindsDeclared, scanModel } from "../source-scan.js";
|
|
6
|
+
import { matchLineEndings, spliceSource } from "./authored-source.js";
|
|
7
|
+
import { assertSpliceVisible, LandscapeSpliceError, } from "./contract.js";
|
|
8
|
+
import { assertMergeableDelta } from "./delta-blocks.js";
|
|
9
|
+
import { relSortKey, relStatementKey, scannedStatementKey } from "./identity/edges.js";
|
|
10
|
+
import { newAdditions } from "./identity/existing.js";
|
|
11
|
+
import { planInteriors } from "./identity/interior.js";
|
|
12
|
+
import { ownerOf } from "./identity/owner.js";
|
|
13
|
+
import { elementSpot, relSpot, topStatements } from "./placement.js";
|
|
14
|
+
import { nestedInsert } from "./text/spot.js";
|
|
15
|
+
/* ------------------------------------------------------------------ */
|
|
16
|
+
/* Merging */
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
/**
|
|
19
|
+
* Plan the merge of the feature's new elements + relationships into the living
|
|
20
|
+
* landscape's `model { ... }` block (preserving the rest of the file).
|
|
21
|
+
*
|
|
22
|
+
* The additions are SPLICED from delta.likec4 as authored — byte for byte,
|
|
23
|
+
* technology, style, icons, links, metadata, nested children and all — never
|
|
24
|
+
* re-serialized from the parsed model: a rebuild keeps only the fields loam
|
|
25
|
+
* models, and every field it forgets is authored detail destroyed. The one
|
|
26
|
+
* edit on the way over is dropping the feature's own tag — the additions are
|
|
27
|
+
* baseline now (SCHEMA.md documents the drop as why unarchive restores bytes
|
|
28
|
+
* instead of recomputing) — and a construct the strip empties goes with it.
|
|
29
|
+
*
|
|
30
|
+
* Placement is deterministic and SERVICE-GROUPED (the spot* helpers in
|
|
31
|
+
* placement.ts):
|
|
32
|
+
* a top-level addition lands beside what already belongs to its service, so
|
|
33
|
+
* two concurrent archives touching different services usually splice on
|
|
34
|
+
* different lines and git merges their PRs — the single shared append point
|
|
35
|
+
* every archive used to hit made two concurrent archives conflict BY
|
|
36
|
+
* CONSTRUCTION. A NESTED element lands inside its parent's block — inside the
|
|
37
|
+
* living parent when the landscape already has it, riding verbatim inside the
|
|
38
|
+
* spliced parent when the parent is new from the same delta — never as a flat
|
|
39
|
+
* dotted id at top level, which LikeC4 rejects. The additions carry no marker
|
|
40
|
+
* comment: which archive added what is the git history's to say.
|
|
41
|
+
*
|
|
42
|
+
* Existence is checked semantically against the parsed landscape AND against
|
|
43
|
+
* every extending model the request carries (by element id/title and by edge
|
|
44
|
+
* identity), so re-archiving is idempotent whichever document the additions
|
|
45
|
+
* landed in — `./identity/existing.ts` holds that phase and its two joins, and
|
|
46
|
+
* this function only turns the collision it reports into the refusal.
|
|
47
|
+
*
|
|
48
|
+
* Splicing is text surgery, so the computed result is PARSED before it is
|
|
49
|
+
* returned: a merged landscape LikeC4 rejects refuses the archive at plan time
|
|
50
|
+
* (merge-failed, nothing written — the unparseable-delta discipline) instead
|
|
51
|
+
* of landing in the living docs.
|
|
52
|
+
*
|
|
53
|
+
* NOT EVERYTHING LANDS HERE. A service whose model EXTENDS this map owns its
|
|
54
|
+
* own interior, and an addition nested under such a service is ROUTED to that
|
|
55
|
+
* model instead (`./identity/owner.ts` decides, `./model/merge.ts` splices).
|
|
56
|
+
* Until it was, a delta's container landed in the map and the service was
|
|
57
|
+
* `c4.invalid` — a duplicate declaration — the moment its model wrote the same
|
|
58
|
+
* container, which is exactly what the adopt brief tells it to do
|
|
59
|
+
* (verification 2026-09-04, E1). With no extending models in the request this
|
|
60
|
+
* function behaves as it always did.
|
|
61
|
+
*
|
|
62
|
+
* Routing per ADDITION is not the whole of it, because a service the feature
|
|
63
|
+
* INTRODUCES carries its interior in one element's authored bytes and those
|
|
64
|
+
* children carry no feature tag of their own. `./identity/interior.ts` decides, once
|
|
65
|
+
* per such block, whether it hands that interior to the model — cut out of what
|
|
66
|
+
* lands on the map — or rides whole; the routing below DEFERS to that decision
|
|
67
|
+
* for everything written inside the block, which is what keeps the two from
|
|
68
|
+
* placing the same child twice.
|
|
69
|
+
*/
|
|
70
|
+
export async function planLandscapeMerge(merge) {
|
|
71
|
+
const { landscapeText: text, deltaText, deltaElements, newEls, newRels, featureId } = merge;
|
|
72
|
+
const models = merge.models ?? [];
|
|
73
|
+
// What every extending model borrows from this map: its kinds, without which
|
|
74
|
+
// a model's scan reads `container outbox` and `a .delivers b` as property lines.
|
|
75
|
+
const borrowed = kindsDeclared(text);
|
|
76
|
+
// First, and before the early return for "nothing to add": a block this merge
|
|
77
|
+
// cannot carry is lost whether or not the delta also has tagged elements to
|
|
78
|
+
// splice. See delta-blocks.ts.
|
|
79
|
+
assertMergeableDelta(deltaText);
|
|
80
|
+
const land = await loadSource(text);
|
|
81
|
+
if (land.errors.length > 0) {
|
|
82
|
+
throw new LandscapeSpliceError(`landscape.likec4 has ${land.errors.length} error(s) — fix it before archiving`);
|
|
83
|
+
}
|
|
84
|
+
// Service binding for the existence joins AND for routing and placement:
|
|
85
|
+
// living elements first (they win a shared id), the delta's after — a spliced
|
|
86
|
+
// statement's id resolves to its service the moment its bytes land in the scan.
|
|
87
|
+
const bindEls = [...land.elements, ...deltaElements.filter((d) => !land.elements.some((l) => l.id === d.id))];
|
|
88
|
+
// What the living fleet already has — the map AND every extending model, by id
|
|
89
|
+
// and by title. `./identity/existing.ts` holds both joins and their asymmetry.
|
|
90
|
+
const added = newAdditions({
|
|
91
|
+
livingEls: land.elements,
|
|
92
|
+
livingRels: land.relationships,
|
|
93
|
+
bindEls,
|
|
94
|
+
deltaElements,
|
|
95
|
+
candidates: { els: newEls, rels: newRels },
|
|
96
|
+
models,
|
|
97
|
+
borrowed,
|
|
98
|
+
});
|
|
99
|
+
if (added.collision !== undefined) {
|
|
100
|
+
const { addition: e, living: m } = added.collision;
|
|
101
|
+
throw new LandscapeSpliceError(`the delta's '${e.id}' (bound to service '${e.service}') shares the title '${e.title}' with '${m.id}' (bound to service '${m.service}') — a title join across services would silently drop the addition; ` +
|
|
102
|
+
`retitle one of them, or reuse the id '${m.id}' if they really are the same element`);
|
|
103
|
+
}
|
|
104
|
+
const addedEls = added.els;
|
|
105
|
+
const addedRels = added.rels;
|
|
106
|
+
const owner = ownerOf({
|
|
107
|
+
bindEls,
|
|
108
|
+
living: new Set(land.elements.map((e) => e.id)),
|
|
109
|
+
declared: added.declaredIds,
|
|
110
|
+
added: new Set(addedEls.map((e) => e.id)),
|
|
111
|
+
models,
|
|
112
|
+
});
|
|
113
|
+
// Nothing to add: the same shape the merge returned before routing existed,
|
|
114
|
+
// and the reason it is decided HERE rather than after the loops below — a
|
|
115
|
+
// no-op archive must not have to scan the delta, nor answer the landscape
|
|
116
|
+
// guards further down, which refuse documents this merge is not touching.
|
|
117
|
+
// Equivalent to the old "nothing reached the map and nothing was routed":
|
|
118
|
+
// every addition ends up in one of those two, so an empty pair means both.
|
|
119
|
+
if (addedEls.length === 0 && addedRels.length === 0) {
|
|
120
|
+
return { content: null, addedEls: [], addedRels: [], models: [] };
|
|
121
|
+
}
|
|
122
|
+
const scan = scanModel(deltaText);
|
|
123
|
+
if (scan === null) {
|
|
124
|
+
throw new LandscapeSpliceError("delta.likec4 has no model block — nothing to splice the additions from");
|
|
125
|
+
}
|
|
126
|
+
// Everything below either locates a declaration's authored bytes or refuses.
|
|
127
|
+
// `spliced` remembers the delta ranges already carried over, so a child whose
|
|
128
|
+
// parent is itself new is recognised as riding inside the parent's text and
|
|
129
|
+
// is never inserted twice.
|
|
130
|
+
const byId = new Map(scan.elements.map((e) => [e.id, e]));
|
|
131
|
+
// Relationships: match each parsed addition back to its statement in the
|
|
132
|
+
// delta source — full identity (`relStatementKey`), consumed one statement
|
|
133
|
+
// per addition so duplicates stay duplicates. Built before the routing
|
|
134
|
+
// because routing has to know WHERE an edge was written: one drawn inside a
|
|
135
|
+
// block that rides whole is already on the map. A statement is keyed with the
|
|
136
|
+
// tags its kind gives it, which the parsed addition carries and its text does not.
|
|
137
|
+
const pool = new Map();
|
|
138
|
+
for (const s of scan.rels) {
|
|
139
|
+
const k = scannedStatementKey(s, merge.deltaKindTags ?? {});
|
|
140
|
+
pool.set(k, [...(pool.get(k) ?? []), s]);
|
|
141
|
+
}
|
|
142
|
+
const interiors = planInteriors({ scan, deltaElements, owner, addedEls });
|
|
143
|
+
const routed = new Map();
|
|
144
|
+
const into = (model) => {
|
|
145
|
+
const existing = routed.get(model.path);
|
|
146
|
+
if (existing !== undefined)
|
|
147
|
+
return existing;
|
|
148
|
+
const fresh = { model, els: [], rels: [], borrowed };
|
|
149
|
+
routed.set(model.path, fresh);
|
|
150
|
+
return fresh;
|
|
151
|
+
};
|
|
152
|
+
for (const share of interiors.routed)
|
|
153
|
+
into(share.model).els.push(...share.els);
|
|
154
|
+
const mapEls = [];
|
|
155
|
+
for (const e of addedEls) {
|
|
156
|
+
const src = byId.get(e.id);
|
|
157
|
+
// Written inside a block that has already decided: a split block handed it
|
|
158
|
+
// to the model with its siblings, and a whole one carries it onto the map
|
|
159
|
+
// in the parent's own bytes, where the splice loop's `rides` finds it. Both
|
|
160
|
+
// are placed exactly once, which is the point of asking the block first.
|
|
161
|
+
const fate = src === undefined ? null : interiors.covering(src);
|
|
162
|
+
if (fate === "split")
|
|
163
|
+
continue;
|
|
164
|
+
const model = fate === "whole" ? undefined : owner(parentIdOf(e.id));
|
|
165
|
+
if (model === undefined)
|
|
166
|
+
mapEls.push(e);
|
|
167
|
+
else
|
|
168
|
+
into(model).els.push(e);
|
|
169
|
+
}
|
|
170
|
+
const mapRels = [];
|
|
171
|
+
for (const r of addedRels) {
|
|
172
|
+
// An edge written inside a block that rides whole names its endpoints by
|
|
173
|
+
// their LOCAL names and reads only there; it stays with its block.
|
|
174
|
+
const stmts = pool.get(relStatementKey(r)) ?? [];
|
|
175
|
+
const inBlock = stmts.length > 0 && stmts.every((s) => interiors.covering(s) !== null);
|
|
176
|
+
// Otherwise the SOURCE decides: a call is drawn where the caller draws its
|
|
177
|
+
// calls, and only when the source is not itself interior does the target's
|
|
178
|
+
// owner get the edge. A service-level edge belongs to neither and stays on
|
|
179
|
+
// the map.
|
|
180
|
+
const model = inBlock ? undefined : owner(parentIdOf(r.source)) ?? owner(parentIdOf(r.target));
|
|
181
|
+
if (model === undefined)
|
|
182
|
+
mapRels.push(r);
|
|
183
|
+
else
|
|
184
|
+
into(model).rels.push(r);
|
|
185
|
+
}
|
|
186
|
+
const touchesMap = mapEls.length > 0 || mapRels.length > 0;
|
|
187
|
+
const spliced = [];
|
|
188
|
+
const rides = (start, end) => spliced.some((r) => start >= r.start && end <= r.end);
|
|
189
|
+
// The living model, scanned on MASKED source (scanModel) and RE-SCANNED
|
|
190
|
+
// after every splice: each addition lands in the text exactly as the
|
|
191
|
+
// previous one left it, so an archive of N additions produces the same
|
|
192
|
+
// bytes as N single-addition archives run back to back. Placement then
|
|
193
|
+
// composes per statement — the unit the order-independence argument below
|
|
194
|
+
// is stated in — instead of per archive, where a batch computed against a
|
|
195
|
+
// stale layout could interleave with itself. Masking matters — a `model {`
|
|
196
|
+
// spelled inside a comment or string above the real block must not capture
|
|
197
|
+
// the match, or every top-level addition lands inside the comment (legal
|
|
198
|
+
// LikeC4, so the parse net below would pass a landscape containing none of
|
|
199
|
+
// the architecture).
|
|
200
|
+
let content = text;
|
|
201
|
+
let livingScan = scanModel(content);
|
|
202
|
+
let stmts = livingScan === null ? [] : topStatements(livingScan, bindEls);
|
|
203
|
+
const rescan = () => {
|
|
204
|
+
livingScan = scanModel(content);
|
|
205
|
+
stmts = livingScan === null ? [] : topStatements(livingScan, bindEls);
|
|
206
|
+
};
|
|
207
|
+
const requireModel = () => {
|
|
208
|
+
if (livingScan === null)
|
|
209
|
+
throw new LandscapeSpliceError("landscape.likec4 has no model block");
|
|
210
|
+
return livingScan;
|
|
211
|
+
};
|
|
212
|
+
// Built fresh at every use, never captured: `content` and `stmts` are rebound
|
|
213
|
+
// by each rescan, and a region assembled before a splice describes a document
|
|
214
|
+
// that no longer exists.
|
|
215
|
+
const modelRegion = () => ({ text: content, stmts, blocks: requireModel().blocks });
|
|
216
|
+
// Every insert must be one the next scan sees (`assertSpliceVisible`).
|
|
217
|
+
const applyAt = (at, insert, what) => {
|
|
218
|
+
const before = livingScan;
|
|
219
|
+
content = content.slice(0, at) + insert + content.slice(at);
|
|
220
|
+
rescan();
|
|
221
|
+
assertSpliceVisible(before, livingScan, what);
|
|
222
|
+
};
|
|
223
|
+
const applyTop = (spot, block, what) => {
|
|
224
|
+
// A bare spot shares its line with other text (the closing brace, or a
|
|
225
|
+
// statement the block displaces) — it brings its own newlines; a
|
|
226
|
+
// line-start spot slots between lines.
|
|
227
|
+
applyAt(spot.at, spot.bare ? `\n${block}\n` : `${block}\n`, what);
|
|
228
|
+
};
|
|
229
|
+
// Placement walks the scanned statement layout, so a declaration the scan
|
|
230
|
+
// cannot see is one placement would blindly splice around — LikeC4 accepts
|
|
231
|
+
// two declarations on one line, but scanModel's statement head runs to the
|
|
232
|
+
// end of the line, so the second rides invisibly inside the first: an
|
|
233
|
+
// element bound to its service would miss its neighborhood, and a bodyless
|
|
234
|
+
// parent gaining a body could wrap the wrong declaration. Refuse
|
|
235
|
+
// mechanically (the parse-net discipline) instead of splicing blind.
|
|
236
|
+
//
|
|
237
|
+
// THAT something is unlocated is decided here, from the parse already in
|
|
238
|
+
// hand; WHAT and why is `firstUnlocated`'s, at the price of a second parse on
|
|
239
|
+
// this path alone. The message used to guess "most often two declarations
|
|
240
|
+
// sharing one line" whatever the map held, and a fleet read it over a
|
|
241
|
+
// declaration on a line of its own in a second `model { }` block the scan
|
|
242
|
+
// did not read then (2026-10): it names LikeC4's line now, and a shared line
|
|
243
|
+
// only when that line shows one.
|
|
244
|
+
if (livingScan !== null) {
|
|
245
|
+
const seen = new Set(livingScan.elements.map((e) => e.id));
|
|
246
|
+
const blind = land.elements.some((e) => !seen.has(e.id)) || livingScan.rels.length < land.relationships.length;
|
|
247
|
+
if (blind)
|
|
248
|
+
throw new LandscapeSpliceError(unlocatedReason("landscape.likec4", await firstUnlocated(text, livingScan)));
|
|
249
|
+
}
|
|
250
|
+
const livingParentOf = (parentId) => {
|
|
251
|
+
if (livingScan === null)
|
|
252
|
+
return null;
|
|
253
|
+
const direct = livingScan.elements.find((e) => e.id === parentId);
|
|
254
|
+
if (direct !== undefined)
|
|
255
|
+
return direct;
|
|
256
|
+
// The delta may spell an existing element under its own id; the title is
|
|
257
|
+
// the stable cross-namespace name (the same rule the existence check uses).
|
|
258
|
+
const title = deltaElements.find((e) => e.id === parentId)?.title;
|
|
259
|
+
const livingId = title === undefined ? undefined : land.elements.find((e) => e.title === title)?.id;
|
|
260
|
+
if (livingId === undefined)
|
|
261
|
+
return null;
|
|
262
|
+
return livingScan.elements.find((e) => e.id === livingId) ?? null;
|
|
263
|
+
};
|
|
264
|
+
// Ancestors first: a spliced parent covers its children before they are seen.
|
|
265
|
+
const depth = (id) => id.split(".").length;
|
|
266
|
+
const sortedEls = [...mapEls].sort((a, b) => depth(a.id) - depth(b.id) || (byId.get(a.id)?.start ?? 0) - (byId.get(b.id)?.start ?? 0));
|
|
267
|
+
for (const e of sortedEls) {
|
|
268
|
+
const src = byId.get(e.id);
|
|
269
|
+
if (src === undefined) {
|
|
270
|
+
throw new LandscapeSpliceError(`cannot locate '${e.id}' in delta.likec4 — the landscape merge splices authored source, and this declaration was not found`);
|
|
271
|
+
}
|
|
272
|
+
if (rides(src.start, src.end))
|
|
273
|
+
continue;
|
|
274
|
+
// Every split block's children, whichever block they belong to:
|
|
275
|
+
// `spliceSource` keeps only the ranges that fall inside the bytes it is
|
|
276
|
+
// carrying, so a block riding inside ANOTHER new block still loses its own
|
|
277
|
+
// interior on the way to the map.
|
|
278
|
+
const omit = interiors.omit;
|
|
279
|
+
const dot = e.id.lastIndexOf(".");
|
|
280
|
+
if (dot === -1) {
|
|
281
|
+
const spot = elementSpot(modelRegion(), e.id, elementService(e));
|
|
282
|
+
applyTop(spot, spliceSource(deltaText, src, { featureId, indent: " ", omit }), e.id);
|
|
283
|
+
spliced.push({ start: src.start, end: src.end });
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const parentId = e.id.slice(0, dot);
|
|
287
|
+
const parent = livingParentOf(parentId);
|
|
288
|
+
if (parent === null) {
|
|
289
|
+
throw new LandscapeSpliceError(`'${e.id}' nests under '${parentId}', which is neither in the living landscape nor added by this delta — there is nowhere to insert it`);
|
|
290
|
+
}
|
|
291
|
+
const nested = nestedInsert(content, parent, spliceSource(deltaText, src, { featureId, indent: parent.indent + " ", omit }));
|
|
292
|
+
applyAt(nested.at, nested.insert, e.id);
|
|
293
|
+
spliced.push({ start: src.start, end: src.end });
|
|
294
|
+
}
|
|
295
|
+
// Each map-bound addition takes its statement out of the pool built above:
|
|
296
|
+
// one statement per addition, so duplicates stay duplicates.
|
|
297
|
+
for (const r of mapRels) {
|
|
298
|
+
const s = pool.get(relStatementKey(r))?.shift();
|
|
299
|
+
if (s === undefined) {
|
|
300
|
+
throw new LandscapeSpliceError(`cannot locate the '${r.source} -> ${r.target}' relationship in delta.likec4 — the landscape merge splices authored source, and no matching declaration was found`);
|
|
301
|
+
}
|
|
302
|
+
if (rides(s.start, s.end))
|
|
303
|
+
continue;
|
|
304
|
+
const key = relSortKey(deltaElements, r);
|
|
305
|
+
// Deliberately no `known` fleet set: this resolves only the anchor a new
|
|
306
|
+
// relationship lands after (placement.ts's reason — cosmetic grouping,
|
|
307
|
+
// safety-netted by the re-parse below), never which service a check
|
|
308
|
+
// grades.
|
|
309
|
+
const spot = relSpot(modelRegion(), serviceOf(deltaElements, r.source), key);
|
|
310
|
+
applyTop(spot, spliceSource(deltaText, s, { featureId, indent: " " }), `${r.source} -> ${r.target}`);
|
|
311
|
+
}
|
|
312
|
+
// The safety net: prove the computed landscape parses before anything is
|
|
313
|
+
// written. Splice bugs — and legal inputs the living document cannot absorb,
|
|
314
|
+
// like a kind its specification never declares — refuse here, at plan time,
|
|
315
|
+
// instead of corrupting the one file the whole fleet reads. Skipped when
|
|
316
|
+
// every addition was routed away: the text is the one already parsed above,
|
|
317
|
+
// and the models get their own net from the caller, which is the only side
|
|
318
|
+
// that can stage a model beside the map it extends.
|
|
319
|
+
// The splice composed bytes from two documents, and the delta's newlines are
|
|
320
|
+
// not necessarily the map's. Corrected before the net, so what is proven is
|
|
321
|
+
// what would be written.
|
|
322
|
+
content = matchLineEndings(text, content);
|
|
323
|
+
if (touchesMap) {
|
|
324
|
+
const check = await loadSource(content);
|
|
325
|
+
if (check.errors.length > 0) {
|
|
326
|
+
const detail = check.errors
|
|
327
|
+
.slice(0, 3)
|
|
328
|
+
.map(errorText)
|
|
329
|
+
.join("; ");
|
|
330
|
+
throw new LandscapeSpliceError(`the merged landscape would not parse (${check.errors.length} error(s): ${detail}) — nothing was written. ` +
|
|
331
|
+
`The delta's additions do not fit the living landscape as authored — most often an element kind or tag ` +
|
|
332
|
+
`its specification block does not declare; fix the landscape's specification or the delta, then re-run`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return { content: touchesMap ? content : null, addedEls: mapEls, addedRels: mapRels, models: [...routed.values()] };
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=landscape-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"landscape-merge.js","sourceRoot":"","sources":["../../../../src/core/c4/splice/landscape-merge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAuB,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,SAAS,EAA2D,MAAM,mBAAmB,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GAKrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAoB,MAAM,gBAAgB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAa,MAAM,gBAAgB,CAAC;AAEzD,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA4B;IACnE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAC5F,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAClC,6EAA6E;IAC7E,iFAAiF;IACjF,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACrC,8EAA8E;IAC9E,4EAA4E;IAC5E,+BAA+B;IAC/B,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,oBAAoB,CAAC,wBAAwB,IAAI,CAAC,MAAM,CAAC,MAAM,qCAAqC,CAAC,CAAC;IAClH,CAAC;IACD,yEAAyE;IACzE,8EAA8E;IAC9E,gFAAgF;IAChF,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9G,+EAA+E;IAC/E,+EAA+E;IAC/E,MAAM,KAAK,GAAG,YAAY,CAAC;QACzB,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,UAAU,EAAE,IAAI,CAAC,aAAa;QAC9B,OAAO;QACP,aAAa;QACb,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;QAC1C,MAAM;QACN,QAAQ;KACT,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;QACnD,MAAM,IAAI,oBAAoB,CAC5B,gBAAgB,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,OAAO,wBAAwB,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,OAAO,sEAAsE;YACxM,yCAAyC,CAAC,CAAC,EAAE,uCAAuC,CACvF,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC;IAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;IAE7B,MAAM,KAAK,GAAG,OAAO,CAAC;QACpB,OAAO;QACP,MAAM,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/C,QAAQ,EAAE,KAAK,CAAC,WAAW;QAC3B,KAAK,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM;KACP,CAAC,CAAC;IACH,4EAA4E;IAC5E,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,2EAA2E;IAC3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpE,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,oBAAoB,CAAC,wEAAwE,CAAC,CAAC;IAC3G,CAAC;IAED,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,yEAAyE;IACzE,2EAA2E;IAC3E,uEAAuE;IACvE,4EAA4E;IAC5E,8EAA8E;IAC9E,mFAAmF;IACnF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,SAAS,GAAG,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,GAAG,EAA0B,CAAC;IACjD,MAAM,IAAI,GAAG,CAAC,KAAqB,EAAkB,EAAE;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QAC5C,MAAM,KAAK,GAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,MAAM;QAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAW,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3B,2EAA2E;QAC3E,0EAA0E;QAC1E,4EAA4E;QAC5E,yEAAyE;QACzE,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,IAAI,KAAK,OAAO;YAAE,SAAS;QAC/B,MAAM,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrE,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACnC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,yEAAyE;QACzE,mEAAmE;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACvF,2EAA2E;QAC3E,2EAA2E;QAC3E,2EAA2E;QAC3E,WAAW;QACX,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/F,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACpC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAE3D,MAAM,OAAO,GAA0C,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,GAAW,EAAW,EAAE,CACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAExD,wEAAwE;IACxE,qEAAqE;IACrE,uEAAuE;IACvE,uEAAuE;IACvE,0EAA0E;IAC1E,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,qBAAqB;IACrB,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAChC,KAAK,GAAG,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,GAAiB,EAAE;QACtC,IAAI,UAAU,KAAK,IAAI;YAAE,MAAM,IAAI,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;QAC/F,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IACF,8EAA8E;IAC9E,8EAA8E;IAC9E,yBAAyB;IACzB,MAAM,WAAW,GAAG,GAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACjG,uEAAuE;IACvE,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,MAAc,EAAE,IAAY,EAAQ,EAAE;QACjE,MAAM,MAAM,GAAG,UAAU,CAAC;QAC1B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC;QACT,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAE,KAAa,EAAE,IAAY,EAAQ,EAAE;QACjE,uEAAuE;QACvE,iEAAiE;QACjE,uCAAuC;QACvC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC;IAEF,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,sEAAsE;IACtE,2EAA2E;IAC3E,iEAAiE;IACjE,qEAAqE;IACrE,EAAE;IACF,yEAAyE;IACzE,8EAA8E;IAC9E,0EAA0E;IAC1E,sEAAsE;IACtE,0EAA0E;IAC1E,6EAA6E;IAC7E,iCAAiC;IACjC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAC/G,IAAI,KAAK;YAAE,MAAM,IAAI,oBAAoB,CAAC,eAAe,CAAC,kBAAkB,EAAE,MAAM,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACzH,CAAC;IAED,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAyB,EAAE;QACjE,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACrC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAClE,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QACxC,yEAAyE;QACzE,4EAA4E;QAC5E,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,KAAK,CAAC;QAClE,MAAM,QAAQ,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC;QACpG,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC;IACpE,CAAC,CAAC;IAEF,8EAA8E;IAC9E,MAAM,KAAK,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3D,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CACnG,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,oBAAoB,CAC5B,kBAAkB,CAAC,CAAC,EAAE,qGAAqG,CAC5H,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACxC,gEAAgE;QAChE,wEAAwE;QACxE,2EAA2E;QAC3E,kCAAkC;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAC5B,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACtF,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YACjD,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,oBAAoB,CAC5B,IAAI,CAAC,CAAC,EAAE,kBAAkB,QAAQ,qGAAqG,CACxI,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,YAAY,CACzB,OAAO,EACP,MAAM,EACN,YAAY,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAChF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,2EAA2E;IAC3E,6DAA6D;IAC7D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QAChD,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,oBAAoB,CAC5B,sBAAsB,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,qHAAqH,CACnK,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QACzC,yEAAyE;QACzE,uEAAuE;QACvE,oEAAoE;QACpE,UAAU;QACV,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7E,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACxG,CAAC;IAED,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,2EAA2E;IAC3E,oDAAoD;IACpD,6EAA6E;IAC7E,4EAA4E;IAC5E,yBAAyB;IACzB,OAAO,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;iBACxB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;iBACX,GAAG,CAAC,SAAS,CAAC;iBACd,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,oBAAoB,CAC5B,yCAAyC,KAAK,CAAC,MAAM,CAAC,MAAM,cAAc,MAAM,2BAA2B;gBACzG,wGAAwG;gBACxG,uGAAuG,CAC1G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AACtH,CAAC","sourcesContent":["\nimport { parentIdOf } from \"../../kernel/ids/fqn/ancestors.js\";\nimport { errorText, loadSource, type Elem, type Rel } from \"../likec4.js\";\nimport { firstUnlocated, unlocatedReason } from \"../locate/unlocated.js\";\nimport { elementService, serviceOf } from \"../resolve/service.js\";\nimport { kindsDeclared, scanModel, type ScannedElement, type ScannedModel, type ScannedRel } from \"../source-scan.js\";\nimport { matchLineEndings, spliceSource } from \"./authored-source.js\";\nimport {\n assertSpliceVisible,\n LandscapeSpliceError,\n type ExtendingModel,\n type LandscapeMergeRequest,\n type LandscapePlan,\n type ModelAdditions,\n} from \"./contract.js\";\nimport { assertMergeableDelta } from \"./delta-blocks.js\";\nimport { relSortKey, relStatementKey, scannedStatementKey } from \"./identity/edges.js\";\nimport { newAdditions } from \"./identity/existing.js\";\nimport { planInteriors } from \"./identity/interior.js\";\nimport { ownerOf } from \"./identity/owner.js\";\nimport { elementSpot, relSpot, topStatements, type ModelRegion } from \"./placement.js\";\nimport { nestedInsert, type Spot } from \"./text/spot.js\";\n\n/* ------------------------------------------------------------------ */\n/* Merging */\n/* ------------------------------------------------------------------ */\n\n/**\n * Plan the merge of the feature's new elements + relationships into the living\n * landscape's `model { ... }` block (preserving the rest of the file).\n *\n * The additions are SPLICED from delta.likec4 as authored — byte for byte,\n * technology, style, icons, links, metadata, nested children and all — never\n * re-serialized from the parsed model: a rebuild keeps only the fields loam\n * models, and every field it forgets is authored detail destroyed. The one\n * edit on the way over is dropping the feature's own tag — the additions are\n * baseline now (SCHEMA.md documents the drop as why unarchive restores bytes\n * instead of recomputing) — and a construct the strip empties goes with it.\n *\n * Placement is deterministic and SERVICE-GROUPED (the spot* helpers in\n * placement.ts):\n * a top-level addition lands beside what already belongs to its service, so\n * two concurrent archives touching different services usually splice on\n * different lines and git merges their PRs — the single shared append point\n * every archive used to hit made two concurrent archives conflict BY\n * CONSTRUCTION. A NESTED element lands inside its parent's block — inside the\n * living parent when the landscape already has it, riding verbatim inside the\n * spliced parent when the parent is new from the same delta — never as a flat\n * dotted id at top level, which LikeC4 rejects. The additions carry no marker\n * comment: which archive added what is the git history's to say.\n *\n * Existence is checked semantically against the parsed landscape AND against\n * every extending model the request carries (by element id/title and by edge\n * identity), so re-archiving is idempotent whichever document the additions\n * landed in — `./identity/existing.ts` holds that phase and its two joins, and\n * this function only turns the collision it reports into the refusal.\n *\n * Splicing is text surgery, so the computed result is PARSED before it is\n * returned: a merged landscape LikeC4 rejects refuses the archive at plan time\n * (merge-failed, nothing written — the unparseable-delta discipline) instead\n * of landing in the living docs.\n *\n * NOT EVERYTHING LANDS HERE. A service whose model EXTENDS this map owns its\n * own interior, and an addition nested under such a service is ROUTED to that\n * model instead (`./identity/owner.ts` decides, `./model/merge.ts` splices).\n * Until it was, a delta's container landed in the map and the service was\n * `c4.invalid` — a duplicate declaration — the moment its model wrote the same\n * container, which is exactly what the adopt brief tells it to do\n * (verification 2026-09-04, E1). With no extending models in the request this\n * function behaves as it always did.\n *\n * Routing per ADDITION is not the whole of it, because a service the feature\n * INTRODUCES carries its interior in one element's authored bytes and those\n * children carry no feature tag of their own. `./identity/interior.ts` decides, once\n * per such block, whether it hands that interior to the model — cut out of what\n * lands on the map — or rides whole; the routing below DEFERS to that decision\n * for everything written inside the block, which is what keeps the two from\n * placing the same child twice.\n */\nexport async function planLandscapeMerge(merge: LandscapeMergeRequest): Promise<LandscapePlan> {\n const { landscapeText: text, deltaText, deltaElements, newEls, newRels, featureId } = merge;\n const models = merge.models ?? [];\n // What every extending model borrows from this map: its kinds, without which\n // a model's scan reads `container outbox` and `a .delivers b` as property lines.\n const borrowed = kindsDeclared(text);\n // First, and before the early return for \"nothing to add\": a block this merge\n // cannot carry is lost whether or not the delta also has tagged elements to\n // splice. See delta-blocks.ts.\n assertMergeableDelta(deltaText);\n const land = await loadSource(text);\n if (land.errors.length > 0) {\n throw new LandscapeSpliceError(`landscape.likec4 has ${land.errors.length} error(s) — fix it before archiving`);\n }\n // Service binding for the existence joins AND for routing and placement:\n // living elements first (they win a shared id), the delta's after — a spliced\n // statement's id resolves to its service the moment its bytes land in the scan.\n const bindEls = [...land.elements, ...deltaElements.filter((d) => !land.elements.some((l) => l.id === d.id))];\n // What the living fleet already has — the map AND every extending model, by id\n // and by title. `./identity/existing.ts` holds both joins and their asymmetry.\n const added = newAdditions({\n livingEls: land.elements,\n livingRels: land.relationships,\n bindEls,\n deltaElements,\n candidates: { els: newEls, rels: newRels },\n models,\n borrowed,\n });\n if (added.collision !== undefined) {\n const { addition: e, living: m } = added.collision;\n throw new LandscapeSpliceError(\n `the delta's '${e.id}' (bound to service '${e.service}') shares the title '${e.title}' with '${m.id}' (bound to service '${m.service}') — a title join across services would silently drop the addition; ` +\n `retitle one of them, or reuse the id '${m.id}' if they really are the same element`,\n );\n }\n const addedEls = added.els;\n const addedRels = added.rels;\n\n const owner = ownerOf({\n bindEls,\n living: new Set(land.elements.map((e) => e.id)),\n declared: added.declaredIds,\n added: new Set(addedEls.map((e) => e.id)),\n models,\n });\n // Nothing to add: the same shape the merge returned before routing existed,\n // and the reason it is decided HERE rather than after the loops below — a\n // no-op archive must not have to scan the delta, nor answer the landscape\n // guards further down, which refuse documents this merge is not touching.\n // Equivalent to the old \"nothing reached the map and nothing was routed\":\n // every addition ends up in one of those two, so an empty pair means both.\n if (addedEls.length === 0 && addedRels.length === 0) {\n return { content: null, addedEls: [], addedRels: [], models: [] };\n }\n\n const scan = scanModel(deltaText);\n if (scan === null) {\n throw new LandscapeSpliceError(\"delta.likec4 has no model block — nothing to splice the additions from\");\n }\n\n // Everything below either locates a declaration's authored bytes or refuses.\n // `spliced` remembers the delta ranges already carried over, so a child whose\n // parent is itself new is recognised as riding inside the parent's text and\n // is never inserted twice.\n const byId = new Map(scan.elements.map((e) => [e.id, e]));\n // Relationships: match each parsed addition back to its statement in the\n // delta source — full identity (`relStatementKey`), consumed one statement\n // per addition so duplicates stay duplicates. Built before the routing\n // because routing has to know WHERE an edge was written: one drawn inside a\n // block that rides whole is already on the map. A statement is keyed with the\n // tags its kind gives it, which the parsed addition carries and its text does not.\n const pool = new Map<string, ScannedRel[]>();\n for (const s of scan.rels) {\n const k = scannedStatementKey(s, merge.deltaKindTags ?? {});\n pool.set(k, [...(pool.get(k) ?? []), s]);\n }\n\n const interiors = planInteriors({ scan, deltaElements, owner, addedEls });\n const routed = new Map<string, ModelAdditions>();\n const into = (model: ExtendingModel): ModelAdditions => {\n const existing = routed.get(model.path);\n if (existing !== undefined) return existing;\n const fresh: ModelAdditions = { model, els: [], rels: [], borrowed };\n routed.set(model.path, fresh);\n return fresh;\n };\n for (const share of interiors.routed) into(share.model).els.push(...share.els);\n\n const mapEls: Elem[] = [];\n for (const e of addedEls) {\n const src = byId.get(e.id);\n // Written inside a block that has already decided: a split block handed it\n // to the model with its siblings, and a whole one carries it onto the map\n // in the parent's own bytes, where the splice loop's `rides` finds it. Both\n // are placed exactly once, which is the point of asking the block first.\n const fate = src === undefined ? null : interiors.covering(src);\n if (fate === \"split\") continue;\n const model = fate === \"whole\" ? undefined : owner(parentIdOf(e.id));\n if (model === undefined) mapEls.push(e);\n else into(model).els.push(e);\n }\n const mapRels: Rel[] = [];\n for (const r of addedRels) {\n // An edge written inside a block that rides whole names its endpoints by\n // their LOCAL names and reads only there; it stays with its block.\n const stmts = pool.get(relStatementKey(r)) ?? [];\n const inBlock = stmts.length > 0 && stmts.every((s) => interiors.covering(s) !== null);\n // Otherwise the SOURCE decides: a call is drawn where the caller draws its\n // calls, and only when the source is not itself interior does the target's\n // owner get the edge. A service-level edge belongs to neither and stays on\n // the map.\n const model = inBlock ? undefined : owner(parentIdOf(r.source)) ?? owner(parentIdOf(r.target));\n if (model === undefined) mapRels.push(r);\n else into(model).rels.push(r);\n }\n const touchesMap = mapEls.length > 0 || mapRels.length > 0;\n\n const spliced: Array<{ start: number; end: number }> = [];\n const rides = (start: number, end: number): boolean =>\n spliced.some((r) => start >= r.start && end <= r.end);\n\n // The living model, scanned on MASKED source (scanModel) and RE-SCANNED\n // after every splice: each addition lands in the text exactly as the\n // previous one left it, so an archive of N additions produces the same\n // bytes as N single-addition archives run back to back. Placement then\n // composes per statement — the unit the order-independence argument below\n // is stated in — instead of per archive, where a batch computed against a\n // stale layout could interleave with itself. Masking matters — a `model {`\n // spelled inside a comment or string above the real block must not capture\n // the match, or every top-level addition lands inside the comment (legal\n // LikeC4, so the parse net below would pass a landscape containing none of\n // the architecture).\n let content = text;\n let livingScan = scanModel(content);\n let stmts = livingScan === null ? [] : topStatements(livingScan, bindEls);\n const rescan = (): void => {\n livingScan = scanModel(content);\n stmts = livingScan === null ? [] : topStatements(livingScan, bindEls);\n };\n const requireModel = (): ScannedModel => {\n if (livingScan === null) throw new LandscapeSpliceError(\"landscape.likec4 has no model block\");\n return livingScan;\n };\n // Built fresh at every use, never captured: `content` and `stmts` are rebound\n // by each rescan, and a region assembled before a splice describes a document\n // that no longer exists.\n const modelRegion = (): ModelRegion => ({ text: content, stmts, blocks: requireModel().blocks });\n // Every insert must be one the next scan sees (`assertSpliceVisible`).\n const applyAt = (at: number, insert: string, what: string): void => {\n const before = livingScan;\n content = content.slice(0, at) + insert + content.slice(at);\n rescan();\n assertSpliceVisible(before, livingScan, what);\n };\n const applyTop = (spot: Spot, block: string, what: string): void => {\n // A bare spot shares its line with other text (the closing brace, or a\n // statement the block displaces) — it brings its own newlines; a\n // line-start spot slots between lines.\n applyAt(spot.at, spot.bare ? `\\n${block}\\n` : `${block}\\n`, what);\n };\n\n // Placement walks the scanned statement layout, so a declaration the scan\n // cannot see is one placement would blindly splice around — LikeC4 accepts\n // two declarations on one line, but scanModel's statement head runs to the\n // end of the line, so the second rides invisibly inside the first: an\n // element bound to its service would miss its neighborhood, and a bodyless\n // parent gaining a body could wrap the wrong declaration. Refuse\n // mechanically (the parse-net discipline) instead of splicing blind.\n //\n // THAT something is unlocated is decided here, from the parse already in\n // hand; WHAT and why is `firstUnlocated`'s, at the price of a second parse on\n // this path alone. The message used to guess \"most often two declarations\n // sharing one line\" whatever the map held, and a fleet read it over a\n // declaration on a line of its own in a second `model { }` block the scan\n // did not read then (2026-10): it names LikeC4's line now, and a shared line\n // only when that line shows one.\n if (livingScan !== null) {\n const seen = new Set(livingScan.elements.map((e) => e.id));\n const blind = land.elements.some((e) => !seen.has(e.id)) || livingScan.rels.length < land.relationships.length;\n if (blind) throw new LandscapeSpliceError(unlocatedReason(\"landscape.likec4\", await firstUnlocated(text, livingScan)));\n }\n\n const livingParentOf = (parentId: string): ScannedElement | null => {\n if (livingScan === null) return null;\n const direct = livingScan.elements.find((e) => e.id === parentId);\n if (direct !== undefined) return direct;\n // The delta may spell an existing element under its own id; the title is\n // the stable cross-namespace name (the same rule the existence check uses).\n const title = deltaElements.find((e) => e.id === parentId)?.title;\n const livingId = title === undefined ? undefined : land.elements.find((e) => e.title === title)?.id;\n if (livingId === undefined) return null;\n return livingScan.elements.find((e) => e.id === livingId) ?? null;\n };\n\n // Ancestors first: a spliced parent covers its children before they are seen.\n const depth = (id: string): number => id.split(\".\").length;\n const sortedEls = [...mapEls].sort(\n (a, b) => depth(a.id) - depth(b.id) || (byId.get(a.id)?.start ?? 0) - (byId.get(b.id)?.start ?? 0),\n );\n for (const e of sortedEls) {\n const src = byId.get(e.id);\n if (src === undefined) {\n throw new LandscapeSpliceError(\n `cannot locate '${e.id}' in delta.likec4 — the landscape merge splices authored source, and this declaration was not found`,\n );\n }\n if (rides(src.start, src.end)) continue;\n // Every split block's children, whichever block they belong to:\n // `spliceSource` keeps only the ranges that fall inside the bytes it is\n // carrying, so a block riding inside ANOTHER new block still loses its own\n // interior on the way to the map.\n const omit = interiors.omit;\n const dot = e.id.lastIndexOf(\".\");\n if (dot === -1) {\n const spot = elementSpot(modelRegion(), e.id, elementService(e));\n applyTop(spot, spliceSource(deltaText, src, { featureId, indent: \" \", omit }), e.id);\n spliced.push({ start: src.start, end: src.end });\n continue;\n }\n const parentId = e.id.slice(0, dot);\n const parent = livingParentOf(parentId);\n if (parent === null) {\n throw new LandscapeSpliceError(\n `'${e.id}' nests under '${parentId}', which is neither in the living landscape nor added by this delta — there is nowhere to insert it`,\n );\n }\n const nested = nestedInsert(\n content,\n parent,\n spliceSource(deltaText, src, { featureId, indent: parent.indent + \" \", omit }),\n );\n applyAt(nested.at, nested.insert, e.id);\n spliced.push({ start: src.start, end: src.end });\n }\n\n // Each map-bound addition takes its statement out of the pool built above:\n // one statement per addition, so duplicates stay duplicates.\n for (const r of mapRels) {\n const s = pool.get(relStatementKey(r))?.shift();\n if (s === undefined) {\n throw new LandscapeSpliceError(\n `cannot locate the '${r.source} -> ${r.target}' relationship in delta.likec4 — the landscape merge splices authored source, and no matching declaration was found`,\n );\n }\n if (rides(s.start, s.end)) continue;\n const key = relSortKey(deltaElements, r);\n // Deliberately no `known` fleet set: this resolves only the anchor a new\n // relationship lands after (placement.ts's reason — cosmetic grouping,\n // safety-netted by the re-parse below), never which service a check\n // grades.\n const spot = relSpot(modelRegion(), serviceOf(deltaElements, r.source), key);\n applyTop(spot, spliceSource(deltaText, s, { featureId, indent: \" \" }), `${r.source} -> ${r.target}`);\n }\n\n // The safety net: prove the computed landscape parses before anything is\n // written. Splice bugs — and legal inputs the living document cannot absorb,\n // like a kind its specification never declares — refuse here, at plan time,\n // instead of corrupting the one file the whole fleet reads. Skipped when\n // every addition was routed away: the text is the one already parsed above,\n // and the models get their own net from the caller, which is the only side\n // that can stage a model beside the map it extends.\n // The splice composed bytes from two documents, and the delta's newlines are\n // not necessarily the map's. Corrected before the net, so what is proven is\n // what would be written.\n content = matchLineEndings(text, content);\n if (touchesMap) {\n const check = await loadSource(content);\n if (check.errors.length > 0) {\n const detail = check.errors\n .slice(0, 3)\n .map(errorText)\n .join(\"; \");\n throw new LandscapeSpliceError(\n `the merged landscape would not parse (${check.errors.length} error(s): ${detail}) — nothing was written. ` +\n `The delta's additions do not fit the living landscape as authored — most often an element kind or tag ` +\n `its specification block does not declare; fix the landscape's specification or the delta, then re-run`,\n );\n }\n }\n\n return { content: touchesMap ? content : null, addedEls: mapEls, addedRels: mapRels, models: [...routed.values()] };\n}\n"]}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { scanModel } from "../../source-scan.js";
|
|
2
|
+
import { matchLineEndings, spliceSource } from "../authored-source.js";
|
|
3
|
+
import { assertSpliceVisible, LandscapeSpliceError } from "../contract.js";
|
|
4
|
+
import { relStatementKey, scannedStatementKey } from "../identity/edges.js";
|
|
5
|
+
import { HOME_BLOCK } from "../placement.js";
|
|
6
|
+
import { closeSpot, nestedInsert, spotAfter } from "../text/spot.js";
|
|
7
|
+
/** The merged model source. Refuses (never guesses) when the delta or the model cannot be read. */
|
|
8
|
+
export function spliceModel(req) {
|
|
9
|
+
const { additions, deltaText, featureId } = req;
|
|
10
|
+
const { model, borrowed } = additions;
|
|
11
|
+
const scan = scanModel(deltaText);
|
|
12
|
+
if (scan === null) {
|
|
13
|
+
throw new LandscapeSpliceError("delta.likec4 has no model block — nothing to splice the additions from");
|
|
14
|
+
}
|
|
15
|
+
const byId = new Map(scan.elements.map((e) => [e.id, e]));
|
|
16
|
+
const pool = new Map();
|
|
17
|
+
for (const s of scan.rels) {
|
|
18
|
+
const k = scannedStatementKey(s, req.deltaKindTags ?? {});
|
|
19
|
+
pool.set(k, [...(pool.get(k) ?? []), s]);
|
|
20
|
+
}
|
|
21
|
+
// Read with the map's kinds: the model declares none, and a `container
|
|
22
|
+
// outbox` frame or an `a .delivers b` edge it cannot see is a parent with
|
|
23
|
+
// nowhere to nest into, or an anchor the next edge lands above.
|
|
24
|
+
let content = withModelBlock(model.text, borrowed);
|
|
25
|
+
let live = read(content, model.path, borrowed);
|
|
26
|
+
// The delta ranges already carried over, so a child whose parent is itself
|
|
27
|
+
// new is recognised as riding inside the parent's text — the same rule the
|
|
28
|
+
// landscape merge states, and the reason `node` inside a new `cache` is never
|
|
29
|
+
// spliced twice.
|
|
30
|
+
const spliced = [];
|
|
31
|
+
const rides = (start, end) => spliced.some((r) => start >= r.start && end <= r.end);
|
|
32
|
+
// Every insert must be one the next scan sees — the landscape merge's backstop.
|
|
33
|
+
const applyAt = (at, insert, what) => {
|
|
34
|
+
const before = live;
|
|
35
|
+
content = content.slice(0, at) + insert + content.slice(at);
|
|
36
|
+
live = read(content, model.path, borrowed);
|
|
37
|
+
assertSpliceVisible(before, live, what);
|
|
38
|
+
};
|
|
39
|
+
// Ancestors first, exactly as the landscape merge orders them: a spliced
|
|
40
|
+
// parent covers its children before they are seen.
|
|
41
|
+
const depth = (id) => id.split(".").length;
|
|
42
|
+
const ordered = [...additions.els].sort((a, b) => depth(a.id) - depth(b.id) || (byId.get(a.id)?.start ?? 0) - (byId.get(b.id)?.start ?? 0));
|
|
43
|
+
for (const e of ordered) {
|
|
44
|
+
const src = byId.get(e.id);
|
|
45
|
+
if (src === undefined) {
|
|
46
|
+
throw new LandscapeSpliceError(`cannot locate '${e.id}' in delta.likec4 — the model merge splices authored source, and this declaration was not found`);
|
|
47
|
+
}
|
|
48
|
+
if (rides(src.start, src.end))
|
|
49
|
+
continue;
|
|
50
|
+
const [at, insert] = elementInsert({
|
|
51
|
+
content,
|
|
52
|
+
live,
|
|
53
|
+
block: (indent) => spliceSource(deltaText, src, { featureId, indent }),
|
|
54
|
+
parent: parentIdOf(e),
|
|
55
|
+
});
|
|
56
|
+
applyAt(at, insert, e.id);
|
|
57
|
+
spliced.push({ start: src.start, end: src.end });
|
|
58
|
+
}
|
|
59
|
+
for (const r of additions.rels) {
|
|
60
|
+
const s = pool.get(relStatementKey(r))?.shift();
|
|
61
|
+
if (s === undefined) {
|
|
62
|
+
throw new LandscapeSpliceError(`cannot locate the '${r.source} -> ${r.target}' relationship in delta.likec4 — the model merge splices authored source, and no matching declaration was found`);
|
|
63
|
+
}
|
|
64
|
+
if (rides(s.start, s.end))
|
|
65
|
+
continue;
|
|
66
|
+
const { close } = live.blocks[HOME_BLOCK];
|
|
67
|
+
const base = blockIndent(content, close);
|
|
68
|
+
// Top-level in the model block: an edge written inside an `extend` block is
|
|
69
|
+
// that block's, and anchoring after it would splice into someone's body.
|
|
70
|
+
// And in the HOME block: the anchor's own close is what `spotAfter` clamps
|
|
71
|
+
// to, and an edge last in a later block would otherwise pull this one there.
|
|
72
|
+
const top = live.rels.filter((x) => x.block === HOME_BLOCK && !live.elements.some((el) => x.start > el.start && x.start < el.end));
|
|
73
|
+
const anchor = top.at(-1);
|
|
74
|
+
const spot = anchor === undefined ? closeSpot(content, close) : spotAfter(content, close, anchor.end);
|
|
75
|
+
const block = spliceSource(deltaText, s, { featureId, indent: `${base} ` });
|
|
76
|
+
applyAt(spot.at, spot.bare ? `\n${block}\n` : `${block}\n`, `${r.source} -> ${r.target}`);
|
|
77
|
+
}
|
|
78
|
+
// The delta's newlines are not necessarily this model's, and a merge that left
|
|
79
|
+
// both conventions in one file is noise in every editor and every diff — the
|
|
80
|
+
// same correction the landscape merge makes, from the same helper
|
|
81
|
+
// (verification 2026-09-04, W-CRLF).
|
|
82
|
+
return matchLineEndings(model.text, content);
|
|
83
|
+
}
|
|
84
|
+
/** The parent an addition nests under. Routing only ever sends nested ids here. */
|
|
85
|
+
function parentIdOf(e) {
|
|
86
|
+
return e.id.slice(0, e.id.lastIndexOf("."));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Where one element's block goes, as `(offset, text)`.
|
|
90
|
+
*
|
|
91
|
+
* Two arms, and the second is the one that makes a freshly adopted service
|
|
92
|
+
* work: a model that has never named this container's parent has no `extend`
|
|
93
|
+
* block for it, so the merge writes one rather than refusing. A parent the
|
|
94
|
+
* merged project will not resolve is caught by the caller's parse net, which is
|
|
95
|
+
* the only reader that can see the map and the model together.
|
|
96
|
+
*/
|
|
97
|
+
function elementInsert(req) {
|
|
98
|
+
const { content, live, block, parent } = req;
|
|
99
|
+
const declared = live.elements.find((x) => x.id === parent);
|
|
100
|
+
if (declared !== undefined) {
|
|
101
|
+
const nested = nestedInsert(content, declared, block(`${declared.indent} `));
|
|
102
|
+
return [nested.at, nested.insert];
|
|
103
|
+
}
|
|
104
|
+
const { close } = live.blocks[HOME_BLOCK];
|
|
105
|
+
const base = blockIndent(content, close);
|
|
106
|
+
const body = `${base} extend ${parent} {\n${block(`${base} `)}\n${base} }`;
|
|
107
|
+
const spot = closeSpot(content, close);
|
|
108
|
+
return [spot.at, spot.bare ? `\n${body}\n` : `${body}\n`];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The model, with a `model { }` block appended when the file has none.
|
|
112
|
+
*
|
|
113
|
+
* `../../service-model/shape.ts` answers `extending` for an empty file, a
|
|
114
|
+
* views-only file and a tags-only `specification { }` — three shapes it calls
|
|
115
|
+
* legal on purpose — so routing hands those models a nested addition, and
|
|
116
|
+
* refusing there took a whole legal shape away from `loam archive` for a
|
|
117
|
+
* document the merge is perfectly able to author (review of E1: before the
|
|
118
|
+
* routing existed, the same delta merged onto the map). It is the call
|
|
119
|
+
* `elementInsert` already makes one level down — a model that has never named
|
|
120
|
+
* the parent gains the `extend` block rather than refusing — and the caller's
|
|
121
|
+
* parse net proves the result either way.
|
|
122
|
+
*/
|
|
123
|
+
function withModelBlock(text, borrowed) {
|
|
124
|
+
if (scanModel(text, borrowed) !== null)
|
|
125
|
+
return text;
|
|
126
|
+
const pad = text === "" || text.endsWith("\n") ? "" : "\n";
|
|
127
|
+
return `${text}${pad}model {\n}\n`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The model's `model { }` block, re-scanned after every splice so each addition
|
|
131
|
+
* lands in the text the previous one left — the landscape merge's rule, for the
|
|
132
|
+
* same reason: placement composes per statement, not per archive.
|
|
133
|
+
*
|
|
134
|
+
* `withModelBlock` guarantees the FIRST read finds one, so a null here means a
|
|
135
|
+
* splice destroyed the block it was writing into: mechanical, so it refuses at
|
|
136
|
+
* plan time with nothing written, exactly as the parse nets do.
|
|
137
|
+
*/
|
|
138
|
+
function read(content, path, borrowed) {
|
|
139
|
+
const scan = scanModel(content, borrowed);
|
|
140
|
+
if (scan === null) {
|
|
141
|
+
throw new LandscapeSpliceError(`merging this feature's additions left ${path} without a model block — nothing was written; re-run after reporting it`);
|
|
142
|
+
}
|
|
143
|
+
return scan;
|
|
144
|
+
}
|
|
145
|
+
/** The indentation of the line the model block's closing brace sits on, or "" when it shares one. */
|
|
146
|
+
function blockIndent(text, close) {
|
|
147
|
+
const lineStart = text.lastIndexOf("\n", close - 1) + 1;
|
|
148
|
+
const before = text.slice(lineStart, close);
|
|
149
|
+
return /^[ \t]*$/.test(before) ? before : "";
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../../../../src/core/c4/splice/model/merge.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The other half of the archive's C4 merge: what a feature adds INSIDE a\n * service, spliced into the service's own extending `model.likec4`.\n *\n * `../landscape-merge.ts` routes the additions (`../identity/owner.ts` states\n * the rule) and this carries them over, by the same discipline: authored source,\n * byte for byte,\n * with the feature's own tag stripped and the indentation rebased — never a\n * re-serialization of the parsed model, which keeps only the fields loam models.\n *\n * PLACEMENT IS SIMPLER HERE, and deliberately so. The map groups additions by\n * service because every service writes into it and concurrent archives must\n * merge in git; a service model has ONE service in it, so there is no\n * neighborhood to join. An element lands inside the `extend <fqn> { … }` block\n * that owns its parent — or inside its parent's own block when the model\n * already declares that container — and a model with no `extend` block for the\n * fqn gains one at the end of its `model { }` block, as a model with no `model\n * { }` block at all gains that. A relationship lands after the last top-level\n * relationship of that block, or last in it. A model written in SEVERAL\n * `model { }` blocks is read whole — a parent's `extend` frame is found in\n * whichever block holds it — and \"its block\" for everything else is\n * `HOME_BLOCK`, the first, for the reasons `../placement.ts` gives the map.\n *\n * WHAT THIS DOES NOT DO IS PROVE THE RESULT. The landscape merge parses its own\n * output because a landscape is a self-contained document; an extending model\n * is not — it is read beside the `architecture/` project, and staging that set\n * means touching the docs repo. So the parse net lives with the caller\n * (`commands/archive/plan/model/extending.ts`), which is also the side that\n * holds the merged MAP the model must be proven against.\n */\nimport type { Elem } from \"../../likec4.js\";\nimport { scanModel, type ScanKinds, type ScannedModel, type ScannedRel } from \"../../source-scan.js\";\nimport { matchLineEndings, spliceSource } from \"../authored-source.js\";\nimport { assertSpliceVisible, LandscapeSpliceError, type KindTags, type ModelAdditions } from \"../contract.js\";\nimport { relStatementKey, scannedStatementKey } from \"../identity/edges.js\";\nimport { HOME_BLOCK } from \"../placement.js\";\nimport { closeSpot, nestedInsert, spotAfter } from \"../text/spot.js\";\n\nexport interface ModelMergeRequest {\n /** One model's share of the merge, as `planLandscapeMerge` routed it. */\n additions: ModelAdditions;\n /** delta.likec4 as authored — the bytes the additions are spliced from. */\n deltaText: string;\n featureId: string;\n /** The delta's relationship kinds' tags — the landscape merge's own reason (`../identity/edges.ts`). */\n deltaKindTags?: KindTags;\n}\n\n/** The merged model source. Refuses (never guesses) when the delta or the model cannot be read. */\nexport function spliceModel(req: ModelMergeRequest): string {\n const { additions, deltaText, featureId } = req;\n const { model, borrowed } = additions;\n const scan = scanModel(deltaText);\n if (scan === null) {\n throw new LandscapeSpliceError(\"delta.likec4 has no model block — nothing to splice the additions from\");\n }\n const byId = new Map(scan.elements.map((e) => [e.id, e]));\n const pool = new Map<string, ScannedRel[]>();\n for (const s of scan.rels) {\n const k = scannedStatementKey(s, req.deltaKindTags ?? {});\n pool.set(k, [...(pool.get(k) ?? []), s]);\n }\n\n // Read with the map's kinds: the model declares none, and a `container\n // outbox` frame or an `a .delivers b` edge it cannot see is a parent with\n // nowhere to nest into, or an anchor the next edge lands above.\n let content = withModelBlock(model.text, borrowed);\n let live = read(content, model.path, borrowed);\n // The delta ranges already carried over, so a child whose parent is itself\n // new is recognised as riding inside the parent's text — the same rule the\n // landscape merge states, and the reason `node` inside a new `cache` is never\n // spliced twice.\n const spliced: Array<{ start: number; end: number }> = [];\n const rides = (start: number, end: number): boolean =>\n spliced.some((r) => start >= r.start && end <= r.end);\n // Every insert must be one the next scan sees — the landscape merge's backstop.\n const applyAt = (at: number, insert: string, what: string): void => {\n const before = live;\n content = content.slice(0, at) + insert + content.slice(at);\n live = read(content, model.path, borrowed);\n assertSpliceVisible(before, live, what);\n };\n\n // Ancestors first, exactly as the landscape merge orders them: a spliced\n // parent covers its children before they are seen.\n const depth = (id: string): number => id.split(\".\").length;\n const ordered = [...additions.els].sort(\n (a, b) => depth(a.id) - depth(b.id) || (byId.get(a.id)?.start ?? 0) - (byId.get(b.id)?.start ?? 0),\n );\n for (const e of ordered) {\n const src = byId.get(e.id);\n if (src === undefined) {\n throw new LandscapeSpliceError(\n `cannot locate '${e.id}' in delta.likec4 — the model merge splices authored source, and this declaration was not found`,\n );\n }\n if (rides(src.start, src.end)) continue;\n const [at, insert] = elementInsert({\n content,\n live,\n block: (indent) => spliceSource(deltaText, src, { featureId, indent }),\n parent: parentIdOf(e),\n });\n applyAt(at, insert, e.id);\n spliced.push({ start: src.start, end: src.end });\n }\n\n for (const r of additions.rels) {\n const s = pool.get(relStatementKey(r))?.shift();\n if (s === undefined) {\n throw new LandscapeSpliceError(\n `cannot locate the '${r.source} -> ${r.target}' relationship in delta.likec4 — the model merge splices authored source, and no matching declaration was found`,\n );\n }\n if (rides(s.start, s.end)) continue;\n const { close } = live.blocks[HOME_BLOCK]!;\n const base = blockIndent(content, close);\n // Top-level in the model block: an edge written inside an `extend` block is\n // that block's, and anchoring after it would splice into someone's body.\n // And in the HOME block: the anchor's own close is what `spotAfter` clamps\n // to, and an edge last in a later block would otherwise pull this one there.\n const top = live.rels.filter(\n (x) => x.block === HOME_BLOCK && !live.elements.some((el) => x.start > el.start && x.start < el.end),\n );\n const anchor = top.at(-1);\n const spot = anchor === undefined ? closeSpot(content, close) : spotAfter(content, close, anchor.end);\n const block = spliceSource(deltaText, s, { featureId, indent: `${base} ` });\n applyAt(spot.at, spot.bare ? `\\n${block}\\n` : `${block}\\n`, `${r.source} -> ${r.target}`);\n }\n // The delta's newlines are not necessarily this model's, and a merge that left\n // both conventions in one file is noise in every editor and every diff — the\n // same correction the landscape merge makes, from the same helper\n // (verification 2026-09-04, W-CRLF).\n return matchLineEndings(model.text, content);\n}\n\n/** The parent an addition nests under. Routing only ever sends nested ids here. */\nfunction parentIdOf(e: Elem): string {\n return e.id.slice(0, e.id.lastIndexOf(\".\"));\n}\n\ninterface ElementInsert {\n content: string;\n live: ScannedModel;\n /** The authored block at a given indent — computed late, because the indent depends on where it lands. */\n block: (indent: string) => string;\n parent: string;\n}\n\n/**\n * Where one element's block goes, as `(offset, text)`.\n *\n * Two arms, and the second is the one that makes a freshly adopted service\n * work: a model that has never named this container's parent has no `extend`\n * block for it, so the merge writes one rather than refusing. A parent the\n * merged project will not resolve is caught by the caller's parse net, which is\n * the only reader that can see the map and the model together.\n */\nfunction elementInsert(req: ElementInsert): [number, string] {\n const { content, live, block, parent } = req;\n const declared = live.elements.find((x) => x.id === parent);\n if (declared !== undefined) {\n const nested = nestedInsert(content, declared, block(`${declared.indent} `));\n return [nested.at, nested.insert];\n }\n const { close } = live.blocks[HOME_BLOCK]!;\n const base = blockIndent(content, close);\n const body = `${base} extend ${parent} {\\n${block(`${base} `)}\\n${base} }`;\n const spot = closeSpot(content, close);\n return [spot.at, spot.bare ? `\\n${body}\\n` : `${body}\\n`];\n}\n\n/**\n * The model, with a `model { }` block appended when the file has none.\n *\n * `../../service-model/shape.ts` answers `extending` for an empty file, a\n * views-only file and a tags-only `specification { }` — three shapes it calls\n * legal on purpose — so routing hands those models a nested addition, and\n * refusing there took a whole legal shape away from `loam archive` for a\n * document the merge is perfectly able to author (review of E1: before the\n * routing existed, the same delta merged onto the map). It is the call\n * `elementInsert` already makes one level down — a model that has never named\n * the parent gains the `extend` block rather than refusing — and the caller's\n * parse net proves the result either way.\n */\nfunction withModelBlock(text: string, borrowed: ScanKinds): string {\n if (scanModel(text, borrowed) !== null) return text;\n const pad = text === \"\" || text.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${text}${pad}model {\\n}\\n`;\n}\n\n/**\n * The model's `model { }` block, re-scanned after every splice so each addition\n * lands in the text the previous one left — the landscape merge's rule, for the\n * same reason: placement composes per statement, not per archive.\n *\n * `withModelBlock` guarantees the FIRST read finds one, so a null here means a\n * splice destroyed the block it was writing into: mechanical, so it refuses at\n * plan time with nothing written, exactly as the parse nets do.\n */\nfunction read(content: string, path: string, borrowed: ScanKinds): ScannedModel {\n const scan = scanModel(content, borrowed);\n if (scan === null) {\n throw new LandscapeSpliceError(\n `merging this feature's additions left ${path} without a model block — nothing was written; re-run after reporting it`,\n );\n }\n return scan;\n}\n\n/** The indentation of the line the model block's closing brace sits on, or \"\" when it shares one. */\nfunction blockIndent(text: string, close: number): string {\n const lineStart = text.lastIndexOf(\"\\n\", close - 1) + 1;\n const before = text.slice(lineStart, close);\n return /^[ \\t]*$/.test(before) ? before : \"\";\n}\n"]}
|