@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,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The link half of `subsystem move` and `rename`: every relative markdown link
|
|
3
|
+
* the renames would break, re-expressed so it reaches the same file.
|
|
4
|
+
*
|
|
5
|
+
* THE DEFECT THIS CLOSES. A move is a directory rename, and a relative link is
|
|
6
|
+
* a route from one directory to another. `services/orders/spec.md` citing
|
|
7
|
+
* `../../glossary/order.md` is two directories below the docs root; moved into
|
|
8
|
+
* `services/commerce/orders/` it is three, and the same text names
|
|
9
|
+
* `services/glossary/order.md`, which is nothing. The move reported success,
|
|
10
|
+
* staged the renames in git, and the next `validate --all` failed
|
|
11
|
+
* `link.unresolved` on every moved document that cited anything outside its
|
|
12
|
+
* own directory — the "failing between two commits" state the commit window
|
|
13
|
+
* exists to refuse. The same rename breaks the other direction too: a
|
|
14
|
+
* capability document or a glossary term citing `services/orders/spec.md`
|
|
15
|
+
* now points where nothing is.
|
|
16
|
+
*
|
|
17
|
+
* SO BOTH DIRECTIONS ARE REWRITTEN, with the one rule archive's merge uses
|
|
18
|
+
* (`core/links/parse.ts`'s `rebaseLinks`): the target is unchanged, only the
|
|
19
|
+
* route to it, and a link whose text still reaches its target from the new
|
|
20
|
+
* place keeps its exact spelling.
|
|
21
|
+
*
|
|
22
|
+
* - Every markdown file under a moved directory, whatever its name — a runbook,
|
|
23
|
+
* an ADR, a subsystem's own notes: the rename moves them all, so it owes them
|
|
24
|
+
* all the same correction. Written at the OLD path, because the transaction
|
|
25
|
+
* swaps files before it renames directories (`core/staging/txn/`), so the
|
|
26
|
+
* rewritten bytes travel with the rename.
|
|
27
|
+
* - Every other document in the link corpus (`core/links/corpus.ts`: the fleet's
|
|
28
|
+
* own documents, every service's, every in-flight feature's) whose links
|
|
29
|
+
* reach INTO a moved directory. Archived features are not in it, for the
|
|
30
|
+
* corpus's own reason: their links describe the tree as it was, and nothing
|
|
31
|
+
* grades them.
|
|
32
|
+
*
|
|
33
|
+
* A document that cannot be decoded is left as it is: rewriting means writing
|
|
34
|
+
* the whole file back, and `link.unreadable` already names it.
|
|
35
|
+
*/
|
|
36
|
+
import { dirname, resolve } from "node:path";
|
|
37
|
+
import { allAuthoredDocuments, movedMarkdown } from "../../../core/links/corpus.js";
|
|
38
|
+
import { rebaseLinks } from "../../../core/links/parse.js";
|
|
39
|
+
import { FleetContext } from "../../../core/fleet-context.js";
|
|
40
|
+
import { movedUnderVouch, parseFrontmatter } from "../../../core/document/frontmatter.js";
|
|
41
|
+
import { parseRequirements } from "../../../core/document/parse.js";
|
|
42
|
+
import { requirementDigest } from "../../../core/document/spec.js";
|
|
43
|
+
import { repoPath } from "../../../core/envelope/json.js";
|
|
44
|
+
import { featuresDir } from "../../../core/repo/paths.js";
|
|
45
|
+
import { inOrder } from "../../../core/kernel/concurrency.js";
|
|
46
|
+
import { acrossRename, isPathInside } from "../../../core/kernel/path-safety.js";
|
|
47
|
+
import { planWrite, readUtf8 } from "../../../core/staging/writes.js";
|
|
48
|
+
export async function movedLinks(docsDir, moves) {
|
|
49
|
+
const retarget = (target) => {
|
|
50
|
+
for (const move of moves) {
|
|
51
|
+
if (isPathInside(move.from, target))
|
|
52
|
+
return acrossRename(target, move.from, move.to);
|
|
53
|
+
}
|
|
54
|
+
return target;
|
|
55
|
+
};
|
|
56
|
+
const out = { writes: [], relinked: [], notices: [] };
|
|
57
|
+
// The moved documents first, then every other document the corpus names —
|
|
58
|
+
// one list, deduplicated in order, because the order is what `relinked`
|
|
59
|
+
// reports and a person reads it top to bottom.
|
|
60
|
+
const candidates = [];
|
|
61
|
+
for (const move of moves)
|
|
62
|
+
candidates.push(...(await movedMarkdown(move.from)));
|
|
63
|
+
try {
|
|
64
|
+
const corpus = await allAuthoredDocuments(docsDir, new FleetContext());
|
|
65
|
+
candidates.push(...corpus.filter((path) => !moves.some((move) => isPathInside(move.from, path))));
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
// The corpus walk enumerates every service and feature; a tree it cannot
|
|
69
|
+
// walk is one `validate` will diagnose, and the moved documents are still
|
|
70
|
+
// corrected. A move is not refused over a question it only asks to be
|
|
71
|
+
// helpful — but it does not pretend the question was answered either.
|
|
72
|
+
out.notices.push(`links INTO the moved directories were not checked — the fleet's documents could not be walked (${err instanceof Error ? err.message : String(err)}); ` +
|
|
73
|
+
"`loam validate --all` names any that broke.");
|
|
74
|
+
}
|
|
75
|
+
const seen = new Set();
|
|
76
|
+
const unique = [];
|
|
77
|
+
for (const path of candidates) {
|
|
78
|
+
if (seen.has(resolve(path)))
|
|
79
|
+
continue;
|
|
80
|
+
seen.add(resolve(path));
|
|
81
|
+
unique.push(path);
|
|
82
|
+
}
|
|
83
|
+
// Read and rewrite with bounded concurrency — the whole corpus is read
|
|
84
|
+
// before the commit window can land — and apply in input order (`inOrder`).
|
|
85
|
+
const rewritten = await inOrder(unique, async (path) => {
|
|
86
|
+
let text;
|
|
87
|
+
try {
|
|
88
|
+
text = await readUtf8(path);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Absent (the corpus names every slot a service MAY fill — most have no
|
|
92
|
+
// runbook) or undecodable: either way there are no links to rewrite
|
|
93
|
+
// that loam could write back, and `link.unreadable` names the second.
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const after = retarget(path);
|
|
97
|
+
const next = rebaseLinks(text, { from: dirname(path), to: dirname(after), retarget });
|
|
98
|
+
return next === text ? null : { path, after, text, next };
|
|
99
|
+
});
|
|
100
|
+
for (const one of rewritten) {
|
|
101
|
+
if (one === null)
|
|
102
|
+
continue;
|
|
103
|
+
const { path, after, text, next } = one;
|
|
104
|
+
out.writes.push(planWrite(path, next));
|
|
105
|
+
out.relinked.push(after);
|
|
106
|
+
const where = repoPath(docsDir, after);
|
|
107
|
+
if (movedUnderVouch(parseFrontmatter(next), next) && !movedUnderVouch(parseFrontmatter(text), text)) {
|
|
108
|
+
out.notices.push(`${where} is vouched, and this move rewrote links in it — content.stale follows until its owner re-vouches.`);
|
|
109
|
+
}
|
|
110
|
+
// Living documents only: a `Based-On:` pin holds the digest of a LIVING
|
|
111
|
+
// requirement, so a feature's own delta text moving pins nothing.
|
|
112
|
+
const pinned = (md) => parseRequirements(md).map(requirementDigest).join(",");
|
|
113
|
+
if (!isPathInside(featuresDir(docsDir), path) && pinned(next) !== pinned(text)) {
|
|
114
|
+
out.notices.push(`${where}: links this move rewrote sit inside requirements, so a feature in flight that pins one with Based-On: ` +
|
|
115
|
+
"reports delta.baseline-stale until `loam rebase` re-pins it.");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The rewritten documents that do NOT ride a rename — the ones a move touches
|
|
122
|
+
* outside the directories it names, which its uncommitted-work refusal and its
|
|
123
|
+
* git staging have to be told about by path.
|
|
124
|
+
*/
|
|
125
|
+
export function outside(links, moves) {
|
|
126
|
+
return links.writes.map((w) => w.path).filter((path) => !moves.some((move) => isPathInside(move.from, path)));
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../../../src/commands/subsystem/txn/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The link half of `subsystem move` and `rename`: every relative markdown link\n * the renames would break, re-expressed so it reaches the same file.\n *\n * THE DEFECT THIS CLOSES. A move is a directory rename, and a relative link is\n * a route from one directory to another. `services/orders/spec.md` citing\n * `../../glossary/order.md` is two directories below the docs root; moved into\n * `services/commerce/orders/` it is three, and the same text names\n * `services/glossary/order.md`, which is nothing. The move reported success,\n * staged the renames in git, and the next `validate --all` failed\n * `link.unresolved` on every moved document that cited anything outside its\n * own directory — the \"failing between two commits\" state the commit window\n * exists to refuse. The same rename breaks the other direction too: a\n * capability document or a glossary term citing `services/orders/spec.md`\n * now points where nothing is.\n *\n * SO BOTH DIRECTIONS ARE REWRITTEN, with the one rule archive's merge uses\n * (`core/links/parse.ts`'s `rebaseLinks`): the target is unchanged, only the\n * route to it, and a link whose text still reaches its target from the new\n * place keeps its exact spelling.\n *\n * - Every markdown file under a moved directory, whatever its name — a runbook,\n * an ADR, a subsystem's own notes: the rename moves them all, so it owes them\n * all the same correction. Written at the OLD path, because the transaction\n * swaps files before it renames directories (`core/staging/txn/`), so the\n * rewritten bytes travel with the rename.\n * - Every other document in the link corpus (`core/links/corpus.ts`: the fleet's\n * own documents, every service's, every in-flight feature's) whose links\n * reach INTO a moved directory. Archived features are not in it, for the\n * corpus's own reason: their links describe the tree as it was, and nothing\n * grades them.\n *\n * A document that cannot be decoded is left as it is: rewriting means writing\n * the whole file back, and `link.unreadable` already names it.\n */\nimport { dirname, resolve } from \"node:path\";\nimport { allAuthoredDocuments, movedMarkdown } from \"../../../core/links/corpus.js\";\nimport { rebaseLinks } from \"../../../core/links/parse.js\";\nimport { FleetContext } from \"../../../core/fleet-context.js\";\nimport { movedUnderVouch, parseFrontmatter } from \"../../../core/document/frontmatter.js\";\nimport { parseRequirements } from \"../../../core/document/parse.js\";\nimport { requirementDigest } from \"../../../core/document/spec.js\";\nimport { repoPath } from \"../../../core/envelope/json.js\";\nimport { featuresDir } from \"../../../core/repo/paths.js\";\nimport { inOrder } from \"../../../core/kernel/concurrency.js\";\nimport { acrossRename, isPathInside } from \"../../../core/kernel/path-safety.js\";\nimport { planWrite, readUtf8, type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\n/** One directory rename, absolute paths. */\nexport interface DirectoryMove {\n from: string;\n to: string;\n}\n\n/** The link rewrites a set of renames owes, and where each rewritten document will be read from. */\nexport interface MovedLinks {\n /** Planned at each document's CURRENT path — the swap lands before the rename carries it. */\n writes: PlannedWrite[];\n /** Each rewritten document's path once the move has landed, absolute, in the order written. */\n relinked: string[];\n /**\n * The notes a person owes a reading of. A rewritten route is still a\n * changed byte: under a `content_digest` it is `content.stale` until the\n * owner re-vouches, and inside a requirement it moves the digest a\n * `Based-On:` pin holds, so a feature in flight that pins it is\n * `delta.baseline-stale` until it is rebased. Neither is softened — the\n * archive merge reports the first the same way (`revouchOwed`) — but both\n * are said here, by path, rather than discovered by the next gate.\n */\n notices: string[];\n}\n\nexport async function movedLinks(docsDir: DocsDir, moves: readonly DirectoryMove[]): Promise<MovedLinks> {\n const retarget = (target: string): string => {\n for (const move of moves) {\n if (isPathInside(move.from, target)) return acrossRename(target, move.from, move.to);\n }\n return target;\n };\n const out: MovedLinks = { writes: [], relinked: [], notices: [] };\n // The moved documents first, then every other document the corpus names —\n // one list, deduplicated in order, because the order is what `relinked`\n // reports and a person reads it top to bottom.\n const candidates: string[] = [];\n for (const move of moves) candidates.push(...(await movedMarkdown(move.from)));\n try {\n const corpus = await allAuthoredDocuments(docsDir, new FleetContext());\n candidates.push(...corpus.filter((path) => !moves.some((move) => isPathInside(move.from, path))));\n } catch (err) {\n // The corpus walk enumerates every service and feature; a tree it cannot\n // walk is one `validate` will diagnose, and the moved documents are still\n // corrected. A move is not refused over a question it only asks to be\n // helpful — but it does not pretend the question was answered either.\n out.notices.push(\n `links INTO the moved directories were not checked — the fleet's documents could not be walked (${err instanceof Error ? err.message : String(err)}); ` +\n \"`loam validate --all` names any that broke.\",\n );\n }\n const seen = new Set<string>();\n const unique: string[] = [];\n for (const path of candidates) {\n if (seen.has(resolve(path))) continue;\n seen.add(resolve(path));\n unique.push(path);\n }\n // Read and rewrite with bounded concurrency — the whole corpus is read\n // before the commit window can land — and apply in input order (`inOrder`).\n const rewritten = await inOrder(unique, async (path) => {\n let text: string;\n try {\n text = await readUtf8(path);\n } catch {\n // Absent (the corpus names every slot a service MAY fill — most have no\n // runbook) or undecodable: either way there are no links to rewrite\n // that loam could write back, and `link.unreadable` names the second.\n return null;\n }\n const after = retarget(path);\n const next = rebaseLinks(text, { from: dirname(path), to: dirname(after), retarget });\n return next === text ? null : { path, after, text, next };\n });\n for (const one of rewritten) {\n if (one === null) continue;\n const { path, after, text, next } = one;\n out.writes.push(planWrite(path, next));\n out.relinked.push(after);\n const where = repoPath(docsDir, after);\n if (movedUnderVouch(parseFrontmatter(next), next) && !movedUnderVouch(parseFrontmatter(text), text)) {\n out.notices.push(`${where} is vouched, and this move rewrote links in it — content.stale follows until its owner re-vouches.`);\n }\n // Living documents only: a `Based-On:` pin holds the digest of a LIVING\n // requirement, so a feature's own delta text moving pins nothing.\n const pinned = (md: string): string => parseRequirements(md).map(requirementDigest).join(\",\");\n if (!isPathInside(featuresDir(docsDir), path) && pinned(next) !== pinned(text)) {\n out.notices.push(\n `${where}: links this move 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 return out;\n}\n\n/**\n * The rewritten documents that do NOT ride a rename — the ones a move touches\n * outside the directories it names, which its uncommitted-work refusal and its\n * git staging have to be told about by path.\n */\nexport function outside(links: MovedLinks, moves: readonly DirectoryMove[]): string[] {\n return links.writes.map((w) => w.path).filter((path) => !moves.some((move) => isPathInside(move.from, path)));\n}\n"]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one `loam subsystem sync` SAYS it did — the `--json` envelope and the
|
|
3
|
+
* human lines, in one place.
|
|
4
|
+
*
|
|
5
|
+
* It sits beside `./views.ts` and `./exclude.ts` because it is the third answer
|
|
6
|
+
* about the same three files, and it moved out of `../sync.ts` for that file's
|
|
7
|
+
* standing reason: `sync.ts` is the lock, the transaction and the plan, and it
|
|
8
|
+
* reached the 400-line limit carrying the output too. Composing a report is not
|
|
9
|
+
* a phase of the commit, so nothing here reads the disk or decides anything — a
|
|
10
|
+
* caller hands over what happened and this spells it.
|
|
11
|
+
*/
|
|
12
|
+
import { emitJson } from "../../../core/envelope/json.js";
|
|
13
|
+
import { authoredRefusal } from "../../../core/repo/tree/render/service/header.js";
|
|
14
|
+
import { LANDSCAPE_UNREADABLE_NOTE } from "./views.js";
|
|
15
|
+
/** The second generated file's name, spelled once here so the key and the sentence cannot drift. */
|
|
16
|
+
const SERVICE_VIEWS = "architecture/services.likec4";
|
|
17
|
+
export function reportSync(json, out) {
|
|
18
|
+
// One reason today, and it is exactly the `action` it explains — spelled as a
|
|
19
|
+
// record so a second cause is an added value rather than a re-read of the
|
|
20
|
+
// sentence a person sees.
|
|
21
|
+
const blocked = out.action === "blocked" ? { reason: "landscape-invalid" } : null;
|
|
22
|
+
if (json) {
|
|
23
|
+
emitJson({
|
|
24
|
+
command: "subsystem",
|
|
25
|
+
path: "architecture/subsystems.likec4",
|
|
26
|
+
action: out.action,
|
|
27
|
+
subsystems: out.subsystems,
|
|
28
|
+
// ADDITIVE, and emitted on every run including the untouched one: a
|
|
29
|
+
// consumer must be able to read what happened to the second generated file
|
|
30
|
+
// without branching on whether this run happened to change it. `path` and
|
|
31
|
+
// `action` keep their frozen meaning — the subsystem file — so nothing
|
|
32
|
+
// reading them sees a new one.
|
|
33
|
+
serviceViews: { path: SERVICE_VIEWS, action: out.serviceViews },
|
|
34
|
+
...(blocked === null ? {} : { blocked }),
|
|
35
|
+
...(out.recovered === null ? {} : { recovered: out.recovered }),
|
|
36
|
+
projects: {
|
|
37
|
+
root: out.projects.root,
|
|
38
|
+
created: out.projects.created,
|
|
39
|
+
removed: out.projects.removed,
|
|
40
|
+
current: out.projects.current,
|
|
41
|
+
// Additive, and emitted in every mode including the untouched one: a
|
|
42
|
+
// consumer must be able to read what the root project now excludes
|
|
43
|
+
// without branching on whether this run happened to change it.
|
|
44
|
+
//
|
|
45
|
+
// `unreadable` travels with it because `entries: []` alone collapses the
|
|
46
|
+
// two answers `readRootExclude` insists must stay apart — "the file
|
|
47
|
+
// excludes nothing" and "loam could not read the file" are opposite
|
|
48
|
+
// facts about what the renderer will load, and the text view had the
|
|
49
|
+
// distinction while `--json` did not (verification 2026-09-04, review C).
|
|
50
|
+
exclude: {
|
|
51
|
+
updated: out.projects.exclude.updated,
|
|
52
|
+
entries: out.projects.exclude.entries,
|
|
53
|
+
added: out.projects.exclude.added,
|
|
54
|
+
removed: out.projects.exclude.removed,
|
|
55
|
+
unreadable: out.projects.exclude.unreadable,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (out.recovered !== null && out.recovered.outcome !== "consistent") {
|
|
62
|
+
console.log(`note: recovered an interrupted \`loam ${out.recovered.command}\` commit first (${out.recovered.outcome}).`);
|
|
63
|
+
}
|
|
64
|
+
console.log(views(out));
|
|
65
|
+
serviceViews(out.serviceViews);
|
|
66
|
+
// Owed on BOTH arms: the run that declined to rewrite an existing file, and
|
|
67
|
+
// the run that wrote the tolerant shape because there was none to protect.
|
|
68
|
+
if (out.mapUnreadable)
|
|
69
|
+
console.log(LANDSCAPE_UNREADABLE_NOTE);
|
|
70
|
+
projects(out.projects);
|
|
71
|
+
exclude(out.projects);
|
|
72
|
+
}
|
|
73
|
+
/** The one line about the generated views file. */
|
|
74
|
+
function views(out) {
|
|
75
|
+
// "nothing to write" is a claim about the WHOLE run, and it is false the moment
|
|
76
|
+
// any of this verb's FOUR writers landed something beside a current subsystem
|
|
77
|
+
// views file: the per-service views file, a project file created, one removed,
|
|
78
|
+
// or the root `exclude` rewritten. The exclude arm was missed when it was
|
|
79
|
+
// added, so the tail contradicted the very next line of output (verification
|
|
80
|
+
// 2026-09-04, review C) — and the per-service file is the same trap one file
|
|
81
|
+
// over, which is why it is in the same expression rather than a second one.
|
|
82
|
+
const quiet = out.serviceViews === "current" &&
|
|
83
|
+
out.projects.created.length === 0 &&
|
|
84
|
+
out.projects.removed.length === 0 &&
|
|
85
|
+
!out.projects.exclude.updated;
|
|
86
|
+
const sentence = {
|
|
87
|
+
current: `architecture/subsystems.likec4 is current (${out.subsystems} subsystem(s))${quiet ? " — nothing to write." : "."}`,
|
|
88
|
+
created: `wrote architecture/subsystems.likec4 — ${out.subsystems} subsystem view(s).`,
|
|
89
|
+
updated: `updated architecture/subsystems.likec4 — ${out.subsystems} subsystem view(s).`,
|
|
90
|
+
removed: `removed architecture/subsystems.likec4 — the tree has no subsystems, so the generated file must be absent.`,
|
|
91
|
+
blocked: "architecture/subsystems.likec4 left as it is — architecture/ does not parse as one project, so the " +
|
|
92
|
+
"render's element join is the landscape file's alone (a use-case document that binds an element of its " +
|
|
93
|
+
"own is not in it), and rewriting the file would take its `include` lines with it.",
|
|
94
|
+
refused: authoredRefusal("architecture/subsystems.likec4"),
|
|
95
|
+
};
|
|
96
|
+
return sentence[out.action];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The one line about `architecture/services.likec4`, printed on every answer but
|
|
100
|
+
* `current` — so on the two that left the file alone (`blocked`, `refused`) as
|
|
101
|
+
* well as the three that changed it. "Nothing happened to it, and here is why"
|
|
102
|
+
* is exactly the sentence a person needs; only "nothing happened to it because
|
|
103
|
+
* nothing needed to" is silence worth keeping.
|
|
104
|
+
*
|
|
105
|
+
* SILENT WHEN CURRENT, and that is the difference from the subsystem file's line
|
|
106
|
+
* above: that one is the sentence this command has always ended on and a person
|
|
107
|
+
* reads it as "the run happened", while a second unconditional line about a file
|
|
108
|
+
* nothing touched is noise on every run in a fleet that is already in order. The
|
|
109
|
+
* `--json` key is unconditional for the opposite reason — a consumer branches on
|
|
110
|
+
* a value, not on a line's presence.
|
|
111
|
+
*
|
|
112
|
+
* No view COUNT here, deliberately. The subsystem line counts subsystems because
|
|
113
|
+
* the tree answers that without reading anything; the per-service file draws
|
|
114
|
+
* only the services the MAP resolves, and the honest count is the render's, not
|
|
115
|
+
* the tree's. loam never reads a generated file's content (docs/DESIGN.md rule
|
|
116
|
+
* 26), so counting the views in it is the one place the count could come from
|
|
117
|
+
* and the one place it may not.
|
|
118
|
+
*/
|
|
119
|
+
function serviceViews(action) {
|
|
120
|
+
if (action === "current")
|
|
121
|
+
return;
|
|
122
|
+
const sentence = {
|
|
123
|
+
created: `wrote ${SERVICE_VIEWS} — one overview view per service the fleet map draws.`,
|
|
124
|
+
updated: `updated ${SERVICE_VIEWS} — one overview view per service the fleet map draws.`,
|
|
125
|
+
removed: `removed ${SERVICE_VIEWS} — the fleet map draws none of the services under services/, so the generated file must be absent.`,
|
|
126
|
+
blocked: `${SERVICE_VIEWS} left as it is — architecture/ does not parse as one project, so no service resolves to a ` +
|
|
127
|
+
"map element and the render would have emptied the file rather than improved it.",
|
|
128
|
+
refused: authoredRefusal(SERVICE_VIEWS),
|
|
129
|
+
};
|
|
130
|
+
console.log(sentence[action]);
|
|
131
|
+
}
|
|
132
|
+
/** The per-service project files this run created and removed. */
|
|
133
|
+
function projects(out) {
|
|
134
|
+
if (out.created.length > 0) {
|
|
135
|
+
console.log(`wrote ${out.created.length} services/<…>/likec4.config.json — one LikeC4 project per service model whose ` +
|
|
136
|
+
"model stands alone (an existing file is yours and is never rewritten; commit the new ones before a " +
|
|
137
|
+
"`loam subsystem move`, which refuses over untracked paths). With more than one project, " +
|
|
138
|
+
"likec4 validate at the docs root needs --project <name>; build and export take every project.");
|
|
139
|
+
}
|
|
140
|
+
// Named one per line: this is a DELETE of a file a team may have written, and
|
|
141
|
+
// a count would leave a reader nothing to check against their own diff.
|
|
142
|
+
for (const path of out.removed)
|
|
143
|
+
console.log(`removed ${path}`);
|
|
144
|
+
if (out.removed.length > 0) {
|
|
145
|
+
console.log("— that model extends the fleet map, and a project file beside it registers a second renderer project " +
|
|
146
|
+
"rooted at the service directory: `likec4 validate .` then refuses without `--project`, and wherever " +
|
|
147
|
+
"that project claims the model it loads it alone, where the map's kinds are not, and the fleet project " +
|
|
148
|
+
"loses the service's interior. This is what `service.likec4-config-stray` names.");
|
|
149
|
+
}
|
|
150
|
+
if (!out.root && out.modelled > 0) {
|
|
151
|
+
console.log("note: no likec4.config.json at the docs root, so no service project files were written — " +
|
|
152
|
+
"`loam doctor` prints the root file.");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** The root project's `exclude`, and the one state loam refuses to touch. */
|
|
156
|
+
function exclude(out) {
|
|
157
|
+
const plan = out.exclude;
|
|
158
|
+
if (plan.updated) {
|
|
159
|
+
// Named entries rather than a count: this line is the whole record of a
|
|
160
|
+
// rewrite to a file the team owns, and "updated the exclude list" gives a
|
|
161
|
+
// reader nothing to check against their own diff.
|
|
162
|
+
const parts = [
|
|
163
|
+
...(plan.added.length > 0 ? [`+${plan.added.join(" +")}`] : []),
|
|
164
|
+
...(plan.removed.length > 0 ? [`-${plan.removed.join(" -")}`] : []),
|
|
165
|
+
];
|
|
166
|
+
console.log(`rewrote likec4.config.json's \`exclude\` (${parts.join(" ")}) — the root project excludes exactly the ` +
|
|
167
|
+
"models that stand alone; a model that extends the fleet map renders from the docs root and must not be excluded.");
|
|
168
|
+
}
|
|
169
|
+
if (plan.unreadable) {
|
|
170
|
+
console.log("note: likec4.config.json at the docs root is not a JSON object with a string `exclude` list, so it was " +
|
|
171
|
+
"left exactly as it is — loam does not rewrite a project file it cannot read.");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../../src/commands/subsystem/txn/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What one `loam subsystem sync` SAYS it did — the `--json` envelope and the\n * human lines, in one place.\n *\n * It sits beside `./views.ts` and `./exclude.ts` because it is the third answer\n * about the same three files, and it moved out of `../sync.ts` for that file's\n * standing reason: `sync.ts` is the lock, the transaction and the plan, and it\n * reached the 400-line limit carrying the output too. Composing a report is not\n * a phase of the commit, so nothing here reads the disk or decides anything — a\n * caller hands over what happened and this spells it.\n */\nimport { emitJson } from \"../../../core/envelope/json.js\";\nimport { authoredRefusal } from \"../../../core/repo/tree/render/service/header.js\";\nimport type { CommitRecovery } from \"../../../core/staging/interrupted.js\";\nimport type { ExcludePlan } from \"./exclude.js\";\nimport { LANDSCAPE_UNREADABLE_NOTE } from \"./views.js\";\n\n/**\n * What one sync did to the views file — and ONLY that file; the projects report\n * separately.\n *\n * `blocked` is the fifth answer: the map cannot be read, a generated file\n * already exists, and this run left it exactly as it is. The tolerant render\n * used to run anyway and rewrote a good file down to title and description\n * (verification 2026-09-04, W5). The project half is unaffected and still runs —\n * neither the per-service files nor the root `exclude` depend on the map.\n *\n * `refused` is the sixth, and it is about OWNERSHIP rather than about the map:\n * the file standing at a path loam generates does not open with loam's mark, so\n * it is somebody's authored document and this command will not take it. It is\n * the only action that also sets a non-zero exit code (`../sync.ts` says why),\n * because unlike `blocked` it is not a state any later run clears on its own.\n */\nexport type SyncAction = \"current\" | \"created\" | \"updated\" | \"removed\" | \"blocked\" | \"refused\";\n\n/** The second generated file's name, spelled once here so the key and the sentence cannot drift. */\nconst SERVICE_VIEWS = \"architecture/services.likec4\";\n\n/** Why a run answered `blocked`. One reason today; a key rather than a bare string so a second one is additive. */\ninterface SyncBlocked {\n reason: \"landscape-invalid\";\n}\n\n/** The additive `projects` payload key, and what the text lines are composed from. */\nexport interface ProjectsReport {\n root: boolean;\n /** POSIX paths relative to the DOCS ROOT, written this run, sorted by path. */\n created: string[];\n /**\n * POSIX paths relative to the DOCS ROOT, DELETED this run, sorted by path — a\n * `likec4.config.json` beside a model that extends the map. `[]` rather than\n * absent on a run that removed none, so a consumer reads the key.\n *\n * SORTED BY PATH rather than by service id, which is the order the survey\n * hands them over in: `../sync.ts` sorts both arrays where it spells them, so\n * the `--json` list and the `removed <path>` lines below can never disagree.\n */\n removed: string[];\n current: number;\n modelled: number;\n exclude: ExcludePlan;\n}\n\n/** Everything one run has to say, as the caller knows it. */\nexport interface SyncReport {\n /** `architecture/subsystems.likec4` — and nothing else; the `--json` `action` key is exactly this. */\n action: SyncAction;\n /**\n * `architecture/services.likec4` — the per-service overviews.\n *\n * A field of its own rather than a folded `action`, for the reason the shared\n * finding code carries the path: the two files drift for different reasons and\n * a reader told only that \"the generated views changed\" would have to diff the\n * repo to find out which one. `blocked` reaches it exactly as it reaches the\n * other, and for a sharper reason — with no readable map no service resolves,\n * so the tolerant render is the empty file rather than a poorer one.\n */\n serviceViews: SyncAction;\n subsystems: number;\n recovered: CommitRecovery | null;\n projects: ProjectsReport;\n /** The map could not be read at all — the note is owed whether or not a file was protected. */\n mapUnreadable: boolean;\n}\n\nexport function reportSync(json: boolean, out: SyncReport): void {\n // One reason today, and it is exactly the `action` it explains — spelled as a\n // record so a second cause is an added value rather than a re-read of the\n // sentence a person sees.\n const blocked: SyncBlocked | null = out.action === \"blocked\" ? { reason: \"landscape-invalid\" } : null;\n if (json) {\n emitJson({\n command: \"subsystem\",\n path: \"architecture/subsystems.likec4\",\n action: out.action,\n subsystems: out.subsystems,\n // ADDITIVE, and emitted on every run including the untouched one: a\n // consumer must be able to read what happened to the second generated file\n // without branching on whether this run happened to change it. `path` and\n // `action` keep their frozen meaning — the subsystem file — so nothing\n // reading them sees a new one.\n serviceViews: { path: SERVICE_VIEWS, action: out.serviceViews },\n ...(blocked === null ? {} : { blocked }),\n ...(out.recovered === null ? {} : { recovered: out.recovered }),\n projects: {\n root: out.projects.root,\n created: out.projects.created,\n removed: out.projects.removed,\n current: out.projects.current,\n // Additive, and emitted in every mode including the untouched one: a\n // consumer must be able to read what the root project now excludes\n // without branching on whether this run happened to change it.\n //\n // `unreadable` travels with it because `entries: []` alone collapses the\n // two answers `readRootExclude` insists must stay apart — \"the file\n // excludes nothing\" and \"loam could not read the file\" are opposite\n // facts about what the renderer will load, and the text view had the\n // distinction while `--json` did not (verification 2026-09-04, review C).\n exclude: {\n updated: out.projects.exclude.updated,\n entries: out.projects.exclude.entries,\n added: out.projects.exclude.added,\n removed: out.projects.exclude.removed,\n unreadable: out.projects.exclude.unreadable,\n },\n },\n });\n return;\n }\n if (out.recovered !== null && out.recovered.outcome !== \"consistent\") {\n console.log(\n `note: recovered an interrupted \\`loam ${out.recovered.command}\\` commit first (${out.recovered.outcome}).`,\n );\n }\n console.log(views(out));\n serviceViews(out.serviceViews);\n // Owed on BOTH arms: the run that declined to rewrite an existing file, and\n // the run that wrote the tolerant shape because there was none to protect.\n if (out.mapUnreadable) console.log(LANDSCAPE_UNREADABLE_NOTE);\n projects(out.projects);\n exclude(out.projects);\n}\n\n/** The one line about the generated views file. */\nfunction views(out: SyncReport): string {\n // \"nothing to write\" is a claim about the WHOLE run, and it is false the moment\n // any of this verb's FOUR writers landed something beside a current subsystem\n // views file: the per-service views file, a project file created, one removed,\n // or the root `exclude` rewritten. The exclude arm was missed when it was\n // added, so the tail contradicted the very next line of output (verification\n // 2026-09-04, review C) — and the per-service file is the same trap one file\n // over, which is why it is in the same expression rather than a second one.\n const quiet =\n out.serviceViews === \"current\" &&\n out.projects.created.length === 0 &&\n out.projects.removed.length === 0 &&\n !out.projects.exclude.updated;\n const sentence: Record<SyncAction, string> = {\n current: `architecture/subsystems.likec4 is current (${out.subsystems} subsystem(s))${quiet ? \" — nothing to write.\" : \".\"}`,\n created: `wrote architecture/subsystems.likec4 — ${out.subsystems} subsystem view(s).`,\n updated: `updated architecture/subsystems.likec4 — ${out.subsystems} subsystem view(s).`,\n removed: `removed architecture/subsystems.likec4 — the tree has no subsystems, so the generated file must be absent.`,\n blocked:\n \"architecture/subsystems.likec4 left as it is — architecture/ does not parse as one project, so the \" +\n \"render's element join is the landscape file's alone (a use-case document that binds an element of its \" +\n \"own is not in it), and rewriting the file would take its `include` lines with it.\",\n refused: authoredRefusal(\"architecture/subsystems.likec4\"),\n };\n return sentence[out.action];\n}\n\n/**\n * The one line about `architecture/services.likec4`, printed on every answer but\n * `current` — so on the two that left the file alone (`blocked`, `refused`) as\n * well as the three that changed it. \"Nothing happened to it, and here is why\"\n * is exactly the sentence a person needs; only \"nothing happened to it because\n * nothing needed to\" is silence worth keeping.\n *\n * SILENT WHEN CURRENT, and that is the difference from the subsystem file's line\n * above: that one is the sentence this command has always ended on and a person\n * reads it as \"the run happened\", while a second unconditional line about a file\n * nothing touched is noise on every run in a fleet that is already in order. The\n * `--json` key is unconditional for the opposite reason — a consumer branches on\n * a value, not on a line's presence.\n *\n * No view COUNT here, deliberately. The subsystem line counts subsystems because\n * the tree answers that without reading anything; the per-service file draws\n * only the services the MAP resolves, and the honest count is the render's, not\n * the tree's. loam never reads a generated file's content (docs/DESIGN.md rule\n * 26), so counting the views in it is the one place the count could come from\n * and the one place it may not.\n */\nfunction serviceViews(action: SyncAction): void {\n if (action === \"current\") return;\n const sentence: Record<Exclude<SyncAction, \"current\">, string> = {\n created: `wrote ${SERVICE_VIEWS} — one overview view per service the fleet map draws.`,\n updated: `updated ${SERVICE_VIEWS} — one overview view per service the fleet map draws.`,\n removed: `removed ${SERVICE_VIEWS} — the fleet map draws none of the services under services/, so the generated file must be absent.`,\n blocked:\n `${SERVICE_VIEWS} left as it is — architecture/ does not parse as one project, so no service resolves to a ` +\n \"map element and the render would have emptied the file rather than improved it.\",\n refused: authoredRefusal(SERVICE_VIEWS),\n };\n console.log(sentence[action]);\n}\n\n/** The per-service project files this run created and removed. */\nfunction projects(out: ProjectsReport): void {\n if (out.created.length > 0) {\n console.log(\n `wrote ${out.created.length} services/<…>/likec4.config.json — one LikeC4 project per service model whose ` +\n \"model stands alone (an existing file is yours and is never rewritten; commit the new ones before a \" +\n \"`loam subsystem move`, which refuses over untracked paths). With more than one project, \" +\n \"likec4 validate at the docs root needs --project <name>; build and export take every project.\",\n );\n }\n // Named one per line: this is a DELETE of a file a team may have written, and\n // a count would leave a reader nothing to check against their own diff.\n for (const path of out.removed) console.log(`removed ${path}`);\n if (out.removed.length > 0) {\n console.log(\n \"— that model extends the fleet map, and a project file beside it registers a second renderer project \" +\n \"rooted at the service directory: `likec4 validate .` then refuses without `--project`, and wherever \" +\n \"that project claims the model it loads it alone, where the map's kinds are not, and the fleet project \" +\n \"loses the service's interior. This is what `service.likec4-config-stray` names.\",\n );\n }\n if (!out.root && out.modelled > 0) {\n console.log(\n \"note: no likec4.config.json at the docs root, so no service project files were written — \" +\n \"`loam doctor` prints the root file.\",\n );\n }\n}\n\n/** The root project's `exclude`, and the one state loam refuses to touch. */\nfunction exclude(out: ProjectsReport): void {\n const plan = out.exclude;\n if (plan.updated) {\n // Named entries rather than a count: this line is the whole record of a\n // rewrite to a file the team owns, and \"updated the exclude list\" gives a\n // reader nothing to check against their own diff.\n const parts = [\n ...(plan.added.length > 0 ? [`+${plan.added.join(\" +\")}`] : []),\n ...(plan.removed.length > 0 ? [`-${plan.removed.join(\" -\")}`] : []),\n ];\n console.log(\n `rewrote likec4.config.json's \\`exclude\\` (${parts.join(\" \")}) — the root project excludes exactly the ` +\n \"models that stand alone; a model that extends the fleet map renders from the docs root and must not be excluded.\",\n );\n }\n if (plan.unreadable) {\n console.log(\n \"note: likec4.config.json at the docs root is not a JSON object with a string `exclude` list, so it was \" +\n \"left exactly as it is — loam does not rewrite a project file it cannot read.\",\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared commit window every subsystem WRITE verb goes through — `new`,
|
|
3
|
+
* `rm`, `move` and `rename` all land here: lock, recover a predecessor's
|
|
4
|
+
* journal, plan against the walked tree, regenerate BOTH generated views files
|
|
5
|
+
* from the PLANNED post-state, commit through the journaled transaction
|
|
6
|
+
* (directory renames included), report. One window, because those files must
|
|
7
|
+
* land in the same commit as whatever changed the tree — a marker without its
|
|
8
|
+
* view, or renames without theirs, is exactly the `subsystem.views-stale` state
|
|
9
|
+
* the generated files' contract refuses to leave between two commits. The
|
|
10
|
+
* per-service file is in that rule and not beside it: its titles are
|
|
11
|
+
* `<subsystem path> / <service id>`, so the placement a verb changes is written
|
|
12
|
+
* into it too.
|
|
13
|
+
*
|
|
14
|
+
* This window does NOT write the per-service project files
|
|
15
|
+
* (`services/<…>/<id>/likec4.config.json`); only `../sync.ts` does, and the
|
|
16
|
+
* asymmetry is deliberate rather than an omission. The views file must ride
|
|
17
|
+
* in the verb's commit because its bytes depend on the PLACEMENT the verb is
|
|
18
|
+
* changing. A project file's bytes depend on the service id alone, which no
|
|
19
|
+
* verb here changes — and the file lives INSIDE the service directory, so a
|
|
20
|
+
* `move` carries it to the new location as part of the rename it already
|
|
21
|
+
* journals (in a git-backed repo that move REFUSES first, `move-uncommitted`,
|
|
22
|
+
* until the files `sync` created are committed — the refusal names them, and
|
|
23
|
+
* `sync`'s own output says to commit them), and `rm` never reaches one,
|
|
24
|
+
* because it refuses any subsystem that still holds a member
|
|
25
|
+
* (`subsystem-not-empty`, `../edit.ts`). No verb can
|
|
26
|
+
* therefore leave a project file stale or orphaned, and a verb that filled
|
|
27
|
+
* gaps in passing would silently write files a `--json` reader of `new` or
|
|
28
|
+
* `rename` was never told to expect. The one state a verb can leave is a
|
|
29
|
+
* model with no file beside it, and that is the state `validate --all` names
|
|
30
|
+
* as `service.likec4-config-missing`, with `loam subsystem sync` as the
|
|
31
|
+
* repair — one writer, so the create-only rule has one place to hold.
|
|
32
|
+
*
|
|
33
|
+
* NEITHER generated file is written over a document loam did not write, and
|
|
34
|
+
* that guard is checked HERE as well as in `../sync.ts` — see the comment at
|
|
35
|
+
* the check. Both are filenames loam RESERVES inside a directory the team
|
|
36
|
+
* owns, both are rewritten whole, and until the check below existed all four
|
|
37
|
+
* verbs took an authored file at either path without a word. Unlike sync,
|
|
38
|
+
* which reports the one file `refused` and completes the rest, a verb refuses
|
|
39
|
+
* WHOLE: the file has to land in this commit, so half of this commit is not a
|
|
40
|
+
* lesser version of it.
|
|
41
|
+
*/
|
|
42
|
+
import { existsSync } from "node:fs";
|
|
43
|
+
import { readFile } from "node:fs/promises";
|
|
44
|
+
import { fail, repoPath } from "../../../core/envelope/json.js";
|
|
45
|
+
import { listFleetTree } from "../../../core/repo/repo.js";
|
|
46
|
+
import { stageWrites } from "../../../core/staging/commit.js";
|
|
47
|
+
import {} from "../../../core/staging/interrupted.js";
|
|
48
|
+
import { openCommitWindow } from "../../../core/staging/recovery/recover.js";
|
|
49
|
+
import { commitStaged } from "../../../core/staging/txn/transaction.js";
|
|
50
|
+
import {} from "../../../core/staging/writes.js";
|
|
51
|
+
import { authoredGeneratedPaths, authoredRefusal } from "../../../core/repo/tree/render/service/header.js";
|
|
52
|
+
import { expectedViews, LANDSCAPE_UNREADABLE_NOTE, planGenerated } from "./views.js";
|
|
53
|
+
/** The text tail a verb's success line carries about the generated files — one clause per file that moved. */
|
|
54
|
+
export function reportViews(views) {
|
|
55
|
+
return ([
|
|
56
|
+
["architecture/subsystems.likec4", views.subsystems],
|
|
57
|
+
["architecture/services.likec4", views.services],
|
|
58
|
+
]
|
|
59
|
+
// `current` says nothing: the tail hangs off a success line, and a verb
|
|
60
|
+
// that renamed one directory must not print two clauses about files that
|
|
61
|
+
// did not move.
|
|
62
|
+
.filter(([, action]) => action !== "current")
|
|
63
|
+
.map(([file, action]) => ` — ${file} ${action}`)
|
|
64
|
+
.join(""));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Lock → recover → plan → stage (views included) → journaled commit → report.
|
|
68
|
+
* `plan` returning null means it already reported a refusal; nothing was
|
|
69
|
+
* staged and nothing is written.
|
|
70
|
+
*/
|
|
71
|
+
export async function commitWindow(docsDir, json, plan) {
|
|
72
|
+
// Refuse-fast (0), as archive takes the lock: two concurrent verbs answer
|
|
73
|
+
// `docs-busy` rather than queue behind each other.
|
|
74
|
+
const opened = await openCommitWindow(docsDir, 0);
|
|
75
|
+
if (!opened.ok) {
|
|
76
|
+
fail(json, opened.code, opened.message);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const { recovered } = opened;
|
|
80
|
+
try {
|
|
81
|
+
const txn = await plan(await listFleetTree(docsDir));
|
|
82
|
+
if (txn === null)
|
|
83
|
+
return;
|
|
84
|
+
const expected = await expectedViews(docsDir, txn.tree);
|
|
85
|
+
// OWNERSHIP BEFORE ANYTHING IS STAGED, and the WHOLE verb is refused.
|
|
86
|
+
//
|
|
87
|
+
// The guard first shipped in `../sync.ts` alone, and this window is the
|
|
88
|
+
// other writer of exactly the same two reserved paths — for `subsystem
|
|
89
|
+
// new`, `rm`, `move` and `rename` at once. Reproduced before this call
|
|
90
|
+
// existed: with a hand-authored `architecture/services.likec4` in the tree,
|
|
91
|
+
// `loam subsystem new platform` printed "architecture/services.likec4
|
|
92
|
+
// updated" and destroyed it, first line and all. One predicate, one
|
|
93
|
+
// sentence, shared from beneath every writer
|
|
94
|
+
// (`core/repo/tree/render/service/header.ts`).
|
|
95
|
+
//
|
|
96
|
+
// WHY THE WHOLE OPERATION AND NOT JUST THE FILE. `sync` can decline one file
|
|
97
|
+
// and still do the rest, because nothing else it writes depends on that file
|
|
98
|
+
// and every part of it is idempotent. This window cannot: its entire reason
|
|
99
|
+
// for existing is that the generated files land in the SAME commit as the
|
|
100
|
+
// change to the tree, so completing the structural half and reporting the
|
|
101
|
+
// file as refused would MANUFACTURE the `subsystem.views-stale` state the
|
|
102
|
+
// banner above says this window refuses to leave between two commits — and
|
|
103
|
+
// it would do so irreversibly, since `move` and `rename` also stage their
|
|
104
|
+
// renames in git. A half-done move nobody asked for is worse than a refusal
|
|
105
|
+
// a person can act on, and a refusal is re-runnable the moment the authored
|
|
106
|
+
// file is out of the reserved path.
|
|
107
|
+
//
|
|
108
|
+
// It runs AFTER `plan`, which writes nothing and has already answered the
|
|
109
|
+
// verb-specific refusals (`unknown-target`, `subsystem-not-empty`,
|
|
110
|
+
// `move-uncommitted`): a caller whose name is wrong AND whose tree holds an
|
|
111
|
+
// authored views file is better told about the name.
|
|
112
|
+
const authored = await authoredGeneratedPaths([expected.subsystems.path, expected.services.path]);
|
|
113
|
+
if (authored.length > 0) {
|
|
114
|
+
fail(json,
|
|
115
|
+
// The code is `already-exists` and not a new one because it is exactly
|
|
116
|
+
// what that code has always meant here — "refusing to create over
|
|
117
|
+
// something that already exists, because overwriting would destroy work
|
|
118
|
+
// nobody asked to lose" — and it is already this command's documented
|
|
119
|
+
// refusal for the flat namespace. A second code for the same sentence
|
|
120
|
+
// would be a second branch an agent has to learn for no new decision.
|
|
121
|
+
"already-exists", authored.map((path) => authoredRefusal(repoPath(docsDir, path))).join(" ") +
|
|
122
|
+
" NOTHING was written and nothing was renamed: this command lands the generated views file in the same " +
|
|
123
|
+
"commit as the change to the tree, so it refuses whole rather than leaving the tree changed — and, for " +
|
|
124
|
+
"`move` and `rename`, renames staged in git — with a views file it may not write.");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const writes = [...txn.writes];
|
|
128
|
+
// BOTH generated files, in the ONE commit that changes the tree. The
|
|
129
|
+
// per-service file is not a bystander here: its view titles are
|
|
130
|
+
// `<subsystem path> / <service id>`, so every `move` and `rename` restales
|
|
131
|
+
// it exactly as it restales the subsystem views, and leaving it for a later
|
|
132
|
+
// `sync` is the failing-between-two-commits state this window exists to
|
|
133
|
+
// refuse.
|
|
134
|
+
const views = {
|
|
135
|
+
subsystems: await stageGenerated(expected.subsystems, writes, false),
|
|
136
|
+
// PROTECTED when the map did not parse as a project, and only this file
|
|
137
|
+
// is: `renderSubsystemViews` answers null off the TREE, which is readable
|
|
138
|
+
// either way, while `renderServiceOverviews` answers null whenever no
|
|
139
|
+
// service resolves to an element — which is what an unreadable map looks
|
|
140
|
+
// like from here. Under `known: false` a null render is therefore not
|
|
141
|
+
// evidence of absence, and writing it would delete the whole file over a
|
|
142
|
+
// sibling document that does not parse. A verb still rewrites a file it
|
|
143
|
+
// CAN render (the tolerant arm this window has always taken), and the
|
|
144
|
+
// person is told by the note at the foot of this function.
|
|
145
|
+
services: await stageGenerated(expected.services, writes, !expected.known),
|
|
146
|
+
};
|
|
147
|
+
const staged = await stageWrites(writes);
|
|
148
|
+
const committed = await commitStaged({
|
|
149
|
+
root: docsDir,
|
|
150
|
+
command: "subsystem",
|
|
151
|
+
rerun: "loam subsystem sync",
|
|
152
|
+
target: txn.target,
|
|
153
|
+
...(txn.moves === undefined ? {} : { moves: txn.moves }),
|
|
154
|
+
}, staged, txn.what);
|
|
155
|
+
if (!committed.ok) {
|
|
156
|
+
const code = committed.code === "rollback-incomplete"
|
|
157
|
+
? committed.code
|
|
158
|
+
: committed.raced
|
|
159
|
+
? (txn.racedCode ?? txn.failedCode ?? committed.code)
|
|
160
|
+
: (txn.failedCode ?? committed.code);
|
|
161
|
+
fail(json, code, committed.message);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
await txn.report(views, recovered);
|
|
165
|
+
// A verb CANNOT leave this file behind the tree — its bytes depend on the
|
|
166
|
+
// placement the verb just changed, so the tolerant render lands even when the
|
|
167
|
+
// map is unreadable and the file loses its includes. `sync` may decline that
|
|
168
|
+
// rewrite (`action: "blocked"`); a verb may not, so the person is told
|
|
169
|
+
// instead, and the same note names the run that puts the includes back.
|
|
170
|
+
if (!json && !expected.known)
|
|
171
|
+
console.log(LANDSCAPE_UNREADABLE_NOTE);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
await opened.release();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Compare ONE generated file against what it must say, append the write when
|
|
179
|
+
* they differ, and name what happened. The compare is `planGenerated`'s, the
|
|
180
|
+
* one `../sync.ts` makes too — `./views.ts` says why it is over CONTENT, not
|
|
181
|
+
* bytes, and why there is one spelling of it.
|
|
182
|
+
*
|
|
183
|
+
* `protect` is the caller's statement that a NULL render is not evidence: the
|
|
184
|
+
* file is left exactly as it is rather than deleted. It is never a licence to
|
|
185
|
+
* skip a real rewrite — a file loam can render is rendered, which is the
|
|
186
|
+
* difference between this window and `../sync.ts`'s `blocked`.
|
|
187
|
+
*/
|
|
188
|
+
async function stageGenerated(file, writes, protect) {
|
|
189
|
+
const current = existsSync(file.path) ? await readFile(file.path, "utf8") : null;
|
|
190
|
+
const planned = planGenerated(file, current);
|
|
191
|
+
if (planned.write === null || (protect && file.content === null))
|
|
192
|
+
return "current";
|
|
193
|
+
writes.push(planned.write);
|
|
194
|
+
return planned.action;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=txn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txn.js","sourceRoot":"","sources":["../../../../src/commands/subsystem/txn/txn.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The shared commit window every subsystem WRITE verb goes through — `new`,\n * `rm`, `move` and `rename` all land here: lock, recover a predecessor's\n * journal, plan against the walked tree, regenerate BOTH generated views files\n * from the PLANNED post-state, commit through the journaled transaction\n * (directory renames included), report. One window, because those files must\n * land in the same commit as whatever changed the tree — a marker without its\n * view, or renames without theirs, is exactly the `subsystem.views-stale` state\n * the generated files' contract refuses to leave between two commits. The\n * per-service file is in that rule and not beside it: its titles are\n * `<subsystem path> / <service id>`, so the placement a verb changes is written\n * into it too.\n *\n * This window does NOT write the per-service project files\n * (`services/<…>/<id>/likec4.config.json`); only `../sync.ts` does, and the\n * asymmetry is deliberate rather than an omission. The views file must ride\n * in the verb's commit because its bytes depend on the PLACEMENT the verb is\n * changing. A project file's bytes depend on the service id alone, which no\n * verb here changes — and the file lives INSIDE the service directory, so a\n * `move` carries it to the new location as part of the rename it already\n * journals (in a git-backed repo that move REFUSES first, `move-uncommitted`,\n * until the files `sync` created are committed — the refusal names them, and\n * `sync`'s own output says to commit them), and `rm` never reaches one,\n * because it refuses any subsystem that still holds a member\n * (`subsystem-not-empty`, `../edit.ts`). No verb can\n * therefore leave a project file stale or orphaned, and a verb that filled\n * gaps in passing would silently write files a `--json` reader of `new` or\n * `rename` was never told to expect. The one state a verb can leave is a\n * model with no file beside it, and that is the state `validate --all` names\n * as `service.likec4-config-missing`, with `loam subsystem sync` as the\n * repair — one writer, so the create-only rule has one place to hold.\n *\n * NEITHER generated file is written over a document loam did not write, and\n * that guard is checked HERE as well as in `../sync.ts` — see the comment at\n * the check. Both are filenames loam RESERVES inside a directory the team\n * owns, both are rewritten whole, and until the check below existed all four\n * verbs took an authored file at either path without a word. Unlike sync,\n * which reports the one file `refused` and completes the rest, a verb refuses\n * WHOLE: the file has to land in this commit, so half of this commit is not a\n * lesser version of it.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { fail, repoPath, type ErrorCode } from \"../../../core/envelope/json.js\";\nimport { listFleetTree } from \"../../../core/repo/repo.js\";\nimport type { FleetTree } from \"../../../core/repo/tree/walk.js\";\nimport { stageWrites } from \"../../../core/staging/commit.js\";\nimport { type CommitRecovery } from \"../../../core/staging/interrupted.js\";\nimport { openCommitWindow } from \"../../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../../core/staging/txn/transaction.js\";\nimport { type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport { authoredGeneratedPaths, authoredRefusal } from \"../../../core/repo/tree/render/service/header.js\";\nimport { type ExpectedFile, expectedViews, LANDSCAPE_UNREADABLE_NOTE, planGenerated, type ViewsAction } from \"./views.js\";\n\n/**\n * What one commit did to EACH generated file, kept apart.\n *\n * One action per file rather than one folded answer, for the reason\n * `./views.ts` gives about the expected bytes: the two files change for\n * different reasons and are named separately everywhere a person or a `--json`\n * reader meets them. The `views` key a verb has always emitted still carries\n * `subsystems` and nothing else — a payload key's meaning is frozen, so the\n * second file arrives as a key of its own beside it.\n */\nexport interface ViewsActions {\n /** `architecture/subsystems.likec4` — the verb's `--json` `views` key, unchanged. */\n subsystems: ViewsAction;\n /** `architecture/services.likec4` — the per-service overviews, one per service the map draws. */\n services: ViewsAction;\n}\n\n/** The text tail a verb's success line carries about the generated files — one clause per file that moved. */\nexport function reportViews(views: ViewsActions): string {\n return (\n [\n [\"architecture/subsystems.likec4\", views.subsystems] as const,\n [\"architecture/services.likec4\", views.services] as const,\n ]\n // `current` says nothing: the tail hangs off a success line, and a verb\n // that renamed one directory must not print two clauses about files that\n // did not move.\n .filter(([, action]) => action !== \"current\")\n .map(([file, action]) => ` — ${file} ${action}`)\n .join(\"\")\n );\n}\n\n/** What one subsystem verb asks the shared commit window to land. */\nexport interface SubsystemTxn {\n /** The journal's `target` — what this commit is FOR. */\n target: string;\n /**\n * Marker writes (create/delete), or a move's link rewrites (`./links.ts`) —\n * planned at the document's pre-move path, which the swap lands on before\n * the renames carry it; the views write is derived and appended.\n */\n writes: PlannedWrite[];\n /** The tree AS THE COMMIT LEAVES IT — the views file is rendered from this. */\n tree: FleetTree;\n /** Directory renames, performed after the swaps, in this order. */\n moves?: { from: string; to: string }[];\n /** Remap of a RACED commit failure (new: a lost marker create is `already-exists`). */\n racedCode?: ErrorCode;\n /** Remap of a rolled-back commit failure (move: `move-failed` — no merge was computed). */\n failedCode?: ErrorCode;\n /** The rollback sentence's verb for half-state files. */\n what: string;\n report: (views: ViewsActions, recovered: CommitRecovery | null) => void | Promise<void>;\n}\n\n/**\n * Lock → recover → plan → stage (views included) → journaled commit → report.\n * `plan` returning null means it already reported a refusal; nothing was\n * staged and nothing is written.\n */\nexport async function commitWindow(\n docsDir: DocsDir,\n json: boolean,\n plan: (tree: FleetTree) => Promise<SubsystemTxn | null>,\n): Promise<void> {\n // Refuse-fast (0), as archive takes the lock: two concurrent verbs answer\n // `docs-busy` rather than queue behind each other.\n const opened = await openCommitWindow(docsDir, 0);\n if (!opened.ok) {\n fail(json, opened.code, opened.message);\n return;\n }\n const { recovered } = opened;\n try {\n const txn = await plan(await listFleetTree(docsDir));\n if (txn === null) return;\n\n const expected = await expectedViews(docsDir, txn.tree);\n // OWNERSHIP BEFORE ANYTHING IS STAGED, and the WHOLE verb is refused.\n //\n // The guard first shipped in `../sync.ts` alone, and this window is the\n // other writer of exactly the same two reserved paths — for `subsystem\n // new`, `rm`, `move` and `rename` at once. Reproduced before this call\n // existed: with a hand-authored `architecture/services.likec4` in the tree,\n // `loam subsystem new platform` printed \"architecture/services.likec4\n // updated\" and destroyed it, first line and all. One predicate, one\n // sentence, shared from beneath every writer\n // (`core/repo/tree/render/service/header.ts`).\n //\n // WHY THE WHOLE OPERATION AND NOT JUST THE FILE. `sync` can decline one file\n // and still do the rest, because nothing else it writes depends on that file\n // and every part of it is idempotent. This window cannot: its entire reason\n // for existing is that the generated files land in the SAME commit as the\n // change to the tree, so completing the structural half and reporting the\n // file as refused would MANUFACTURE the `subsystem.views-stale` state the\n // banner above says this window refuses to leave between two commits — and\n // it would do so irreversibly, since `move` and `rename` also stage their\n // renames in git. A half-done move nobody asked for is worse than a refusal\n // a person can act on, and a refusal is re-runnable the moment the authored\n // file is out of the reserved path.\n //\n // It runs AFTER `plan`, which writes nothing and has already answered the\n // verb-specific refusals (`unknown-target`, `subsystem-not-empty`,\n // `move-uncommitted`): a caller whose name is wrong AND whose tree holds an\n // authored views file is better told about the name.\n const authored = await authoredGeneratedPaths([expected.subsystems.path, expected.services.path]);\n if (authored.length > 0) {\n fail(\n json,\n // The code is `already-exists` and not a new one because it is exactly\n // what that code has always meant here — \"refusing to create over\n // something that already exists, because overwriting would destroy work\n // nobody asked to lose\" — and it is already this command's documented\n // refusal for the flat namespace. A second code for the same sentence\n // would be a second branch an agent has to learn for no new decision.\n \"already-exists\",\n authored.map((path) => authoredRefusal(repoPath(docsDir, path))).join(\" \") +\n \" NOTHING was written and nothing was renamed: this command lands the generated views file in the same \" +\n \"commit as the change to the tree, so it refuses whole rather than leaving the tree changed — and, for \" +\n \"`move` and `rename`, renames staged in git — with a views file it may not write.\",\n );\n return;\n }\n const writes = [...txn.writes];\n // BOTH generated files, in the ONE commit that changes the tree. The\n // per-service file is not a bystander here: its view titles are\n // `<subsystem path> / <service id>`, so every `move` and `rename` restales\n // it exactly as it restales the subsystem views, and leaving it for a later\n // `sync` is the failing-between-two-commits state this window exists to\n // refuse.\n const views: ViewsActions = {\n subsystems: await stageGenerated(expected.subsystems, writes, false),\n // PROTECTED when the map did not parse as a project, and only this file\n // is: `renderSubsystemViews` answers null off the TREE, which is readable\n // either way, while `renderServiceOverviews` answers null whenever no\n // service resolves to an element — which is what an unreadable map looks\n // like from here. Under `known: false` a null render is therefore not\n // evidence of absence, and writing it would delete the whole file over a\n // sibling document that does not parse. A verb still rewrites a file it\n // CAN render (the tolerant arm this window has always taken), and the\n // person is told by the note at the foot of this function.\n services: await stageGenerated(expected.services, writes, !expected.known),\n };\n const staged = await stageWrites(writes);\n const committed = await commitStaged(\n {\n root: docsDir,\n command: \"subsystem\",\n rerun: \"loam subsystem sync\",\n target: txn.target,\n ...(txn.moves === undefined ? {} : { moves: txn.moves }),\n },\n staged,\n txn.what,\n );\n if (!committed.ok) {\n const code =\n committed.code === \"rollback-incomplete\"\n ? committed.code\n : committed.raced\n ? (txn.racedCode ?? txn.failedCode ?? committed.code)\n : (txn.failedCode ?? committed.code);\n fail(json, code, committed.message);\n return;\n }\n await txn.report(views, recovered);\n // A verb CANNOT leave this file behind the tree — its bytes depend on the\n // placement the verb just changed, so the tolerant render lands even when the\n // map is unreadable and the file loses its includes. `sync` may decline that\n // rewrite (`action: \"blocked\"`); a verb may not, so the person is told\n // instead, and the same note names the run that puts the includes back.\n if (!json && !expected.known) console.log(LANDSCAPE_UNREADABLE_NOTE);\n } finally {\n await opened.release();\n }\n}\n\n/**\n * Compare ONE generated file against what it must say, append the write when\n * they differ, and name what happened. The compare is `planGenerated`'s, the\n * one `../sync.ts` makes too — `./views.ts` says why it is over CONTENT, not\n * bytes, and why there is one spelling of it.\n *\n * `protect` is the caller's statement that a NULL render is not evidence: the\n * file is left exactly as it is rather than deleted. It is never a licence to\n * skip a real rewrite — a file loam can render is rendered, which is the\n * difference between this window and `../sync.ts`'s `blocked`.\n */\nasync function stageGenerated(file: ExpectedFile, writes: PlannedWrite[], protect: boolean): Promise<ViewsAction> {\n const current = existsSync(file.path) ? await readFile(file.path, \"utf8\") : null;\n const planned = planGenerated(file, current);\n if (planned.write === null || (protect && file.content === null)) return \"current\";\n writes.push(planned.write);\n return planned.action;\n}\n"]}
|