@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,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The component closure the merge computes over `$ref`s. The two plain
|
|
3
|
+
* questions it asks — which refs does this tree contain, and what does one
|
|
4
|
+
* point at — moved to `../depth.ts` once the reader needed them too (that
|
|
5
|
+
* module's header says why the root, not here).
|
|
6
|
+
*
|
|
7
|
+
* The closure is verdict-driven, not reachability-driven: every component the
|
|
8
|
+
* feature DECLARES is classified against its `x-loam-baselines` entry exactly
|
|
9
|
+
* as an operation is classified against its pin, and reachability decides only
|
|
10
|
+
* one thing — whether a genuinely NEW component rides along — whenever the
|
|
11
|
+
* delta merges paths at all. The old rule, "copy everything reachable from any
|
|
12
|
+
* feature path item", let a QUOTED operation drag its authoring-time component
|
|
13
|
+
* copy over someone else's landed change; the walk now starts from what this
|
|
14
|
+
* merge actually WROTE, so a quote pulls nothing.
|
|
15
|
+
*
|
|
16
|
+
* Where the delta merges no path, that walk starts from nothing, and "is a new
|
|
17
|
+
* component reachable?" has no meaningful answer to give: a components-only
|
|
18
|
+
* delta declared every one of them on purpose and there is no operation for
|
|
19
|
+
* them to hide behind. Parking them forever is what made such a delta merge
|
|
20
|
+
* nothing at all, at exit 0 — `componentsAreTheDelta` is that case, and only
|
|
21
|
+
* that case.
|
|
22
|
+
*/
|
|
23
|
+
import { isDeepStrictEqual } from "node:util";
|
|
24
|
+
import { isMap, isScalar } from "yaml";
|
|
25
|
+
import { classifyBaselineDigests, valueDigest, withoutFeatureKeysDeep } from "../digest.js";
|
|
26
|
+
import { entryFor, restatedSurfaces, surfaceIn } from "../baseline/record.js";
|
|
27
|
+
import { collectRefs, resolvePointer } from "../depth.js";
|
|
28
|
+
/** One mapping node's pair for a key, matched AS A STRING — `setKeyed`'s find, reusable at any depth. */
|
|
29
|
+
export function pairAt(node, key) {
|
|
30
|
+
return isMap(node) ? node.items.find((it) => isScalar(it.key) && String(it.key.value) === key) : undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Write one value under the mapping at `parent`, matching the existing key AS A
|
|
34
|
+
* STRING: a living `404:` response is the YAML number 404, and a plain `setIn`
|
|
35
|
+
* with the string "404" misses it and APPENDS a second pair — the contract then
|
|
36
|
+
* declares the key twice, forever, with the pre-merge copy first in reading
|
|
37
|
+
* order. Path-agnostic on purpose, so it is the one upsert both contract axes
|
|
38
|
+
* write through: a component here and in the strip's twin write on the feature
|
|
39
|
+
* side, a component surface or a slot on the event axis
|
|
40
|
+
* (../../asyncapi/merge/{components,markers}.ts).
|
|
41
|
+
*/
|
|
42
|
+
export function setKeyed(doc, parent, key, value) {
|
|
43
|
+
const existing = pairAt(doc.getIn(parent), key);
|
|
44
|
+
if (existing !== undefined)
|
|
45
|
+
existing.value = doc.createNode(value);
|
|
46
|
+
else
|
|
47
|
+
doc.setIn([...parent, key], value);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Merge the feature's components into the living document by verdict:
|
|
51
|
+
*
|
|
52
|
+
* - quote → skipped; the living copy stays, whatever landed on it since.
|
|
53
|
+
* - edit, stale (under --approve), or unpinned-and-differing → copied; the
|
|
54
|
+
* unpinned copy is the old upsert, kept for never-rebased deltas.
|
|
55
|
+
* - unpinned and living-equal → skipped, as it always was: nothing to write.
|
|
56
|
+
* - unfounded (pinned, living gone — the gate refused; --approve) → copied,
|
|
57
|
+
* because a written operation may reference it and the merge must never
|
|
58
|
+
* leave a dangling ref behind.
|
|
59
|
+
* - NEW (unpinned, living-absent) → copied only when reachable from written
|
|
60
|
+
* content or from another copied component's own refs. The visited-set
|
|
61
|
+
* fixpoint is what keeps A↔B cycles terminating and unrelated namespaces
|
|
62
|
+
* uncopied. When the components ARE the delta there is no written content
|
|
63
|
+
* to be reachable from, so every one of them is copied outright.
|
|
64
|
+
*
|
|
65
|
+
* The unresolved sweep is unchanged in meaning: every local ref reachable from
|
|
66
|
+
* written content and copied components must resolve in the copy set or the
|
|
67
|
+
* living document.
|
|
68
|
+
*/
|
|
69
|
+
export function mergeComponentClosure(input) {
|
|
70
|
+
const { living, featPlain, livingPlain, record, written, componentsAreTheDelta } = input;
|
|
71
|
+
const componentsModified = [];
|
|
72
|
+
const componentsAdded = [];
|
|
73
|
+
const componentsQuoted = [];
|
|
74
|
+
const componentsStale = [];
|
|
75
|
+
const unresolved = [];
|
|
76
|
+
const copies = [];
|
|
77
|
+
const copied = new Set();
|
|
78
|
+
/** Genuinely new components, parked until something written reaches them. */
|
|
79
|
+
const parked = new Map();
|
|
80
|
+
/**
|
|
81
|
+
* Which declared surfaces the living contract does not have — recorded here,
|
|
82
|
+
* during classification, because this is the one place that asks. What was
|
|
83
|
+
* ADDED is decided at the write below instead: a parked component the
|
|
84
|
+
* fixpoint never reaches is absent from living and stays that way, and
|
|
85
|
+
* calling it added would name a component the merge did not write.
|
|
86
|
+
*/
|
|
87
|
+
const absentFromLiving = new Set();
|
|
88
|
+
// ONE enumeration (baseline/record.ts) with the rebase plan and the gate —
|
|
89
|
+
// and ONE living lookup — so "which components does this delta declare, and
|
|
90
|
+
// do they exist" cannot drift between the command that pins, the gate that
|
|
91
|
+
// grades and this closure that writes.
|
|
92
|
+
for (const surface of restatedSurfaces(featPlain)) {
|
|
93
|
+
if (surface.kind !== "component")
|
|
94
|
+
continue;
|
|
95
|
+
const cut = surface.id.indexOf("/");
|
|
96
|
+
const entry = { kind: surface.id.slice(0, cut), name: surface.id.slice(cut + 1), value: surface.value };
|
|
97
|
+
const inLiving = surfaceIn(livingPlain, surface);
|
|
98
|
+
if (!inLiving.found)
|
|
99
|
+
absentFromLiving.add(surface.id);
|
|
100
|
+
const verdict = classifyBaselineDigests(entryFor(record, surface), valueDigest(surface.value), inLiving.found ? valueDigest(inLiving.value) : undefined);
|
|
101
|
+
if (verdict === "quote") {
|
|
102
|
+
componentsQuoted.push(surface.id);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (verdict === "unpinned") {
|
|
106
|
+
if (!inLiving.found) {
|
|
107
|
+
parked.set(surface.id, entry);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (isDeepStrictEqual(inLiving.value, surface.value))
|
|
111
|
+
continue;
|
|
112
|
+
componentsModified.push(surface.id);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if (verdict === "stale")
|
|
116
|
+
componentsStale.push(surface.id);
|
|
117
|
+
if (inLiving.found && !isDeepStrictEqual(inLiving.value, surface.value))
|
|
118
|
+
componentsModified.push(surface.id);
|
|
119
|
+
}
|
|
120
|
+
copies.push(entry);
|
|
121
|
+
copied.add(surface.id);
|
|
122
|
+
}
|
|
123
|
+
// A components-only delta wrote no path, so the fixpoint below would start
|
|
124
|
+
// from an empty queue and every parked component would stay parked forever —
|
|
125
|
+
// the merge published a document byte-identical to the living one and archive
|
|
126
|
+
// said `ok`. The promotion happens HERE, before the queue is built, and that
|
|
127
|
+
// order is the whole point: a component promoted afterwards would carry its
|
|
128
|
+
// own `$ref`s past the sweep, and `openapi.ref-unresolved` would stop firing
|
|
129
|
+
// for exactly the deltas that most need it — a new schema pointing at a
|
|
130
|
+
// second one the author forgot to bring. Iterated as a SNAPSHOT: this loop
|
|
131
|
+
// empties `parked` as it goes and `visitRef` deletes from the same Map below,
|
|
132
|
+
// and neither may read it live while writing it.
|
|
133
|
+
if (componentsAreTheDelta) {
|
|
134
|
+
const promotions = [...parked.entries()];
|
|
135
|
+
for (const [id, entry] of promotions) {
|
|
136
|
+
parked.delete(id);
|
|
137
|
+
copies.push(entry);
|
|
138
|
+
copied.add(id);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// The reachability fixpoint: refs out of written content and out of every
|
|
142
|
+
// copy — classification copies and any promotions now, parked promotions as
|
|
143
|
+
// they join.
|
|
144
|
+
const queue = [
|
|
145
|
+
...written.map((w) => ({ node: w.value, from: w.from })),
|
|
146
|
+
...copies.map((c) => ({ node: c.value, from: `components/${c.kind}/${c.name}` })),
|
|
147
|
+
];
|
|
148
|
+
const visited = new Set();
|
|
149
|
+
const visitRef = (ref, from) => {
|
|
150
|
+
if (!ref.startsWith("#/"))
|
|
151
|
+
return;
|
|
152
|
+
const match = /^#\/components\/([^/]+)\/([^/]+)(?:\/|$)/.exec(ref);
|
|
153
|
+
if (!match) {
|
|
154
|
+
if (!resolvePointer(featPlain, ref).found && !resolvePointer(livingPlain, ref).found) {
|
|
155
|
+
unresolved.push({ ref, from });
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const key = `${match[1]}/${match[2]}`;
|
|
160
|
+
if (visited.has(key))
|
|
161
|
+
return;
|
|
162
|
+
visited.add(key);
|
|
163
|
+
// Already copied by verdict: its own refs are in the queue from the start.
|
|
164
|
+
if (copied.has(key))
|
|
165
|
+
return;
|
|
166
|
+
const parkedEntry = parked.get(key);
|
|
167
|
+
if (parkedEntry !== undefined) {
|
|
168
|
+
parked.delete(key);
|
|
169
|
+
copies.push(parkedEntry);
|
|
170
|
+
copied.add(key);
|
|
171
|
+
queue.push({ node: parkedEntry.value, from: `components/${key}` });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Not copied and not new: a quoted or unchanged declaration, or something
|
|
175
|
+
// the feature never spells. Either way the LIVING document must have it.
|
|
176
|
+
if (!resolvePointer(livingPlain, `#/components/${key}`).found) {
|
|
177
|
+
unresolved.push({ ref, from });
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
while (queue.length > 0) {
|
|
181
|
+
const { node, from } = queue.pop();
|
|
182
|
+
for (const ref of collectRefs(node))
|
|
183
|
+
visitRef(ref, from);
|
|
184
|
+
}
|
|
185
|
+
for (const { kind, name, value } of copies) {
|
|
186
|
+
// Decided at the write, over the copies that actually happened: a promoted
|
|
187
|
+
// component is an addition, a parked one that nothing reached is not.
|
|
188
|
+
if (absentFromLiving.has(`${kind}/${name}`))
|
|
189
|
+
componentsAdded.push(`${kind}/${name}`);
|
|
190
|
+
// The value is deep-stripped of loam's bookkeeping keys — a component
|
|
191
|
+
// holding an operation shape nests them where the path-level strip never
|
|
192
|
+
// walks, and `--approve` once published `x-loam-remove: true` into a
|
|
193
|
+
// living component. Promoted copies go through this same write, so a
|
|
194
|
+
// components-only delta cannot be the one shape that publishes a marker.
|
|
195
|
+
setKeyed(living, ["components", kind], name, withoutFeatureKeysDeep(value));
|
|
196
|
+
}
|
|
197
|
+
return { componentsModified, componentsAdded, componentsQuoted, componentsStale, unresolved };
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../../../src/core/openapi/merge/components.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The component closure the merge computes over `$ref`s. The two plain\n * questions it asks — which refs does this tree contain, and what does one\n * point at — moved to `../depth.ts` once the reader needed them too (that\n * module's header says why the root, not here).\n *\n * The closure is verdict-driven, not reachability-driven: every component the\n * feature DECLARES is classified against its `x-loam-baselines` entry exactly\n * as an operation is classified against its pin, and reachability decides only\n * one thing — whether a genuinely NEW component rides along — whenever the\n * delta merges paths at all. The old rule, \"copy everything reachable from any\n * feature path item\", let a QUOTED operation drag its authoring-time component\n * copy over someone else's landed change; the walk now starts from what this\n * merge actually WROTE, so a quote pulls nothing.\n *\n * Where the delta merges no path, that walk starts from nothing, and \"is a new\n * component reachable?\" has no meaningful answer to give: a components-only\n * delta declared every one of them on purpose and there is no operation for\n * them to hide behind. Parking them forever is what made such a delta merge\n * nothing at all, at exit 0 — `componentsAreTheDelta` is that case, and only\n * that case.\n */\nimport { isDeepStrictEqual } from \"node:util\";\nimport { isMap, isScalar, type Document, type Pair } from \"yaml\";\nimport { classifyBaselineDigests, valueDigest, withoutFeatureKeysDeep } from \"../digest.js\";\nimport { entryFor, restatedSurfaces, surfaceIn, type BaselineRecord } from \"../baseline/record.js\";\nimport { collectRefs, resolvePointer } from \"../depth.js\";\n\n/** Everything the closure needs; one object because the merge is its only caller. */\nexport interface ComponentClosureInput {\n /** The living document the copies are written into. */\n living: Document;\n featPlain: unknown;\n livingPlain: unknown;\n /** The feature's `x-loam-baselines` record, read once by the merge. */\n record: BaselineRecord;\n /** The plain values the path merge actually wrote, labelled for the ref sweep. */\n written: Array<{ from: string; value: unknown }>;\n /**\n * True only when the feature's `paths` holds no entry at all, so `written` is\n * empty and nothing this merge wrote can reach a new component. The merge\n * computes it from the path ENTRIES, not from what the path loop happened to\n * write: one path entry, even an entirely quoted one, means the reachability\n * question is real and this stays false. Widening it past that would copy the\n * authoring-time component a quoted operation carries — the exact revert the\n * verdict-driven closure exists to stop.\n */\n componentsAreTheDelta: boolean;\n}\n\n/** What the closure computed: components overwritten, added, quoted, stale, and refs nothing resolves. */\nexport interface ComponentClosureOutcome {\n componentsModified: string[];\n /** `<kind>/<name>` of components written where the living contract had none. */\n componentsAdded: string[];\n componentsQuoted: string[];\n componentsStale: string[];\n unresolved: Array<{ ref: string; from: string }>;\n}\n\n/** One mapping node's pair for a key, matched AS A STRING — `setKeyed`'s find, reusable at any depth. */\nexport function pairAt(node: unknown, key: string): Pair | undefined {\n return isMap(node) ? node.items.find((it) => isScalar(it.key) && String(it.key.value) === key) : undefined;\n}\n\n/**\n * Write one value under the mapping at `parent`, matching the existing key AS A\n * STRING: a living `404:` response is the YAML number 404, and a plain `setIn`\n * with the string \"404\" misses it and APPENDS a second pair — the contract then\n * declares the key twice, forever, with the pre-merge copy first in reading\n * order. Path-agnostic on purpose, so it is the one upsert both contract axes\n * write through: a component here and in the strip's twin write on the feature\n * side, a component surface or a slot on the event axis\n * (../../asyncapi/merge/{components,markers}.ts).\n */\nexport function setKeyed(doc: Document, parent: string[], key: string, value: unknown): void {\n const existing = pairAt(doc.getIn(parent), key);\n if (existing !== undefined) existing.value = doc.createNode(value);\n else doc.setIn([...parent, key], value);\n}\n\n/**\n * Merge the feature's components into the living document by verdict:\n *\n * - quote → skipped; the living copy stays, whatever landed on it since.\n * - edit, stale (under --approve), or unpinned-and-differing → copied; the\n * unpinned copy is the old upsert, kept for never-rebased deltas.\n * - unpinned and living-equal → skipped, as it always was: nothing to write.\n * - unfounded (pinned, living gone — the gate refused; --approve) → copied,\n * because a written operation may reference it and the merge must never\n * leave a dangling ref behind.\n * - NEW (unpinned, living-absent) → copied only when reachable from written\n * content or from another copied component's own refs. The visited-set\n * fixpoint is what keeps A↔B cycles terminating and unrelated namespaces\n * uncopied. When the components ARE the delta there is no written content\n * to be reachable from, so every one of them is copied outright.\n *\n * The unresolved sweep is unchanged in meaning: every local ref reachable from\n * written content and copied components must resolve in the copy set or the\n * living document.\n */\nexport function mergeComponentClosure(input: ComponentClosureInput): ComponentClosureOutcome {\n const { living, featPlain, livingPlain, record, written, componentsAreTheDelta } = input;\n const componentsModified: string[] = [];\n const componentsAdded: string[] = [];\n const componentsQuoted: string[] = [];\n const componentsStale: string[] = [];\n const unresolved: ComponentClosureOutcome[\"unresolved\"] = [];\n const copies: Array<{ kind: string; name: string; value: unknown }> = [];\n const copied = new Set<string>();\n /** Genuinely new components, parked until something written reaches them. */\n const parked = new Map<string, { kind: string; name: string; value: unknown }>();\n /**\n * Which declared surfaces the living contract does not have — recorded here,\n * during classification, because this is the one place that asks. What was\n * ADDED is decided at the write below instead: a parked component the\n * fixpoint never reaches is absent from living and stays that way, and\n * calling it added would name a component the merge did not write.\n */\n const absentFromLiving = new Set<string>();\n\n // ONE enumeration (baseline/record.ts) with the rebase plan and the gate —\n // and ONE living lookup — so \"which components does this delta declare, and\n // do they exist\" cannot drift between the command that pins, the gate that\n // grades and this closure that writes.\n for (const surface of restatedSurfaces(featPlain)) {\n if (surface.kind !== \"component\") continue;\n const cut = surface.id.indexOf(\"/\");\n const entry = { kind: surface.id.slice(0, cut), name: surface.id.slice(cut + 1), value: surface.value };\n const inLiving = surfaceIn(livingPlain, surface);\n if (!inLiving.found) absentFromLiving.add(surface.id);\n const verdict = classifyBaselineDigests(\n entryFor(record, surface),\n valueDigest(surface.value),\n inLiving.found ? valueDigest(inLiving.value) : undefined,\n );\n if (verdict === \"quote\") {\n componentsQuoted.push(surface.id);\n continue;\n }\n if (verdict === \"unpinned\") {\n if (!inLiving.found) {\n parked.set(surface.id, entry);\n continue;\n }\n if (isDeepStrictEqual(inLiving.value, surface.value)) continue;\n componentsModified.push(surface.id);\n } else {\n if (verdict === \"stale\") componentsStale.push(surface.id);\n if (inLiving.found && !isDeepStrictEqual(inLiving.value, surface.value)) componentsModified.push(surface.id);\n }\n copies.push(entry);\n copied.add(surface.id);\n }\n\n // A components-only delta wrote no path, so the fixpoint below would start\n // from an empty queue and every parked component would stay parked forever —\n // the merge published a document byte-identical to the living one and archive\n // said `ok`. The promotion happens HERE, before the queue is built, and that\n // order is the whole point: a component promoted afterwards would carry its\n // own `$ref`s past the sweep, and `openapi.ref-unresolved` would stop firing\n // for exactly the deltas that most need it — a new schema pointing at a\n // second one the author forgot to bring. Iterated as a SNAPSHOT: this loop\n // empties `parked` as it goes and `visitRef` deletes from the same Map below,\n // and neither may read it live while writing it.\n if (componentsAreTheDelta) {\n const promotions = [...parked.entries()];\n for (const [id, entry] of promotions) {\n parked.delete(id);\n copies.push(entry);\n copied.add(id);\n }\n }\n\n // The reachability fixpoint: refs out of written content and out of every\n // copy — classification copies and any promotions now, parked promotions as\n // they join.\n const queue: Array<{ node: unknown; from: string }> = [\n ...written.map((w) => ({ node: w.value, from: w.from })),\n ...copies.map((c) => ({ node: c.value, from: `components/${c.kind}/${c.name}` })),\n ];\n const visited = new Set<string>();\n const visitRef = (ref: string, from: string): void => {\n if (!ref.startsWith(\"#/\")) return;\n const match = /^#\\/components\\/([^/]+)\\/([^/]+)(?:\\/|$)/.exec(ref);\n if (!match) {\n if (!resolvePointer(featPlain, ref).found && !resolvePointer(livingPlain, ref).found) {\n unresolved.push({ ref, from });\n }\n return;\n }\n const key = `${match[1]!}/${match[2]!}`;\n if (visited.has(key)) return;\n visited.add(key);\n // Already copied by verdict: its own refs are in the queue from the start.\n if (copied.has(key)) return;\n const parkedEntry = parked.get(key);\n if (parkedEntry !== undefined) {\n parked.delete(key);\n copies.push(parkedEntry);\n copied.add(key);\n queue.push({ node: parkedEntry.value, from: `components/${key}` });\n return;\n }\n // Not copied and not new: a quoted or unchanged declaration, or something\n // the feature never spells. Either way the LIVING document must have it.\n if (!resolvePointer(livingPlain, `#/components/${key}`).found) {\n unresolved.push({ ref, from });\n }\n };\n while (queue.length > 0) {\n const { node, from } = queue.pop()!;\n for (const ref of collectRefs(node)) visitRef(ref, from);\n }\n\n for (const { kind, name, value } of copies) {\n // Decided at the write, over the copies that actually happened: a promoted\n // component is an addition, a parked one that nothing reached is not.\n if (absentFromLiving.has(`${kind}/${name}`)) componentsAdded.push(`${kind}/${name}`);\n // The value is deep-stripped of loam's bookkeeping keys — a component\n // holding an operation shape nests them where the path-level strip never\n // walks, and `--approve` once published `x-loam-remove: true` into a\n // living component. Promoted copies go through this same write, so a\n // components-only delta cannot be the one shape that publishes a marker.\n setKeyed(living, [\"components\", kind], name, withoutFeatureKeysDeep(value));\n }\n\n return { componentsModified, componentsAdded, componentsQuoted, componentsStale, unresolved };\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** A document the merge planner cannot read. Commands map this domain error to their own envelope. */
|
|
2
|
+
export class OpenapiMergeError extends Error {
|
|
3
|
+
source;
|
|
4
|
+
service;
|
|
5
|
+
name = "OpenapiMergeError";
|
|
6
|
+
constructor(source, service, detail) {
|
|
7
|
+
super(`${source} openapi for ${service} is not valid YAML: ${detail}`);
|
|
8
|
+
this.source = source;
|
|
9
|
+
this.service = service;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** The `fail` the tree helpers take, for one side of this axis. */
|
|
13
|
+
export function openapiRefusal(source, service) {
|
|
14
|
+
return (detail) => new OpenapiMergeError(source, service, detail);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../src/core/openapi/merge/error.ts"],"names":[],"mappings":"AAeA,sGAAsG;AACtG,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAI/B,MAAM;IACN,OAAO;IAJA,IAAI,GAAG,mBAAmB,CAAC;IAE7C,YACW,MAA0B,EAC1B,OAAe,EACxB,MAAc;QAEd,KAAK,CAAC,GAAG,MAAM,gBAAgB,OAAO,uBAAuB,MAAM,EAAE,CAAC,CAAC;sBAJ9D,MAAM;uBACN,OAAO;IAIlB,CAAC;CACF;AAED,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAC,MAA0B,EAAE,OAAe;IACxE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC","sourcesContent":["/**\n * The one refusal every stage of the contract delta path raises: a document the\n * planner cannot read, named by which side it came from.\n *\n * It is the package's leaf for the same reason the pin, the markers and the\n * merge each throw it: whichever of them fails, the command above has to map\n * one domain error onto its own envelope. A module that owned the error would\n * be imported by its two siblings for that reason alone.\n *\n * Every stage reads and writes its contract through ../contract-tree.ts, and\n * hands those helpers `openapiRefusal` as the error to raise — which is what\n * makes each of them fail with this one identically.\n */\nexport type OpenapiMergeSource = \"feature\" | \"living\";\n\n/** A document the merge planner cannot read. Commands map this domain error to their own envelope. */\nexport class OpenapiMergeError extends Error {\n override readonly name = \"OpenapiMergeError\";\n\n constructor(\n readonly source: OpenapiMergeSource,\n readonly service: string,\n detail: string,\n ) {\n super(`${source} openapi for ${service} is not valid YAML: ${detail}`);\n }\n}\n\n/** The `fail` the tree helpers take, for one side of this axis. */\nexport function openapiRefusal(source: OpenapiMergeSource, service: string): (detail: string) => OpenapiMergeError {\n return (detail) => new OpenapiMergeError(source, service, detail);\n}\n"]}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keys loam adds to a feature's contract that must never reach the living
|
|
3
|
+
* one: `x-loam-remove`, `x-loam-based-on`, and the root `x-loam-baselines`
|
|
4
|
+
* record.
|
|
5
|
+
*
|
|
6
|
+
* They are gathered here rather than spread through the merge because they are
|
|
7
|
+
* the vocabulary both ends of the delta path share — `stripOpenapiRemovalMarkers`
|
|
8
|
+
* takes them out for the projection a service repository sees, and the merge
|
|
9
|
+
* takes them out again on the way into the living document. Two spellings of
|
|
10
|
+
* "which keys are feature-only" is how one of the two starts leaking a marker.
|
|
11
|
+
*/
|
|
12
|
+
import { isDeepStrictEqual } from "node:util";
|
|
13
|
+
import { isMap, isScalar } from "yaml";
|
|
14
|
+
// Every `isRecord` below asks one question of a resolved plain tree: is this a
|
|
15
|
+
// node that can hold OpenAPI keys — an object, not an array?
|
|
16
|
+
import { isRecord } from "../../kernel/records.js";
|
|
17
|
+
import { HTTP_METHODS } from "../doc.js";
|
|
18
|
+
import { FEATURE_ONLY_KEYS, isRemoval, operationBaselineOf, withoutFeatureKeysDeep, withoutOperationBaseline, OPENAPI_BASELINE_KEY, OPENAPI_BASELINES_KEY, } from "../digest.js";
|
|
19
|
+
import { setKeyed } from "./components.js";
|
|
20
|
+
import { openapiRefusal } from "./error.js";
|
|
21
|
+
import { readTree, writeTreeOver } from "../contract-tree.js";
|
|
22
|
+
/**
|
|
23
|
+
* Remove feature-only operation-removal markers — and the root
|
|
24
|
+
* `x-loam-baselines` record — before a feature contract is used to create a
|
|
25
|
+
* brand-new living document. Normally coherence refuses the removal shape
|
|
26
|
+
* because there cannot be a removal target; this guard also keeps `--approve`
|
|
27
|
+
* from ever persisting a marker into living docs. The record needs the strip
|
|
28
|
+
* on THIS path even more than the pins do: archive's create branch publishes
|
|
29
|
+
* this function's output verbatim, and a components-only delta has nothing
|
|
30
|
+
* strippable inside `paths` at all — the root key must not ride out on the
|
|
31
|
+
* early returns below.
|
|
32
|
+
*/
|
|
33
|
+
export function stripOpenapiRemovalMarkers(featureText, service) {
|
|
34
|
+
// One refusal for every branch below, so each fails the same way.
|
|
35
|
+
const fail = openapiRefusal("feature", service);
|
|
36
|
+
const { doc: feature, plain } = readTree(featureText, fail);
|
|
37
|
+
const hasRecord = isRecord(plain) && OPENAPI_BASELINES_KEY in plain;
|
|
38
|
+
// Shape from the RESOLVED tree, for the same reason the merge reads it there:
|
|
39
|
+
// an aliased `paths` or path item is not a map node, and treating it as
|
|
40
|
+
// "nothing to strip" is how a feature-only marker reached a living contract.
|
|
41
|
+
const paths = plainChild(plain, "paths");
|
|
42
|
+
if (!isRecord(paths)) {
|
|
43
|
+
if (!hasRecord)
|
|
44
|
+
return featureText;
|
|
45
|
+
feature.deleteIn([OPENAPI_BASELINES_KEY]);
|
|
46
|
+
return writeTreeOver(feature, featureText, fail);
|
|
47
|
+
}
|
|
48
|
+
const cleaned = {};
|
|
49
|
+
let stripped = false;
|
|
50
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
51
|
+
const kept = withoutFeatureMarkers(item);
|
|
52
|
+
if (!isDeepStrictEqual(kept, item))
|
|
53
|
+
stripped = true;
|
|
54
|
+
// A path the strip emptied goes with its last operation: `\/x: {}` is a
|
|
55
|
+
// path the contract advertises and nothing answers.
|
|
56
|
+
if (kept !== undefined)
|
|
57
|
+
cleaned[path] = kept;
|
|
58
|
+
}
|
|
59
|
+
// Component values get the same discipline as path items: a component
|
|
60
|
+
// holding an operation shape (a `pathItems` component, a callback) nests
|
|
61
|
+
// the feature-only keys where the paths walk never looks, and the create
|
|
62
|
+
// branch publishes this function's output verbatim. The write is
|
|
63
|
+
// string-key-matched (setKeyed) so a numeric component name is
|
|
64
|
+
// replaced, never duplicated.
|
|
65
|
+
const comps = plainChild(plain, "components");
|
|
66
|
+
if (isRecord(comps)) {
|
|
67
|
+
for (const [kind, names] of Object.entries(comps)) {
|
|
68
|
+
if (!isRecord(names))
|
|
69
|
+
continue;
|
|
70
|
+
for (const [name, value] of Object.entries(names)) {
|
|
71
|
+
const kept = withoutFeatureKeysDeep(value);
|
|
72
|
+
if (kept !== value) {
|
|
73
|
+
setKeyed(feature, ["components", kind], name, kept);
|
|
74
|
+
stripped = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!stripped) {
|
|
80
|
+
if (!hasRecord)
|
|
81
|
+
return featureText;
|
|
82
|
+
feature.deleteIn([OPENAPI_BASELINES_KEY]);
|
|
83
|
+
return writeTreeOver(feature, featureText, fail);
|
|
84
|
+
}
|
|
85
|
+
// Edit the AST in place when every node the strip touches IS a node — the
|
|
86
|
+
// author's comments, key order and formatting are theirs to keep. An alias
|
|
87
|
+
// cannot be edited in place (there is one shared value behind it, and
|
|
88
|
+
// deleting a key through it would change every use), so those documents get
|
|
89
|
+
// their `paths` rewritten from the resolved tree instead: losing formatting
|
|
90
|
+
// is a cost, shipping the marker is a corruption.
|
|
91
|
+
//
|
|
92
|
+
// The test has to reach the OPERATION nodes too, not just the path items. The
|
|
93
|
+
// in-place branch strips a surviving operation's pin through
|
|
94
|
+
// `["paths", p, m, x-loam-based-on]`, and an aliased operation is exactly one
|
|
95
|
+
// level below where the check used to look — so `deleteIn` walked into a node
|
|
96
|
+
// that is not a collection and threw out of archive as `internal`, on a
|
|
97
|
+
// document whose only fault was writing one operation twice.
|
|
98
|
+
//
|
|
99
|
+
// What disqualifies a method is "there is something here to strip and I cannot
|
|
100
|
+
// reach it", not "this is not a map node". Only a resolved MAPPING can be a
|
|
101
|
+
// removal marker or carry a pin, so a method spelled as a scalar — `get: ~`,
|
|
102
|
+
// or a string — is nothing the in-place branch would have touched; demanding a
|
|
103
|
+
// map node of it too demoted whole documents to the rewrite branch and cost
|
|
104
|
+
// their author every comment, anchor and hand-chosen key order inside `paths`,
|
|
105
|
+
// in the bytes archive installs as the living contract. What is left is the
|
|
106
|
+
// real hazard: a mapping the AST does not hand back as a map. An alias is the
|
|
107
|
+
// one node kind that resolves to a mapping without being one, and a method
|
|
108
|
+
// whose KEY is an alias is not findable by name at all, so `deleteIn` reports
|
|
109
|
+
// nothing deleted and the marker ships in silence. Both answer `undefined` or
|
|
110
|
+
// a non-map here, and both belong on the safe branch.
|
|
111
|
+
const editable = isMap(feature.get("paths")) &&
|
|
112
|
+
Object.entries(paths).every(([p, item]) => isMap(feature.getIn(["paths", p])) &&
|
|
113
|
+
(!isRecord(item) ||
|
|
114
|
+
Object.entries(item).every(([m, op]) => !HTTP_METHODS.has(m) || !isRecord(op) || isMap(feature.getIn(["paths", p, m])))));
|
|
115
|
+
if (!editable) {
|
|
116
|
+
feature.setIn(["paths"], cleaned);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
120
|
+
if (!isRecord(item))
|
|
121
|
+
continue;
|
|
122
|
+
for (const [m, value] of Object.entries(item)) {
|
|
123
|
+
// A loam marker at PATH level, deleted here for the same reason the
|
|
124
|
+
// resolved-tree branch drops it: the two branches must agree exactly
|
|
125
|
+
// about what a living contract may carry.
|
|
126
|
+
if (FEATURE_ONLY_KEYS.has(m))
|
|
127
|
+
feature.deleteIn(["paths", path, m]);
|
|
128
|
+
if (!HTTP_METHODS.has(m))
|
|
129
|
+
continue;
|
|
130
|
+
if (isRemoval(value))
|
|
131
|
+
feature.deleteIn(["paths", path, m]);
|
|
132
|
+
// The surviving operations keep their formatting but lose their pin:
|
|
133
|
+
// the in-place branch must strip everything the resolved-tree branch
|
|
134
|
+
// does, or the two disagree about what a living contract may carry.
|
|
135
|
+
else if (operationBaselineOf(value) !== undefined) {
|
|
136
|
+
feature.deleteIn(["paths", path, m, OPENAPI_BASELINE_KEY]);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// The merge's twin: no OPERATIONS left means the path goes, surviving
|
|
140
|
+
// path-level keys included — `{}` was only the easy shape of dead.
|
|
141
|
+
dropPathIfNoOperations(feature, path);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// The root record goes on BOTH serialization branches: it is feature
|
|
145
|
+
// bookkeeping exactly like the pins, and the rewrite branch above replaced
|
|
146
|
+
// only `paths`, so the root key survives either way without this.
|
|
147
|
+
if (hasRecord)
|
|
148
|
+
feature.deleteIn([OPENAPI_BASELINES_KEY]);
|
|
149
|
+
return writeTreeOver(feature, featureText, fail);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Removing the last method leaves a path the contract still advertises and
|
|
153
|
+
* nothing answers — and `{}` is only the easy shape of that state: a surviving
|
|
154
|
+
* path-LEVEL key (`parameters`, `summary`) kept the path alive with zero
|
|
155
|
+
* operations just as misleadingly. No methods left means the path goes,
|
|
156
|
+
* whatever else survived beside them. One cleanup for both sides of the delta
|
|
157
|
+
* path, so they cannot disagree about it: the merge runs it on the living
|
|
158
|
+
* document, the strip on the feature's.
|
|
159
|
+
*/
|
|
160
|
+
export function dropPathIfNoOperations(doc, path) {
|
|
161
|
+
const remaining = doc.getIn(["paths", path]);
|
|
162
|
+
if (isMap(remaining) && !remaining.items.some((it) => isScalar(it.key) && HTTP_METHODS.has(String(it.key.value)))) {
|
|
163
|
+
doc.deleteIn(["paths", path]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export function opLabel(before, after, method, path) {
|
|
167
|
+
const operation = operationIdOf(after) ?? operationIdOf(before);
|
|
168
|
+
return operation !== undefined ? `'${operation}' (${method} ${path})` : `${method} ${path}`;
|
|
169
|
+
}
|
|
170
|
+
/** Read an operationId from a YAML or plain operation node. */
|
|
171
|
+
export function operationIdOf(node) {
|
|
172
|
+
const value = isMap(node)
|
|
173
|
+
? node.get("operationId")
|
|
174
|
+
: node !== null && typeof node === "object"
|
|
175
|
+
? node["operationId"]
|
|
176
|
+
: undefined;
|
|
177
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Copy a path item without anything that belongs to the FEATURE rather than to
|
|
181
|
+
* the contract: removal-marker operations, the `x-loam-based-on` pins on the
|
|
182
|
+
* operations that survive, and a loam marker written at PATH level. All three
|
|
183
|
+
* are instructions to loam, and a living contract that carries any of them is
|
|
184
|
+
* lying to the next reader — and, for the pin, to the next feature's baseline.
|
|
185
|
+
*
|
|
186
|
+
* The path-level case used to fall through: the filter guarded only HTTP
|
|
187
|
+
* methods, so `x-loam-remove: true` beside the methods was copied verbatim into
|
|
188
|
+
* the fleet's living contract, where it also kept the empty-path cleanup from
|
|
189
|
+
* ever seeing an empty path.
|
|
190
|
+
*/
|
|
191
|
+
export function withoutFeatureMarkers(node) {
|
|
192
|
+
if (node === null || typeof node !== "object" || Array.isArray(node))
|
|
193
|
+
return node;
|
|
194
|
+
const entries = Object.entries(node)
|
|
195
|
+
.filter(([key, value]) => !FEATURE_ONLY_KEYS.has(key) && !(HTTP_METHODS.has(key) && isRemoval(value)))
|
|
196
|
+
.map(([key, value]) => [key, HTTP_METHODS.has(key) ? withoutOperationBaseline(value) : value]);
|
|
197
|
+
return entries.length === 0 ? undefined : Object.fromEntries(entries);
|
|
198
|
+
}
|
|
199
|
+
export function plainChild(parent, key) {
|
|
200
|
+
return parent !== null && typeof parent === "object"
|
|
201
|
+
? parent[key]
|
|
202
|
+
: undefined;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=markers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markers.js","sourceRoot":"","sources":["../../../../src/core/openapi/merge/markers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The keys loam adds to a feature's contract that must never reach the living\n * one: `x-loam-remove`, `x-loam-based-on`, and the root `x-loam-baselines`\n * record.\n *\n * They are gathered here rather than spread through the merge because they are\n * the vocabulary both ends of the delta path share — `stripOpenapiRemovalMarkers`\n * takes them out for the projection a service repository sees, and the merge\n * takes them out again on the way into the living document. Two spellings of\n * \"which keys are feature-only\" is how one of the two starts leaking a marker.\n */\nimport { isDeepStrictEqual } from \"node:util\";\nimport { isMap, isScalar, type Document } from \"yaml\";\n// Every `isRecord` below asks one question of a resolved plain tree: is this a\n// node that can hold OpenAPI keys — an object, not an array?\nimport { isRecord } from \"../../kernel/records.js\";\nimport { HTTP_METHODS } from \"../doc.js\";\nimport {\n FEATURE_ONLY_KEYS,\n isRemoval,\n operationBaselineOf,\n withoutFeatureKeysDeep,\n withoutOperationBaseline,\n OPENAPI_BASELINE_KEY,\n OPENAPI_BASELINES_KEY,\n} from \"../digest.js\";\nimport { setKeyed } from \"./components.js\";\nimport { openapiRefusal } from \"./error.js\";\nimport { readTree, writeTreeOver } from \"../contract-tree.js\";\n\n/**\n * Remove feature-only operation-removal markers — and the root\n * `x-loam-baselines` record — before a feature contract is used to create a\n * brand-new living document. Normally coherence refuses the removal shape\n * because there cannot be a removal target; this guard also keeps `--approve`\n * from ever persisting a marker into living docs. The record needs the strip\n * on THIS path even more than the pins do: archive's create branch publishes\n * this function's output verbatim, and a components-only delta has nothing\n * strippable inside `paths` at all — the root key must not ride out on the\n * early returns below.\n */\nexport function stripOpenapiRemovalMarkers(featureText: string, service: string): string {\n // One refusal for every branch below, so each fails the same way.\n const fail = openapiRefusal(\"feature\", service);\n const { doc: feature, plain } = readTree(featureText, fail);\n const hasRecord = isRecord(plain) && OPENAPI_BASELINES_KEY in plain;\n // Shape from the RESOLVED tree, for the same reason the merge reads it there:\n // an aliased `paths` or path item is not a map node, and treating it as\n // \"nothing to strip\" is how a feature-only marker reached a living contract.\n const paths = plainChild(plain, \"paths\");\n if (!isRecord(paths)) {\n if (!hasRecord) return featureText;\n feature.deleteIn([OPENAPI_BASELINES_KEY]);\n return writeTreeOver(feature, featureText, fail);\n }\n\n const cleaned: Record<string, unknown> = {};\n let stripped = false;\n for (const [path, item] of Object.entries(paths)) {\n const kept = withoutFeatureMarkers(item);\n if (!isDeepStrictEqual(kept, item)) stripped = true;\n // A path the strip emptied goes with its last operation: `\\/x: {}` is a\n // path the contract advertises and nothing answers.\n if (kept !== undefined) cleaned[path] = kept;\n }\n // Component values get the same discipline as path items: a component\n // holding an operation shape (a `pathItems` component, a callback) nests\n // the feature-only keys where the paths walk never looks, and the create\n // branch publishes this function's output verbatim. The write is\n // string-key-matched (setKeyed) so a numeric component name is\n // replaced, never duplicated.\n const comps = plainChild(plain, \"components\");\n if (isRecord(comps)) {\n for (const [kind, names] of Object.entries(comps)) {\n if (!isRecord(names)) continue;\n for (const [name, value] of Object.entries(names)) {\n const kept = withoutFeatureKeysDeep(value);\n if (kept !== value) {\n setKeyed(feature, [\"components\", kind], name, kept);\n stripped = true;\n }\n }\n }\n }\n\n if (!stripped) {\n if (!hasRecord) return featureText;\n feature.deleteIn([OPENAPI_BASELINES_KEY]);\n return writeTreeOver(feature, featureText, fail);\n }\n\n // Edit the AST in place when every node the strip touches IS a node — the\n // author's comments, key order and formatting are theirs to keep. An alias\n // cannot be edited in place (there is one shared value behind it, and\n // deleting a key through it would change every use), so those documents get\n // their `paths` rewritten from the resolved tree instead: losing formatting\n // is a cost, shipping the marker is a corruption.\n //\n // The test has to reach the OPERATION nodes too, not just the path items. The\n // in-place branch strips a surviving operation's pin through\n // `[\"paths\", p, m, x-loam-based-on]`, and an aliased operation is exactly one\n // level below where the check used to look — so `deleteIn` walked into a node\n // that is not a collection and threw out of archive as `internal`, on a\n // document whose only fault was writing one operation twice.\n //\n // What disqualifies a method is \"there is something here to strip and I cannot\n // reach it\", not \"this is not a map node\". Only a resolved MAPPING can be a\n // removal marker or carry a pin, so a method spelled as a scalar — `get: ~`,\n // or a string — is nothing the in-place branch would have touched; demanding a\n // map node of it too demoted whole documents to the rewrite branch and cost\n // their author every comment, anchor and hand-chosen key order inside `paths`,\n // in the bytes archive installs as the living contract. What is left is the\n // real hazard: a mapping the AST does not hand back as a map. An alias is the\n // one node kind that resolves to a mapping without being one, and a method\n // whose KEY is an alias is not findable by name at all, so `deleteIn` reports\n // nothing deleted and the marker ships in silence. Both answer `undefined` or\n // a non-map here, and both belong on the safe branch.\n const editable =\n isMap(feature.get(\"paths\")) &&\n Object.entries(paths).every(\n ([p, item]) =>\n isMap(feature.getIn([\"paths\", p])) &&\n (!isRecord(item) ||\n Object.entries(item).every(\n ([m, op]) => !HTTP_METHODS.has(m) || !isRecord(op) || isMap(feature.getIn([\"paths\", p, m])),\n )),\n );\n if (!editable) {\n feature.setIn([\"paths\"], cleaned);\n } else {\n for (const [path, item] of Object.entries(paths)) {\n if (!isRecord(item)) continue;\n for (const [m, value] of Object.entries(item)) {\n // A loam marker at PATH level, deleted here for the same reason the\n // resolved-tree branch drops it: the two branches must agree exactly\n // about what a living contract may carry.\n if (FEATURE_ONLY_KEYS.has(m)) feature.deleteIn([\"paths\", path, m]);\n if (!HTTP_METHODS.has(m)) continue;\n if (isRemoval(value)) feature.deleteIn([\"paths\", path, m]);\n // The surviving operations keep their formatting but lose their pin:\n // the in-place branch must strip everything the resolved-tree branch\n // does, or the two disagree about what a living contract may carry.\n else if (operationBaselineOf(value) !== undefined) {\n feature.deleteIn([\"paths\", path, m, OPENAPI_BASELINE_KEY]);\n }\n }\n // The merge's twin: no OPERATIONS left means the path goes, surviving\n // path-level keys included — `{}` was only the easy shape of dead.\n dropPathIfNoOperations(feature, path);\n }\n }\n // The root record goes on BOTH serialization branches: it is feature\n // bookkeeping exactly like the pins, and the rewrite branch above replaced\n // only `paths`, so the root key survives either way without this.\n if (hasRecord) feature.deleteIn([OPENAPI_BASELINES_KEY]);\n return writeTreeOver(feature, featureText, fail);\n}\n\n/**\n * Removing the last method leaves a path the contract still advertises and\n * nothing answers — and `{}` is only the easy shape of that state: a surviving\n * path-LEVEL key (`parameters`, `summary`) kept the path alive with zero\n * operations just as misleadingly. No methods left means the path goes,\n * whatever else survived beside them. One cleanup for both sides of the delta\n * path, so they cannot disagree about it: the merge runs it on the living\n * document, the strip on the feature's.\n */\nexport function dropPathIfNoOperations(doc: Document, path: string): void {\n const remaining = doc.getIn([\"paths\", path]);\n if (isMap(remaining) && !remaining.items.some((it) => isScalar(it.key) && HTTP_METHODS.has(String(it.key.value)))) {\n doc.deleteIn([\"paths\", path]);\n }\n}\n\nexport function opLabel(before: unknown, after: unknown, method: string, path: string): string {\n const operation = operationIdOf(after) ?? operationIdOf(before);\n return operation !== undefined ? `'${operation}' (${method} ${path})` : `${method} ${path}`;\n}\n\n/** Read an operationId from a YAML or plain operation node. */\nexport function operationIdOf(node: unknown): string | undefined {\n const value = isMap(node)\n ? node.get(\"operationId\")\n : node !== null && typeof node === \"object\"\n ? (node as Record<string, unknown>)[\"operationId\"]\n : undefined;\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n\n\n/**\n * Copy a path item without anything that belongs to the FEATURE rather than to\n * the contract: removal-marker operations, the `x-loam-based-on` pins on the\n * operations that survive, and a loam marker written at PATH level. All three\n * are instructions to loam, and a living contract that carries any of them is\n * lying to the next reader — and, for the pin, to the next feature's baseline.\n *\n * The path-level case used to fall through: the filter guarded only HTTP\n * methods, so `x-loam-remove: true` beside the methods was copied verbatim into\n * the fleet's living contract, where it also kept the empty-path cleanup from\n * ever seeing an empty path.\n */\nexport function withoutFeatureMarkers(node: unknown): unknown {\n if (node === null || typeof node !== \"object\" || Array.isArray(node)) return node;\n const entries = Object.entries(node as Record<string, unknown>)\n .filter(([key, value]) => !FEATURE_ONLY_KEYS.has(key) && !(HTTP_METHODS.has(key) && isRemoval(value)))\n .map(([key, value]) => [key, HTTP_METHODS.has(key) ? withoutOperationBaseline(value) : value] as const);\n return entries.length === 0 ? undefined : Object.fromEntries(entries);\n}\n\nexport function plainChild(parent: unknown, key: string): unknown {\n return parent !== null && typeof parent === \"object\"\n ? (parent as Record<string, unknown>)[key]\n : undefined;\n}\n"]}
|