@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,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A service's OWN use cases: the `dynamic view`s its LikeC4 project declares,
|
|
3
|
+
* read the way the renderer reads that project.
|
|
4
|
+
*
|
|
5
|
+
* THE SLOT IS THE PROJECT. `loam subsystem sync` writes a
|
|
6
|
+
* `services/<…>/<svc>/likec4.config.json` that registers every `.likec4` under
|
|
7
|
+
* the service directory as one LikeC4 project, so the renderer already shows a
|
|
8
|
+
* `views.likec4` beside the model, or a `usecases/<name>.likec4` under it. loam
|
|
9
|
+
* reads exactly that set — `model.likec4` plus every sibling, recursively, minus
|
|
10
|
+
* whatever that project file's own `exclude` drops (`./exclude.ts`) — and
|
|
11
|
+
* nothing else, because a slot narrower than the renderer's would leave a flow
|
|
12
|
+
* that renders and is graded by nothing, which is the report this module
|
|
13
|
+
* answers: an intra-service flow behind an `arch.spec.md` requirement whose
|
|
14
|
+
* `Covers:` names containers had no home. `architecture/usecases/` is a
|
|
15
|
+
* separate project that cannot resolve a container (one such file turned a
|
|
16
|
+
* whole fleet `landscape.invalid`), and the author's workaround beside the
|
|
17
|
+
* model was invisible to every check. The read is NOT gated on the project
|
|
18
|
+
* file's presence: that file is create-only and a team may delete it, its
|
|
19
|
+
* absence has a warning of its own (`service.likec4-config-missing`), and a
|
|
20
|
+
* flow the renderer cannot show yet is still a flow loam can grade.
|
|
21
|
+
*
|
|
22
|
+
* MODEL FACTS STAY SINGLE-FILE. `c4.valid`'s counts, `Covers:` resolution,
|
|
23
|
+
* `health.dependency-unmodelled` and every other model reader keep the
|
|
24
|
+
* single-file load the service target already made; the project is loaded here
|
|
25
|
+
* for the VIEWS and their `sourcePath` only, and only when there is something
|
|
26
|
+
* to grade. A sibling that declares elements extends what a hop may name, and
|
|
27
|
+
* that is the renderer's reading too.
|
|
28
|
+
*
|
|
29
|
+
* TWO SHAPES, ONE SLOT. A model that stands alone is a project of its own
|
|
30
|
+
* directory, exactly as above. A model that EXTENDS the fleet map is not: its
|
|
31
|
+
* containers are declared inside an element the map owns, so a flow beside it
|
|
32
|
+
* naming one of those containers only resolves in a project that also holds the
|
|
33
|
+
* map (`c4/service-model/documents.ts`, `serviceFlowDocuments`). That project is
|
|
34
|
+
* staged from the DOCS ROOT, so every view comes back spelled
|
|
35
|
+
* `services/<tree>/usecases/x.likec4` — and the service prefix is stripped here,
|
|
36
|
+
* because every finding this scan feeds names a file relative to the service
|
|
37
|
+
* directory and a reader must not have to work out which spelling they were
|
|
38
|
+
* given. The same prefix is the FILTER: the map's own `architecture/usecases/`
|
|
39
|
+
* flows are in that project too, and without it every service in the fleet would
|
|
40
|
+
* be graded for every fleet-level use case.
|
|
41
|
+
*
|
|
42
|
+
* THE CHEAP GATE, in order, so a fleet without the axis pays one recursive
|
|
43
|
+
* readdir per service and nothing else:
|
|
44
|
+
*
|
|
45
|
+
* 1. no sibling → nothing new is loaded, and the model's own tagged views are
|
|
46
|
+
* graded at zero cost against the project the model was READ in. For a
|
|
47
|
+
* standalone model that is the single-file load already in hand, which IS
|
|
48
|
+
* its whole project; for an extending one it is `ServiceModel.project`, the
|
|
49
|
+
* map and this model together — NOT the service's own slice of it, which is
|
|
50
|
+
* what the caller passes as `model` and what every count and `Covers:` line
|
|
51
|
+
* is answered from. A hop backed by a map edge is backed wherever the view
|
|
52
|
+
* is written, and grading the two arms against different documents made one
|
|
53
|
+
* view `usecase.step-unbacked` in model.likec4 and clean in a sibling. A
|
|
54
|
+
* standalone model's views came back named `source.c4`
|
|
55
|
+
* (`core/usecases/place.ts` records the rule) and an extending model's carry
|
|
56
|
+
* their docs-relative path, so the file is spelled here, where it is known,
|
|
57
|
+
* for both: `model.likec4`;
|
|
58
|
+
* 2. siblings, no tagged view in the model, and no reserved tag REFERENCED in
|
|
59
|
+
* any document — a `#` then `cap-`, `req-` or `suite-` (`mentionsTagPrefix`,
|
|
60
|
+
* the fleet's own byte gate) → nothing opted in, no workspace. An untagged
|
|
61
|
+
* `views.likec4` is somebody's hand-drawn diagram, never graded, exactly as
|
|
62
|
+
* an untagged fleet view is — and its parse errors are the renderer's
|
|
63
|
+
* business until a view opts the project in. That includes one whose prose
|
|
64
|
+
* names a prefix without the `#` (a title about an e2e-suite job): the gate
|
|
65
|
+
* used to open on the bare substring, and such a sibling that did not parse
|
|
66
|
+
* became `usecase.flow-invalid` over a diagram that opted nothing in;
|
|
67
|
+
* 3. otherwise `loadProject` over model + siblings, the way the renderer reads
|
|
68
|
+
* them. `own` and the project's views are never merged: when siblings
|
|
69
|
+
* exist the project is the whole answer, which is what keeps one view from
|
|
70
|
+
* being graded twice.
|
|
71
|
+
*
|
|
72
|
+
* A REQUEST RECORD rather than three parameters, for the reason
|
|
73
|
+
* docs/CODE-STYLE.md gives: the paths, the single-file doc and the fleet set
|
|
74
|
+
* are only ever passed together, and a caller handing in a doc loaded from
|
|
75
|
+
* some other path is exactly the inconsistent pair a record makes
|
|
76
|
+
* unrepresentable.
|
|
77
|
+
*/
|
|
78
|
+
import { relative } from "node:path";
|
|
79
|
+
import { architectureDocuments } from "../../c4/project/documents.js";
|
|
80
|
+
import { asLoadedDoc, loadProject } from "../../c4/project/load.js";
|
|
81
|
+
import { serviceFlowDocuments } from "../../c4/service-model/documents.js";
|
|
82
|
+
import { ARTIFACT_FILES } from "../../repo/paths.js";
|
|
83
|
+
import { isUseCase, mentionsTagPrefix } from "../fleet.js";
|
|
84
|
+
import { keepIncluded, serviceProjectExclude } from "./exclude.js";
|
|
85
|
+
/**
|
|
86
|
+
* The service's declared use cases, with the model they are drawn over.
|
|
87
|
+
*
|
|
88
|
+
* Reads only, throws nothing: every failure is the `unreadable` arm. The caller
|
|
89
|
+
* has already established that `model.likec4` parses on its own — a project
|
|
90
|
+
* whose model is broken is `c4.invalid`'s business, and loading it again here
|
|
91
|
+
* would only repeat that cascade under a second code.
|
|
92
|
+
*/
|
|
93
|
+
export async function readServiceFlows(req) {
|
|
94
|
+
const found = await architectureDocuments(req.paths.dir, [req.paths.model]);
|
|
95
|
+
// What the RENDERER holds, for the standalone shape where this directory's
|
|
96
|
+
// own `likec4.config.json` IS the project config: a sibling its `exclude`
|
|
97
|
+
// covers is in no project loam may claim to be reading (`./exclude.ts`). The
|
|
98
|
+
// extending shape reads the root project instead, so its list does not apply
|
|
99
|
+
// — a per-service config beside an extending model is `service.likec4-config-stray`.
|
|
100
|
+
const siblings = req.extending === undefined
|
|
101
|
+
? keepIncluded(req.paths.dir, await serviceProjectExclude(req.paths.dir), found)
|
|
102
|
+
: found;
|
|
103
|
+
// The scope of the no-sibling arm, and it is the PROJECT for both shapes: the
|
|
104
|
+
// single-file load for a standalone model (which is its whole project), and
|
|
105
|
+
// the map-plus-model load for an extending one. Reading `req.model` there for
|
|
106
|
+
// an extending model read its own slice instead, so one view was graded two
|
|
107
|
+
// different ways depending on which file it was written in.
|
|
108
|
+
const alone = req.extending?.project ?? req.model;
|
|
109
|
+
const scope = { elements: alone.elements, relationships: alone.relationships, known: req.known };
|
|
110
|
+
const own = (req.model.views ?? []).filter(isUseCase);
|
|
111
|
+
if (siblings.length === 0) {
|
|
112
|
+
if (own.length === 0)
|
|
113
|
+
return { kind: "none" };
|
|
114
|
+
return { kind: "read", views: own.map((view) => ({ ...view, sourcePath: ARTIFACT_FILES.model })), model: scope };
|
|
115
|
+
}
|
|
116
|
+
if (own.length === 0 && !(await mentionsTagPrefix(siblings)))
|
|
117
|
+
return { kind: "none" };
|
|
118
|
+
const base = req.extending?.docsDir ?? req.paths.dir;
|
|
119
|
+
const documents = req.extending === undefined
|
|
120
|
+
? [req.paths.model, ...siblings]
|
|
121
|
+
: await serviceFlowDocuments(req.extending.docsDir, req.paths);
|
|
122
|
+
const project = await loadProject(base, documents);
|
|
123
|
+
if (!project.clean) {
|
|
124
|
+
// Each error already carries the real path of its document (`loadProject`
|
|
125
|
+
// rewrites the staged path back), and the flattening is `asLoadedDoc`'s —
|
|
126
|
+
// the fleet's own path-sorted order, taken from the one place it is
|
|
127
|
+
// spelled rather than re-spelled here: the caller names the FIRST broken
|
|
128
|
+
// file, and a second sort rule would let the service target name a
|
|
129
|
+
// different first file than the fleet target names for the same project.
|
|
130
|
+
return { kind: "unreadable", errors: asLoadedDoc(project).errors };
|
|
131
|
+
}
|
|
132
|
+
// The prefix the service's own documents are spelled under inside this
|
|
133
|
+
// project: empty for a standalone model (the project IS the directory, so
|
|
134
|
+
// every view in it is this service's) and `services/<tree>/` for an extending
|
|
135
|
+
// one, whose project also holds the whole fleet map.
|
|
136
|
+
const prefix = req.extending === undefined ? "" : `${relative(base, req.paths.dir).split(/[\\/]/).join("/")}/`;
|
|
137
|
+
return {
|
|
138
|
+
kind: "read",
|
|
139
|
+
views: rebase(project.views.filter(isUseCase), prefix),
|
|
140
|
+
model: { elements: project.elements, relationships: project.relationships, known: req.known },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The views this SERVICE declares, spelled relative to its own directory.
|
|
145
|
+
*
|
|
146
|
+
* With an empty prefix — the standalone shape — this is the identity, including
|
|
147
|
+
* for a view whose `sourcePath` is absent: that project holds nothing but the
|
|
148
|
+
* service's own files, so there is nothing to attribute and nothing to strip.
|
|
149
|
+
*
|
|
150
|
+
* With a prefix, it is both the filter and the rebase, and both halves are one
|
|
151
|
+
* rule about which document belongs to whom. The project also holds the fleet
|
|
152
|
+
* map, so `architecture/usecases/checkout.likec4` is in it — and without the
|
|
153
|
+
* filter every service in the fleet would be graded for every fleet-level use
|
|
154
|
+
* case. A view carrying no `sourcePath` cannot be attributed at all and is
|
|
155
|
+
* dropped for the same reason: the path is the only evidence there is.
|
|
156
|
+
*/
|
|
157
|
+
function rebase(views, prefix) {
|
|
158
|
+
if (prefix === "")
|
|
159
|
+
return [...views];
|
|
160
|
+
return views
|
|
161
|
+
.filter((view) => view.sourcePath?.startsWith(prefix) === true)
|
|
162
|
+
.map((view) => ({ ...view, sourcePath: (view.sourcePath ?? "").slice(prefix.length) }));
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../../../src/core/usecases/service/flows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAG3E,OAAO,EAAE,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAwEnE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAuB;IAC5D,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,2EAA2E;IAC3E,0EAA0E;IAC1E,6EAA6E;IAC7E,6EAA6E;IAC7E,qFAAqF;IACrF,MAAM,QAAQ,GACZ,GAAG,CAAC,SAAS,KAAK,SAAS;QACzB,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;QAChF,CAAC,CAAC,KAAK,CAAC;IACZ,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,4EAA4E;IAC5E,4DAA4D;IAC5D,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,EAAE,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC;IAClD,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IACjG,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACnH,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEtF,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,EAAE,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;IACrD,MAAM,SAAS,GACb,GAAG,CAAC,SAAS,KAAK,SAAS;QACzB,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC;QAChC,CAAC,CAAC,MAAM,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,0EAA0E;QAC1E,0EAA0E;QAC1E,oEAAoE;QACpE,yEAAyE;QACzE,mEAAmE;QACnE,yEAAyE;QACzE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IACrE,CAAC;IACD,uEAAuE;IACvE,0EAA0E;IAC1E,8EAA8E;IAC9E,qDAAqD;IACrD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC/G,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QACtD,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE;KAC9F,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,MAAM,CAAC,KAA4B,EAAE,MAAc;IAC1D,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IACrC,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;SAC9D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * A service's OWN use cases: the `dynamic view`s its LikeC4 project declares,\n * read the way the renderer reads that project.\n *\n * THE SLOT IS THE PROJECT. `loam subsystem sync` writes a\n * `services/<…>/<svc>/likec4.config.json` that registers every `.likec4` under\n * the service directory as one LikeC4 project, so the renderer already shows a\n * `views.likec4` beside the model, or a `usecases/<name>.likec4` under it. loam\n * reads exactly that set — `model.likec4` plus every sibling, recursively, minus\n * whatever that project file's own `exclude` drops (`./exclude.ts`) — and\n * nothing else, because a slot narrower than the renderer's would leave a flow\n * that renders and is graded by nothing, which is the report this module\n * answers: an intra-service flow behind an `arch.spec.md` requirement whose\n * `Covers:` names containers had no home. `architecture/usecases/` is a\n * separate project that cannot resolve a container (one such file turned a\n * whole fleet `landscape.invalid`), and the author's workaround beside the\n * model was invisible to every check. The read is NOT gated on the project\n * file's presence: that file is create-only and a team may delete it, its\n * absence has a warning of its own (`service.likec4-config-missing`), and a\n * flow the renderer cannot show yet is still a flow loam can grade.\n *\n * MODEL FACTS STAY SINGLE-FILE. `c4.valid`'s counts, `Covers:` resolution,\n * `health.dependency-unmodelled` and every other model reader keep the\n * single-file load the service target already made; the project is loaded here\n * for the VIEWS and their `sourcePath` only, and only when there is something\n * to grade. A sibling that declares elements extends what a hop may name, and\n * that is the renderer's reading too.\n *\n * TWO SHAPES, ONE SLOT. A model that stands alone is a project of its own\n * directory, exactly as above. A model that EXTENDS the fleet map is not: its\n * containers are declared inside an element the map owns, so a flow beside it\n * naming one of those containers only resolves in a project that also holds the\n * map (`c4/service-model/documents.ts`, `serviceFlowDocuments`). That project is\n * staged from the DOCS ROOT, so every view comes back spelled\n * `services/<tree>/usecases/x.likec4` — and the service prefix is stripped here,\n * because every finding this scan feeds names a file relative to the service\n * directory and a reader must not have to work out which spelling they were\n * given. The same prefix is the FILTER: the map's own `architecture/usecases/`\n * flows are in that project too, and without it every service in the fleet would\n * be graded for every fleet-level use case.\n *\n * THE CHEAP GATE, in order, so a fleet without the axis pays one recursive\n * readdir per service and nothing else:\n *\n * 1. no sibling → nothing new is loaded, and the model's own tagged views are\n * graded at zero cost against the project the model was READ in. For a\n * standalone model that is the single-file load already in hand, which IS\n * its whole project; for an extending one it is `ServiceModel.project`, the\n * map and this model together — NOT the service's own slice of it, which is\n * what the caller passes as `model` and what every count and `Covers:` line\n * is answered from. A hop backed by a map edge is backed wherever the view\n * is written, and grading the two arms against different documents made one\n * view `usecase.step-unbacked` in model.likec4 and clean in a sibling. A\n * standalone model's views came back named `source.c4`\n * (`core/usecases/place.ts` records the rule) and an extending model's carry\n * their docs-relative path, so the file is spelled here, where it is known,\n * for both: `model.likec4`;\n * 2. siblings, no tagged view in the model, and no reserved tag REFERENCED in\n * any document — a `#` then `cap-`, `req-` or `suite-` (`mentionsTagPrefix`,\n * the fleet's own byte gate) → nothing opted in, no workspace. An untagged\n * `views.likec4` is somebody's hand-drawn diagram, never graded, exactly as\n * an untagged fleet view is — and its parse errors are the renderer's\n * business until a view opts the project in. That includes one whose prose\n * names a prefix without the `#` (a title about an e2e-suite job): the gate\n * used to open on the bare substring, and such a sibling that did not parse\n * became `usecase.flow-invalid` over a diagram that opted nothing in;\n * 3. otherwise `loadProject` over model + siblings, the way the renderer reads\n * them. `own` and the project's views are never merged: when siblings\n * exist the project is the whole answer, which is what keeps one view from\n * being graded twice.\n *\n * A REQUEST RECORD rather than three parameters, for the reason\n * docs/CODE-STYLE.md gives: the paths, the single-file doc and the fleet set\n * are only ever passed together, and a caller handing in a doc loaded from\n * some other path is exactly the inconsistent pair a record makes\n * unrepresentable.\n */\nimport { relative } from \"node:path\";\nimport type { LikeC4Error, LoadedDoc } from \"../../c4/likec4.js\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport { architectureDocuments } from \"../../c4/project/documents.js\";\nimport { asLoadedDoc, loadProject } from \"../../c4/project/load.js\";\nimport { serviceFlowDocuments } from \"../../c4/service-model/documents.js\";\nimport type { StepScope } from \"../../c4/resolve/steps.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\nimport { ARTIFACT_FILES, type ServicePaths } from \"../../repo/paths.js\";\nimport { isUseCase, mentionsTagPrefix } from \"../fleet.js\";\nimport { keepIncluded, serviceProjectExclude } from \"./exclude.js\";\n\nexport interface ServiceFlowRequest {\n paths: ServicePaths;\n /**\n * The single-file load the service target already made and has verified\n * parses. Its views are the project when no sibling exists; its elements are\n * the model a no-sibling flow is graded over.\n */\n model: LoadedDoc;\n /** The enumerated fleet, for `serviceResolver`'s reason: without it a container resolves to a service that has never existed. */\n known: ReadonlySet<string>;\n /**\n * Set only when this model EXTENDS the fleet map, and then both halves of it\n * — a record rather than two optional fields, for docs/CODE-STYLE.md's reason:\n * they are only ever passed together, and a caller that supplied one without\n * the other is exactly the inconsistent pair a record makes unrepresentable.\n *\n * `docsDir` decides which documents the sibling project holds (the map as\n * well, or the directory alone) and which root they are staged from, and\n * therefore how LikeC4 spells every `sourcePath` that comes back.\n *\n * `project` is the per-service project the model was READ in — the map plus\n * this model (`ServiceModel.project`) — and it is the scope a hop resolves\n * against when there is no sibling file. `model` above is then the service's\n * own SLICE of that project, which is the right answer for every count and\n * every `Covers:` line and the wrong one here: a hop backed by a MAP edge is\n * backed, and grading it against the slice reported `usecase.step-unbacked`\n * (exit 1) for a view in model.likec4 that was clean the moment the same view\n * moved to a sibling file, where the loaded project holds the map. One\n * question, two answers, decided by which file the author happened to write\n * the view in.\n *\n * Absent means the standalone shape — the service directory is the project and\n * the single-file load IS that project, exactly as it has always been.\n */\n extending?: { docsDir: DocsDir; project: LoadedDoc };\n}\n\n/**\n * What a service's flows are, or the honest refusal to say.\n *\n * Three variants rather than a record with flags, for `UseCaseScan`'s reason\n * one package up: a project that did not parse has no elements to resolve\n * against and no views to grade, and a caller handed `{ views: [], unreadable:\n * true }` is one `.length` check away from reporting a service as flow-free\n * when nobody could read it. `none` is the gate's answer — nothing opted in,\n * nothing was loaded — and it is distinct from `read` with no views (a project\n * that writes a reserved tag reference only outside a view — in a comment, or\n * on an element — and so declares no tagged view), because only the second one\n * cost a workspace.\n */\nexport type ServiceFlowScan =\n | { kind: \"none\" }\n | {\n kind: \"read\";\n /** The reserved-tag views ONLY, each carrying a `sourcePath` relative to the SERVICE directory. */\n views: ParsedView[];\n /** What a hop is attributed against — `known` required, as `UseCaseScan.model` requires it. */\n model: StepScope & { known: ReadonlySet<string> };\n }\n | {\n kind: \"unreadable\";\n /**\n * Every error the project raised, each carrying the real absolute path of\n * the document that raised it, sorted by that path — so a caller can name\n * the file, and a project with two broken documents reports them in a\n * stable order.\n */\n errors: LikeC4Error[];\n };\n\n/**\n * The service's declared use cases, with the model they are drawn over.\n *\n * Reads only, throws nothing: every failure is the `unreadable` arm. The caller\n * has already established that `model.likec4` parses on its own — a project\n * whose model is broken is `c4.invalid`'s business, and loading it again here\n * would only repeat that cascade under a second code.\n */\nexport async function readServiceFlows(req: ServiceFlowRequest): Promise<ServiceFlowScan> {\n const found = await architectureDocuments(req.paths.dir, [req.paths.model]);\n // What the RENDERER holds, for the standalone shape where this directory's\n // own `likec4.config.json` IS the project config: a sibling its `exclude`\n // covers is in no project loam may claim to be reading (`./exclude.ts`). The\n // extending shape reads the root project instead, so its list does not apply\n // — a per-service config beside an extending model is `service.likec4-config-stray`.\n const siblings =\n req.extending === undefined\n ? keepIncluded(req.paths.dir, await serviceProjectExclude(req.paths.dir), found)\n : found;\n // The scope of the no-sibling arm, and it is the PROJECT for both shapes: the\n // single-file load for a standalone model (which is its whole project), and\n // the map-plus-model load for an extending one. Reading `req.model` there for\n // an extending model read its own slice instead, so one view was graded two\n // different ways depending on which file it was written in.\n const alone = req.extending?.project ?? req.model;\n const scope = { elements: alone.elements, relationships: alone.relationships, known: req.known };\n const own = (req.model.views ?? []).filter(isUseCase);\n if (siblings.length === 0) {\n if (own.length === 0) return { kind: \"none\" };\n return { kind: \"read\", views: own.map((view) => ({ ...view, sourcePath: ARTIFACT_FILES.model })), model: scope };\n }\n if (own.length === 0 && !(await mentionsTagPrefix(siblings))) return { kind: \"none\" };\n\n const base = req.extending?.docsDir ?? req.paths.dir;\n const documents =\n req.extending === undefined\n ? [req.paths.model, ...siblings]\n : await serviceFlowDocuments(req.extending.docsDir, req.paths);\n const project = await loadProject(base, documents);\n if (!project.clean) {\n // Each error already carries the real path of its document (`loadProject`\n // rewrites the staged path back), and the flattening is `asLoadedDoc`'s —\n // the fleet's own path-sorted order, taken from the one place it is\n // spelled rather than re-spelled here: the caller names the FIRST broken\n // file, and a second sort rule would let the service target name a\n // different first file than the fleet target names for the same project.\n return { kind: \"unreadable\", errors: asLoadedDoc(project).errors };\n }\n // The prefix the service's own documents are spelled under inside this\n // project: empty for a standalone model (the project IS the directory, so\n // every view in it is this service's) and `services/<tree>/` for an extending\n // one, whose project also holds the whole fleet map.\n const prefix = req.extending === undefined ? \"\" : `${relative(base, req.paths.dir).split(/[\\\\/]/).join(\"/\")}/`;\n return {\n kind: \"read\",\n views: rebase(project.views.filter(isUseCase), prefix),\n model: { elements: project.elements, relationships: project.relationships, known: req.known },\n };\n}\n\n/**\n * The views this SERVICE declares, spelled relative to its own directory.\n *\n * With an empty prefix — the standalone shape — this is the identity, including\n * for a view whose `sourcePath` is absent: that project holds nothing but the\n * service's own files, so there is nothing to attribute and nothing to strip.\n *\n * With a prefix, it is both the filter and the rebase, and both halves are one\n * rule about which document belongs to whom. The project also holds the fleet\n * map, so `architecture/usecases/checkout.likec4` is in it — and without the\n * filter every service in the fleet would be graded for every fleet-level use\n * case. A view carrying no `sourcePath` cannot be attributed at all and is\n * dropped for the same reason: the path is the only evidence there is.\n */\nfunction rebase(views: readonly ParsedView[], prefix: string): ParsedView[] {\n if (prefix === \"\") return [...views];\n return views\n .filter((view) => view.sourcePath?.startsWith(prefix) === true)\n .map((view) => ({ ...view, sourcePath: (view.sourcePath ?? \"\").slice(prefix.length) }));\n}\n"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ancestorIds } from "../../kernel/ids/fqn/ancestors.js";
|
|
2
|
+
import { compareIds } from "../../repo/entries.js";
|
|
3
|
+
import { EXTERNAL_TAG } from "../../vocabulary/maturity.js";
|
|
4
|
+
/**
|
|
5
|
+
* Every endpoint the views' steps draw, resolved through the scan's ONE
|
|
6
|
+
* element→service resolver — the resolver `attributeStep` grades the same hops
|
|
7
|
+
* with, built over the same enumerated fleet (`readUseCases`). A second
|
|
8
|
+
* resolver here could not disagree today and would be a second place to change.
|
|
9
|
+
*
|
|
10
|
+
* AN ENDPOINT THAT RESOLVES TO NO ENUMERATED SERVICE IS REPORTED, NEVER DROPPED.
|
|
11
|
+
* This answer is what a test environment is provisioned from, and a silently
|
|
12
|
+
* shorter list is the one failure that cannot be seen from the list itself: the
|
|
13
|
+
* stand comes up, the missing participant is simply absent, and the journey
|
|
14
|
+
* fails against something nobody was told to start. The actor who begins a
|
|
15
|
+
* flow, a topic in the middle, a partner's API — each is named here, so the
|
|
16
|
+
* reader decides whether it needs a double, a fixture or a directory. The
|
|
17
|
+
* caller that only wants seeds (`servicesInFlowsClaiming`) reads `services` and
|
|
18
|
+
* ignores the rest, which is a choice it can see itself making.
|
|
19
|
+
*
|
|
20
|
+
* Sorted with compareIds rather than in step order: a union has no document
|
|
21
|
+
* order to preserve, and a payload ordered by LikeC4's record order would
|
|
22
|
+
* reorder under a dependency bump.
|
|
23
|
+
*/
|
|
24
|
+
export function participantsOf(scan, views) {
|
|
25
|
+
const known = scan.model.known;
|
|
26
|
+
const services = new Set();
|
|
27
|
+
const unresolved = new Set();
|
|
28
|
+
for (const view of views) {
|
|
29
|
+
for (const step of view.steps) {
|
|
30
|
+
for (const id of [step.source, step.target]) {
|
|
31
|
+
const service = scan.resolve(id);
|
|
32
|
+
if (known.has(service))
|
|
33
|
+
services.add(service);
|
|
34
|
+
else
|
|
35
|
+
unresolved.add(id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const byId = new Map(scan.model.elements.map((e) => [e.id, e]));
|
|
40
|
+
return {
|
|
41
|
+
services: [...services].sort(compareIds),
|
|
42
|
+
unresolved: [...unresolved].sort(compareIds).map((element) => ({ element, external: isExternal(element, byId, known) })),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `#external` on the element or on anything it is drawn inside — up to, and
|
|
47
|
+
* including, the first element that stands for a service.
|
|
48
|
+
*
|
|
49
|
+
* The walk is `core/gate/partners.ts`' reading of the same tag (`endFacts`),
|
|
50
|
+
* stop included, so `list suites` and the gate cannot disagree about whether
|
|
51
|
+
* an endpoint is ours. Walking up is what is true for a stand: `stripe.api`
|
|
52
|
+
* drawn inside an `#external` `stripe` is somebody else's endpoint whether or
|
|
53
|
+
* not the container repeats the tag, and LikeC4 does not inherit tags
|
|
54
|
+
* downward, so reading the element's own tags alone would print "ours, with no
|
|
55
|
+
* directory" over a partner's API. Stopping is just as true: an element bound
|
|
56
|
+
* with `metadata { service '<id>' }`, or titled for a real `services/<id>/`,
|
|
57
|
+
* IS a service, and what sits above it is a grouping whose `#external` is the
|
|
58
|
+
* grouping's claim, not the service's. Without the stop a service bound inside
|
|
59
|
+
* an `#external` zone and not yet given a directory was printed as "bring a
|
|
60
|
+
* double" while the gate graded it as ours. The tag on that element itself is
|
|
61
|
+
* read before the stop, as the gate reads it.
|
|
62
|
+
*
|
|
63
|
+
* "Stands for a service" is `commands/validate/fleet/census.ts`'
|
|
64
|
+
* `standsForService`, spelled here rather than imported because core may not
|
|
65
|
+
* reach into commands — as `core/gate/partners.ts` spells it, and as
|
|
66
|
+
* `core/c4/resolve/systems.ts` does for the feature-scope graders.
|
|
67
|
+
*
|
|
68
|
+
* A tag a KIND declares (`element topic { #external }`) arrives on every element
|
|
69
|
+
* of that kind in the parsed model, so a topic counts without repeating it.
|
|
70
|
+
*/
|
|
71
|
+
function isExternal(element, byId, known) {
|
|
72
|
+
for (const id of ancestorIds(element)) {
|
|
73
|
+
const e = byId.get(id);
|
|
74
|
+
if (e === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (e.tags.includes(EXTERNAL_TAG))
|
|
77
|
+
return true;
|
|
78
|
+
if (e.service !== undefined || known.has(e.title))
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=participants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"participants.js","sourceRoot":"","sources":["../../../../src/core/usecases/suites/participants.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AA2B5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,KAA4B;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACjC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;;oBACzC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACxC,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;KACzH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAS,UAAU,CAAC,OAAe,EAAE,IAA+B,EAAE,KAA0B;IAC9F,KAAK,MAAM,EAAE,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QAC9B,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Who takes part in a set of use cases — the union a test environment is built\n * from, and the participants that union cannot place.\n *\n * It began as `servicesInFlowsClaiming` in `../capability.ts`, which answered\n * the same question for the flows claiming one capability and kept only the\n * half `loam explore` needed: the enumerated services. A suite asks it of a\n * different set of views — the ones carrying one `#suite-` tag — and needs the\n * other half too, so the walk moved here and grew a second output rather than\n * being written twice. Two walks over \"which services does this flow touch\"\n * would be two answers to the question a test stand is provisioned from.\n *\n * THE DEPENDENCY RUNS PARENT → CHILD, never back. `../capability.ts` and\n * `../fleet.ts` (which takes the suite prefix from `./suites.ts`) import this\n * package, so nothing here may value-import `core/usecases/` — the package\n * graph would close a cycle `import/no-cycle` cannot see (docs/DESIGN.md rule\n * 21). `UseCaseScan` crosses as a TYPE only, which erases.\n */\nimport type { Elem } from \"../../c4/likec4.js\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport { ancestorIds } from \"../../kernel/ids/fqn/ancestors.js\";\nimport { compareIds } from \"../../repo/entries.js\";\nimport { EXTERNAL_TAG } from \"../../vocabulary/maturity.js\";\nimport type { UseCaseScan } from \"../fleet.js\";\n\n/** A scan that read — the only kind with elements to resolve against. */\nexport type ReadScan = Extract<UseCaseScan, { kind: \"read\" }>;\n\n/** A participant the element→service join could not land on an enumerated service. */\nexport interface UnresolvedParticipant {\n /** The element id a step drew, exactly as the view spells it. */\n element: string;\n /**\n * Does the element, or anything it is drawn inside short of a service, carry\n * `#external`? Then it is deliberately not the fleet's, and a stand needs a\n * double for it rather than a directory. See `isExternal` for why an\n * ancestor's tag counts and why the walk stops at a service.\n */\n external: boolean;\n}\n\n/** The union of a set of views' participants, split by whether the fleet can stand each one up. */\nexport interface Participants {\n /** Enumerated service ids, sorted and deduplicated. */\n services: string[];\n /** Everything else the steps drew, one entry per element id, sorted by it. */\n unresolved: UnresolvedParticipant[];\n}\n\n/**\n * Every endpoint the views' steps draw, resolved through the scan's ONE\n * element→service resolver — the resolver `attributeStep` grades the same hops\n * with, built over the same enumerated fleet (`readUseCases`). A second\n * resolver here could not disagree today and would be a second place to change.\n *\n * AN ENDPOINT THAT RESOLVES TO NO ENUMERATED SERVICE IS REPORTED, NEVER DROPPED.\n * This answer is what a test environment is provisioned from, and a silently\n * shorter list is the one failure that cannot be seen from the list itself: the\n * stand comes up, the missing participant is simply absent, and the journey\n * fails against something nobody was told to start. The actor who begins a\n * flow, a topic in the middle, a partner's API — each is named here, so the\n * reader decides whether it needs a double, a fixture or a directory. The\n * caller that only wants seeds (`servicesInFlowsClaiming`) reads `services` and\n * ignores the rest, which is a choice it can see itself making.\n *\n * Sorted with compareIds rather than in step order: a union has no document\n * order to preserve, and a payload ordered by LikeC4's record order would\n * reorder under a dependency bump.\n */\nexport function participantsOf(scan: ReadScan, views: readonly ParsedView[]): Participants {\n const known = scan.model.known;\n const services = new Set<string>();\n const unresolved = new Set<string>();\n for (const view of views) {\n for (const step of view.steps) {\n for (const id of [step.source, step.target]) {\n const service = scan.resolve(id);\n if (known.has(service)) services.add(service);\n else unresolved.add(id);\n }\n }\n }\n const byId = new Map(scan.model.elements.map((e) => [e.id, e]));\n return {\n services: [...services].sort(compareIds),\n unresolved: [...unresolved].sort(compareIds).map((element) => ({ element, external: isExternal(element, byId, known) })),\n };\n}\n\n/**\n * `#external` on the element or on anything it is drawn inside — up to, and\n * including, the first element that stands for a service.\n *\n * The walk is `core/gate/partners.ts`' reading of the same tag (`endFacts`),\n * stop included, so `list suites` and the gate cannot disagree about whether\n * an endpoint is ours. Walking up is what is true for a stand: `stripe.api`\n * drawn inside an `#external` `stripe` is somebody else's endpoint whether or\n * not the container repeats the tag, and LikeC4 does not inherit tags\n * downward, so reading the element's own tags alone would print \"ours, with no\n * directory\" over a partner's API. Stopping is just as true: an element bound\n * with `metadata { service '<id>' }`, or titled for a real `services/<id>/`,\n * IS a service, and what sits above it is a grouping whose `#external` is the\n * grouping's claim, not the service's. Without the stop a service bound inside\n * an `#external` zone and not yet given a directory was printed as \"bring a\n * double\" while the gate graded it as ours. The tag on that element itself is\n * read before the stop, as the gate reads it.\n *\n * \"Stands for a service\" is `commands/validate/fleet/census.ts`'\n * `standsForService`, spelled here rather than imported because core may not\n * reach into commands — as `core/gate/partners.ts` spells it, and as\n * `core/c4/resolve/systems.ts` does for the feature-scope graders.\n *\n * A tag a KIND declares (`element topic { #external }`) arrives on every element\n * of that kind in the parsed model, so a topic counts without repeating it.\n */\nfunction isExternal(element: string, byId: ReadonlyMap<string, Elem>, known: ReadonlySet<string>): boolean {\n for (const id of ancestorIds(element)) {\n const e = byId.get(id);\n if (e === undefined) continue;\n if (e.tags.includes(EXTERNAL_TAG)) return true;\n if (e.service !== undefined || known.has(e.title)) return false;\n }\n return false;\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { compareIds } from "../../repo/entries.js";
|
|
2
|
+
import { participantsOf } from "./participants.js";
|
|
3
|
+
/**
|
|
4
|
+
* The reserved tag prefix, matched EXACTLY — case included — as `cap-` and
|
|
5
|
+
* `req-` are. Exported for `../fleet.ts`, where it joins the other two in the
|
|
6
|
+
* one opt-in predicate and the one byte gate in front of it.
|
|
7
|
+
*/
|
|
8
|
+
export const SUITE_TAG_PREFIX = "suite-";
|
|
9
|
+
/**
|
|
10
|
+
* The suite names one view declares: the tags with the prefix stripped,
|
|
11
|
+
* deduplicated and sorted.
|
|
12
|
+
*
|
|
13
|
+
* A bare `#suite-` is a suite named `''` and is KEPT, for the reason a bare
|
|
14
|
+
* `#cap-` stays a claim: the prefix is the opt-in however little follows it,
|
|
15
|
+
* and a view that asked to be in a suite must not silently be in none.
|
|
16
|
+
*/
|
|
17
|
+
function suiteNames(view) {
|
|
18
|
+
const names = view.tags.filter((tag) => tag.startsWith(SUITE_TAG_PREFIX)).map((tag) => tag.slice(SUITE_TAG_PREFIX.length));
|
|
19
|
+
return [...new Set(names)].sort(compareIds);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Group the scan's use cases by suite.
|
|
23
|
+
*
|
|
24
|
+
* The order is by (document, view id). `../place.ts`' `viewFile` is how a
|
|
25
|
+
* document is SPELLED, and it only prefixes `sourcePath` with a constant, so
|
|
26
|
+
* ordering on `sourcePath` itself orders identically without pointing this
|
|
27
|
+
* package back at its parent.
|
|
28
|
+
*/
|
|
29
|
+
export function suiteListing(scan) {
|
|
30
|
+
const ordered = [...scan.views].sort((a, b) => compareIds(a.sourcePath ?? "", b.sourcePath ?? "") || compareIds(a.id, b.id));
|
|
31
|
+
const byName = new Map();
|
|
32
|
+
const ungrouped = [];
|
|
33
|
+
for (const view of ordered) {
|
|
34
|
+
const names = suiteNames(view);
|
|
35
|
+
if (names.length === 0)
|
|
36
|
+
ungrouped.push(view);
|
|
37
|
+
for (const name of names)
|
|
38
|
+
byName.set(name, [...(byName.get(name) ?? []), view]);
|
|
39
|
+
}
|
|
40
|
+
const suites = [...byName]
|
|
41
|
+
.sort(([a], [b]) => compareIds(a, b))
|
|
42
|
+
.map(([name, views]) => ({ name, views, ...participantsOf(scan, views) }));
|
|
43
|
+
return { suites, ungrouped };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=suites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suites.js","sourceRoot":"","sources":["../../../../src/core/usecases/suites/suites.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAA6C,MAAM,mBAAmB,CAAC;AAE9F;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAEzC;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,IAAiC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3H,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9C,CAAC;AA6BD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAClC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CACvF,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC/C,MAAM,SAAS,GAAiB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACpC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * Suites: which use cases run together, and what a run of one needs standing up.\n *\n * A use case joins a suite by carrying a `#suite-<name>` tag on its `dynamic\n * view`. A TAG rather than a directory, because suites are many-to-many — one\n * journey belongs to the smoke suite and the payments suite at once — and a\n * directory gives exactly one group. The tag also buys the typo check for free:\n * LikeC4 refuses an undeclared tag, so a suite declared once in the landscape's\n * `specification` block makes a mistyped suite a parse error, where a mistyped\n * directory would silently open a second, empty suite.\n *\n * A SEPARATE PREFIX, not `#cap-`. A capability says what a flow is FOR and may\n * be claimed once per meaning; a suite says what a flow is RUN WITH, and a\n * flow is routinely in several. Reusing the capability tag would make every\n * suite a business promise and every smoke run a capability, and the `#cap-`\n * resolution ladder (`../../capabilities/usecase-join.ts`) would convict every\n * suite name the vocabulary does not declare. The prefix also keeps the tag\n * clear of the feature-id grammar: a view tag is never read as a `#FEAT-`\n * marker (feature tags are read off elements and relationships only), and no\n * other reserved prefix — `cap-`, `req-`, `obl-` — is a prefix of this one or\n * has it as a prefix, so no tag can be claimed by two readers.\n *\n * TAGGING IS THE OPT-IN, and that is the owner's call recorded in SCHEMA.md: a\n * view carrying only `#suite-` tags IS a use case — `../fleet.ts`' `isUseCase`\n * admits it — and is graded hop by hop like any other. Nothing here grades; this\n * module groups the views the scan already admitted.\n *\n * Depends on its parent by TYPE only — `./participants.ts` says why the value\n * direction is parent → child.\n */\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport { compareIds } from \"../../repo/entries.js\";\nimport { participantsOf, type ReadScan, type UnresolvedParticipant } from \"./participants.js\";\n\n/**\n * The reserved tag prefix, matched EXACTLY — case included — as `cap-` and\n * `req-` are. Exported for `../fleet.ts`, where it joins the other two in the\n * one opt-in predicate and the one byte gate in front of it.\n */\nexport const SUITE_TAG_PREFIX = \"suite-\";\n\n/**\n * The suite names one view declares: the tags with the prefix stripped,\n * deduplicated and sorted.\n *\n * A bare `#suite-` is a suite named `''` and is KEPT, for the reason a bare\n * `#cap-` stays a claim: the prefix is the opt-in however little follows it,\n * and a view that asked to be in a suite must not silently be in none.\n */\nfunction suiteNames(view: { tags: readonly string[] }): string[] {\n const names = view.tags.filter((tag) => tag.startsWith(SUITE_TAG_PREFIX)).map((tag) => tag.slice(SUITE_TAG_PREFIX.length));\n return [...new Set(names)].sort(compareIds);\n}\n\n/** One suite: its name, its use cases, and the environment their union needs. */\nexport interface Suite {\n /** The tag without `#suite-` — what `loam list suites <name>` takes. */\n name: string;\n /** The use cases carrying the tag, ordered by (document, view id). */\n views: ParsedView[];\n /** The enumerated services those use cases draw — what must be up. */\n services: string[];\n /** Participants that resolve to no enumerated service — named, never dropped. */\n unresolved: UnresolvedParticipant[];\n}\n\n/** Every suite the fleet's use cases declare, and the use cases in none. */\nexport interface SuiteListing {\n /** Sorted by name. */\n suites: Suite[];\n /**\n * The use cases carrying no `#suite-` tag, ordered by (document, view id).\n *\n * Answered because everything else here is per-suite: a journey in no suite\n * is absent from every suite's list, which is the one absence a per-suite\n * output cannot show. Legal and normal — an unfiled service is the same shape\n * — so it is named and never graded.\n */\n ungrouped: ParsedView[];\n}\n\n/**\n * Group the scan's use cases by suite.\n *\n * The order is by (document, view id). `../place.ts`' `viewFile` is how a\n * document is SPELLED, and it only prefixes `sourcePath` with a constant, so\n * ordering on `sourcePath` itself orders identically without pointing this\n * package back at its parent.\n */\nexport function suiteListing(scan: ReadScan): SuiteListing {\n const ordered = [...scan.views].sort(\n (a, b) => compareIds(a.sourcePath ?? \"\", b.sourcePath ?? \"\") || compareIds(a.id, b.id),\n );\n const byName = new Map<string, ParsedView[]>();\n const ungrouped: ParsedView[] = [];\n for (const view of ordered) {\n const names = suiteNames(view);\n if (names.length === 0) ungrouped.push(view);\n for (const name of names) byName.set(name, [...(byName.get(name) ?? []), view]);\n }\n const suites = [...byName]\n .sort(([a], [b]) => compareIds(a, b))\n .map(([name, views]) => ({ name, views, ...participantsOf(scan, views) }));\n return { suites, ungrouped };\n}\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which business flows run through a service — the blast radius `loam delta`
|
|
3
|
+
* and `loam status` report beside the requirements and contracts a feature
|
|
4
|
+
* changes.
|
|
5
|
+
*
|
|
6
|
+
* ## The join is on ENDPOINTS, never on relationships
|
|
7
|
+
*
|
|
8
|
+
* `core/usecases/operations.ts` asks what a hop EXERCISES, which needs the
|
|
9
|
+
* relationship behind it. This asks something weaker and more useful early:
|
|
10
|
+
* does this hop mention the service at all? So it resolves the step's own two
|
|
11
|
+
* endpoints and stops — no `attributeStep`, no candidate scan.
|
|
12
|
+
*
|
|
13
|
+
* That is the difference between answering and not answering for the service a
|
|
14
|
+
* feature is about to INTRODUCE. A flow drawn for work that has not happened yet
|
|
15
|
+
* has hops nothing in the model backs — `usecase.step-unbacked` is validate's
|
|
16
|
+
* finding about exactly that, and it is an ERROR precisely because the fleet map
|
|
17
|
+
* has not caught up — and a relationship join reports such a flow as touching
|
|
18
|
+
* nobody. The endpoints are still there; the arrow is what is missing. An
|
|
19
|
+
* implementer reading a delta brief needs to know the flow exists most of all in
|
|
20
|
+
* that state, because that is the state their change is supposed to end.
|
|
21
|
+
*
|
|
22
|
+
* ## Everything a caller sees, it sees per HOP
|
|
23
|
+
*
|
|
24
|
+
* A view is reported only when at least one of its hops touches the addressed
|
|
25
|
+
* services, and only those hops travel. "Checkout touches you" is not actionable;
|
|
26
|
+
* "Checkout touches you at step 4" is where the reader goes to look.
|
|
27
|
+
*/
|
|
28
|
+
import { compareIds } from "../repo/entries.js";
|
|
29
|
+
import { readUseCases } from "./fleet.js";
|
|
30
|
+
import { viewFile } from "./place.js";
|
|
31
|
+
/** The addressed services one hop mentions, source and target both, sorted and de-duplicated. */
|
|
32
|
+
function touched(step, scan, services) {
|
|
33
|
+
const hit = [step.source, step.target].map((id) => scan.resolve(id)).filter((id) => services.has(id));
|
|
34
|
+
return [...new Set(hit)].sort(compareIds);
|
|
35
|
+
}
|
|
36
|
+
/** One view's touching hops, in the author's own step order — the order the diagram reads in. */
|
|
37
|
+
function touchedView(view, scan, services) {
|
|
38
|
+
const steps = [];
|
|
39
|
+
for (const step of view.steps) {
|
|
40
|
+
const hit = touched(step, scan, services);
|
|
41
|
+
if (hit.length === 0)
|
|
42
|
+
continue;
|
|
43
|
+
steps.push({
|
|
44
|
+
ordinal: step.ordinal,
|
|
45
|
+
...(step.title === undefined ? {} : { title: step.title }),
|
|
46
|
+
source: step.source,
|
|
47
|
+
target: step.target,
|
|
48
|
+
services: hit,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (steps.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
return {
|
|
54
|
+
id: view.id,
|
|
55
|
+
...(view.title === undefined ? {} : { title: view.title }),
|
|
56
|
+
file: viewFile(view),
|
|
57
|
+
tags: [...view.tags].sort(compareIds),
|
|
58
|
+
steps,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The flows touching a set of services, over a scan somebody already has.
|
|
63
|
+
*
|
|
64
|
+
* Separate from `useCaseBlastRadius` below because `core/pack/joins.ts` reads
|
|
65
|
+
* the scan ONCE and asks two different questions of it — this one and the
|
|
66
|
+
* capability claim join — and a second read there would be a second LikeC4
|
|
67
|
+
* project load inside a single `loam context`.
|
|
68
|
+
*
|
|
69
|
+
* An `unreadable` scan answers with nothing. Every caller pairs this with the
|
|
70
|
+
* scan's own health, because an empty list means "no flow mentions these
|
|
71
|
+
* services" and "nobody could look" only when read together.
|
|
72
|
+
*/
|
|
73
|
+
export function flowsTouching(scan, services) {
|
|
74
|
+
if (scan.kind !== "read")
|
|
75
|
+
return [];
|
|
76
|
+
return (scan.views
|
|
77
|
+
.map((view) => touchedView(view, scan, services))
|
|
78
|
+
.filter((flow) => flow !== null)
|
|
79
|
+
// Sorted by (file, view id) rather than reported in LikeC4's own record
|
|
80
|
+
// order: nothing in loam has measured that the parse preserves declaration
|
|
81
|
+
// order, so a payload ordered by it would reorder under a dependency bump.
|
|
82
|
+
.sort((a, b) => compareIds(a.file, b.file) || compareIds(a.id, b.id)));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The flows touching a set of services, read and joined in one call.
|
|
86
|
+
*
|
|
87
|
+
* The load underneath is `readUseCases`, which carries its own cheap gate: a
|
|
88
|
+
* fleet whose `architecture/` documents never mention the reserved tag prefix
|
|
89
|
+
* answers `{ flows: [] }` without starting LikeC4 at all. That gate is what
|
|
90
|
+
* makes this callable from `loam delta`, which sits in `/loam-implement`'s inner
|
|
91
|
+
* loop and would otherwise pay a Langium workspace spin-up on every iteration of
|
|
92
|
+
* somebody's afternoon.
|
|
93
|
+
*/
|
|
94
|
+
export async function useCaseBlastRadius(req) {
|
|
95
|
+
const scan = await readUseCases({ docsDir: req.docsDir, known: req.known });
|
|
96
|
+
if (scan.kind !== "read") {
|
|
97
|
+
return { unreadable: true, ...(scan.errors[0] === undefined ? {} : { error: scan.errors[0] }), flows: [] };
|
|
98
|
+
}
|
|
99
|
+
return { unreadable: false, flows: flowsTouching(scan, req.services) };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=touch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touch.js","sourceRoot":"","sources":["../../../src/core/usecases/touch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Which business flows run through a service — the blast radius `loam delta`\n * and `loam status` report beside the requirements and contracts a feature\n * changes.\n *\n * ## The join is on ENDPOINTS, never on relationships\n *\n * `core/usecases/operations.ts` asks what a hop EXERCISES, which needs the\n * relationship behind it. This asks something weaker and more useful early:\n * does this hop mention the service at all? So it resolves the step's own two\n * endpoints and stops — no `attributeStep`, no candidate scan.\n *\n * That is the difference between answering and not answering for the service a\n * feature is about to INTRODUCE. A flow drawn for work that has not happened yet\n * has hops nothing in the model backs — `usecase.step-unbacked` is validate's\n * finding about exactly that, and it is an ERROR precisely because the fleet map\n * has not caught up — and a relationship join reports such a flow as touching\n * nobody. The endpoints are still there; the arrow is what is missing. An\n * implementer reading a delta brief needs to know the flow exists most of all in\n * that state, because that is the state their change is supposed to end.\n *\n * ## Everything a caller sees, it sees per HOP\n *\n * A view is reported only when at least one of its hops touches the addressed\n * services, and only those hops travel. \"Checkout touches you\" is not actionable;\n * \"Checkout touches you at step 4\" is where the reader goes to look.\n */\nimport { compareIds } from \"../repo/entries.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\nimport type { ParsedStep, ParsedView } from \"../c4/parsed/dynamic-views.js\";\nimport { readUseCases, type UseCaseScan } from \"./fleet.js\";\nimport { viewFile } from \"./place.js\";\n\n/** One hop of a flow that mentions a service the caller asked about. */\nexport interface TouchedStep {\n /** The view's own leaf numbering — what the author sees on the diagram. */\n ordinal: number;\n title?: string;\n /** The step's endpoints as the view declares them: element ids, already oriented. */\n source: string;\n target: string;\n /**\n * Which of the ADDRESSED services this hop mentions, sorted. Both, when a flow\n * calls a service and it answers within the same addressed set.\n */\n services: string[];\n}\n\n/** One flow that touches the addressed services, with only the hops that do. */\nexport interface TouchedUseCase {\n id: string;\n title?: string;\n /** Repo-relative document the view is written in — where the reader goes to change it. */\n file: string;\n /**\n * The `#cap-` tags the view carries, verbatim and unresolved.\n *\n * Verbatim because resolving them means reading\n * `architecture/capabilities.yaml`, and a slug is not injective — the join can\n * legitimately answer \"two capabilities\" (core/capabilities/usecase-join.ts).\n * A blast-radius list is not the place to make that call: `loam validate --all`\n * already grades every tag with `usecase.capability-unresolved`, and a second\n * resolution here would be a second answer to the same question.\n */\n tags: string[];\n steps: TouchedStep[];\n}\n\n/**\n * The flows over a set of services, and whether loam could look at all.\n *\n * `unreadable` is a HOLE, in the sense `core/pack/pack.ts` uses the word: `flows`\n * is empty because `architecture/` did not parse, not because the fleet draws no\n * use cases. A consumer that cannot tell those apart reads \"no business flow\n * depends on this\" off a directory nobody could open, which is the vacuously\n * green answer every surface in loam is built to refuse.\n */\nexport interface UseCaseBlastRadius {\n unreadable: boolean;\n /** LikeC4's first message, so a reader knows which document to open. */\n error?: string;\n flows: TouchedUseCase[];\n}\n\nexport interface BlastRadiusRequest {\n docsDir: DocsDir;\n /**\n * The fleet the element→service resolver is built with. Wider than `services`\n * on purpose: it should be every service the resolver could legitimately land\n * on, so a hop into a modelled container resolves to its owner rather than to\n * the container's own title.\n */\n known: ReadonlySet<string>;\n /** The services being asked about. */\n services: ReadonlySet<string>;\n}\n\n/** The addressed services one hop mentions, source and target both, sorted and de-duplicated. */\nfunction touched(step: ParsedStep, scan: Extract<UseCaseScan, { kind: \"read\" }>, services: ReadonlySet<string>): string[] {\n const hit = [step.source, step.target].map((id) => scan.resolve(id)).filter((id) => services.has(id));\n return [...new Set(hit)].sort(compareIds);\n}\n\n/** One view's touching hops, in the author's own step order — the order the diagram reads in. */\nfunction touchedView(view: ParsedView, scan: Extract<UseCaseScan, { kind: \"read\" }>, services: ReadonlySet<string>): TouchedUseCase | null {\n const steps: TouchedStep[] = [];\n for (const step of view.steps) {\n const hit = touched(step, scan, services);\n if (hit.length === 0) continue;\n steps.push({\n ordinal: step.ordinal,\n ...(step.title === undefined ? {} : { title: step.title }),\n source: step.source,\n target: step.target,\n services: hit,\n });\n }\n if (steps.length === 0) return null;\n return {\n id: view.id,\n ...(view.title === undefined ? {} : { title: view.title }),\n file: viewFile(view),\n tags: [...view.tags].sort(compareIds),\n steps,\n };\n}\n\n/**\n * The flows touching a set of services, over a scan somebody already has.\n *\n * Separate from `useCaseBlastRadius` below because `core/pack/joins.ts` reads\n * the scan ONCE and asks two different questions of it — this one and the\n * capability claim join — and a second read there would be a second LikeC4\n * project load inside a single `loam context`.\n *\n * An `unreadable` scan answers with nothing. Every caller pairs this with the\n * scan's own health, because an empty list means \"no flow mentions these\n * services\" and \"nobody could look\" only when read together.\n */\nexport function flowsTouching(scan: UseCaseScan, services: ReadonlySet<string>): TouchedUseCase[] {\n if (scan.kind !== \"read\") return [];\n return (\n scan.views\n .map((view) => touchedView(view, scan, services))\n .filter((flow): flow is TouchedUseCase => flow !== null)\n // Sorted by (file, view id) rather than reported in LikeC4's own record\n // order: nothing in loam has measured that the parse preserves declaration\n // order, so a payload ordered by it would reorder under a dependency bump.\n .sort((a, b) => compareIds(a.file, b.file) || compareIds(a.id, b.id))\n );\n}\n\n/**\n * The flows touching a set of services, read and joined in one call.\n *\n * The load underneath is `readUseCases`, which carries its own cheap gate: a\n * fleet whose `architecture/` documents never mention the reserved tag prefix\n * answers `{ flows: [] }` without starting LikeC4 at all. That gate is what\n * makes this callable from `loam delta`, which sits in `/loam-implement`'s inner\n * loop and would otherwise pay a Langium workspace spin-up on every iteration of\n * somebody's afternoon.\n */\nexport async function useCaseBlastRadius(req: BlastRadiusRequest): Promise<UseCaseBlastRadius> {\n const scan = await readUseCases({ docsDir: req.docsDir, known: req.known });\n if (scan.kind !== \"read\") {\n return { unreadable: true, ...(scan.errors[0] === undefined ? {} : { error: scan.errors[0] }), flows: [] };\n }\n return { unreadable: false, flows: flowsTouching(scan, req.services) };\n}\n"]}
|