@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,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Five of the six files `loam new` scaffolds, and what each one says. The
|
|
3
|
+
* sixth, the `--capability` delta, is in `./capability-template.ts`.
|
|
4
|
+
*
|
|
5
|
+
* They are here rather than inline because every one of them is a document a
|
|
6
|
+
* person edits next, and the wording IS the instruction: the delta's comments
|
|
7
|
+
* teach the grammar `core/document/parse.ts` matches on, and the intent's
|
|
8
|
+
* frontmatter is serialized rather than interpolated because a title is free
|
|
9
|
+
* text somebody types — `Checkout: split payments` reopens the mapping and the
|
|
10
|
+
* file stops parsing.
|
|
11
|
+
*/
|
|
12
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
13
|
+
import { serviceElementId } from "../../core/c4/seed/template.js";
|
|
14
|
+
import { ARCH_REQUIREMENT_SENTINEL, ARCH_SHALL_SENTINEL, REQUIREMENT_SENTINEL, SCENARIO_SENTINEL, SERVICE_DESCRIPTION_SENTINEL, GIVEN_SENTINEL, SHALL_SENTINEL, THEN_SENTINEL, WHEN_SENTINEL, } from "../../core/coherence/authoring/sentinels.js";
|
|
15
|
+
/**
|
|
16
|
+
* The LikeC4 identifier the delta declares a service under: the id the fleet
|
|
17
|
+
* map already draws it as (`drawn`), since a context id the map lacks lines up
|
|
18
|
+
* with nothing at archive, else `serviceElementId` — seed's `svc_<id>`, where
|
|
19
|
+
* this used to camel-case the name into a third spelling beside the seed's and
|
|
20
|
+
* the map's. A collision inside one delta takes the seed's `_<n>` suffix.
|
|
21
|
+
*/
|
|
22
|
+
function identifier(name, taken, drawn) {
|
|
23
|
+
if (drawn !== undefined)
|
|
24
|
+
return drawn;
|
|
25
|
+
const base = serviceElementId(name);
|
|
26
|
+
let id = base;
|
|
27
|
+
for (let n = 2; taken.has(id); n += 1)
|
|
28
|
+
id = `${base}_${n}`;
|
|
29
|
+
taken.add(id);
|
|
30
|
+
return id;
|
|
31
|
+
}
|
|
32
|
+
/** One context line. A nested id (`a.b`) is no top-level declaration, so it names its parent instead. */
|
|
33
|
+
function contextLine(id, name) {
|
|
34
|
+
const dot = id.lastIndexOf(".");
|
|
35
|
+
if (dot < 0)
|
|
36
|
+
return ` // ${id} = softwareSystem '${name}'`;
|
|
37
|
+
return ` // ${id.slice(dot + 1)} = softwareSystem '${name}' // inside ${id.slice(0, dot)} { }, as the map draws it; edges name it ${id}`;
|
|
38
|
+
}
|
|
39
|
+
/** `FEAT-101` -> `feat_101`: LikeC4 view names take no dashes. */
|
|
40
|
+
function viewName(featureId) {
|
|
41
|
+
return featureId.toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
42
|
+
}
|
|
43
|
+
/* ------------------------------------------------------------------ */
|
|
44
|
+
/* Templates */
|
|
45
|
+
/* ------------------------------------------------------------------ */
|
|
46
|
+
export function intentTemplate(featureId, title) {
|
|
47
|
+
const heading = title ?? featureId;
|
|
48
|
+
// The frontmatter is SERIALIZED, never interpolated. A title is free text a
|
|
49
|
+
// person types — `Checkout: split payments` used to be pasted straight after
|
|
50
|
+
// `title: `, where the colon reopens the mapping and the file stops parsing;
|
|
51
|
+
// `Orders #42 rework` lost everything from the `#` as a YAML comment, so the
|
|
52
|
+
// feature quietly answered to a title nobody wrote. The yaml serializer is the
|
|
53
|
+
// only thing that knows every case, and it is already how migrate-openspec
|
|
54
|
+
// writes the same three keys.
|
|
55
|
+
//
|
|
56
|
+
// `owner` is deliberately NOT a key here. Scaffolding `owner:` writes an
|
|
57
|
+
// explicit null, which is a claim ("this feature has no owner") rather than
|
|
58
|
+
// the truth ("nobody has said yet") — and every reader then has to tell an
|
|
59
|
+
// absent key from a null one. The prompt survives as a comment.
|
|
60
|
+
//
|
|
61
|
+
// `## Open questions` is where loam-feature's analyze step writes, so it is
|
|
62
|
+
// scaffolded as a heading over a comment and nothing else. `intent.empty`
|
|
63
|
+
// (coherence/authoring/scaffold.ts) reads past the whole section, so neither
|
|
64
|
+
// the untouched comment nor a page of questions counts as the Why.
|
|
65
|
+
const frontmatter = stringifyYaml({ feature: featureId, ...(title === undefined ? {} : { title }), status: "proposed" }, { lineWidth: 0 }).trimEnd();
|
|
66
|
+
return `---
|
|
67
|
+
${frontmatter}
|
|
68
|
+
# owner: <the team or person who answers for this>
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
# ${heading}
|
|
72
|
+
|
|
73
|
+
## Why
|
|
74
|
+
|
|
75
|
+
<!-- The problem in business terms. This is what a reviewer reads first, and what
|
|
76
|
+
the requirement deltas below have to be justified by. -->
|
|
77
|
+
|
|
78
|
+
## Scope
|
|
79
|
+
|
|
80
|
+
<!-- Which services this touches — and, more usefully, which it deliberately does not. -->
|
|
81
|
+
|
|
82
|
+
## Open questions
|
|
83
|
+
|
|
84
|
+
<!-- Optional, never graded. What the documents leave open: an ambiguous SHALL, a value or
|
|
85
|
+
window two services state differently, an edge with no stated timeout, retry or
|
|
86
|
+
compensation. A person answers each by editing this section. -->
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
export function deltaTemplate(featureId, touched, created, drawn = new Map()) {
|
|
90
|
+
// The map's ids are claimed first: a new service's id never collides with a box quoted as context.
|
|
91
|
+
const taken = new Set(drawn.values());
|
|
92
|
+
const touchedIds = touched.map((s) => [identifier(s, taken, drawn.get(s)), s]);
|
|
93
|
+
const createdIds = created.map((s) => [identifier(s, taken), s]);
|
|
94
|
+
const lines = [];
|
|
95
|
+
if (touchedIds.length > 0) {
|
|
96
|
+
// Context elements ship COMMENTED OUT, exactly like the example edge below.
|
|
97
|
+
// Declared-and-untagged is the one shape `delta.nothing-tagged` exists to
|
|
98
|
+
// refuse (an author who forgot the tags), so writing these live made every
|
|
99
|
+
// `loam new --touches X` fail its own validator on the very first run —
|
|
100
|
+
// which teaches people that the validator is noise. Uncomment a line when an
|
|
101
|
+
// edge below actually needs the identifier.
|
|
102
|
+
lines.push(" // Services this feature touches, as context for the diagram. Uncomment the");
|
|
103
|
+
lines.push(" // ones an edge below names. A service the fleet map already draws keeps the");
|
|
104
|
+
lines.push(" // identifier architecture/ gives it, so the merge lines up; one it does not");
|
|
105
|
+
lines.push(" // draw yet gets svc_<id>, the convention `loam seed` writes. They stay UNTAGGED:");
|
|
106
|
+
lines.push(` // only #${featureId} is the change, and everything else here is context.`);
|
|
107
|
+
for (const [id, name] of touchedIds)
|
|
108
|
+
lines.push(contextLine(id, name));
|
|
109
|
+
lines.push("");
|
|
110
|
+
}
|
|
111
|
+
if (createdIds.length > 0) {
|
|
112
|
+
lines.push(" // Services this feature introduces. The tag is what `loam archive` folds");
|
|
113
|
+
lines.push(" // into the living landscape.");
|
|
114
|
+
for (const [id, name] of createdIds) {
|
|
115
|
+
lines.push(` ${id} = softwareSystem '${name}' {`);
|
|
116
|
+
lines.push(` #${featureId}`);
|
|
117
|
+
// Interpolated from sentinels.ts, never spelled here: the placeholder
|
|
118
|
+
// gate refuses this exact string at archive, and a second spelling is
|
|
119
|
+
// how a template rewording silently retires the check that guards it.
|
|
120
|
+
lines.push(` description '${SERVICE_DESCRIPTION_SENTINEL}'`);
|
|
121
|
+
lines.push(" }");
|
|
122
|
+
}
|
|
123
|
+
lines.push("");
|
|
124
|
+
}
|
|
125
|
+
// The example edge uses identifiers already declared above when there are two
|
|
126
|
+
// to join; otherwise placeholders, so it never invents a service.
|
|
127
|
+
const from = touchedIds[0]?.[0] ?? createdIds[0]?.[0] ?? "consumer";
|
|
128
|
+
const to = createdIds[0]?.[0] ?? touchedIds[1]?.[0] ?? "provider";
|
|
129
|
+
lines.push(" // New calls. `metadata { op }` is the spine: it names the OpenAPI operationId");
|
|
130
|
+
lines.push(" // the call uses, and `loam validate` checks it against the target's contract.");
|
|
131
|
+
lines.push(" // Uncomment and adjust (both endpoints have to be declared above):");
|
|
132
|
+
lines.push(" //");
|
|
133
|
+
lines.push(` // ${from} -> ${to} 'Calls createSplit' {`);
|
|
134
|
+
lines.push(` // #${featureId}`);
|
|
135
|
+
lines.push(" // metadata { op 'createSplit' }");
|
|
136
|
+
lines.push(" // }");
|
|
137
|
+
return `// ${featureId} — architecture delta.
|
|
138
|
+
//
|
|
139
|
+
// Everything tagged #${featureId} is exactly what \`loam archive\` folds into
|
|
140
|
+
// architecture/landscape.likec4. Everything else here is context for the diagram.
|
|
141
|
+
//
|
|
142
|
+
// If ${featureId} changes no architecture, DELETE this file: a requirements-only
|
|
143
|
+
// feature is complete without it, and an empty \`model {}\` is just as legal.
|
|
144
|
+
|
|
145
|
+
specification {
|
|
146
|
+
element softwareSystem
|
|
147
|
+
tag ${featureId}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
model {
|
|
151
|
+
${lines.join("\n")}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
views {
|
|
155
|
+
view ${viewName(featureId)} {
|
|
156
|
+
include *
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The business axis, scaffolded with its example INSIDE the comment — the same
|
|
163
|
+
* mechanism as `archSpecTemplate` below, for the same reason: this template
|
|
164
|
+
* used to ship a live `### Requirement: TODO — name the behaviour` that
|
|
165
|
+
* parsed as a real requirement, validated clean, and archived a literal TODO
|
|
166
|
+
* into the living spec at exit 0. The indented headings sit past the
|
|
167
|
+
* line-anchored patterns core/document/parse.ts matches on, so the scaffold
|
|
168
|
+
* declares nothing until a person copies the block out and writes over the
|
|
169
|
+
* fill-ins — and `scaffold.placeholder` gates the archive if the fill-ins
|
|
170
|
+
* survive the copy.
|
|
171
|
+
*
|
|
172
|
+
* No nested HTML comments: the `Operations:` guidance that used to be its own
|
|
173
|
+
* comment lives in this one's prose, because an inner `-->` would end the
|
|
174
|
+
* outer comment early and re-expose the example to the parser.
|
|
175
|
+
*/
|
|
176
|
+
export function specTemplate(featureId, service) {
|
|
177
|
+
return `# ${service} — requirement delta for ${featureId}
|
|
178
|
+
|
|
179
|
+
<!-- Sections: ADDED / MODIFIED / REMOVED. Delete the ones you do not need.
|
|
180
|
+
A MODIFIED requirement carries its full new text, not a diff.
|
|
181
|
+
Every requirement needs at least one scenario — \`loam validate\` gates on it.
|
|
182
|
+
|
|
183
|
+
An \`Operations:\` body line names the operationIds the requirement
|
|
184
|
+
governs. \`loam validate\` checks each one against the service's OpenAPI,
|
|
185
|
+
and \`loam archive\` refuses to merge a requirement that governs an
|
|
186
|
+
operation nobody defines — add the line once the contract exists.
|
|
187
|
+
|
|
188
|
+
A \`Publishes:\` / \`Consumes:\` body line does the same for event messages:
|
|
189
|
+
it names what the requirement puts on or takes off the bus, checked
|
|
190
|
+
against the service's AsyncAPI contract. If ${featureId} changes that
|
|
191
|
+
contract, hand-create specs/${service}/asyncapi.yaml — an AsyncAPI 3.0
|
|
192
|
+
document holding only the slots this feature adds, changes or removes,
|
|
193
|
+
messages under \`components.messages\` (loam scaffolds none: an event
|
|
194
|
+
contract is genuinely optional) — and run \`loam rebase ${featureId}\`
|
|
195
|
+
when it edits a slot the living contract already has, so that slot pins.
|
|
196
|
+
The same holds for an openapi.yaml beside this file: only what changes.
|
|
197
|
+
|
|
198
|
+
Copy the block below out of this comment, unindent it, and replace the
|
|
199
|
+
TODOs and every <angle-bracket> fill-in — \`loam archive\` refuses the
|
|
200
|
+
scaffold's own wording (\`scaffold.placeholder\`):
|
|
201
|
+
|
|
202
|
+
## ADDED Requirements
|
|
203
|
+
|
|
204
|
+
### Requirement: ${REQUIREMENT_SENTINEL}
|
|
205
|
+
Requirement-ID: ${featureId}.${service}.requirement
|
|
206
|
+
|
|
207
|
+
The service SHALL ${SHALL_SENTINEL}.
|
|
208
|
+
|
|
209
|
+
#### Scenario: ${SCENARIO_SENTINEL}
|
|
210
|
+
- **Given** ${GIVEN_SENTINEL}
|
|
211
|
+
- **When** ${WHEN_SENTINEL}
|
|
212
|
+
- **Then** ${THEN_SENTINEL}
|
|
213
|
+
-->
|
|
214
|
+
`;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The architecture axis, scaffolded EMPTY on purpose.
|
|
218
|
+
*
|
|
219
|
+
* Same grammar as spec.md, so the template body has to be unparseable as
|
|
220
|
+
* requirements or the scaffold would ship a requirement nobody wrote — the
|
|
221
|
+
* headings are therefore indented inside an HTML comment, which puts them past
|
|
222
|
+
* the line-anchored `## ADDED Requirements` / `### Requirement:` patterns
|
|
223
|
+
* core/document/parse.ts matches on. Copy the block out of the comment and unindent it.
|
|
224
|
+
*/
|
|
225
|
+
export function archSpecTemplate(featureId, service) {
|
|
226
|
+
return `# ${service} — architecture requirement delta for ${featureId}
|
|
227
|
+
|
|
228
|
+
<!-- The architecture axis: the obligations no business scenario was ever going
|
|
229
|
+
to mention — the outbox, the retries, the timeouts, the alerts.
|
|
230
|
+
|
|
231
|
+
\`Covers:\` is to an arch requirement what \`Operations:\` is to a business
|
|
232
|
+
one — it names the MODEL OBJECTS the scenarios below exercise, so coverage
|
|
233
|
+
is derived instead of trusted. Three forms, comma-separated:
|
|
234
|
+
|
|
235
|
+
Covers: ${service} a C4 element — its id, or the service a
|
|
236
|
+
bound/titled element stands for
|
|
237
|
+
Covers: consumer -> ${service} an edge, each side resolved the same way
|
|
238
|
+
Covers: alert:<id>, sli:<id> a signal declared in health.yaml
|
|
239
|
+
|
|
240
|
+
Every tagged element and edge in delta.likec4 wants one (\`c4.uncovered\`).
|
|
241
|
+
Delete this file if ${featureId} adds no architectural obligation.
|
|
242
|
+
|
|
243
|
+
Copy the block below out of this comment and unindent it:
|
|
244
|
+
|
|
245
|
+
## ADDED Requirements
|
|
246
|
+
|
|
247
|
+
### Requirement: ${ARCH_REQUIREMENT_SENTINEL}
|
|
248
|
+
Requirement-ID: ${featureId}.${service}.arch
|
|
249
|
+
|
|
250
|
+
The service SHALL ${ARCH_SHALL_SENTINEL}.
|
|
251
|
+
|
|
252
|
+
Covers: ${service}
|
|
253
|
+
|
|
254
|
+
#### Scenario: ${SCENARIO_SENTINEL}
|
|
255
|
+
- **Given** ${GIVEN_SENTINEL}
|
|
256
|
+
- **When** ${WHEN_SENTINEL}
|
|
257
|
+
- **Then** ${THEN_SENTINEL}
|
|
258
|
+
-->
|
|
259
|
+
`;
|
|
260
|
+
}
|
|
261
|
+
export function openapiTemplate(service) {
|
|
262
|
+
return `openapi: 3.1.0
|
|
263
|
+
info:
|
|
264
|
+
title: ${service}
|
|
265
|
+
version: "0.1"
|
|
266
|
+
|
|
267
|
+
# The operations this feature adds. \`operationId\` is the token the C4 edge
|
|
268
|
+
# (metadata { op }) and the requirement (Operations:) both point at — keep the
|
|
269
|
+
# three spellings identical or \`loam validate\` will say so.
|
|
270
|
+
paths: {}
|
|
271
|
+
# /splits:
|
|
272
|
+
# post:
|
|
273
|
+
# operationId: createSplit
|
|
274
|
+
# responses:
|
|
275
|
+
# "201":
|
|
276
|
+
# description: Created
|
|
277
|
+
`;
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/commands/new/templates.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Five of the six files `loam new` scaffolds, and what each one says. The\n * sixth, the `--capability` delta, is in `./capability-template.ts`.\n *\n * They are here rather than inline because every one of them is a document a\n * person edits next, and the wording IS the instruction: the delta's comments\n * teach the grammar `core/document/parse.ts` matches on, and the intent's\n * frontmatter is serialized rather than interpolated because a title is free\n * text somebody types — `Checkout: split payments` reopens the mapping and the\n * file stops parsing.\n */\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { serviceElementId } from \"../../core/c4/seed/template.js\";\nimport {\n ARCH_REQUIREMENT_SENTINEL,\n ARCH_SHALL_SENTINEL,\n REQUIREMENT_SENTINEL,\n SCENARIO_SENTINEL,\n SERVICE_DESCRIPTION_SENTINEL,\n GIVEN_SENTINEL,\n SHALL_SENTINEL,\n THEN_SENTINEL,\n WHEN_SENTINEL,\n} from \"../../core/coherence/authoring/sentinels.js\";\n\n/**\n * The LikeC4 identifier the delta declares a service under: the id the fleet\n * map already draws it as (`drawn`), since a context id the map lacks lines up\n * with nothing at archive, else `serviceElementId` — seed's `svc_<id>`, where\n * this used to camel-case the name into a third spelling beside the seed's and\n * the map's. A collision inside one delta takes the seed's `_<n>` suffix.\n */\nfunction identifier(name: string, taken: Set<string>, drawn?: string): string {\n if (drawn !== undefined) return drawn;\n const base = serviceElementId(name);\n let id = base;\n for (let n = 2; taken.has(id); n += 1) id = `${base}_${n}`;\n taken.add(id);\n return id;\n}\n\n/** One context line. A nested id (`a.b`) is no top-level declaration, so it names its parent instead. */\nfunction contextLine(id: string, name: string): string {\n const dot = id.lastIndexOf(\".\");\n if (dot < 0) return ` // ${id} = softwareSystem '${name}'`;\n return ` // ${id.slice(dot + 1)} = softwareSystem '${name}' // inside ${id.slice(0, dot)} { }, as the map draws it; edges name it ${id}`;\n}\n\n/** `FEAT-101` -> `feat_101`: LikeC4 view names take no dashes. */\nfunction viewName(featureId: string): string {\n return featureId.toLowerCase().replace(/[^a-z0-9]+/g, \"_\");\n}\n\n/* ------------------------------------------------------------------ */\n/* Templates */\n/* ------------------------------------------------------------------ */\n\nexport function intentTemplate(featureId: string, title: string | undefined): string {\n const heading = title ?? featureId;\n // The frontmatter is SERIALIZED, never interpolated. A title is free text a\n // person types — `Checkout: split payments` used to be pasted straight after\n // `title: `, where the colon reopens the mapping and the file stops parsing;\n // `Orders #42 rework` lost everything from the `#` as a YAML comment, so the\n // feature quietly answered to a title nobody wrote. The yaml serializer is the\n // only thing that knows every case, and it is already how migrate-openspec\n // writes the same three keys.\n //\n // `owner` is deliberately NOT a key here. Scaffolding `owner:` writes an\n // explicit null, which is a claim (\"this feature has no owner\") rather than\n // the truth (\"nobody has said yet\") — and every reader then has to tell an\n // absent key from a null one. The prompt survives as a comment.\n //\n // `## Open questions` is where loam-feature's analyze step writes, so it is\n // scaffolded as a heading over a comment and nothing else. `intent.empty`\n // (coherence/authoring/scaffold.ts) reads past the whole section, so neither\n // the untouched comment nor a page of questions counts as the Why.\n const frontmatter = stringifyYaml(\n { feature: featureId, ...(title === undefined ? {} : { title }), status: \"proposed\" },\n { lineWidth: 0 },\n ).trimEnd();\n return `---\n${frontmatter}\n# owner: <the team or person who answers for this>\n---\n\n# ${heading}\n\n## Why\n\n<!-- The problem in business terms. This is what a reviewer reads first, and what\n the requirement deltas below have to be justified by. -->\n\n## Scope\n\n<!-- Which services this touches — and, more usefully, which it deliberately does not. -->\n\n## Open questions\n\n<!-- Optional, never graded. What the documents leave open: an ambiguous SHALL, a value or\n window two services state differently, an edge with no stated timeout, retry or\n compensation. A person answers each by editing this section. -->\n`;\n}\n\nexport function deltaTemplate(featureId: string, touched: string[], created: string[], drawn: ReadonlyMap<string, string> = new Map()): string {\n // The map's ids are claimed first: a new service's id never collides with a box quoted as context.\n const taken = new Set<string>(drawn.values());\n const touchedIds = touched.map((s) => [identifier(s, taken, drawn.get(s)), s] as const);\n const createdIds = created.map((s) => [identifier(s, taken), s] as const);\n\n const lines: string[] = [];\n if (touchedIds.length > 0) {\n // Context elements ship COMMENTED OUT, exactly like the example edge below.\n // Declared-and-untagged is the one shape `delta.nothing-tagged` exists to\n // refuse (an author who forgot the tags), so writing these live made every\n // `loam new --touches X` fail its own validator on the very first run —\n // which teaches people that the validator is noise. Uncomment a line when an\n // edge below actually needs the identifier.\n lines.push(\" // Services this feature touches, as context for the diagram. Uncomment the\");\n lines.push(\" // ones an edge below names. A service the fleet map already draws keeps the\");\n lines.push(\" // identifier architecture/ gives it, so the merge lines up; one it does not\");\n lines.push(\" // draw yet gets svc_<id>, the convention `loam seed` writes. They stay UNTAGGED:\");\n lines.push(` // only #${featureId} is the change, and everything else here is context.`);\n for (const [id, name] of touchedIds) lines.push(contextLine(id, name));\n lines.push(\"\");\n }\n if (createdIds.length > 0) {\n lines.push(\" // Services this feature introduces. The tag is what `loam archive` folds\");\n lines.push(\" // into the living landscape.\");\n for (const [id, name] of createdIds) {\n lines.push(` ${id} = softwareSystem '${name}' {`);\n lines.push(` #${featureId}`);\n // Interpolated from sentinels.ts, never spelled here: the placeholder\n // gate refuses this exact string at archive, and a second spelling is\n // how a template rewording silently retires the check that guards it.\n lines.push(` description '${SERVICE_DESCRIPTION_SENTINEL}'`);\n lines.push(\" }\");\n }\n lines.push(\"\");\n }\n\n // The example edge uses identifiers already declared above when there are two\n // to join; otherwise placeholders, so it never invents a service.\n const from = touchedIds[0]?.[0] ?? createdIds[0]?.[0] ?? \"consumer\";\n const to = createdIds[0]?.[0] ?? touchedIds[1]?.[0] ?? \"provider\";\n lines.push(\" // New calls. `metadata { op }` is the spine: it names the OpenAPI operationId\");\n lines.push(\" // the call uses, and `loam validate` checks it against the target's contract.\");\n lines.push(\" // Uncomment and adjust (both endpoints have to be declared above):\");\n lines.push(\" //\");\n lines.push(` // ${from} -> ${to} 'Calls createSplit' {`);\n lines.push(` // #${featureId}`);\n lines.push(\" // metadata { op 'createSplit' }\");\n lines.push(\" // }\");\n\n return `// ${featureId} — architecture delta.\n//\n// Everything tagged #${featureId} is exactly what \\`loam archive\\` folds into\n// architecture/landscape.likec4. Everything else here is context for the diagram.\n//\n// If ${featureId} changes no architecture, DELETE this file: a requirements-only\n// feature is complete without it, and an empty \\`model {}\\` is just as legal.\n\nspecification {\n element softwareSystem\n tag ${featureId}\n}\n\nmodel {\n${lines.join(\"\\n\")}\n}\n\nviews {\n view ${viewName(featureId)} {\n include *\n }\n}\n`;\n}\n\n/**\n * The business axis, scaffolded with its example INSIDE the comment — the same\n * mechanism as `archSpecTemplate` below, for the same reason: this template\n * used to ship a live `### Requirement: TODO — name the behaviour` that\n * parsed as a real requirement, validated clean, and archived a literal TODO\n * into the living spec at exit 0. The indented headings sit past the\n * line-anchored patterns core/document/parse.ts matches on, so the scaffold\n * declares nothing until a person copies the block out and writes over the\n * fill-ins — and `scaffold.placeholder` gates the archive if the fill-ins\n * survive the copy.\n *\n * No nested HTML comments: the `Operations:` guidance that used to be its own\n * comment lives in this one's prose, because an inner `-->` would end the\n * outer comment early and re-expose the example to the parser.\n */\nexport function specTemplate(featureId: string, service: string): string {\n return `# ${service} — requirement delta for ${featureId}\n\n<!-- Sections: ADDED / MODIFIED / REMOVED. Delete the ones you do not need.\n A MODIFIED requirement carries its full new text, not a diff.\n Every requirement needs at least one scenario — \\`loam validate\\` gates on it.\n\n An \\`Operations:\\` body line names the operationIds the requirement\n governs. \\`loam validate\\` checks each one against the service's OpenAPI,\n and \\`loam archive\\` refuses to merge a requirement that governs an\n operation nobody defines — add the line once the contract exists.\n\n A \\`Publishes:\\` / \\`Consumes:\\` body line does the same for event messages:\n it names what the requirement puts on or takes off the bus, checked\n against the service's AsyncAPI contract. If ${featureId} changes that\n contract, hand-create specs/${service}/asyncapi.yaml — an AsyncAPI 3.0\n document holding only the slots this feature adds, changes or removes,\n messages under \\`components.messages\\` (loam scaffolds none: an event\n contract is genuinely optional) — and run \\`loam rebase ${featureId}\\`\n when it edits a slot the living contract already has, so that slot pins.\n The same holds for an openapi.yaml beside this file: only what changes.\n\n Copy the block below out of this comment, unindent it, and replace the\n TODOs and every <angle-bracket> fill-in — \\`loam archive\\` refuses the\n scaffold's own wording (\\`scaffold.placeholder\\`):\n\n ## ADDED Requirements\n\n ### Requirement: ${REQUIREMENT_SENTINEL}\n Requirement-ID: ${featureId}.${service}.requirement\n\n The service SHALL ${SHALL_SENTINEL}.\n\n #### Scenario: ${SCENARIO_SENTINEL}\n - **Given** ${GIVEN_SENTINEL}\n - **When** ${WHEN_SENTINEL}\n - **Then** ${THEN_SENTINEL}\n-->\n`;\n}\n\n/**\n * The architecture axis, scaffolded EMPTY on purpose.\n *\n * Same grammar as spec.md, so the template body has to be unparseable as\n * requirements or the scaffold would ship a requirement nobody wrote — the\n * headings are therefore indented inside an HTML comment, which puts them past\n * the line-anchored `## ADDED Requirements` / `### Requirement:` patterns\n * core/document/parse.ts matches on. Copy the block out of the comment and unindent it.\n */\nexport function archSpecTemplate(featureId: string, service: string): string {\n return `# ${service} — architecture requirement delta for ${featureId}\n\n<!-- The architecture axis: the obligations no business scenario was ever going\n to mention — the outbox, the retries, the timeouts, the alerts.\n\n \\`Covers:\\` is to an arch requirement what \\`Operations:\\` is to a business\n one — it names the MODEL OBJECTS the scenarios below exercise, so coverage\n is derived instead of trusted. Three forms, comma-separated:\n\n Covers: ${service} a C4 element — its id, or the service a\n bound/titled element stands for\n Covers: consumer -> ${service} an edge, each side resolved the same way\n Covers: alert:<id>, sli:<id> a signal declared in health.yaml\n\n Every tagged element and edge in delta.likec4 wants one (\\`c4.uncovered\\`).\n Delete this file if ${featureId} adds no architectural obligation.\n\n Copy the block below out of this comment and unindent it:\n\n ## ADDED Requirements\n\n ### Requirement: ${ARCH_REQUIREMENT_SENTINEL}\n Requirement-ID: ${featureId}.${service}.arch\n\n The service SHALL ${ARCH_SHALL_SENTINEL}.\n\n Covers: ${service}\n\n #### Scenario: ${SCENARIO_SENTINEL}\n - **Given** ${GIVEN_SENTINEL}\n - **When** ${WHEN_SENTINEL}\n - **Then** ${THEN_SENTINEL}\n-->\n`;\n}\n\nexport function openapiTemplate(service: string): string {\n return `openapi: 3.1.0\ninfo:\n title: ${service}\n version: \"0.1\"\n\n# The operations this feature adds. \\`operationId\\` is the token the C4 edge\n# (metadata { op }) and the requirement (Operations:) both point at — keep the\n# three spellings identical or \\`loam validate\\` will say so.\npaths: {}\n# /splits:\n# post:\n# operationId: createSplit\n# responses:\n# \"201\":\n# description: Created\n`;\n}\n"]}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { configOrRefuse, emitJson, fail } from "../core/envelope/json.js";
|
|
5
|
+
import { DocsRepoUnavailableError } from "../core/repo/state.js";
|
|
6
|
+
import { discoverMembers } from "../core/workspace/discover.js";
|
|
7
|
+
import { renderWorkspace } from "../core/workspace/render.js";
|
|
8
|
+
import { docsRepoReady, reportDocsRepoError } from "./policy/gate.js";
|
|
9
|
+
/**
|
|
10
|
+
* A fixed default name, not `<basename(docsDir)>.code-workspace`: predictable
|
|
11
|
+
* beats collision-proof for a file that is regenerable on demand, and `--out`
|
|
12
|
+
* is the lever for anyone holding two fleets' workspaces in one directory.
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_OUT = "loam.code-workspace";
|
|
15
|
+
/**
|
|
16
|
+
* Is there a directory at `path`? A probe that cannot answer says "no": for a
|
|
17
|
+
* value the user typed, "cannot be read" earns the same `invalid-option`
|
|
18
|
+
* refusal as "is not there" — never an `internal` escape. throwIfNoEntry folds
|
|
19
|
+
* the absent case into the same answer with no window between probe and use;
|
|
20
|
+
* the catch covers the errnos statSync can still raise (EACCES, ENOTDIR — a
|
|
21
|
+
* path routed through a file).
|
|
22
|
+
*/
|
|
23
|
+
function directoryAt(path) {
|
|
24
|
+
try {
|
|
25
|
+
return statSync(path, { throwIfNoEntry: false })?.isDirectory() === true;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** The write-path errnos that mean the OUT PATH is wrong, not loam. */
|
|
32
|
+
const OUT_PATH_ERRNOS = new Set(["EISDIR", "EACCES", "EPERM", "ENOTDIR", "EINVAL"]);
|
|
33
|
+
export function registerOpen(program) {
|
|
34
|
+
program
|
|
35
|
+
.command("open")
|
|
36
|
+
.description("Write a .code-workspace joining the docs repo and every bound service checkout")
|
|
37
|
+
.option("--root <dir>", "scan this directory for bound checkouts instead of the defaults; repeatable", (value, prev = []) => [...prev, value])
|
|
38
|
+
.option("--out <file>", `workspace file to write (default ${DEFAULT_OUT} in the current directory)`)
|
|
39
|
+
.option("--force", "overwrite the workspace file if it already exists")
|
|
40
|
+
.option("--json", "emit the machine contract instead of the human view")
|
|
41
|
+
.action(async (opts) => {
|
|
42
|
+
const json = opts.json === true;
|
|
43
|
+
const config = await configOrRefuse(json);
|
|
44
|
+
if (config === null)
|
|
45
|
+
return;
|
|
46
|
+
const { docsDir } = config;
|
|
47
|
+
// "docs", not "services": this command enumerates checkouts on the LOCAL
|
|
48
|
+
// filesystem, not services/ in the docs repo, and a docs repo nobody has
|
|
49
|
+
// run `loam adopt` against is still worth opening an editor on.
|
|
50
|
+
if (!docsRepoReady(json, docsDir, "docs"))
|
|
51
|
+
return;
|
|
52
|
+
// Both typed paths are validated before any discovery runs: a --root or
|
|
53
|
+
// --out typo is a fact about the INVOCATION, not the fleet, and it must
|
|
54
|
+
// refuse before the scan — not after verdicts were computed over
|
|
55
|
+
// directories nobody meant, and not from the write at the very end.
|
|
56
|
+
const roots = (opts.root ?? []).map((dir) => resolve(dir));
|
|
57
|
+
for (const dir of roots) {
|
|
58
|
+
if (!directoryAt(dir)) {
|
|
59
|
+
fail(json, "invalid-option", `--root does not name a readable directory: ${dir}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const out = resolve(opts.out ?? DEFAULT_OUT);
|
|
64
|
+
const parent = dirname(out);
|
|
65
|
+
if (!directoryAt(parent)) {
|
|
66
|
+
fail(json, "invalid-option", `--out points into a directory that does not exist: ${parent}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
let discovery;
|
|
70
|
+
try {
|
|
71
|
+
discovery = await discoverMembers({
|
|
72
|
+
docsDir,
|
|
73
|
+
// parseConfig always derives `root`; the fallback only documents
|
|
74
|
+
// which absence the optional type would otherwise leave a guess.
|
|
75
|
+
configRoot: config.root ?? process.cwd(),
|
|
76
|
+
...(config.service === undefined ? {} : { service: config.service }),
|
|
77
|
+
...(roots.length === 0 ? {} : { roots }),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
// The gate above passed, so this is the repo vanishing mid-run —
|
|
82
|
+
// the same breach the enumeration reports, spelled the same way.
|
|
83
|
+
if (!(err instanceof DocsRepoUnavailableError))
|
|
84
|
+
throw err;
|
|
85
|
+
reportDocsRepoError(json, err);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// An explicit --root that cannot be LISTED refuses: the caller named the
|
|
89
|
+
// directory, so "I could not look" must never come back as an empty
|
|
90
|
+
// scan. The default roots keep degrading to empty — a CI sandbox that
|
|
91
|
+
// denies the docs repo's parent is survivable, and both views still
|
|
92
|
+
// report the degrade below.
|
|
93
|
+
if (roots.length > 0 && discovery.unreadableRoots.length > 0) {
|
|
94
|
+
const listing = discovery.unreadableRoots
|
|
95
|
+
.map((entry) => `${entry.root} (${entry.problem})`)
|
|
96
|
+
.join("; ");
|
|
97
|
+
fail(json, "invalid-option", `--root cannot be scanned: ${listing}`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (discovery.duplicates.length > 0) {
|
|
101
|
+
const claims = discovery.duplicates.map((d) => `'${d.service}' is declared by ${d.paths.join(" and ")}`);
|
|
102
|
+
fail(json, "binding-duplicate", `Two checkouts declare the same service for this docs repo: ${claims.join("; ")}. ` +
|
|
103
|
+
"loam will not guess which checkout speaks for the service — narrow the scan " +
|
|
104
|
+
"with --root, or fix the stray loam.json, then re-run.");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Only reachable from the docs repo itself — a service-repo invocation
|
|
108
|
+
// always contributes its own checkout as a member. Skipped candidates
|
|
109
|
+
// ride the message: a checkout whose binding would not parse is the
|
|
110
|
+
// likeliest reason the scan came up empty, and the real fix is that
|
|
111
|
+
// file, not --root.
|
|
112
|
+
if (!discovery.members.some((member) => member.via !== "docs-repo")) {
|
|
113
|
+
const unread = discovery.skipped.length === 0
|
|
114
|
+
? ""
|
|
115
|
+
: ` ${discovery.skipped.length} candidate binding(s) could not be read and did not` +
|
|
116
|
+
` count: ${discovery.skipped.map((s) => `${s.path} (${s.problem})`).join("; ")}.`;
|
|
117
|
+
fail(json, "no-members", `No service checkout bound to ${docsDir} was found under ` +
|
|
118
|
+
`${discovery.scannedRoots.join(", ")} — the workspace would hold only the docs ` +
|
|
119
|
+
"repo. Clone a bound service repo beside it, run `loam open` from a service " +
|
|
120
|
+
`repo, or pass --root naming the directory the checkouts live in.${unread}`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const rendered = renderWorkspace(discovery.members, out);
|
|
124
|
+
try {
|
|
125
|
+
// "wx" makes probe-and-write one operation, so a concurrent writer
|
|
126
|
+
// cannot land between an existsSync and the write. --force is honest
|
|
127
|
+
// here where init's generated files needed skip-forever: a workspace
|
|
128
|
+
// file is wholly derived, so overwriting it loses nothing authored.
|
|
129
|
+
await writeFile(out, rendered.text, {
|
|
130
|
+
encoding: "utf8",
|
|
131
|
+
flag: opts.force === true ? "w" : "wx",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
const e = err;
|
|
136
|
+
if (e.code === "EEXIST") {
|
|
137
|
+
fail(json, "already-exists", `${out} already exists. Pass --out naming another file, or --force to overwrite it.`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// The path-shaped failures: --out names a directory (EISDIR — the
|
|
141
|
+
// exact target the EEXIST remedy above just told the caller to
|
|
142
|
+
// --force), or a place this process may not write. Each is a fact
|
|
143
|
+
// about the out path, so it earns invalid-option, not internal.
|
|
144
|
+
if (typeof e.code === "string" && OUT_PATH_ERRNOS.has(e.code)) {
|
|
145
|
+
fail(json, "invalid-option", `The workspace file cannot be written at ${out}: ${e.message}. ` +
|
|
146
|
+
"Pass --out naming a writable file path.");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
if (json) {
|
|
152
|
+
emitJson({
|
|
153
|
+
command: "open",
|
|
154
|
+
docsDir,
|
|
155
|
+
out,
|
|
156
|
+
written: true,
|
|
157
|
+
members: rendered.folders.map((folder) => ({
|
|
158
|
+
path: folder.member.path,
|
|
159
|
+
// The exact spelling written into the workspace file, so a
|
|
160
|
+
// consumer never re-derives (and mis-derives) the relative form.
|
|
161
|
+
folder: folder.path,
|
|
162
|
+
name: folder.name,
|
|
163
|
+
service: folder.member.service,
|
|
164
|
+
via: folder.member.via,
|
|
165
|
+
...(folder.member.via === "scan" ? { root: folder.member.root } : {}),
|
|
166
|
+
})),
|
|
167
|
+
scannedRoots: discovery.scannedRoots,
|
|
168
|
+
unreadableRoots: discovery.unreadableRoots,
|
|
169
|
+
skipped: discovery.skipped,
|
|
170
|
+
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
printWorkspace(out, discovery, rendered.folders);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function viaText(folder) {
|
|
177
|
+
const member = folder.member;
|
|
178
|
+
if (member.via === "docs-repo")
|
|
179
|
+
return "docs repo";
|
|
180
|
+
if (member.via === "current-repo")
|
|
181
|
+
return "this repo";
|
|
182
|
+
return `found under ${member.root}`;
|
|
183
|
+
}
|
|
184
|
+
function printWorkspace(out, discovery, folders) {
|
|
185
|
+
console.log(`workspace: ${out} (${folders.length} folders)`);
|
|
186
|
+
for (const folder of folders) {
|
|
187
|
+
console.log(` ${folder.name} ${folder.path} (${viaText(folder)})`);
|
|
188
|
+
}
|
|
189
|
+
// Reported beside the result, not folded into it: an unreadable binding or
|
|
190
|
+
// an unlistable default root proves nothing, but silence about either would
|
|
191
|
+
// read as "not bound" / "nothing there".
|
|
192
|
+
for (const entry of discovery.unreadableRoots) {
|
|
193
|
+
console.log(` ! could not scan ${entry.root}: ${entry.problem}`);
|
|
194
|
+
}
|
|
195
|
+
for (const entry of discovery.skipped) {
|
|
196
|
+
console.log(` ! skipped ${entry.path}: ${entry.problem}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { statSync } from \"node:fs\";\nimport { writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { configOrRefuse, emitJson, fail } from \"../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../core/repo/state.js\";\nimport { discoverMembers, type Discovery } from \"../core/workspace/discover.js\";\nimport { renderWorkspace, type RenderedFolder } from \"../core/workspace/render.js\";\nimport { docsRepoReady, reportDocsRepoError } from \"./policy/gate.js\";\n\ninterface OpenOptions {\n json?: boolean;\n /** --root, collected: each value REPLACES the default scan roots. */\n root?: string[];\n out?: string;\n force?: boolean;\n}\n\n/**\n * A fixed default name, not `<basename(docsDir)>.code-workspace`: predictable\n * beats collision-proof for a file that is regenerable on demand, and `--out`\n * is the lever for anyone holding two fleets' workspaces in one directory.\n */\nconst DEFAULT_OUT = \"loam.code-workspace\";\n\n/**\n * Is there a directory at `path`? A probe that cannot answer says \"no\": for a\n * value the user typed, \"cannot be read\" earns the same `invalid-option`\n * refusal as \"is not there\" — never an `internal` escape. throwIfNoEntry folds\n * the absent case into the same answer with no window between probe and use;\n * the catch covers the errnos statSync can still raise (EACCES, ENOTDIR — a\n * path routed through a file).\n */\nfunction directoryAt(path: string): boolean {\n try {\n return statSync(path, { throwIfNoEntry: false })?.isDirectory() === true;\n } catch {\n return false;\n }\n}\n\n/** The write-path errnos that mean the OUT PATH is wrong, not loam. */\nconst OUT_PATH_ERRNOS = new Set([\"EISDIR\", \"EACCES\", \"EPERM\", \"ENOTDIR\", \"EINVAL\"]);\n\nexport function registerOpen(program: Command): void {\n program\n .command(\"open\")\n .description(\"Write a .code-workspace joining the docs repo and every bound service checkout\")\n .option(\n \"--root <dir>\",\n \"scan this directory for bound checkouts instead of the defaults; repeatable\",\n (value: string, prev: string[] = []) => [...prev, value],\n )\n .option(\"--out <file>\", `workspace file to write (default ${DEFAULT_OUT} in the current directory)`)\n .option(\"--force\", \"overwrite the workspace file if it already exists\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: OpenOptions) => {\n const json = opts.json === true;\n const config = await configOrRefuse(json);\n if (config === null) return;\n const { docsDir } = config;\n // \"docs\", not \"services\": this command enumerates checkouts on the LOCAL\n // filesystem, not services/ in the docs repo, and a docs repo nobody has\n // run `loam adopt` against is still worth opening an editor on.\n if (!docsRepoReady(json, docsDir, \"docs\")) return;\n\n // Both typed paths are validated before any discovery runs: a --root or\n // --out typo is a fact about the INVOCATION, not the fleet, and it must\n // refuse before the scan — not after verdicts were computed over\n // directories nobody meant, and not from the write at the very end.\n const roots = (opts.root ?? []).map((dir) => resolve(dir));\n for (const dir of roots) {\n if (!directoryAt(dir)) {\n fail(json, \"invalid-option\", `--root does not name a readable directory: ${dir}`);\n return;\n }\n }\n const out = resolve(opts.out ?? DEFAULT_OUT);\n const parent = dirname(out);\n if (!directoryAt(parent)) {\n fail(json, \"invalid-option\", `--out points into a directory that does not exist: ${parent}`);\n return;\n }\n\n let discovery: Discovery;\n try {\n discovery = await discoverMembers({\n docsDir,\n // parseConfig always derives `root`; the fallback only documents\n // which absence the optional type would otherwise leave a guess.\n configRoot: config.root ?? process.cwd(),\n ...(config.service === undefined ? {} : { service: config.service }),\n ...(roots.length === 0 ? {} : { roots }),\n });\n } catch (err) {\n // The gate above passed, so this is the repo vanishing mid-run —\n // the same breach the enumeration reports, spelled the same way.\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n reportDocsRepoError(json, err);\n return;\n }\n\n // An explicit --root that cannot be LISTED refuses: the caller named the\n // directory, so \"I could not look\" must never come back as an empty\n // scan. The default roots keep degrading to empty — a CI sandbox that\n // denies the docs repo's parent is survivable, and both views still\n // report the degrade below.\n if (roots.length > 0 && discovery.unreadableRoots.length > 0) {\n const listing = discovery.unreadableRoots\n .map((entry) => `${entry.root} (${entry.problem})`)\n .join(\"; \");\n fail(json, \"invalid-option\", `--root cannot be scanned: ${listing}`);\n return;\n }\n\n if (discovery.duplicates.length > 0) {\n const claims = discovery.duplicates.map(\n (d) => `'${d.service}' is declared by ${d.paths.join(\" and \")}`,\n );\n fail(\n json,\n \"binding-duplicate\",\n `Two checkouts declare the same service for this docs repo: ${claims.join(\"; \")}. ` +\n \"loam will not guess which checkout speaks for the service — narrow the scan \" +\n \"with --root, or fix the stray loam.json, then re-run.\",\n );\n return;\n }\n // Only reachable from the docs repo itself — a service-repo invocation\n // always contributes its own checkout as a member. Skipped candidates\n // ride the message: a checkout whose binding would not parse is the\n // likeliest reason the scan came up empty, and the real fix is that\n // file, not --root.\n if (!discovery.members.some((member) => member.via !== \"docs-repo\")) {\n const unread = discovery.skipped.length === 0\n ? \"\"\n : ` ${discovery.skipped.length} candidate binding(s) could not be read and did not` +\n ` count: ${discovery.skipped.map((s) => `${s.path} (${s.problem})`).join(\"; \")}.`;\n fail(\n json,\n \"no-members\",\n `No service checkout bound to ${docsDir} was found under ` +\n `${discovery.scannedRoots.join(\", \")} — the workspace would hold only the docs ` +\n \"repo. Clone a bound service repo beside it, run `loam open` from a service \" +\n `repo, or pass --root naming the directory the checkouts live in.${unread}`,\n );\n return;\n }\n\n const rendered = renderWorkspace(discovery.members, out);\n try {\n // \"wx\" makes probe-and-write one operation, so a concurrent writer\n // cannot land between an existsSync and the write. --force is honest\n // here where init's generated files needed skip-forever: a workspace\n // file is wholly derived, so overwriting it loses nothing authored.\n await writeFile(out, rendered.text, {\n encoding: \"utf8\",\n flag: opts.force === true ? \"w\" : \"wx\",\n });\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"EEXIST\") {\n fail(\n json,\n \"already-exists\",\n `${out} already exists. Pass --out naming another file, or --force to overwrite it.`,\n );\n return;\n }\n // The path-shaped failures: --out names a directory (EISDIR — the\n // exact target the EEXIST remedy above just told the caller to\n // --force), or a place this process may not write. Each is a fact\n // about the out path, so it earns invalid-option, not internal.\n if (typeof e.code === \"string\" && OUT_PATH_ERRNOS.has(e.code)) {\n fail(\n json,\n \"invalid-option\",\n `The workspace file cannot be written at ${out}: ${e.message}. ` +\n \"Pass --out naming a writable file path.\",\n );\n return;\n }\n throw err;\n }\n\n if (json) {\n emitJson({\n command: \"open\",\n docsDir,\n out,\n written: true,\n members: rendered.folders.map((folder) => ({\n path: folder.member.path,\n // The exact spelling written into the workspace file, so a\n // consumer never re-derives (and mis-derives) the relative form.\n folder: folder.path,\n name: folder.name,\n service: folder.member.service,\n via: folder.member.via,\n ...(folder.member.via === \"scan\" ? { root: folder.member.root } : {}),\n })),\n scannedRoots: discovery.scannedRoots,\n unreadableRoots: discovery.unreadableRoots,\n skipped: discovery.skipped,\n });\n return;\n }\n printWorkspace(out, discovery, rendered.folders);\n });\n}\n\nfunction viaText(folder: RenderedFolder): string {\n const member = folder.member;\n if (member.via === \"docs-repo\") return \"docs repo\";\n if (member.via === \"current-repo\") return \"this repo\";\n return `found under ${member.root}`;\n}\n\nfunction printWorkspace(out: string, discovery: Discovery, folders: RenderedFolder[]): void {\n console.log(`workspace: ${out} (${folders.length} folders)`);\n for (const folder of folders) {\n console.log(` ${folder.name} ${folder.path} (${viaText(folder)})`);\n }\n // Reported beside the result, not folded into it: an unreadable binding or\n // an unlistable default root proves nothing, but silence about either would\n // read as \"not bound\" / \"nothing there\".\n for (const entry of discovery.unreadableRoots) {\n console.log(` ! could not scan ${entry.root}: ${entry.problem}`);\n }\n for (const entry of discovery.skipped) {\n console.log(` ! skipped ${entry.path}: ${entry.problem}`);\n }\n}\n"]}
|