@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 @@
|
|
|
1
|
+
{"version":3,"file":"verdict-lines.js","sourceRoot":"","sources":["../../../../../src/commands/archive/plan/contracts/verdict-lines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The plan lines a contract merge's verdicts print — the quote, the stale\n * baseline, the overwrite and the `info` the merge does not carry — spelled\n * once for both planners\n * (./openapi.ts, ./asyncapi.ts), which used to print them in fourteen parallel\n * loops. Every surface reaches the reader by exactly the same sentence an\n * operation or a slot does, because it is graded by exactly the same verdict;\n * one spelling is what keeps the two axes from describing one verdict in two\n * sentences. The label prefix (`path-level …`, `component …`, `components.…`)\n * stays at the call site: it is the one part that differs.\n */\nimport { isDeepStrictEqual } from \"node:util\";\nimport { withoutFeatureKeysDeep } from \"../../../../core/openapi/digest.js\";\nimport { isRecord } from \"../../../../core/kernel/records.js\";\nimport { compareIds } from \"../../../../core/repo/entries.js\";\nimport type { IssueCode } from \"../../../../core/vocabulary/issue.js\";\nimport type { Plan } from \"../state.js\";\n\ntype Say = (line?: string) => void;\n\n/**\n * Said out loud, because \"the plan wrote less than my delta spells\" is the one\n * thing a reader cannot infer from a merged file. Not a warning: quoting the\n * contract around your change is correct authoring, and leaving the quote\n * alone is the correct merge. The path-level and component quotes get the\n * same sentence for the same reason.\n */\nexport function sayQuoted(say: Say, labels: readonly string[]): void {\n for (const label of labels) say(` · quotes ${label} — unchanged since it was pinned, left as living has it`);\n}\n\n/**\n * Stale surfaces reaching the merge at all means --approve pushed past the\n * gate's `openapi.baseline-stale` / `asyncapi.baseline-stale` — the plan still\n * names what it cost.\n */\nexport function sayStale(say: Say, labels: readonly string[]): void {\n for (const label of labels) {\n say(` ⚠ stale baseline on ${label} — the living value moved since this delta was pinned; the overwrite is what --approve chose`);\n }\n}\n\n/** One overwrite the plan warns about. The code is spelled literally at each call site. */\nexport interface Overwrite {\n svc: string;\n code: IssueCode;\n /** What the printed line names: the label with its prefix. */\n label: string;\n /** The warning's sentence, before any consumer clause. */\n message: string;\n /** Who the overwrite lands on (./consumers.ts), or absent where nothing can name it. */\n named?: { clause: string; details: string[] } | null;\n}\n\n/**\n * Warn about one overwrite and print it. The consumer clause, when there is\n * one, ends both the warning's message and the printed line, and its evidence\n * rides as the warning's `details` and as indented lines under it.\n */\nexport function warnOverwrite(plan: Pick<Plan, \"planWarns\">, say: Say, overwrite: Overwrite): void {\n const named = overwrite.named ?? null;\n const clause = named === null ? \"\" : `; ${named.clause}`;\n plan.planWarns.push({\n severity: \"warn\",\n code: overwrite.code,\n subject: overwrite.svc,\n message: overwrite.message + clause,\n ...(named === null ? {} : { details: named.details }),\n });\n say(` ⚠ overwrites ${overwrite.label} — the living definition differs${clause}`);\n for (const line of named?.details ?? []) say(` ${line}`);\n}\n\n/**\n * The `info` keys a feature's contract spells differently from the living one,\n * as `info.<key>` labels, sorted — empty when the delta writes no `info`, or\n * writes exactly what living has.\n *\n * Neither merge carries `info` (nor any root key outside the sections it\n * merges: `../../../../core/asyncapi/merge/markers.ts` names what those are),\n * and that is a decision rather than a gap — a delta is a diff of operations\n * and slots, and its `info` is most often the scaffold's or a copy. But a\n * delta that DID move it — a new version, a rewritten description — lost the\n * change with exit 0 and nothing in the plan, so the reader learned it from\n * the living file weeks later. Only keys the delta declares are compared: a\n * key living has and the delta leaves out is a key nobody asked to change.\n * Feature bookkeeping is never compared: an `x-loam-*` key of `info` itself is\n * skipped, and the merges' own markers are stripped from the values below it\n * (`withoutFeatureKeysDeep`), so a pin can never read as drift.\n */\nexport function infoDrift(livingPlain: unknown, featurePlain: unknown): string[] {\n const feature = isRecord(featurePlain) ? featurePlain.info : undefined;\n if (!isRecord(feature)) return [];\n const living = isRecord(livingPlain) && isRecord(livingPlain.info) ? livingPlain.info : {};\n return Object.keys(feature)\n .filter((key) => !key.startsWith(\"x-loam-\"))\n .filter((key) => !isDeepStrictEqual(withoutFeatureKeysDeep(feature[key]), living[key]))\n .map((key) => `info.${key}`)\n .sort(compareIds);\n}\n\n/** Which contract the drift is about, the code it is reported under, and what the merge carries instead. */\nexport interface InfoDrift {\n svc: string;\n code: IssueCode;\n /** `openapi.yaml` or `asyncapi.yaml` — the living file the author edits instead. */\n file: string;\n /** What the merge DOES carry, in the words the warning prints. */\n carries: string;\n labels: readonly string[];\n}\n\n/**\n * Warn about one contract's `info` drift and print it. A warning, not a gate:\n * keeping the living `info` is the merge working as designed, and the remedy —\n * edit the living file in the same change — is the author's call. What must\n * not happen is the silence.\n */\nexport function warnInfoDrift(plan: Pick<Plan, \"planWarns\">, say: Say, drift: InfoDrift): void {\n if (drift.labels.length === 0) return;\n const which = drift.labels.join(\", \");\n plan.planWarns.push({\n severity: \"warn\",\n code: drift.code,\n subject: drift.svc,\n message:\n `${drift.svc}: the delta's ${which} differ(s) from the living ${drift.file} — the merge carries ${drift.carries} and never ` +\n `info, so the living contract keeps its own. If it should move, edit the living ${drift.file} in this change.`,\n });\n say(` ⚠ info not merged — the delta's ${which} differ(s) from the living ${drift.file}, which keeps its own`);\n}\n"]}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a living document that `loam archive` CREATES says above
|
|
3
|
+
* `## Requirements` — the part of a new service spec, architecture spec or
|
|
4
|
+
* capability document that the requirement algebra has nothing to say about.
|
|
5
|
+
*
|
|
6
|
+
* THE DEFECT THIS CLOSES. A created document used to be a fixed header —
|
|
7
|
+
* `service`, `status: draft`, `# <id>` — and the requirements. Everything else
|
|
8
|
+
* the delta said was dropped in silence: its title, the narrative a reader
|
|
9
|
+
* needs before the first requirement, the frontmatter `owner`, any section
|
|
10
|
+
* written after the last delta section. The requirements arrived byte for byte
|
|
11
|
+
* and the document arrived unreadable to anyone who had not read the delta.
|
|
12
|
+
*
|
|
13
|
+
* WHY NOT CARRY THE WHOLE PREAMBLE. "loam merges requirements, never prose"
|
|
14
|
+
* (SCHEMA) is not an aversion to prose; it is the observation that a delta's
|
|
15
|
+
* prose is ABOUT THE CHANGE. The scaffold's own H1 is "<svc> — requirement
|
|
16
|
+
* delta for <FEAT>" and its intro tells the reviewer what a delta is; carrying
|
|
17
|
+
* either into the living document would make it describe a pull request that
|
|
18
|
+
* merged months ago. A machine cannot tell narrative about the service from
|
|
19
|
+
* narrative about the change, so loam carries only what the author MARKED as
|
|
20
|
+
* the document's own, and says where the rest is:
|
|
21
|
+
*
|
|
22
|
+
* - `owner` from the delta's frontmatter — the one field that describes the
|
|
23
|
+
* service rather than the change or a vouch (copying `vouched_by` or a digest
|
|
24
|
+
* would forge a review nobody performed). A capability document carries no
|
|
25
|
+
* frontmatter by decision (`planCapabilities` says why), so it gets none.
|
|
26
|
+
* - the delta's H1, unless it is about the change — it names the feature or
|
|
27
|
+
* calls itself a delta, which is exactly what the scaffold writes.
|
|
28
|
+
* - the delta's `## Purpose` section, verbatim — the explicit marker, and the
|
|
29
|
+
* one OpenSpec's living specs already use for the document's own narrative.
|
|
30
|
+
* - a back-link to the archived delta, always, so nothing the merge left behind
|
|
31
|
+
* is unreachable from the document it created.
|
|
32
|
+
*
|
|
33
|
+
* Only on CREATION. A living document that already exists keeps its own
|
|
34
|
+
* narrative, edited in place; a `## Purpose` in a delta against it merges as
|
|
35
|
+
* nothing, and `planSpecs` says so rather than letting it vanish.
|
|
36
|
+
*/
|
|
37
|
+
import { dirname, relative, sep } from "node:path";
|
|
38
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
39
|
+
import { parseFrontmatter, stringField } from "../../../../core/document/frontmatter.js";
|
|
40
|
+
import { serializeRequirements } from "../../../../core/document/spec.js";
|
|
41
|
+
import { repoPath } from "../../../../core/envelope/json.js";
|
|
42
|
+
import { fenceTracker } from "../../../../core/kernel/fences.js";
|
|
43
|
+
/** A level-1 heading line. */
|
|
44
|
+
const H1_RE = /^#\s+(.+?)\s*$/;
|
|
45
|
+
/** The marked section — matched on the whole trimmed line, case-insensitively, like `## Requirements`. */
|
|
46
|
+
const PURPOSE_RE = /^##\s+Purpose\s*$/i;
|
|
47
|
+
/** Where a section ends: the next H1 or H2. Deeper headings are the section's own. */
|
|
48
|
+
const SECTION_END_RE = /^#{1,2}\s/;
|
|
49
|
+
/**
|
|
50
|
+
* The created document's whole text, and the one line that tells the person
|
|
51
|
+
* reading the plan what came across from the delta and where the rest is.
|
|
52
|
+
*/
|
|
53
|
+
export function createdDocument(request) {
|
|
54
|
+
const archived = request.retarget(request.deltaPath);
|
|
55
|
+
// Percent-escaped spaces, as `rebaseLinks` writes a route it computed: a bare
|
|
56
|
+
// space would end the link target at the first word.
|
|
57
|
+
const backLink = relative(dirname(request.livingPath), archived).split(sep).join("/").split(" ").join("%20");
|
|
58
|
+
const head = createdHead({ ...request, backLink });
|
|
59
|
+
const where = repoPath(request.docsDir, archived);
|
|
60
|
+
const note = head.carried.length > 0
|
|
61
|
+
? `carried from the delta: ${head.carried.join(", ")} — the rest of its prose stays in ${where}, linked from the new document`
|
|
62
|
+
: `the delta's prose stays in ${where}, linked from the new document — mark what belongs here '## Purpose' and archive carries it`;
|
|
63
|
+
return { text: `${head.text}## Requirements\n\n${serializeRequirements(request.requirements)}`, note };
|
|
64
|
+
}
|
|
65
|
+
/** The head of a document archive creates — see the module comment for what goes in it and why. */
|
|
66
|
+
function createdHead(request) {
|
|
67
|
+
const fm = parseFrontmatter(request.delta);
|
|
68
|
+
const marked = markedParts(fm.body, request.featureId);
|
|
69
|
+
const owner = request.service === null ? undefined : stringField(fm, "owner");
|
|
70
|
+
const carried = [];
|
|
71
|
+
let text = "";
|
|
72
|
+
if (request.service !== null) {
|
|
73
|
+
const fields = {
|
|
74
|
+
service: request.service,
|
|
75
|
+
status: "draft",
|
|
76
|
+
...(request.adoption === undefined ? {} : { adoption: request.adoption }),
|
|
77
|
+
...(owner === undefined ? {} : { owner }),
|
|
78
|
+
};
|
|
79
|
+
text += `---\n${stringifyYaml(fields, { lineWidth: 0 })}---\n\n`;
|
|
80
|
+
if (owner !== undefined)
|
|
81
|
+
carried.push("owner");
|
|
82
|
+
}
|
|
83
|
+
text += `# ${marked.title ?? request.fallbackTitle}\n\n`;
|
|
84
|
+
if (marked.title !== undefined)
|
|
85
|
+
carried.push("its title");
|
|
86
|
+
text += `Created when ${request.featureId} was archived; [its delta](${request.backLink}) keeps the prose written for that change.\n\n`;
|
|
87
|
+
if (marked.purpose !== undefined) {
|
|
88
|
+
text += `## Purpose\n\n${marked.purpose}\n\n`;
|
|
89
|
+
carried.push("its ## Purpose");
|
|
90
|
+
}
|
|
91
|
+
return { text, carried };
|
|
92
|
+
}
|
|
93
|
+
/** Does the delta carry a `## Purpose` section at all — the question a merge into an EXISTING document asks. */
|
|
94
|
+
export function hasPurpose(delta) {
|
|
95
|
+
return markedParts(parseFrontmatter(delta).body, "").purpose !== undefined;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Is this H1 the CHANGE's title rather than the document's? Two mechanical
|
|
99
|
+
* signals, both in words loam owns: it names the feature, or it calls itself a
|
|
100
|
+
* delta — which no living document does, and which every delta title loam
|
|
101
|
+
* scaffolds does both of ("<svc> — requirement delta for <FEAT>"). Anything
|
|
102
|
+
* else is a title an author chose for the thing itself, the shape a domain
|
|
103
|
+
* written into a feature in one go arrives in.
|
|
104
|
+
*/
|
|
105
|
+
function namesTheChange(title, featureId) {
|
|
106
|
+
const lower = title.toLowerCase();
|
|
107
|
+
return (featureId !== "" && lower.includes(featureId.toLowerCase())) || /\bdelta\b/.test(lower);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The delta's title and `## Purpose` body, each only when the author wrote one
|
|
111
|
+
* that belongs to the living document. Fence-aware, like every heading walk in
|
|
112
|
+
* loam: a heading inside a fenced block is quoted text, and a fenced block
|
|
113
|
+
* inside the Purpose is part of it.
|
|
114
|
+
*/
|
|
115
|
+
function markedParts(body, featureId) {
|
|
116
|
+
const fenced = fenceTracker();
|
|
117
|
+
let title;
|
|
118
|
+
let seenSection = false;
|
|
119
|
+
let purpose = null;
|
|
120
|
+
let purposeEnded = false;
|
|
121
|
+
for (const line of body.split(/\r?\n/)) {
|
|
122
|
+
const quoted = fenced(line);
|
|
123
|
+
if (purpose !== null && !purposeEnded) {
|
|
124
|
+
if (quoted || !SECTION_END_RE.test(line)) {
|
|
125
|
+
purpose.push(line);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
purposeEnded = true;
|
|
129
|
+
}
|
|
130
|
+
if (quoted)
|
|
131
|
+
continue;
|
|
132
|
+
const h1 = H1_RE.exec(line);
|
|
133
|
+
// The document's title is an H1 above its first section; one further down
|
|
134
|
+
// is a heading inside the text, not the name of the document.
|
|
135
|
+
if (h1 !== null && !seenSection && title === undefined)
|
|
136
|
+
title = h1[1];
|
|
137
|
+
if (/^##\s/.test(line)) {
|
|
138
|
+
seenSection = true;
|
|
139
|
+
if (purpose === null && PURPOSE_RE.test(line.trim()))
|
|
140
|
+
purpose = [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Blank LINES trimmed, never leading spaces: an indented code block opening
|
|
144
|
+
// the section is the author's text.
|
|
145
|
+
const purposeText = purpose?.join("\n").replace(/^(?:[ \t]*\n)+/, "").trimEnd();
|
|
146
|
+
return {
|
|
147
|
+
...(title === undefined || namesTheChange(title, featureId) ? {} : { title }),
|
|
148
|
+
...(purposeText === undefined || purposeText === "" ? {} : { purpose: purposeText }),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=head.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"head.js","sourceRoot":"","sources":["../../../../../src/commands/archive/plan/document/head.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a living document that `loam archive` CREATES says above\n * `## Requirements` — the part of a new service spec, architecture spec or\n * capability document that the requirement algebra has nothing to say about.\n *\n * THE DEFECT THIS CLOSES. A created document used to be a fixed header —\n * `service`, `status: draft`, `# <id>` — and the requirements. Everything else\n * the delta said was dropped in silence: its title, the narrative a reader\n * needs before the first requirement, the frontmatter `owner`, any section\n * written after the last delta section. The requirements arrived byte for byte\n * and the document arrived unreadable to anyone who had not read the delta.\n *\n * WHY NOT CARRY THE WHOLE PREAMBLE. \"loam merges requirements, never prose\"\n * (SCHEMA) is not an aversion to prose; it is the observation that a delta's\n * prose is ABOUT THE CHANGE. The scaffold's own H1 is \"<svc> — requirement\n * delta for <FEAT>\" and its intro tells the reviewer what a delta is; carrying\n * either into the living document would make it describe a pull request that\n * merged months ago. A machine cannot tell narrative about the service from\n * narrative about the change, so loam carries only what the author MARKED as\n * the document's own, and says where the rest is:\n *\n * - `owner` from the delta's frontmatter — the one field that describes the\n * service rather than the change or a vouch (copying `vouched_by` or a digest\n * would forge a review nobody performed). A capability document carries no\n * frontmatter by decision (`planCapabilities` says why), so it gets none.\n * - the delta's H1, unless it is about the change — it names the feature or\n * calls itself a delta, which is exactly what the scaffold writes.\n * - the delta's `## Purpose` section, verbatim — the explicit marker, and the\n * one OpenSpec's living specs already use for the document's own narrative.\n * - a back-link to the archived delta, always, so nothing the merge left behind\n * is unreachable from the document it created.\n *\n * Only on CREATION. A living document that already exists keeps its own\n * narrative, edited in place; a `## Purpose` in a delta against it merges as\n * nothing, and `planSpecs` says so rather than letting it vanish.\n */\nimport { dirname, relative, sep } from \"node:path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { parseFrontmatter, stringField } from \"../../../../core/document/frontmatter.js\";\nimport { serializeRequirements, type Requirement } from \"../../../../core/document/spec.js\";\nimport { repoPath } from \"../../../../core/envelope/json.js\";\nimport { fenceTracker } from \"../../../../core/kernel/fences.js\";\nimport type { DocsDir } from \"../../../../core/kernel/ids/dirs.js\";\nimport type { Retarget } from \"./links.js\";\n\n/** A level-1 heading line. */\nconst H1_RE = /^#\\s+(.+?)\\s*$/;\n/** The marked section — matched on the whole trimmed line, case-insensitively, like `## Requirements`. */\nconst PURPOSE_RE = /^##\\s+Purpose\\s*$/i;\n/** Where a section ends: the next H1 or H2. Deeper headings are the section's own. */\nconst SECTION_END_RE = /^#{1,2}\\s/;\n\n/** One living document this archive creates, and the delta it is created from. */\nexport interface CreatedRequest {\n docsDir: DocsDir;\n featureId: string;\n /** The delta's path, where it sits BEFORE the archive moves the feature. */\n deltaPath: string;\n /** The delta's text, its links already re-expressed for `livingPath`'s directory. */\n delta: string;\n livingPath: string;\n /** Where each feature file will be after the archive — the back-link's target comes from it. */\n retarget: Retarget;\n /** The heading written when the delta carries no title of its own. */\n fallbackTitle: string;\n /** The `service:` the created frontmatter names; null for a document that carries no frontmatter. */\n service: string | null;\n /**\n * `partial` when the document is a service's FIRST spec.md and the service\n * existed before this feature — so what lands is the feature's slice and\n * not the service. Written to the frontmatter as `adoption: partial`\n * (SCHEMA.md), which the maturity ladder and `loam status` read as \"not\n * adopted yet\" until a person deletes the line.\n */\n adoption?: \"partial\";\n requirements: Requirement[];\n}\n\n/**\n * The created document's whole text, and the one line that tells the person\n * reading the plan what came across from the delta and where the rest is.\n */\nexport function createdDocument(request: CreatedRequest): { text: string; note: string } {\n const archived = request.retarget(request.deltaPath);\n // Percent-escaped spaces, as `rebaseLinks` writes a route it computed: a bare\n // space would end the link target at the first word.\n const backLink = relative(dirname(request.livingPath), archived).split(sep).join(\"/\").split(\" \").join(\"%20\");\n const head = createdHead({ ...request, backLink });\n const where = repoPath(request.docsDir, archived);\n const note =\n head.carried.length > 0\n ? `carried from the delta: ${head.carried.join(\", \")} — the rest of its prose stays in ${where}, linked from the new document`\n : `the delta's prose stays in ${where}, linked from the new document — mark what belongs here '## Purpose' and archive carries it`;\n return { text: `${head.text}## Requirements\\n\\n${serializeRequirements(request.requirements)}`, note };\n}\n\ninterface HeadRequest {\n delta: string;\n featureId: string;\n fallbackTitle: string;\n service: string | null;\n adoption?: \"partial\";\n /** The created document's relative link to the archived delta. */\n backLink: string;\n}\n\ninterface CreatedHead {\n /** Everything above `## Requirements`, ending in a blank line. */\n text: string;\n /** What the delta contributed, in the words the per-file note prints. */\n carried: string[];\n}\n\n/** The head of a document archive creates — see the module comment for what goes in it and why. */\nfunction createdHead(request: HeadRequest): CreatedHead {\n const fm = parseFrontmatter(request.delta);\n const marked = markedParts(fm.body, request.featureId);\n const owner = request.service === null ? undefined : stringField(fm, \"owner\");\n const carried: string[] = [];\n let text = \"\";\n if (request.service !== null) {\n const fields = {\n service: request.service,\n status: \"draft\",\n ...(request.adoption === undefined ? {} : { adoption: request.adoption }),\n ...(owner === undefined ? {} : { owner }),\n };\n text += `---\\n${stringifyYaml(fields, { lineWidth: 0 })}---\\n\\n`;\n if (owner !== undefined) carried.push(\"owner\");\n }\n text += `# ${marked.title ?? request.fallbackTitle}\\n\\n`;\n if (marked.title !== undefined) carried.push(\"its title\");\n text += `Created when ${request.featureId} was archived; [its delta](${request.backLink}) keeps the prose written for that change.\\n\\n`;\n if (marked.purpose !== undefined) {\n text += `## Purpose\\n\\n${marked.purpose}\\n\\n`;\n carried.push(\"its ## Purpose\");\n }\n return { text, carried };\n}\n\n/** Does the delta carry a `## Purpose` section at all — the question a merge into an EXISTING document asks. */\nexport function hasPurpose(delta: string): boolean {\n return markedParts(parseFrontmatter(delta).body, \"\").purpose !== undefined;\n}\n\n/**\n * Is this H1 the CHANGE's title rather than the document's? Two mechanical\n * signals, both in words loam owns: it names the feature, or it calls itself a\n * delta — which no living document does, and which every delta title loam\n * scaffolds does both of (\"<svc> — requirement delta for <FEAT>\"). Anything\n * else is a title an author chose for the thing itself, the shape a domain\n * written into a feature in one go arrives in.\n */\nfunction namesTheChange(title: string, featureId: string): boolean {\n const lower = title.toLowerCase();\n return (featureId !== \"\" && lower.includes(featureId.toLowerCase())) || /\\bdelta\\b/.test(lower);\n}\n\n/**\n * The delta's title and `## Purpose` body, each only when the author wrote one\n * that belongs to the living document. Fence-aware, like every heading walk in\n * loam: a heading inside a fenced block is quoted text, and a fenced block\n * inside the Purpose is part of it.\n */\nfunction markedParts(body: string, featureId: string): { title?: string; purpose?: string } {\n const fenced = fenceTracker();\n let title: string | undefined;\n let seenSection = false;\n let purpose: string[] | null = null;\n let purposeEnded = false;\n for (const line of body.split(/\\r?\\n/)) {\n const quoted = fenced(line);\n if (purpose !== null && !purposeEnded) {\n if (quoted || !SECTION_END_RE.test(line)) {\n purpose.push(line);\n continue;\n }\n purposeEnded = true;\n }\n if (quoted) continue;\n const h1 = H1_RE.exec(line);\n // The document's title is an H1 above its first section; one further down\n // is a heading inside the text, not the name of the document.\n if (h1 !== null && !seenSection && title === undefined) title = h1[1]!;\n if (/^##\\s/.test(line)) {\n seenSection = true;\n if (purpose === null && PURPOSE_RE.test(line.trim())) purpose = [];\n }\n }\n // Blank LINES trimmed, never leading spaces: an indented code block opening\n // the section is the author's text.\n const purposeText = purpose?.join(\"\\n\").replace(/^(?:[ \\t]*\\n)+/, \"\").trimEnd();\n return {\n ...(title === undefined || namesTheChange(title, featureId) ? {} : { title }),\n ...(purposeText === undefined || purposeText === \"\" ? {} : { purpose: purposeText }),\n };\n}\n"]}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where every file of the feature will be once this archive lands — the half of
|
|
3
|
+
* the link rewrite that `core/links/parse.ts`'s `rebaseLinks` cannot know.
|
|
4
|
+
*
|
|
5
|
+
* THE DEFECT THIS CLOSES. The requirement merge has re-expressed a delta's
|
|
6
|
+
* relative links from the directory they were written in to the one they land
|
|
7
|
+
* in since the glossary axis shipped. But it re-expressed them against the
|
|
8
|
+
* target's OLD place, and the same archive moves the targets that sit inside
|
|
9
|
+
* the feature: a link from a delta to `features/<FEAT>/glossary/order.md` was
|
|
10
|
+
* rewritten faithfully into the living spec and resolved to nothing one rename
|
|
11
|
+
* later, when the term had been copied to `glossary/order.md` and the feature
|
|
12
|
+
* directory had gone to `features/archive/<FEAT>/`. Every such link was
|
|
13
|
+
* `link.unresolved` on the first `validate --all` after a clean archive — an
|
|
14
|
+
* error the feature gate could not see, because before the archive the link
|
|
15
|
+
* was correct.
|
|
16
|
+
*
|
|
17
|
+
* TWO RULES, and they are the archive's own moves rather than a guess:
|
|
18
|
+
*
|
|
19
|
+
* - A file the archive COPIES into the living tree — a glossary term, a flow,
|
|
20
|
+
* a topology document — is cited at its living copy. That is the document
|
|
21
|
+
* readers are meant to find, and the one `glossary.unlinked` counts a
|
|
22
|
+
* citation of: a link left on the archived copy would resolve and still
|
|
23
|
+
* leave the living term reading as a word nobody uses.
|
|
24
|
+
* - Every other file under the feature directory — its ADRs above all, the
|
|
25
|
+
* intent, the deltas themselves — is cited where the feature now lives,
|
|
26
|
+
* `features/archive/<FEAT>/`. Nothing else copies a feature ADR anywhere: it
|
|
27
|
+
* records a decision taken for this change, and it stays with the change
|
|
28
|
+
* (SCHEMA "Layout" says so beside the slot).
|
|
29
|
+
*
|
|
30
|
+
* Built per call from three directory walks — the glossary, the flows and the
|
|
31
|
+
* topology documents, the same walks `../specs.ts` and `../landscape.ts` make
|
|
32
|
+
* to copy them; a `Gated` field would be one more value the gate computes for
|
|
33
|
+
* a phase it does not own.
|
|
34
|
+
*
|
|
35
|
+
* THE OTHER TWO HALVES ARE THE LINKS NO MERGE CARRIES. The feature's own
|
|
36
|
+
* documents (`planFeatureLinks` below) stay in the feature and ride the rename,
|
|
37
|
+
* so their links out of it are one directory short the moment it lands. Every
|
|
38
|
+
* other document in the corpus (`planInboundLinks` below) stays where it is
|
|
39
|
+
* while the files it cites inside the feature move away from under it.
|
|
40
|
+
*/
|
|
41
|
+
import { dirname, resolve } from "node:path";
|
|
42
|
+
import { repoPath } from "../../../../core/envelope/json.js";
|
|
43
|
+
import { movedUnderVouch, parseFrontmatter, stringField } from "../../../../core/document/frontmatter.js";
|
|
44
|
+
import { parseRequirements } from "../../../../core/document/parse.js";
|
|
45
|
+
import { requirementDigest } from "../../../../core/document/spec.js";
|
|
46
|
+
import { featureGlossary, livingTermPath } from "../../../../core/glossary/delta.js";
|
|
47
|
+
import { allAuthoredDocuments, movedMarkdown } from "../../../../core/links/corpus.js";
|
|
48
|
+
import { rebaseLinks } from "../../../../core/links/parse.js";
|
|
49
|
+
import { inOrder } from "../../../../core/kernel/concurrency.js";
|
|
50
|
+
import { acrossRename, isPathInside } from "../../../../core/kernel/path-safety.js";
|
|
51
|
+
import { featuresDir, servicePathsAt } from "../../../../core/repo/paths.js";
|
|
52
|
+
import { listServices } from "../../../../core/repo/repo.js";
|
|
53
|
+
import { featureFlows, livingFlowPath } from "../../../../core/usecases/delta/flows.js";
|
|
54
|
+
import { featureDeployments, livingDeploymentPath } from "../../../../core/deployment/delta.js";
|
|
55
|
+
import { NotUtf8Error, planWrite, readUtf8 } from "../../../../core/staging/writes.js";
|
|
56
|
+
export async function featureRetarget(docsDir, gated) {
|
|
57
|
+
const copies = new Map();
|
|
58
|
+
for (const term of (await featureGlossary(gated.featureDir)).terms) {
|
|
59
|
+
copies.set(resolve(term.path), resolve(livingTermPath(docsDir, term.id)));
|
|
60
|
+
}
|
|
61
|
+
for (const flow of await featureFlows(gated.featureDir)) {
|
|
62
|
+
copies.set(resolve(flow.path), resolve(livingFlowPath(docsDir, flow.rel)));
|
|
63
|
+
}
|
|
64
|
+
for (const doc of await featureDeployments(gated.featureDir)) {
|
|
65
|
+
copies.set(resolve(doc.path), resolve(livingDeploymentPath(docsDir, doc.rel)));
|
|
66
|
+
}
|
|
67
|
+
return (target) => copies.get(resolve(target)) ?? followsFeature(gated, target);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The feature's own markdown documents with their relative links re-expressed
|
|
71
|
+
* for `features/archive/<FEAT>/`, planned at their CURRENT paths so the swap
|
|
72
|
+
* lands before the rename carries them (`../../run.ts`).
|
|
73
|
+
*
|
|
74
|
+
* THE DEFECT THIS CLOSES. The archive is a directory rename, and every document
|
|
75
|
+
* that stays in the feature — the intent, its ADRs, the deltas, a capability
|
|
76
|
+
* delta, the archived copy of a term — kept links written one directory
|
|
77
|
+
* shallower than where they now sit: `../../services/x/spec.md` from
|
|
78
|
+
* `features/<FEAT>/intent.md` names `features/services/x/spec.md` once the
|
|
79
|
+
* intent is `features/archive/<FEAT>/intent.md`. Nothing grades an archived
|
|
80
|
+
* feature (`core/links/corpus.ts` says why), so nothing said so — but the
|
|
81
|
+
* living documents link INTO the archived feature's ADRs (`featureRetarget`
|
|
82
|
+
* above), and a reader who followed one landed on a decision whose own links
|
|
83
|
+
* were all off by one.
|
|
84
|
+
*
|
|
85
|
+
* ONE RULE, the rename's: a target inside the feature moves with it and every
|
|
86
|
+
* other target stays put — `subsystem move`'s rule for its own renames
|
|
87
|
+
* (`commands/subsystem/txn/links.ts`). So a link from the intent to its own
|
|
88
|
+
* ADR or its own glossary term is left exactly as written: the archived
|
|
89
|
+
* record keeps citing the archived copy, which is the text the feature was
|
|
90
|
+
* reviewed against, rather than being redirected to a living copy that will go
|
|
91
|
+
* on changing without it. Only the routes the rename broke are touched, and a
|
|
92
|
+
* link whose text still reaches its target keeps its spelling
|
|
93
|
+
* (`rebaseLinks`).
|
|
94
|
+
*
|
|
95
|
+
* The undo is the snapshot's, like every other write here: each rewritten
|
|
96
|
+
* document is a staged write, so its pre-image is parked and `loam unarchive`
|
|
97
|
+
* puts the authored bytes back (`core/staging/snapshot/snapshot.ts` says where
|
|
98
|
+
* it records them).
|
|
99
|
+
*
|
|
100
|
+
* A document that is not UTF-8 is left exactly as written, and the text
|
|
101
|
+
* output says so — `--json` has no key for it, and minting one for a document
|
|
102
|
+
* nothing grades was not worth a contract change. Every other read here would
|
|
103
|
+
* refuse it, but this one only corrects links, and refusing the archive over
|
|
104
|
+
* such a document would be the larger harm.
|
|
105
|
+
*
|
|
106
|
+
* Read with bounded concurrency and applied in input order (`inOrder`), as
|
|
107
|
+
* `subsystem move`'s rewrite reads its own: a large feature — one
|
|
108
|
+
* `loam migrate-openspec` filled with its legacy documents — is read in full
|
|
109
|
+
* under the lock.
|
|
110
|
+
*/
|
|
111
|
+
export async function planFeatureLinks(config, gated, planned, say) {
|
|
112
|
+
const { docsDir } = config;
|
|
113
|
+
const retarget = (target) => followsFeature(gated, target);
|
|
114
|
+
const read = await inOrder(await movedMarkdown(gated.featureDir), async (path) => {
|
|
115
|
+
try {
|
|
116
|
+
return { path, text: await readUtf8(path) };
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (!(err instanceof NotUtf8Error))
|
|
120
|
+
throw err;
|
|
121
|
+
return { path, text: null };
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const relinked = [];
|
|
125
|
+
for (const { path, text } of read) {
|
|
126
|
+
const lands = followsFeature(gated, path);
|
|
127
|
+
if (text === null) {
|
|
128
|
+
say(` ⚠ ${repoPath(docsDir, lands)} is not UTF-8 — its links were left as written`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const next = rebaseLinks(text, { from: dirname(path), to: dirname(lands), retarget });
|
|
132
|
+
if (next === text)
|
|
133
|
+
continue;
|
|
134
|
+
planned.writes.push(planWrite(path, next));
|
|
135
|
+
relinked.push(repoPath(docsDir, lands));
|
|
136
|
+
}
|
|
137
|
+
if (relinked.length === 0)
|
|
138
|
+
return;
|
|
139
|
+
say(` feature documents: ${relinked.length} relinked for ${repoPath(docsDir, gated.archiveDest)}/`);
|
|
140
|
+
for (const path of relinked)
|
|
141
|
+
say(` ${path}`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Every other document in the link corpus whose links reach INTO the feature,
|
|
145
|
+
* re-expressed for where this archive leaves what they cite.
|
|
146
|
+
*
|
|
147
|
+
* THE DEFECT THIS CLOSES. Another change in flight builds on this one's
|
|
148
|
+
* decision (`../FEAT/adrs/0001-x.md` from its intent), or a living ADR cites
|
|
149
|
+
* the decision taken for it while the change is still open. Correct the moment
|
|
150
|
+
* before the archive, so no gate could say otherwise; `link.unresolved` the
|
|
151
|
+
* moment after, because the rename took the directory away from under the
|
|
152
|
+
* link. And no edit the author could make in advance would have helped: the
|
|
153
|
+
* archived path does not exist until the archive does. `subsystem move`
|
|
154
|
+
* rewrites the links into the directories it renames
|
|
155
|
+
* (`commands/subsystem/txn/links.ts`); this is the archive's rename owing the
|
|
156
|
+
* same correction.
|
|
157
|
+
*
|
|
158
|
+
* THE RULE IS `featureRetarget`'s, not the rename's. These documents are not
|
|
159
|
+
* the record of the change; they are the living corpus and the other changes
|
|
160
|
+
* in flight, read against the tree as it is. So a term the archive copies into
|
|
161
|
+
* `glossary/` is cited at the living copy — the one a reader is meant to find
|
|
162
|
+
* and the one `glossary.unlinked` counts — and everything that stays with the
|
|
163
|
+
* change, its ADRs and intent above all, is cited where the feature now lives.
|
|
164
|
+
* Only the routes into the feature change; every other link keeps its
|
|
165
|
+
* spelling (`rebaseLinks`).
|
|
166
|
+
*
|
|
167
|
+
* COMPOSED ONTO THE MERGE. A living spec the merge rewrites can cite the
|
|
168
|
+
* feature in its own narrative, and relinking the bytes on disk would plan a
|
|
169
|
+
* second write of its PRE-merge text — swapped after the merge's, it would
|
|
170
|
+
* undo the merge. So a document this plan already writes is relinked from the
|
|
171
|
+
* text the merge composed, and that one write is replaced in place.
|
|
172
|
+
*
|
|
173
|
+
* THE COSTS ARE SAID THE WAY THE MERGE SAYS ITS OWN. A rewritten route is still
|
|
174
|
+
* a changed byte. Under a vouch stamp it is `content.stale` until the owner
|
|
175
|
+
* re-vouches, so a vouched spec this moves joins `revouchOwed` exactly as one
|
|
176
|
+
* the merge moves does. Inside a living requirement it moves the digest a
|
|
177
|
+
* `Based-On:` pin holds, and the plan names the document. No git refusal of the
|
|
178
|
+
* kind `subsystem move` holds (`move-uncommitted`): archive never stages in
|
|
179
|
+
* git, and its undo is the snapshot — every write here is one of its rows, so
|
|
180
|
+
* `loam unarchive` puts the authored bytes back, a document edited since is
|
|
181
|
+
* `snapshot-stale` like any other, and one whose feature has been archived or
|
|
182
|
+
* removed since is left as it is (`commands/unarchive/restore.ts`).
|
|
183
|
+
*
|
|
184
|
+
* The two notes are the text output's alone — the walk that could not be made
|
|
185
|
+
* and the `Based-On:` cost. `--json` has no key for either: its `warnings` are
|
|
186
|
+
* coherence issues with codes, and a new key for an advisory the next
|
|
187
|
+
* `validate --all` grades in full was not worth a contract change. What an
|
|
188
|
+
* agent acts on is in the payload already: every relinked document is a `plan`
|
|
189
|
+
* row and every re-vouch it owes is on `revouchOwed`.
|
|
190
|
+
*/
|
|
191
|
+
export async function planInboundLinks(config, gated, planned, say) {
|
|
192
|
+
const { docsDir, fleet } = config;
|
|
193
|
+
let corpus;
|
|
194
|
+
try {
|
|
195
|
+
corpus = await allAuthoredDocuments(docsDir, fleet);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
// The gate enumerated this fleet already, so a walk that fails here is a
|
|
199
|
+
// tree `validate` will diagnose. The archive is not refused over a question
|
|
200
|
+
// it asks to keep the corpus readable — `subsystem move` decides the same —
|
|
201
|
+
// but it does not pretend the question was answered either.
|
|
202
|
+
say(` ⚠ links INTO ${repoPath(docsDir, gated.featureDir)}/ were not checked — the fleet's documents could not be walked ` +
|
|
203
|
+
`(${err instanceof Error ? err.message : String(err)}); \`loam validate --all\` names any that broke.`);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const retarget = await featureRetarget(docsDir, gated);
|
|
207
|
+
const vouchable = new Map();
|
|
208
|
+
for (const service of await listServices(docsDir, fleet)) {
|
|
209
|
+
const paths = servicePathsAt(service.dir);
|
|
210
|
+
vouchable.set(resolve(paths.spec), service.id);
|
|
211
|
+
vouchable.set(resolve(paths.archSpec), service.id);
|
|
212
|
+
}
|
|
213
|
+
const plannedAt = new Map(planned.writes.map((write, at) => [resolve(write.path), { at, write }]));
|
|
214
|
+
const seen = new Set();
|
|
215
|
+
const candidates = corpus.filter((path) => {
|
|
216
|
+
const key = resolve(path);
|
|
217
|
+
if (seen.has(key) || isPathInside(gated.featureDir, path))
|
|
218
|
+
return false;
|
|
219
|
+
seen.add(key);
|
|
220
|
+
return true;
|
|
221
|
+
});
|
|
222
|
+
const documents = await inOrder(candidates, async (path) => {
|
|
223
|
+
const composed = plannedAt.get(resolve(path));
|
|
224
|
+
if (composed !== undefined) {
|
|
225
|
+
// A delete or a Buffer is not text this rewrite may compose onto; no
|
|
226
|
+
// markdown planner hands over either.
|
|
227
|
+
const { content } = composed.write;
|
|
228
|
+
return { path, composed, text: typeof content === "string" ? content : null };
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
return { path, composed, text: await readUtf8(path) };
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// Absent (the corpus names every slot a service MAY fill) or not UTF-8,
|
|
235
|
+
// which `link.unreadable` already names: nothing loam could write back.
|
|
236
|
+
return { path, composed, text: null };
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
const pinned = (md) => parseRequirements(md).map(requirementDigest).join(",");
|
|
240
|
+
const relinked = [];
|
|
241
|
+
const notes = [];
|
|
242
|
+
for (const { path, composed, text } of documents) {
|
|
243
|
+
if (text === null)
|
|
244
|
+
continue;
|
|
245
|
+
const next = rebaseLinks(text, { from: dirname(path), to: dirname(path), retarget });
|
|
246
|
+
if (next === text)
|
|
247
|
+
continue;
|
|
248
|
+
// In place, at the index the merge's write already holds: nothing between
|
|
249
|
+
// here and the map above adds, removes or reorders a planned write.
|
|
250
|
+
if (composed === undefined)
|
|
251
|
+
planned.writes.push(planWrite(path, next));
|
|
252
|
+
else
|
|
253
|
+
planned.writes[composed.at] = { ...composed.write, content: next };
|
|
254
|
+
const where = repoPath(docsDir, path);
|
|
255
|
+
relinked.push(where);
|
|
256
|
+
// The merge's own question (`../specs.ts`), asked of the bytes about to be
|
|
257
|
+
// written — and once per document: a spec the merge already named is not
|
|
258
|
+
// owed a second re-vouch for the same commit.
|
|
259
|
+
const service = vouchable.get(resolve(path));
|
|
260
|
+
const fm = parseFrontmatter(next);
|
|
261
|
+
const named = planned.revouchOwed.some((owed) => resolve(owed.path) === resolve(path));
|
|
262
|
+
if (service !== undefined && !named && movedUnderVouch(fm, next)) {
|
|
263
|
+
planned.revouchOwed.push({ service, path, owner: stringField(fm, "owner") ?? null });
|
|
264
|
+
}
|
|
265
|
+
// Living documents only: a pin holds the digest of a LIVING requirement,
|
|
266
|
+
// so another feature's own delta text moving pins nothing.
|
|
267
|
+
if (!isPathInside(featuresDir(docsDir), path) && pinned(next) !== pinned(text)) {
|
|
268
|
+
notes.push(`${where}: links this archive rewrote sit inside requirements, so a feature in flight that pins one with Based-On: ` +
|
|
269
|
+
"reports delta.baseline-stale until `loam rebase` re-pins it.");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (relinked.length === 0)
|
|
273
|
+
return;
|
|
274
|
+
say(` links into the feature: ${relinked.length} document(s) relinked for ${repoPath(docsDir, gated.archiveDest)}/`);
|
|
275
|
+
for (const path of relinked)
|
|
276
|
+
say(` ${path}`);
|
|
277
|
+
for (const note of notes)
|
|
278
|
+
say(` note: ${note}`);
|
|
279
|
+
}
|
|
280
|
+
/** Where `target` will be once the feature directory has moved: its image under the archive when it is inside the feature, itself otherwise. */
|
|
281
|
+
function followsFeature(gated, target) {
|
|
282
|
+
return acrossRename(target, gated.featureDir, gated.archiveDest);
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../../../../src/commands/archive/plan/document/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Where every file of the feature will be once this archive lands — the half of\n * the link rewrite that `core/links/parse.ts`'s `rebaseLinks` cannot know.\n *\n * THE DEFECT THIS CLOSES. The requirement merge has re-expressed a delta's\n * relative links from the directory they were written in to the one they land\n * in since the glossary axis shipped. But it re-expressed them against the\n * target's OLD place, and the same archive moves the targets that sit inside\n * the feature: a link from a delta to `features/<FEAT>/glossary/order.md` was\n * rewritten faithfully into the living spec and resolved to nothing one rename\n * later, when the term had been copied to `glossary/order.md` and the feature\n * directory had gone to `features/archive/<FEAT>/`. Every such link was\n * `link.unresolved` on the first `validate --all` after a clean archive — an\n * error the feature gate could not see, because before the archive the link\n * was correct.\n *\n * TWO RULES, and they are the archive's own moves rather than a guess:\n *\n * - A file the archive COPIES into the living tree — a glossary term, a flow,\n * a topology document — is cited at its living copy. That is the document\n * readers are meant to find, and the one `glossary.unlinked` counts a\n * citation of: a link left on the archived copy would resolve and still\n * leave the living term reading as a word nobody uses.\n * - Every other file under the feature directory — its ADRs above all, the\n * intent, the deltas themselves — is cited where the feature now lives,\n * `features/archive/<FEAT>/`. Nothing else copies a feature ADR anywhere: it\n * records a decision taken for this change, and it stays with the change\n * (SCHEMA \"Layout\" says so beside the slot).\n *\n * Built per call from three directory walks — the glossary, the flows and the\n * topology documents, the same walks `../specs.ts` and `../landscape.ts` make\n * to copy them; a `Gated` field would be one more value the gate computes for\n * a phase it does not own.\n *\n * THE OTHER TWO HALVES ARE THE LINKS NO MERGE CARRIES. The feature's own\n * documents (`planFeatureLinks` below) stay in the feature and ride the rename,\n * so their links out of it are one directory short the moment it lands. Every\n * other document in the corpus (`planInboundLinks` below) stays where it is\n * while the files it cites inside the feature move away from under it.\n */\nimport { dirname, resolve } from \"node:path\";\nimport { repoPath } from \"../../../../core/envelope/json.js\";\nimport { movedUnderVouch, parseFrontmatter, stringField } from \"../../../../core/document/frontmatter.js\";\nimport { parseRequirements } from \"../../../../core/document/parse.js\";\nimport { requirementDigest } from \"../../../../core/document/spec.js\";\nimport { featureGlossary, livingTermPath } from \"../../../../core/glossary/delta.js\";\nimport { allAuthoredDocuments, movedMarkdown } from \"../../../../core/links/corpus.js\";\nimport { rebaseLinks } from \"../../../../core/links/parse.js\";\nimport { inOrder } from \"../../../../core/kernel/concurrency.js\";\nimport { acrossRename, isPathInside } from \"../../../../core/kernel/path-safety.js\";\nimport { featuresDir, servicePathsAt } from \"../../../../core/repo/paths.js\";\nimport { listServices } from \"../../../../core/repo/repo.js\";\nimport { featureFlows, livingFlowPath } from \"../../../../core/usecases/delta/flows.js\";\nimport { featureDeployments, livingDeploymentPath } from \"../../../../core/deployment/delta.js\";\nimport { NotUtf8Error, planWrite, readUtf8 } from \"../../../../core/staging/writes.js\";\nimport type { FleetContext } from \"../../../../core/fleet-context.js\";\nimport type { DocsDir } from \"../../../../core/kernel/ids/dirs.js\";\nimport type { Gated, Plan } from \"../state.js\";\n\n/** Absolute path in, the absolute path the same file will have after this archive out. */\nexport type Retarget = (target: string) => string;\n\nexport async function featureRetarget(docsDir: DocsDir, gated: Pick<Gated, \"featureDir\" | \"archiveDest\">): Promise<Retarget> {\n const copies = new Map<string, string>();\n for (const term of (await featureGlossary(gated.featureDir)).terms) {\n copies.set(resolve(term.path), resolve(livingTermPath(docsDir, term.id)));\n }\n for (const flow of await featureFlows(gated.featureDir)) {\n copies.set(resolve(flow.path), resolve(livingFlowPath(docsDir, flow.rel)));\n }\n for (const doc of await featureDeployments(gated.featureDir)) {\n copies.set(resolve(doc.path), resolve(livingDeploymentPath(docsDir, doc.rel)));\n }\n return (target: string): string => copies.get(resolve(target)) ?? followsFeature(gated, target);\n}\n\n/**\n * The feature's own markdown documents with their relative links re-expressed\n * for `features/archive/<FEAT>/`, planned at their CURRENT paths so the swap\n * lands before the rename carries them (`../../run.ts`).\n *\n * THE DEFECT THIS CLOSES. The archive is a directory rename, and every document\n * that stays in the feature — the intent, its ADRs, the deltas, a capability\n * delta, the archived copy of a term — kept links written one directory\n * shallower than where they now sit: `../../services/x/spec.md` from\n * `features/<FEAT>/intent.md` names `features/services/x/spec.md` once the\n * intent is `features/archive/<FEAT>/intent.md`. Nothing grades an archived\n * feature (`core/links/corpus.ts` says why), so nothing said so — but the\n * living documents link INTO the archived feature's ADRs (`featureRetarget`\n * above), and a reader who followed one landed on a decision whose own links\n * were all off by one.\n *\n * ONE RULE, the rename's: a target inside the feature moves with it and every\n * other target stays put — `subsystem move`'s rule for its own renames\n * (`commands/subsystem/txn/links.ts`). So a link from the intent to its own\n * ADR or its own glossary term is left exactly as written: the archived\n * record keeps citing the archived copy, which is the text the feature was\n * reviewed against, rather than being redirected to a living copy that will go\n * on changing without it. Only the routes the rename broke are touched, and a\n * link whose text still reaches its target keeps its spelling\n * (`rebaseLinks`).\n *\n * The undo is the snapshot's, like every other write here: each rewritten\n * document is a staged write, so its pre-image is parked and `loam unarchive`\n * puts the authored bytes back (`core/staging/snapshot/snapshot.ts` says where\n * it records them).\n *\n * A document that is not UTF-8 is left exactly as written, and the text\n * output says so — `--json` has no key for it, and minting one for a document\n * nothing grades was not worth a contract change. Every other read here would\n * refuse it, but this one only corrects links, and refusing the archive over\n * such a document would be the larger harm.\n *\n * Read with bounded concurrency and applied in input order (`inOrder`), as\n * `subsystem move`'s rewrite reads its own: a large feature — one\n * `loam migrate-openspec` filled with its legacy documents — is read in full\n * under the lock.\n */\nexport async function planFeatureLinks(\n config: { docsDir: DocsDir },\n gated: Pick<Gated, \"featureDir\" | \"archiveDest\">,\n planned: Plan,\n say: (line?: string) => void,\n): Promise<void> {\n const { docsDir } = config;\n const retarget = (target: string): string => followsFeature(gated, target);\n const read = await inOrder(await movedMarkdown(gated.featureDir), async (path) => {\n try {\n return { path, text: await readUtf8(path) };\n } catch (err) {\n if (!(err instanceof NotUtf8Error)) throw err;\n return { path, text: null };\n }\n });\n const relinked: string[] = [];\n for (const { path, text } of read) {\n const lands = followsFeature(gated, path);\n if (text === null) {\n say(` ⚠ ${repoPath(docsDir, lands)} is not UTF-8 — its links were left as written`);\n continue;\n }\n const next = rebaseLinks(text, { from: dirname(path), to: dirname(lands), retarget });\n if (next === text) continue;\n planned.writes.push(planWrite(path, next));\n relinked.push(repoPath(docsDir, lands));\n }\n if (relinked.length === 0) return;\n say(` feature documents: ${relinked.length} relinked for ${repoPath(docsDir, gated.archiveDest)}/`);\n for (const path of relinked) say(` ${path}`);\n}\n\n/**\n * Every other document in the link corpus whose links reach INTO the feature,\n * re-expressed for where this archive leaves what they cite.\n *\n * THE DEFECT THIS CLOSES. Another change in flight builds on this one's\n * decision (`../FEAT/adrs/0001-x.md` from its intent), or a living ADR cites\n * the decision taken for it while the change is still open. Correct the moment\n * before the archive, so no gate could say otherwise; `link.unresolved` the\n * moment after, because the rename took the directory away from under the\n * link. And no edit the author could make in advance would have helped: the\n * archived path does not exist until the archive does. `subsystem move`\n * rewrites the links into the directories it renames\n * (`commands/subsystem/txn/links.ts`); this is the archive's rename owing the\n * same correction.\n *\n * THE RULE IS `featureRetarget`'s, not the rename's. These documents are not\n * the record of the change; they are the living corpus and the other changes\n * in flight, read against the tree as it is. So a term the archive copies into\n * `glossary/` is cited at the living copy — the one a reader is meant to find\n * and the one `glossary.unlinked` counts — and everything that stays with the\n * change, its ADRs and intent above all, is cited where the feature now lives.\n * Only the routes into the feature change; every other link keeps its\n * spelling (`rebaseLinks`).\n *\n * COMPOSED ONTO THE MERGE. A living spec the merge rewrites can cite the\n * feature in its own narrative, and relinking the bytes on disk would plan a\n * second write of its PRE-merge text — swapped after the merge's, it would\n * undo the merge. So a document this plan already writes is relinked from the\n * text the merge composed, and that one write is replaced in place.\n *\n * THE COSTS ARE SAID THE WAY THE MERGE SAYS ITS OWN. A rewritten route is still\n * a changed byte. Under a vouch stamp it is `content.stale` until the owner\n * re-vouches, so a vouched spec this moves joins `revouchOwed` exactly as one\n * the merge moves does. Inside a living requirement it moves the digest a\n * `Based-On:` pin holds, and the plan names the document. No git refusal of the\n * kind `subsystem move` holds (`move-uncommitted`): archive never stages in\n * git, and its undo is the snapshot — every write here is one of its rows, so\n * `loam unarchive` puts the authored bytes back, a document edited since is\n * `snapshot-stale` like any other, and one whose feature has been archived or\n * removed since is left as it is (`commands/unarchive/restore.ts`).\n *\n * The two notes are the text output's alone — the walk that could not be made\n * and the `Based-On:` cost. `--json` has no key for either: its `warnings` are\n * coherence issues with codes, and a new key for an advisory the next\n * `validate --all` grades in full was not worth a contract change. What an\n * agent acts on is in the payload already: every relinked document is a `plan`\n * row and every re-vouch it owes is on `revouchOwed`.\n */\nexport async function planInboundLinks(\n config: { docsDir: DocsDir; fleet: FleetContext },\n gated: Pick<Gated, \"featureDir\" | \"archiveDest\">,\n planned: Plan,\n say: (line?: string) => void,\n): Promise<void> {\n const { docsDir, fleet } = config;\n let corpus: string[];\n try {\n corpus = await allAuthoredDocuments(docsDir, fleet);\n } catch (err) {\n // The gate enumerated this fleet already, so a walk that fails here is a\n // tree `validate` will diagnose. The archive is not refused over a question\n // it asks to keep the corpus readable — `subsystem move` decides the same —\n // but it does not pretend the question was answered either.\n say(\n ` ⚠ links INTO ${repoPath(docsDir, gated.featureDir)}/ were not checked — the fleet's documents could not be walked ` +\n `(${err instanceof Error ? err.message : String(err)}); \\`loam validate --all\\` names any that broke.`,\n );\n return;\n }\n const retarget = await featureRetarget(docsDir, gated);\n const vouchable = new Map<string, string>();\n for (const service of await listServices(docsDir, fleet)) {\n const paths = servicePathsAt(service.dir);\n vouchable.set(resolve(paths.spec), service.id);\n vouchable.set(resolve(paths.archSpec), service.id);\n }\n const plannedAt = new Map(planned.writes.map((write, at) => [resolve(write.path), { at, write }]));\n const seen = new Set<string>();\n const candidates = corpus.filter((path) => {\n const key = resolve(path);\n if (seen.has(key) || isPathInside(gated.featureDir, path)) return false;\n seen.add(key);\n return true;\n });\n const documents = await inOrder(candidates, async (path) => {\n const composed = plannedAt.get(resolve(path));\n if (composed !== undefined) {\n // A delete or a Buffer is not text this rewrite may compose onto; no\n // markdown planner hands over either.\n const { content } = composed.write;\n return { path, composed, text: typeof content === \"string\" ? content : null };\n }\n try {\n return { path, composed, text: await readUtf8(path) };\n } catch {\n // Absent (the corpus names every slot a service MAY fill) or not UTF-8,\n // which `link.unreadable` already names: nothing loam could write back.\n return { path, composed, text: null };\n }\n });\n const pinned = (md: string): string => parseRequirements(md).map(requirementDigest).join(\",\");\n const relinked: string[] = [];\n const notes: string[] = [];\n for (const { path, composed, text } of documents) {\n if (text === null) continue;\n const next = rebaseLinks(text, { from: dirname(path), to: dirname(path), retarget });\n if (next === text) continue;\n // In place, at the index the merge's write already holds: nothing between\n // here and the map above adds, removes or reorders a planned write.\n if (composed === undefined) planned.writes.push(planWrite(path, next));\n else planned.writes[composed.at] = { ...composed.write, content: next };\n const where = repoPath(docsDir, path);\n relinked.push(where);\n // The merge's own question (`../specs.ts`), asked of the bytes about to be\n // written — and once per document: a spec the merge already named is not\n // owed a second re-vouch for the same commit.\n const service = vouchable.get(resolve(path));\n const fm = parseFrontmatter(next);\n const named = planned.revouchOwed.some((owed) => resolve(owed.path) === resolve(path));\n if (service !== undefined && !named && movedUnderVouch(fm, next)) {\n planned.revouchOwed.push({ service, path, owner: stringField(fm, \"owner\") ?? null });\n }\n // Living documents only: a pin holds the digest of a LIVING requirement,\n // so another feature's own delta text moving pins nothing.\n if (!isPathInside(featuresDir(docsDir), path) && pinned(next) !== pinned(text)) {\n notes.push(\n `${where}: links this archive rewrote sit inside requirements, so a feature in flight that pins one with Based-On: ` +\n \"reports delta.baseline-stale until `loam rebase` re-pins it.\",\n );\n }\n }\n if (relinked.length === 0) return;\n say(` links into the feature: ${relinked.length} document(s) relinked for ${repoPath(docsDir, gated.archiveDest)}/`);\n for (const path of relinked) say(` ${path}`);\n for (const note of notes) say(` note: ${note}`);\n}\n\n/** Where `target` will be once the feature directory has moved: its image under the archive when it is inside the feature, itself otherwise. */\nfunction followsFeature(gated: Pick<Gated, \"featureDir\" | \"archiveDest\">, target: string): string {\n return acrossRename(target, gated.featureDir, gated.archiveDest);\n}\n"]}
|