@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5992 -82
- package/COMPARISON.md +168 -63
- package/CONTRIBUTING.md +121 -0
- package/MIGRATING-from-OpenSpec.md +238 -55
- package/QUICKSTART.md +302 -0
- package/README.md +653 -144
- package/ROADMAP.md +1035 -0
- package/SCHEMA.md +3916 -263
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +927 -0
- package/dist/cli.js +133 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +204 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +309 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +74 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +193 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +319 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +298 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +106 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +318 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +30 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +355 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +166 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +305 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +367 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +221 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +6 -8
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +86 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +65 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +227 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +39 -28
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +152 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +66 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +105 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +262 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +146 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +72 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +142 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +63 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +155 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +358 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +344 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +108 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +238 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +75 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +175 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +18 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +62 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +328 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +279 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +199 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +300 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +221 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +278 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +174 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +182 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +53 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/show/service.js +239 -0
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +87 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +47 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +209 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +115 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +269 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +325 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +113 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +98 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +318 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +196 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +249 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +176 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/unarchive/restore.js +254 -0
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +59 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +245 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +204 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +58 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +264 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +85 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +222 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +93 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +371 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +118 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +266 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +71 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +75 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +52 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +89 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +145 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +252 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +241 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +177 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +310 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +279 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +148 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +363 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +178 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +81 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +263 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +278 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +206 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +328 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +220 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +266 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +141 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +230 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +111 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +155 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +169 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +299 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +46 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +44 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +78 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +104 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +138 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +273 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md.js +203 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +254 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +144 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +151 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +193 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +280 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +373 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +323 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +220 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +188 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +311 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +67 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +210 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +19 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +338 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +43 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +146 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +92 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +38 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +290 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +195 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +83 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/asyncapi/read.js +263 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +285 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +385 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +273 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +304 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +58 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +190 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +243 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +110 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +113 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +161 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +89 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +219 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +174 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +173 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +369 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +308 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +167 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +30 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +73 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +337 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +298 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +166 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +47 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +338 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +174 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +123 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +205 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +104 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +267 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +185 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +75 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +332 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +295 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +191 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +335 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +189 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +63 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +95 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +341 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +230 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +237 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +204 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +312 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/docs.js +37 -85
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +238 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +139 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +355 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +224 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +286 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +238 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +234 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +89 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +209 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +180 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +194 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +103 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/explore/explore.js +204 -0
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +174 -146
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +208 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +246 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +176 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +210 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +109 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +73 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/{records.js → kernel/records.js} +11 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +66 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +118 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +265 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +212 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +73 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +324 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +207 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +142 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +174 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +136 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +239 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +54 -108
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +199 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +16 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +204 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +232 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +110 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +220 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +78 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +70 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +241 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +191 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +304 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +116 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +157 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +120 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +244 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +201 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +139 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +280 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +220 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +322 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +308 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +61 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +90 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +255 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +146 -14
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +239 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +252 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +268 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +95 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +204 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/snapshot/snapshot.js +196 -0
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +181 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +60 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +126 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +214 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +163 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +216 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +302 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +216 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +166 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +140 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +101 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +76 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +296 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/grade/capability-tag.js +93 -0
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/core/usecases/grade/requirement-tag.js +94 -0
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/core/usecases/grade/steps.js +266 -0
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/core/usecases/grade/usecases.js +112 -0
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +123 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +180 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +170 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +259 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +158 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/read/shape.js +169 -0
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +165 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +99 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +61 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +59 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +216 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/vocabulary/report.js +90 -0
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +232 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +336 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +18 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +8 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +92 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +134 -0
- package/examples/docs/services/order-service/asyncapi.yaml +109 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +126 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +76 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +68 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
- package/examples/docs/services/platform/notification-service/health.yaml +40 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js +0 -320
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js +0 -317
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js +0 -253
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js +0 -225
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js +0 -47
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"likec4.js","sourceRoot":"","sources":["../../../src/core/c4/likec4.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\nimport { LikeC4 } from \"likec4\";\nimport { declaredService, type DeclaredService } from \"../kernel/ids/service.js\";\nimport { readDynamicViews, type ParsedView } from \"./parsed/dynamic-views.js\";\nimport { readGlobalStyleIds, readViewIds, type ViewIdClaim } from \"./parsed/view-ids.js\";\nimport { readSpecification, type DocSpecification } from \"./parsed/specification.js\";\nimport { readDeployment, type DeploymentModel } from \"./parsed/deployment.js\";\nimport { compareRels, descText, metaKey } from \"./parsed/values.js\";\n\n/** A parse/validation issue reported by LikeC4. */\nexport interface LikeC4Error {\n message: string;\n /** As LikeC4 hands it over: an LSP range line, which starts at 0. Print it through `errorText`. */\n line?: number;\n sourceFsPath?: string;\n}\n\n/**\n * The one spelling of a diagnostic loam prints — `L<n>: <message>`, with the\n * line 1-BASED: the number an editor's gutter shows, so an agent told to open\n * it opens the line the fault is on. LikeC4's `getErrors()` copies the LSP\n * range's start line, which counts from 0, and every message used to print that\n * raw number: the named line landed one above the fault every time\n * (verification 2026-09-04, W6).\n *\n * `likec4 validate` DOES NOT AGREE, and that is deliberate rather than\n * unnoticed. Measured at the 1.59.2 pin on a document whose fault is on file\n * line 10: the CLI prints `Line 9:` and loam prints `L10:` for the same\n * diagnostic — it renders the LSP index raw. Copying that would make loam's\n * output wrong in the way the fix above repaired, so the two spellings differ\n * by exactly one and a reader comparing them should expect it.\n *\n * Four modules used to hand-roll this ternary; they all read this one now, so\n * the base cannot drift between them again.\n *\n * The message itself is BOUNDED here too, and for the same reason it lives in\n * one place: every surface that prints a LikeC4 diagnostic — validate, context,\n * show, tasks, doctor, gate, archive — prints it through this function, so this\n * is the one spelling that can keep all of them small. See `boundedMessage`.\n */\nexport function errorText(e: LikeC4Error): string {\n const message = boundedMessage(e.message);\n return typeof e.line === \"number\" ? `L${e.line + 1}: ${message}` : message;\n}\n\n/**\n * The documents a project's diagnostics name, docs-relative POSIX, deduped and\n * sorted — the one spelling of \"which files broke\" behind `landscape.invalid`,\n * `spine.landscape-invalid`, the brief's unparseable arm, the work packet and\n * `loam explore`. Those surfaces are read one after another on the same tree,\n * and an agent has to be able to tell that they name the same file. Given ONE\n * error it spells that error's document: validate's detail-line prefix.\n */\nexport function brokenDocumentPaths(docsDir: string, errors: readonly LikeC4Error[]): string[] {\n return [...new Set(errors.map((e) => e.sourceFsPath).filter((p): p is string => p !== undefined))]\n .map((abs) => relative(docsDir, abs).split(/[\\\\/]/).join(\"/\"))\n .sort();\n}\n\n/**\n * How many alternatives of a parser's \"one of these possible Token sequences\"\n * list a printed diagnostic keeps — the number `likec4 validate` itself prints\n * before its `...`.\n */\nconst TOKEN_ALTERNATIVES = 4;\n\n/** The heading line of Chevrotain's no-viable-alternative message, whose numbered list follows it. */\nconst TOKEN_SEQUENCES = /possible Token sequences:$/;\n\n/** One numbered alternative in that list: ` 12. [IdTerminal, Dot]`. */\nconst ALTERNATIVE = /^\\s+\\d+\\. /;\n\n/**\n * A LikeC4 message, with Chevrotain's list of expected token sequences cut to\n * its first few alternatives and a count of the rest.\n *\n * When the parser meets a token no rule can take, Chevrotain lists EVERY token\n * sequence any rule could have accepted there — and inside a LikeC4 `model { }`\n * block that is the whole grammar. Measured at the 1.59.2 pin: deleting the\n * closing quote of one `technology '…'` makes three such messages of about\n * 6,160 lines each, and `loam validate --service` printed 18,503 lines\n * (434 KB; 458 KB as `--json`) for one keystroke. `capDetails` bounds how MANY\n * details a finding prints, never how big one is, and `loam context` has no cap\n * at all — so a broken feature delta turned a 24 KB briefing into 626 KB for\n * every agent working on any service the feature touches. An agent in the\n * check-fix loop gets nothing from alternative 4,000: what it acts on is the\n * line number and the `but found: '…'` line, which is kept.\n *\n * Upstream `likec4 validate` keeps the first five lines of any message and\n * prints `...`; this cuts the LIST only, so the `but found:` line after it\n * survives, and says how many alternatives were dropped so nothing reads as\n * complete when it is not (the convention `capDetails` uses). Any other\n * message is returned exactly as LikeC4 wrote it.\n */\nfunction boundedMessage(message: string): string {\n const lines = message.split(\"\\n\");\n if (!TOKEN_SEQUENCES.test(lines[0] ?? \"\")) return message;\n const alternatives = lines.filter((line) => ALTERNATIVE.test(line)).length;\n if (alternatives <= TOKEN_ALTERNATIVES) return message;\n const kept: string[] = [];\n let seen = 0;\n for (const line of lines) {\n if (!ALTERNATIVE.test(line)) kept.push(line);\n else if (++seen <= TOKEN_ALTERNATIVES) kept.push(line);\n else if (seen === TOKEN_ALTERNATIVES + 1) kept.push(` … (+${alternatives - TOKEN_ALTERNATIVES} more)`);\n }\n return kept.join(\"\\n\");\n}\n\n/**\n * Diagnostics as loam keeps them: each one ONCE, in line order.\n *\n * LikeC4 can report one fault more than once: measured at the 1.59.2 pin, one\n * dropped quote in a service model came back as two byte-identical messages at\n * the same line — each of them the full token list `boundedMessage` cuts — and\n * every `details` list printed both. The same message at the same line of the\n * same file is one fault; the identity includes the file because LikeC4 blames\n * a duplicate declaration on BOTH documents of a project, and those are two\n * lines an author has to look at.\n *\n * In line order because LikeC4 hands its lexer's errors over before its\n * parser's: the first location printed for that dropped quote was an\n * \"unexpected character\" twelve lines BELOW it, where the runaway string ended,\n * while the parser's errors two lines below it came after. The sort is stable,\n * so diagnostics on one line keep LikeC4's order, and a list mixing documents\n * stays in line order within each of them — every loader groups by document\n * after this, which is why sorting by line alone is enough. A diagnostic with\n * no line is about the document as a whole and leads.\n *\n * Applied where `getErrors()` is read (`loadSource`, `./workspace.ts`,\n * `./project/load.ts`), so every loader hands every reader the same list and\n * test/likec4-batch-parity.test.ts can keep asserting the two modes equal.\n */\nexport function distinctErrors<E extends LikeC4Error>(errors: readonly E[]): E[] {\n const seen = new Set<string>();\n return errors\n .filter((e) => {\n const key = `${e.sourceFsPath ?? \"\"}\\0${e.line ?? \"\"}\\0${e.message}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n })\n .sort((a, b) => (a.line ?? -1) - (b.line ?? -1));\n}\n\n/** loam-neutral element view (flattened from the LikeC4 parsed model). */\nexport interface Elem {\n id: string;\n kind: string;\n title: string;\n description?: string;\n /**\n * The `services/<id>` directory this element stands for, from the element's\n * `metadata { service '...' }`. Absent on the elements nobody has bound —\n * see `elementService` for the fallback.\n */\n service?: DeclaredService;\n tags: string[];\n}\n\n/** loam-neutral relationship view. */\nexport interface Rel {\n source: string;\n target: string;\n title?: string;\n /** OpenAPI operationId this call uses, from the relationship's `metadata { op '...' }`. */\n op?: string;\n /**\n * AsyncAPI message this edge PRODUCES, from `metadata { publishes '...' }`.\n * Resolved against the edge SOURCE's own contract: a service publishes what it\n * declares an `action: send` for.\n */\n publishes?: string;\n /**\n * AsyncAPI message this edge CONSUMES, from `metadata { consumes '...' }`.\n * Two keys rather than one directional `message`, because the async spine is\n * not symmetric with the HTTP one: there the PROVIDER owns the contract and\n * every consumer is checked against it, while here the PRODUCER owns the\n * message and the consumer lives in another repository entirely. Which side of\n * an edge owes the declaration is read from the key AND the arrow: `consumes`\n * binds the TARGET, so a consume edge points away from the topic, at its\n * consumer (`./direction/direction.ts`; reversed, `spine.message-unbound`).\n */\n consumes?: string;\n tags: string[];\n}\n\nexport interface LoadedDoc {\n errors: LikeC4Error[];\n elements: Elem[];\n relationships: Rel[];\n /**\n * The document's `specification { }` block — what its KINDS declare, as\n * opposed to what its elements do. Optional because a document that did not\n * parse has none, and because the several `LoadedDoc` literals standing in for\n * an absent file (`show`'s missing model.likec4, `unreadableLandscape`) have\n * nothing to put here: a reader must treat \"absent\" and \"declares nothing\" the\n * same way. See `./parsed/specification.ts` for why loam reads it at all —\n * short version: since LikeC4 1.59.0 a kind can carry tags, and only the\n * specification can tell an inherited tag from an authored one.\n */\n specification?: DocSpecification;\n /**\n * The `dynamic view`s the document DECLARES — the ordered steps of a use\n * case, never a rendering (docs/DESIGN.md rule 26). Optional for exactly the\n * reason `specification` is: a document that did not parse has none, and the\n * several `LoadedDoc` literals standing in for an absent file have nothing to\n * put here. Absent and empty mean the same thing to every reader — no views\n * were declared, or none could be read — and neither is a finding: a fleet\n * that draws no diagrams owes loam no views block.\n */\n views?: ParsedView[];\n /**\n * The ids of every view the document AUTHORS, static ones included — a census,\n * not a read of what any of them shows. Separate from `views` above because\n * the two answer different questions off different filters (see\n * `./parsed/view-ids.ts`), and because a static view contributes an id and\n * nothing else loam may look at.\n */\n viewIds?: ViewIdClaim[];\n /**\n * The ids of every GLOBAL STYLE the document declares — `global { styleGroup\n * <id> { … } }` and the single-rule `global { style <id> … }` alike, since\n * LikeC4 files both under one id table (hence not `styleGroups`). A\n * declaration census exactly as `viewIds` is: the ids, sorted, and never a\n * rule inside one (docs/DESIGN.md rule 26 says why a style is a rendering\n * instruction loam may not read). One consumer — the generated subsystem\n * views, which reference the group named `subsystems` when it is declared\n * and nothing otherwise, because a reference to an undeclared id is a parse\n * error that blanks the whole `architecture/` project in the renderer.\n * Optional for the reason `views` is: a document that did not parse has\n * none, and the `LoadedDoc` literals standing in for an absent file have\n * nothing to put here; absent and empty mean the same thing to every reader.\n */\n globalStyles?: string[];\n /**\n * The `deployment { }` model the document declares — nodes, instances and the\n * edges between them (`./parsed/deployment.ts`). Optional for the reason\n * `views` is, and read the same way by every consumer: absent and empty mean\n * \"no topology\", and neither is a finding. A fleet that draws no deployment\n * owes loam none, which is also the whole opt-in the axis has.\n */\n deployment?: DeploymentModel;\n}\n\n/**\n * The slice of a LikeC4 model loam reads: elements and relationships, and on\n * each of those only id/kind/title/description/tags/metadata.\n *\n * It is a type of its own, rather than an inline cast at the one call site,\n * because BOTH of LikeC4's model stages expose exactly this slice — which is\n * what makes the cheap stage a safe substitute for the expensive one. The\n * substitution is pinned in test/likec4-model-parity.test.ts, which flattens\n * both stages through `flattenModel` below and compares the results.\n *\n * Views are deliberately NOT in this interface, even though loam does read them.\n * What this interface pins is the two-stage PARITY that makes the cheap stage a\n * safe substitute for the expensive one — and the stages are not claimed to\n * agree about views, nor need to: the parsed stage is the only one rule 26\n * permits. That read has its own adapter, `./parsed/dynamic-views.ts`.\n */\nexport interface ReadableModel {\n elements: () => Iterable<{\n id: string;\n kind: string;\n title: string;\n description?: unknown;\n tags?: readonly string[];\n metadata?: unknown;\n }>;\n relationships: () => Iterable<{\n source: { id: string };\n target: { id: string };\n title?: string | null;\n tags?: readonly string[];\n metadata?: unknown;\n }>;\n /**\n * The parsed `specification { }` block. Typed `unknown` and normalized by\n * `readSpecification` rather than described here, because it is NOT part of\n * the two-stage parity this interface pins: the shape is LikeC4's internal\n * record (1.59.2 spells element-kind tags and relationship-kind tags\n * differently), and writing it out here would be a structural claim about a\n * dependency's internals that the compiler would then enforce against us.\n */\n specification?: unknown;\n}\n\n/** Flatten a LikeC4 model into loam's neutral `Elem`/`Rel` view. */\nexport function flattenModel(model: ReadableModel): { elements: Elem[]; relationships: Rel[] } {\n const elements: Elem[] = [...model.elements()].map((e) => {\n // The one crossing between LikeC4's parse output and loam's type system:\n // a `metadata { service '...' }` binding is text somebody wrote, and this\n // is where it acquires a type that says so.\n const bound = metaKey(e.metadata, \"service\");\n return {\n id: e.id,\n kind: e.kind,\n title: e.title,\n description: descText(e.description),\n ...(bound === undefined ? {} : { service: declaredService(bound) }),\n tags: [...(e.tags ?? [])],\n };\n });\n const relationships: Rel[] = [...model.relationships()]\n .map((r) => ({\n source: r.source.id,\n target: r.target.id,\n // LikeC4 reports an untitled edge as title: null — normalize to the declared `title?: string`.\n title: r.title ?? undefined,\n op: metaKey(r.metadata, \"op\"),\n publishes: metaKey(r.metadata, \"publishes\"),\n consumes: metaKey(r.metadata, \"consumes\"),\n tags: [...(r.tags ?? [])],\n }))\n // One order for every run and machine: `compareRels` (./parsed/values.ts) says why LikeC4 gives none.\n .sort(compareRels);\n return { elements, relationships };\n}\n\n/**\n * Load and validate a single self-contained `.likec4` document, in-process\n * (no external tool, no JVM). Returns validation errors and, if clean, the\n * flattened elements + relationships.\n */\nexport async function loadFile(path: string): Promise<LoadedDoc> {\n return loadSource(await readFile(path, \"utf8\"));\n}\n\n/**\n * `loadFile` for text that is not (yet) on disk — what the archive merge uses\n * to prove a computed landscape parses BEFORE anything is written.\n */\nexport async function loadSource(src: string): Promise<LoadedDoc> {\n // LikeC4 owns a Langium workspace and registers a process-exit listener for\n // it. Validation creates many short-lived instances, so every acquired\n // instance must be disposed even on an invalid document or a failed model\n // computation. Its logger is disabled because diagnostics are returned in\n // LoadedDoc instead of being written out-of-band to stderr.\n const likec4 = await LikeC4.fromSource(src, { logger: false });\n try {\n // Assigned, not cast: LikeC4 declares `getErrors()` as a non-nullable array\n // whose element type is structurally wider than ours, so the compiler can\n // check the shape here. The cast was the only thing standing between a\n // dependency renaming `message` and a build that still succeeded — and the\n // `?? []` it carried could never fire. Through `distinctErrors`, as every\n // loader's diagnostics are, so this one agrees with the batch loader.\n const errors: LikeC4Error[] = distinctErrors(likec4.getErrors());\n if (errors.length > 0) {\n return { errors, elements: [], relationships: [] };\n }\n\n // `parsedModel`, not `computedModel`: the computed stage RESOLVES every\n // view — expanding its predicates against the model and deriving the\n // ancestor edges a diagram needs (and computing a default view when the\n // document declares none). loam reads what a view DECLARES and never what a\n // view SHOWS (docs/DESIGN.md rule 26), so none of that resolution is ever\n // wanted; it renders nothing. That work is superlinear in the number of\n // RELATIONSHIPS, so a landscape at fleet shape turned `loam list` from under\n // a second into minutes. The elements and relationships below are identical\n // either way. The `await` is load-bearing for anything reading `$data`: it is\n // undefined on the unresolved promise.\n return cleanDoc((await likec4.parsedModel()) as ReadableModel);\n } finally {\n await likec4.dispose();\n }\n}\n\n/**\n * Everything loam reads out of one document that parsed clean, from LikeC4's\n * parsed stage. Shared with `./workspace.ts`'s batch loader, which used to\n * spell the same six reads out again: an adapter wired into one loader and not\n * the other reads as an absence rather than an error, the failure\n * test/likec4-batch-parity.test.ts exists to catch. `./project/load.ts`'s\n * `cleanProjectDoc` wraps the same reads in a project's record, whose error\n * shape differs and which requires the fields `LoadedDoc` leaves optional.\n */\nexport function cleanDoc(model: ReadableModel): LoadedDoc {\n return { errors: [], ...readParsedModel(model) };\n}\n\n/**\n * The six reads themselves — one spelling under every loader (`cleanDoc`\n * above, `./project/load.ts`'s `cleanProjectDoc`), so the parity test guards\n * one function rather than a convention. The return type is inferred on\n * purpose: it is `LoadedDoc` minus `errors` with every read PRESENT, which is\n * what lets a project's record, whose fields are required, spread it.\n */\nexport function readParsedModel(model: ReadableModel) {\n return {\n specification: readSpecification(model.specification),\n views: readDynamicViews(model),\n viewIds: readViewIds(model),\n globalStyles: readGlobalStyleIds(model),\n deployment: readDeployment(model),\n ...flattenModel(model),\n };\n}\n"]}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the parsed model declares and the splice map cannot locate — named the
|
|
3
|
+
* way an author can act on it.
|
|
4
|
+
*
|
|
5
|
+
* The archive splices the landscape by its text scan (`../source-scan.ts`) and
|
|
6
|
+
* refuses rather than splice around a declaration the scan cannot see. That
|
|
7
|
+
* refusal used to guess its cause: "most often two declarations sharing one
|
|
8
|
+
* line", whatever the map held. A fleet on 0.2.0-alpha.7 read it over a
|
|
9
|
+
* standalone declaration on a line of its own — the scan was blind to a second
|
|
10
|
+
* `model { }` block — and was asked to rewrite a valid map to satisfy a message
|
|
11
|
+
* that described something else. So the cause is no longer guessed where it can
|
|
12
|
+
* be read: LikeC4's own locator says on which line the declaration is, the
|
|
13
|
+
* line itself says whether anything but the declaration's own lead (`Lead`)
|
|
14
|
+
* precedes it there, and the scan says what it read in that place instead.
|
|
15
|
+
*
|
|
16
|
+
* A second parse of the landscape, and it is paid only on the refusal path —
|
|
17
|
+
* the merge decides THAT something is unlocated from the parse it already has,
|
|
18
|
+
* and asks this module only for the words.
|
|
19
|
+
*/
|
|
20
|
+
import { LikeC4 } from "likec4";
|
|
21
|
+
import { maskSource } from "../source-mask.js";
|
|
22
|
+
/**
|
|
23
|
+
* The first declaration of `text` that `scan` does not locate — elements in
|
|
24
|
+
* the parser's order, then relationships in document order; null when every
|
|
25
|
+
* one is located.
|
|
26
|
+
*
|
|
27
|
+
* An element is located when the scan holds its id. A relationship has no id
|
|
28
|
+
* the text can carry, so it is located by POSITION: LikeC4 places each edge at
|
|
29
|
+
* its arrow, and each scanned statement may stand for one edge — the second
|
|
30
|
+
* arrow inside one scanned span is the edge the scan swallowed.
|
|
31
|
+
*/
|
|
32
|
+
export async function firstUnlocated(text, scan) {
|
|
33
|
+
const likec4 = await LikeC4.fromSource(text, { logger: false });
|
|
34
|
+
try {
|
|
35
|
+
const model = await likec4.parsedModel();
|
|
36
|
+
const where = placer(text, scan);
|
|
37
|
+
const scanned = new Set(scan.elements.map((e) => e.id));
|
|
38
|
+
for (const e of model.elements()) {
|
|
39
|
+
if (scanned.has(e.id))
|
|
40
|
+
continue;
|
|
41
|
+
return { kind: "element", name: e.id, ...where.place(likec4.languageServices.locate({ element: e.id })?.range.start, { kind: e.kind }) };
|
|
42
|
+
}
|
|
43
|
+
const edges = [...model.relationships()].map((r) => {
|
|
44
|
+
const start = likec4.languageServices.locate({ relation: r.id })?.range.start;
|
|
45
|
+
return { name: `${r.source.id} -> ${r.target.id}`, start, offset: start === undefined ? -1 : where.offset(start) };
|
|
46
|
+
});
|
|
47
|
+
const claimed = new Set();
|
|
48
|
+
for (const edge of edges.sort((a, b) => a.offset - b.offset)) {
|
|
49
|
+
if (edge.offset === -1)
|
|
50
|
+
continue;
|
|
51
|
+
const span = scan.rels.findIndex((s) => edge.offset >= s.start && edge.offset < s.end);
|
|
52
|
+
if (span !== -1 && !claimed.has(span)) {
|
|
53
|
+
claimed.add(span);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
return { kind: "relationship", name: edge.name, ...where.place(edge.start, "edge") };
|
|
57
|
+
}
|
|
58
|
+
// Every located edge has a statement of its own: an unlocated one, if the
|
|
59
|
+
// count says there is one, is among those the locator could not place.
|
|
60
|
+
const lost = edges.find((edge) => edge.offset === -1);
|
|
61
|
+
return lost === undefined ? null : { kind: "relationship", name: lost.name };
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
await likec4.dispose();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** A whole token — not the tail of a longer id — directly before the anchor, the kind written there. */
|
|
68
|
+
const ELEMENT_LEAD = /(?<![\w.-])([A-Za-z_][\w-]*)\s*$/;
|
|
69
|
+
/** An optional source reference and an optional `-[`, directly before the anchor; always matches, possibly empty. */
|
|
70
|
+
const EDGE_LEAD = /(?<![\w.-])(?:[A-Za-z_][\w.-]*\s*)?(?:-\[\s*)?$/;
|
|
71
|
+
/**
|
|
72
|
+
* Where the declaration anchored at `at` starts, in the masked `code` of the
|
|
73
|
+
* line starting at `from`: before its lead when the code there ends in one,
|
|
74
|
+
* else `at`. Masked, a literal or a URI is blank, so the word before one reads
|
|
75
|
+
* as an edge's source here exactly as `relationHead` reads it in the scan
|
|
76
|
+
* (`link https://… -> zulu` is `link -> zulu` to both). Such a line is a
|
|
77
|
+
* scanned edge of its own, so its edge is unlocated only when an earlier
|
|
78
|
+
* statement's span ran on over it — and then the line-break explanation is
|
|
79
|
+
* the one to give, which is what dropping that word leads to.
|
|
80
|
+
*/
|
|
81
|
+
function leadStart(code, span, lead) {
|
|
82
|
+
const before = code.slice(span.from, span.at);
|
|
83
|
+
const m = lead === "edge" ? EDGE_LEAD.exec(before) : ELEMENT_LEAD.exec(before);
|
|
84
|
+
return m === null || (lead !== "edge" && m[1] !== lead.kind) ? span.at : span.from + m.index;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Reads a position against the text and the scan. Lines are split the way LSP
|
|
88
|
+
* counts them — `\r\n`, `\r` or `\n` — because that is the count LikeC4's
|
|
89
|
+
* positions are in. A bare carriage return used to be the one break the scan
|
|
90
|
+
* did not make, and so the cause the "read it as part of" words were written
|
|
91
|
+
* for; `statementHead` breaks there too now, and the words stay for whatever
|
|
92
|
+
* run-on the scan has next.
|
|
93
|
+
*/
|
|
94
|
+
function placer(text, scan) {
|
|
95
|
+
const starts = [0];
|
|
96
|
+
for (const m of text.matchAll(/\r\n|\r|\n/g))
|
|
97
|
+
starts.push(m.index + m[0].length);
|
|
98
|
+
const lineOf = (offset) => starts.findLastIndex((s) => s <= offset) + 1;
|
|
99
|
+
const { code } = maskSource(text);
|
|
100
|
+
const offset = (start) => (starts[start.line] ?? text.length) + start.character;
|
|
101
|
+
const heads = [
|
|
102
|
+
...scan.elements
|
|
103
|
+
.filter((e) => e.extend !== true)
|
|
104
|
+
.map((e) => ({ name: `'${e.id}'`, start: e.start, end: e.bodyOpen === -1 ? e.end : e.bodyOpen })),
|
|
105
|
+
...scan.rels.map((r) => ({ name: `the edge '${r.source} -> ${r.target}'`, start: r.start, end: r.end })),
|
|
106
|
+
];
|
|
107
|
+
const place = (start, lead) => {
|
|
108
|
+
if (start === undefined)
|
|
109
|
+
return {};
|
|
110
|
+
const at = offset(start);
|
|
111
|
+
const from = starts[start.line] ?? at;
|
|
112
|
+
// Measured from where the declaration starts, not from the anchor: its own
|
|
113
|
+
// kind keyword or source is no other statement (`Lead`).
|
|
114
|
+
const before = code.slice(from, leadStart(code, { from, at }, lead));
|
|
115
|
+
// Innermost first: a nested declaration's span lies inside its parent's.
|
|
116
|
+
const cover = heads.filter((h) => at >= h.start && at < h.end).sort((a, b) => b.start - a.start)[0];
|
|
117
|
+
return {
|
|
118
|
+
line: start.line + 1,
|
|
119
|
+
...(/\S/.test(before) ? { sharesLine: true } : {}),
|
|
120
|
+
...(cover === undefined ? {} : { readAs: { name: cover.name, line: lineOf(cover.start) } }),
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
return { place, offset };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The refusal's words for one unlocated declaration of `file`. A shared line
|
|
127
|
+
* is named only when the line shows one, and the statement the scan read
|
|
128
|
+
* instead only when it read one: a guess at the cause is the message this
|
|
129
|
+
* replaced.
|
|
130
|
+
*/
|
|
131
|
+
export function unlocatedReason(file, gap) {
|
|
132
|
+
const remedy = "nothing was written; rewrite it on a line of its own as `name = kind 'title' {` (an edge as `a -> b 'title'`) and re-run — " +
|
|
133
|
+
"and report the original shape: LikeC4 parses it, so it is a form the splice map should read";
|
|
134
|
+
if (gap === null)
|
|
135
|
+
return `${file} declares more than placement can locate, and LikeC4's locator could not say where — ${remedy}`;
|
|
136
|
+
const what = `${file} declares ${gap.kind === "element" ? `'${gap.name}'` : `the relationship '${gap.name}'`}`;
|
|
137
|
+
const where = gap.line === undefined ? "" : ` at line ${gap.line}`;
|
|
138
|
+
const read = gap.readAs;
|
|
139
|
+
if (gap.sharesLine === true) {
|
|
140
|
+
const other = read === undefined ? "the statement before it" : read.name;
|
|
141
|
+
return (`${what}${where} in a form placement cannot locate: it shares that line with ${other}, and the splice map reads ` +
|
|
142
|
+
`one statement per line where LikeC4 accepts two — give each its own line, then re-run`);
|
|
143
|
+
}
|
|
144
|
+
if (read !== undefined) {
|
|
145
|
+
return (`${what}${where} in a form placement cannot locate: the splice map read it as part of ${read.name}, which starts at ` +
|
|
146
|
+
`line ${read.line} — it ran that statement on past a line break LikeC4 makes — ${remedy}`);
|
|
147
|
+
}
|
|
148
|
+
return `${what}${where} in a form placement cannot locate, and the splice map read no statement there — ${remedy}`;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=unlocated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unlocated.js","sourceRoot":"","sources":["../../../../src/core/c4/locate/unlocated.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the parsed model declares and the splice map cannot locate — named the\n * way an author can act on it.\n *\n * The archive splices the landscape by its text scan (`../source-scan.ts`) and\n * refuses rather than splice around a declaration the scan cannot see. That\n * refusal used to guess its cause: \"most often two declarations sharing one\n * line\", whatever the map held. A fleet on 0.2.0-alpha.7 read it over a\n * standalone declaration on a line of its own — the scan was blind to a second\n * `model { }` block — and was asked to rewrite a valid map to satisfy a message\n * that described something else. So the cause is no longer guessed where it can\n * be read: LikeC4's own locator says on which line the declaration is, the\n * line itself says whether anything but the declaration's own lead (`Lead`)\n * precedes it there, and the scan says what it read in that place instead.\n *\n * A second parse of the landscape, and it is paid only on the refusal path —\n * the merge decides THAT something is unlocated from the parse it already has,\n * and asks this module only for the words.\n */\nimport { LikeC4 } from \"likec4\";\nimport { maskSource } from \"../source-mask.js\";\nimport type { ScannedModel } from \"../source-scan.js\";\n\n/** One declaration the parser has and the scan cannot place. */\nexport interface Unlocated {\n kind: \"element\" | \"relationship\";\n /** The element's id, or the relationship as `source -> target`, as the parser resolved them. */\n name: string;\n /** 1-based line LikeC4's locator puts the declaration on; absent when it has no answer. */\n line?: number;\n /**\n * Code other than the declaration's own lead precedes it on its own line —\n * the shared line is then a FACT, not a guess.\n */\n sharesLine?: true;\n /** The scanned statement that covers where the declaration sits, and the line that statement starts on. */\n readAs?: { name: string; line: number };\n}\n\n/**\n * The first declaration of `text` that `scan` does not locate — elements in\n * the parser's order, then relationships in document order; null when every\n * one is located.\n *\n * An element is located when the scan holds its id. A relationship has no id\n * the text can carry, so it is located by POSITION: LikeC4 places each edge at\n * its arrow, and each scanned statement may stand for one edge — the second\n * arrow inside one scanned span is the edge the scan swallowed.\n */\nexport async function firstUnlocated(text: string, scan: ScannedModel): Promise<Unlocated | null> {\n const likec4 = await LikeC4.fromSource(text, { logger: false });\n try {\n const model = await likec4.parsedModel();\n const where = placer(text, scan);\n const scanned = new Set(scan.elements.map((e) => e.id));\n for (const e of model.elements()) {\n if (scanned.has(e.id)) continue;\n return { kind: \"element\", name: e.id, ...where.place(likec4.languageServices.locate({ element: e.id })?.range.start, { kind: e.kind }) };\n }\n const edges = [...model.relationships()].map((r) => {\n const start = likec4.languageServices.locate({ relation: r.id })?.range.start;\n return { name: `${r.source.id} -> ${r.target.id}`, start, offset: start === undefined ? -1 : where.offset(start) };\n });\n const claimed = new Set<number>();\n for (const edge of edges.sort((a, b) => a.offset - b.offset)) {\n if (edge.offset === -1) continue;\n const span = scan.rels.findIndex((s) => edge.offset >= s.start && edge.offset < s.end);\n if (span !== -1 && !claimed.has(span)) {\n claimed.add(span);\n continue;\n }\n return { kind: \"relationship\", name: edge.name, ...where.place(edge.start, \"edge\") };\n }\n // Every located edge has a statement of its own: an unlocated one, if the\n // count says there is one, is among those the locator could not place.\n const lost = edges.find((edge) => edge.offset === -1);\n return lost === undefined ? null : { kind: \"relationship\", name: lost.name };\n } finally {\n await likec4.dispose();\n }\n}\n\n/** An LSP position: a 0-based line and a character within it. */\ninterface Position {\n line: number;\n character: number;\n}\n\n/**\n * The part of a declaration LikeC4's locator leaves BEFORE its anchor. It\n * points an element at its NAME and a relationship at its ARROW — inside\n * `-[…]->`, at the kind — so `container api 'API'` has its kind keyword in\n * front of the anchor and `zulu -> apple` its source. Read as \"code before\n * it\", every unlocated edge and every `kind name` element shared its line with\n * itself, and the line-break explanation `unlocatedReason` holds below the\n * shared-line one was never reached. An element's lead is a token equal to\n * its parsed kind; an edge's is its source reference (`it`, a dotted path or\n * none) and the `-[` opening a bracketed kind.\n */\ntype Lead = { kind: string } | \"edge\";\n\n/** A whole token — not the tail of a longer id — directly before the anchor, the kind written there. */\nconst ELEMENT_LEAD = /(?<![\\w.-])([A-Za-z_][\\w-]*)\\s*$/;\n/** An optional source reference and an optional `-[`, directly before the anchor; always matches, possibly empty. */\nconst EDGE_LEAD = /(?<![\\w.-])(?:[A-Za-z_][\\w.-]*\\s*)?(?:-\\[\\s*)?$/;\n\n/**\n * Where the declaration anchored at `at` starts, in the masked `code` of the\n * line starting at `from`: before its lead when the code there ends in one,\n * else `at`. Masked, a literal or a URI is blank, so the word before one reads\n * as an edge's source here exactly as `relationHead` reads it in the scan\n * (`link https://… -> zulu` is `link -> zulu` to both). Such a line is a\n * scanned edge of its own, so its edge is unlocated only when an earlier\n * statement's span ran on over it — and then the line-break explanation is\n * the one to give, which is what dropping that word leads to.\n */\nfunction leadStart(code: string, span: { from: number; at: number }, lead: Lead): number {\n const before = code.slice(span.from, span.at);\n const m = lead === \"edge\" ? EDGE_LEAD.exec(before) : ELEMENT_LEAD.exec(before);\n return m === null || (lead !== \"edge\" && m[1] !== lead.kind) ? span.at : span.from + m.index;\n}\n\n/** Everything a position tells about a declaration, and the offset arithmetic that is built on. */\ninterface Placer {\n place: (start: Position | undefined, lead: Lead) => Pick<Unlocated, \"line\" | \"sharesLine\" | \"readAs\">;\n offset: (start: Position) => number;\n}\n\n/**\n * Reads a position against the text and the scan. Lines are split the way LSP\n * counts them — `\\r\\n`, `\\r` or `\\n` — because that is the count LikeC4's\n * positions are in. A bare carriage return used to be the one break the scan\n * did not make, and so the cause the \"read it as part of\" words were written\n * for; `statementHead` breaks there too now, and the words stay for whatever\n * run-on the scan has next.\n */\nfunction placer(text: string, scan: ScannedModel): Placer {\n const starts = [0];\n for (const m of text.matchAll(/\\r\\n|\\r|\\n/g)) starts.push(m.index + m[0].length);\n const lineOf = (offset: number): number => starts.findLastIndex((s) => s <= offset) + 1;\n const { code } = maskSource(text);\n const offset = (start: Position): number => (starts[start.line] ?? text.length) + start.character;\n const heads = [\n ...scan.elements\n .filter((e) => e.extend !== true)\n .map((e) => ({ name: `'${e.id}'`, start: e.start, end: e.bodyOpen === -1 ? e.end : e.bodyOpen })),\n ...scan.rels.map((r) => ({ name: `the edge '${r.source} -> ${r.target}'`, start: r.start, end: r.end })),\n ];\n const place = (start: Position | undefined, lead: Lead): Pick<Unlocated, \"line\" | \"sharesLine\" | \"readAs\"> => {\n if (start === undefined) return {};\n const at = offset(start);\n const from = starts[start.line] ?? at;\n // Measured from where the declaration starts, not from the anchor: its own\n // kind keyword or source is no other statement (`Lead`).\n const before = code.slice(from, leadStart(code, { from, at }, lead));\n // Innermost first: a nested declaration's span lies inside its parent's.\n const cover = heads.filter((h) => at >= h.start && at < h.end).sort((a, b) => b.start - a.start)[0];\n return {\n line: start.line + 1,\n ...(/\\S/.test(before) ? { sharesLine: true as const } : {}),\n ...(cover === undefined ? {} : { readAs: { name: cover.name, line: lineOf(cover.start) } }),\n };\n };\n return { place, offset };\n}\n\n/**\n * The refusal's words for one unlocated declaration of `file`. A shared line\n * is named only when the line shows one, and the statement the scan read\n * instead only when it read one: a guess at the cause is the message this\n * replaced.\n */\nexport function unlocatedReason(file: string, gap: Unlocated | null): string {\n const remedy =\n \"nothing was written; rewrite it on a line of its own as `name = kind 'title' {` (an edge as `a -> b 'title'`) and re-run — \" +\n \"and report the original shape: LikeC4 parses it, so it is a form the splice map should read\";\n if (gap === null) return `${file} declares more than placement can locate, and LikeC4's locator could not say where — ${remedy}`;\n const what = `${file} declares ${gap.kind === \"element\" ? `'${gap.name}'` : `the relationship '${gap.name}'`}`;\n const where = gap.line === undefined ? \"\" : ` at line ${gap.line}`;\n const read = gap.readAs;\n if (gap.sharesLine === true) {\n const other = read === undefined ? \"the statement before it\" : read.name;\n return (\n `${what}${where} in a form placement cannot locate: it shares that line with ${other}, and the splice map reads ` +\n `one statement per line where LikeC4 accepts two — give each its own line, then re-run`\n );\n }\n if (read !== undefined) {\n return (\n `${what}${where} in a form placement cannot locate: the splice map read it as part of ${read.name}, which starts at ` +\n `line ${read.line} — it ran that statement on past a line break LikeC4 makes — ${remedy}`\n );\n }\n return `${what}${where} in a form placement cannot locate, and the splice map read no statement there — ${remedy}`;\n}\n"]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The DEPLOYMENT model a document declares — which physical nodes exist, which
|
|
3
|
+
* containers are instanced where, and what talks to what across them.
|
|
4
|
+
*
|
|
5
|
+
* A `deployment { }` block has been legal in a docs repo since LikeC4 could
|
|
6
|
+
* parse one, and until this reader existed loam saw none of it. The parser
|
|
7
|
+
* resolved every `instanceOf` — so a container renamed out from under a
|
|
8
|
+
* deployment node already failed the gate — and after that no requirement could
|
|
9
|
+
* name a node, no `#obl-` tag on a datacenter was graded, and the context pack
|
|
10
|
+
* an agent implements from did not mention topology at all. Integrity held at
|
|
11
|
+
* the level of syntax and was absent at the level of requirements. ROADMAP's
|
|
12
|
+
* deployment axis and `meta/docs/features/FEAT-1-the-deployment-axis/` are the
|
|
13
|
+
* item and the specification; this module is its first half.
|
|
14
|
+
*
|
|
15
|
+
* ## Why this is a `parsed/` reader and not a package of its own
|
|
16
|
+
*
|
|
17
|
+
* It is the same job the three modules beside it do: take one corner of
|
|
18
|
+
* LikeC4's parse output and hand back a loam-neutral record, defensively, with
|
|
19
|
+
* its shape assumptions owned outright. `readSpecification`, `readDynamicViews`
|
|
20
|
+
* and `readViewIds` are all called on the line above `flattenModel(model)` in
|
|
21
|
+
* each of loam's three loaders, and so is this. FEAT-1's delta said
|
|
22
|
+
* `src/core/c4/deploy/`; a package holding this alone would be a directory
|
|
23
|
+
* pretending to be a subject (docs/DESIGN.md), and the delta was corrected
|
|
24
|
+
* rather than the code bent to it — which is what an unarchived feature is for.
|
|
25
|
+
*
|
|
26
|
+
* **`parsed/` is still AT its five-file limit.** The global style-id census
|
|
27
|
+
* rode into `view-ids.ts` because it IS that module's subject — one more
|
|
28
|
+
* table asked the same question — and the next reader that is not a census
|
|
29
|
+
* still needs the split first. The seam to split on is the one this file does
|
|
30
|
+
* not share: `dynamic-views.ts` and `view-ids.ts` read `$data`, this one and
|
|
31
|
+
* `specification.ts` read the model surface.
|
|
32
|
+
*
|
|
33
|
+
* ## What is read, and what is deliberately left
|
|
34
|
+
*
|
|
35
|
+
* Nodes, instances and relationships, with the ids, titles and tags each
|
|
36
|
+
* carries. MEASURED at the 1.59.2 pin, and every line of it needed measuring
|
|
37
|
+
* rather than assuming:
|
|
38
|
+
*
|
|
39
|
+
* - `nodes()` returns deployment NODES only — an `instanceOf` is not among
|
|
40
|
+
* them, which is why instances are a second list rather than a filter.
|
|
41
|
+
* - an instance carries the LOGICAL element it deploys as `element.id`, and
|
|
42
|
+
* that is the whole join back to the C4 model: `eu.a.dbA -> orders.db`.
|
|
43
|
+
* - both nodes and instances carry `tags`, so `#obl-geo` on a datacenter is
|
|
44
|
+
* readable — the fail-open case that made this an item.
|
|
45
|
+
* - a relationship carries `tags` and `metadata` DIRECTLY (`r.metadata`, no
|
|
46
|
+
* `$relationship` indirection), and both model stages return byte-identical
|
|
47
|
+
* results, which is what lets `test/likec4-model-parity.test.ts` cover this
|
|
48
|
+
* read with the substitution it already pins.
|
|
49
|
+
* - a document with NO `deployment { }` block still returns a deployment
|
|
50
|
+
* object whose three iterators are empty. Absent and empty are therefore the
|
|
51
|
+
* same answer here, deliberately: no reader may distinguish "declares none"
|
|
52
|
+
* from "could not be read", because the second is what the defensive returns
|
|
53
|
+
* below produce and a fleet that draws no topology owes loam nothing.
|
|
54
|
+
*
|
|
55
|
+
* `metadata` is NOT carried on the records below, and neither is an instance's
|
|
56
|
+
* `kind`. Both are readable; no check reads them yet, and a field carried
|
|
57
|
+
* before a caller needs it is a field nobody notices going wrong. Add one with
|
|
58
|
+
* the check that consumes it.
|
|
59
|
+
*/
|
|
60
|
+
/** No topology — what an absent block and an unreadable one both come back as. */
|
|
61
|
+
export const NO_DEPLOYMENT = { nodes: [], instances: [], relationships: [] };
|
|
62
|
+
/** Is there anything here? The opt-in every deployment check is gated on. */
|
|
63
|
+
export function hasDeployment(d) {
|
|
64
|
+
return d.nodes.length > 0 || d.instances.length > 0 || d.relationships.length > 0;
|
|
65
|
+
}
|
|
66
|
+
/** A record, or nothing — the parse surface hands back `unknown`. */
|
|
67
|
+
function record(v) {
|
|
68
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : undefined;
|
|
69
|
+
}
|
|
70
|
+
/** An iterable produced by `name()`, or an empty one when the surface is not what we measured. */
|
|
71
|
+
function iterate(source, name) {
|
|
72
|
+
const fn = source[name];
|
|
73
|
+
if (typeof fn !== "function")
|
|
74
|
+
return [];
|
|
75
|
+
try {
|
|
76
|
+
const out = fn.call(source);
|
|
77
|
+
// A generator satisfies this; so does an array. Anything else is a shape
|
|
78
|
+
// change upstream, and the honest answer to one is "no topology read".
|
|
79
|
+
return out !== null && typeof out === "object" && Symbol.iterator in out
|
|
80
|
+
? [...out]
|
|
81
|
+
: [];
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** A string field, or the empty string — never `undefined` leaking into a record. */
|
|
88
|
+
function str(o, key) {
|
|
89
|
+
const v = o[key];
|
|
90
|
+
return typeof v === "string" ? v : "";
|
|
91
|
+
}
|
|
92
|
+
/** Tags as loam models them: a plain array of strings, always present. */
|
|
93
|
+
function tags(o) {
|
|
94
|
+
const v = o["tags"];
|
|
95
|
+
return Array.isArray(v) ? v.filter((t) => typeof t === "string") : [];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read the deployment model off an awaited `parsedModel()`.
|
|
99
|
+
*
|
|
100
|
+
* Defensive throughout, in the shape `readViewIds` established: an entry
|
|
101
|
+
* missing the one field that identifies it is DROPPED rather than reported with
|
|
102
|
+
* a hole, and a surface that is not what was measured yields an empty model
|
|
103
|
+
* instead of throwing. A check that cannot see the topology must say
|
|
104
|
+
* could-not-look through its own silence, never fail the fleet's parse.
|
|
105
|
+
*/
|
|
106
|
+
export function readDeployment(model) {
|
|
107
|
+
const root = record(model);
|
|
108
|
+
if (root === undefined)
|
|
109
|
+
return NO_DEPLOYMENT;
|
|
110
|
+
const deployment = record(root["deployment"]);
|
|
111
|
+
if (deployment === undefined)
|
|
112
|
+
return NO_DEPLOYMENT;
|
|
113
|
+
const nodes = [];
|
|
114
|
+
for (const raw of iterate(deployment, "nodes")) {
|
|
115
|
+
const n = record(raw);
|
|
116
|
+
if (n === undefined)
|
|
117
|
+
continue;
|
|
118
|
+
const id = str(n, "id");
|
|
119
|
+
if (id === "")
|
|
120
|
+
continue;
|
|
121
|
+
nodes.push({ id, kind: str(n, "kind"), title: str(n, "title"), tags: tags(n) });
|
|
122
|
+
}
|
|
123
|
+
const instances = [];
|
|
124
|
+
for (const raw of iterate(deployment, "instances")) {
|
|
125
|
+
const i = record(raw);
|
|
126
|
+
if (i === undefined)
|
|
127
|
+
continue;
|
|
128
|
+
const id = str(i, "id");
|
|
129
|
+
// The logical element is the whole point of the record. An instance whose
|
|
130
|
+
// element cannot be read joins to nothing, so reporting it would put a
|
|
131
|
+
// deployed thing on the map that no requirement could ever cover.
|
|
132
|
+
const element = record(i["element"]);
|
|
133
|
+
if (id === "" || element === undefined)
|
|
134
|
+
continue;
|
|
135
|
+
const elementId = str(element, "id");
|
|
136
|
+
if (elementId === "")
|
|
137
|
+
continue;
|
|
138
|
+
instances.push({ id, element: elementId, title: str(i, "title"), tags: tags(i) });
|
|
139
|
+
}
|
|
140
|
+
const relationships = [];
|
|
141
|
+
for (const raw of iterate(deployment, "relationships")) {
|
|
142
|
+
const r = record(raw);
|
|
143
|
+
if (r === undefined)
|
|
144
|
+
continue;
|
|
145
|
+
const source = record(r["source"]);
|
|
146
|
+
const target = record(r["target"]);
|
|
147
|
+
if (source === undefined || target === undefined)
|
|
148
|
+
continue;
|
|
149
|
+
const from = str(source, "id");
|
|
150
|
+
const to = str(target, "id");
|
|
151
|
+
if (from === "" || to === "")
|
|
152
|
+
continue;
|
|
153
|
+
// LikeC4 reports an untitled edge as `title: null` — normalized to the
|
|
154
|
+
// declared optional exactly as `flattenModel` does for the logical model.
|
|
155
|
+
const title = typeof r["title"] === "string" ? r["title"] : undefined;
|
|
156
|
+
relationships.push({ source: from, target: to, ...(title === undefined ? {} : { title }), tags: tags(r) });
|
|
157
|
+
}
|
|
158
|
+
return { nodes, instances, relationships };
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=deployment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../src/core/c4/parsed/deployment.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The DEPLOYMENT model a document declares — which physical nodes exist, which\n * containers are instanced where, and what talks to what across them.\n *\n * A `deployment { }` block has been legal in a docs repo since LikeC4 could\n * parse one, and until this reader existed loam saw none of it. The parser\n * resolved every `instanceOf` — so a container renamed out from under a\n * deployment node already failed the gate — and after that no requirement could\n * name a node, no `#obl-` tag on a datacenter was graded, and the context pack\n * an agent implements from did not mention topology at all. Integrity held at\n * the level of syntax and was absent at the level of requirements. ROADMAP's\n * deployment axis and `meta/docs/features/FEAT-1-the-deployment-axis/` are the\n * item and the specification; this module is its first half.\n *\n * ## Why this is a `parsed/` reader and not a package of its own\n *\n * It is the same job the three modules beside it do: take one corner of\n * LikeC4's parse output and hand back a loam-neutral record, defensively, with\n * its shape assumptions owned outright. `readSpecification`, `readDynamicViews`\n * and `readViewIds` are all called on the line above `flattenModel(model)` in\n * each of loam's three loaders, and so is this. FEAT-1's delta said\n * `src/core/c4/deploy/`; a package holding this alone would be a directory\n * pretending to be a subject (docs/DESIGN.md), and the delta was corrected\n * rather than the code bent to it — which is what an unarchived feature is for.\n *\n * **`parsed/` is still AT its five-file limit.** The global style-id census\n * rode into `view-ids.ts` because it IS that module's subject — one more\n * table asked the same question — and the next reader that is not a census\n * still needs the split first. The seam to split on is the one this file does\n * not share: `dynamic-views.ts` and `view-ids.ts` read `$data`, this one and\n * `specification.ts` read the model surface.\n *\n * ## What is read, and what is deliberately left\n *\n * Nodes, instances and relationships, with the ids, titles and tags each\n * carries. MEASURED at the 1.59.2 pin, and every line of it needed measuring\n * rather than assuming:\n *\n * - `nodes()` returns deployment NODES only — an `instanceOf` is not among\n * them, which is why instances are a second list rather than a filter.\n * - an instance carries the LOGICAL element it deploys as `element.id`, and\n * that is the whole join back to the C4 model: `eu.a.dbA -> orders.db`.\n * - both nodes and instances carry `tags`, so `#obl-geo` on a datacenter is\n * readable — the fail-open case that made this an item.\n * - a relationship carries `tags` and `metadata` DIRECTLY (`r.metadata`, no\n * `$relationship` indirection), and both model stages return byte-identical\n * results, which is what lets `test/likec4-model-parity.test.ts` cover this\n * read with the substitution it already pins.\n * - a document with NO `deployment { }` block still returns a deployment\n * object whose three iterators are empty. Absent and empty are therefore the\n * same answer here, deliberately: no reader may distinguish \"declares none\"\n * from \"could not be read\", because the second is what the defensive returns\n * below produce and a fleet that draws no topology owes loam nothing.\n *\n * `metadata` is NOT carried on the records below, and neither is an instance's\n * `kind`. Both are readable; no check reads them yet, and a field carried\n * before a caller needs it is a field nobody notices going wrong. Add one with\n * the check that consumes it.\n */\n\n/** One deployment node — a region, a datacenter, a cluster; the kinds are the fleet's own. */\nexport interface DeployNode {\n /** The dotted path LikeC4 gives it: `eu.dcA.k8sA`. */\n id: string;\n /** The `deploymentNode` kind the specification declares. */\n kind: string;\n title: string;\n tags: string[];\n}\n\n/** One deployed instance of a logical element. */\nexport interface DeployInstance {\n id: string;\n /**\n * The id of the C4 element this instance deploys — the join back to the\n * logical model, and the only reason an instance is worth reading at all.\n */\n element: string;\n title: string;\n tags: string[];\n}\n\n/** One edge between deployment objects — replication, failover, a network hop. */\nexport interface DeployRel {\n source: string;\n target: string;\n title?: string;\n tags: string[];\n}\n\n/** A document's whole deployment model, flattened. */\nexport interface DeploymentModel {\n nodes: DeployNode[];\n instances: DeployInstance[];\n relationships: DeployRel[];\n}\n\n/** No topology — what an absent block and an unreadable one both come back as. */\nexport const NO_DEPLOYMENT: DeploymentModel = { nodes: [], instances: [], relationships: [] };\n\n/** Is there anything here? The opt-in every deployment check is gated on. */\nexport function hasDeployment(d: DeploymentModel): boolean {\n return d.nodes.length > 0 || d.instances.length > 0 || d.relationships.length > 0;\n}\n\n/** A record, or nothing — the parse surface hands back `unknown`. */\nfunction record(v: unknown): Record<string, unknown> | undefined {\n return v && typeof v === \"object\" && !Array.isArray(v) ? (v as Record<string, unknown>) : undefined;\n}\n\n/** An iterable produced by `name()`, or an empty one when the surface is not what we measured. */\nfunction iterate(source: Record<string, unknown>, name: string): unknown[] {\n const fn = source[name];\n if (typeof fn !== \"function\") return [];\n try {\n const out: unknown = (fn as () => unknown).call(source);\n // A generator satisfies this; so does an array. Anything else is a shape\n // change upstream, and the honest answer to one is \"no topology read\".\n return out !== null && typeof out === \"object\" && Symbol.iterator in (out as object)\n ? [...(out as Iterable<unknown>)]\n : [];\n } catch {\n return [];\n }\n}\n\n/** A string field, or the empty string — never `undefined` leaking into a record. */\nfunction str(o: Record<string, unknown>, key: string): string {\n const v = o[key];\n return typeof v === \"string\" ? v : \"\";\n}\n\n/** Tags as loam models them: a plain array of strings, always present. */\nfunction tags(o: Record<string, unknown>): string[] {\n const v = o[\"tags\"];\n return Array.isArray(v) ? v.filter((t): t is string => typeof t === \"string\") : [];\n}\n\n/**\n * Read the deployment model off an awaited `parsedModel()`.\n *\n * Defensive throughout, in the shape `readViewIds` established: an entry\n * missing the one field that identifies it is DROPPED rather than reported with\n * a hole, and a surface that is not what was measured yields an empty model\n * instead of throwing. A check that cannot see the topology must say\n * could-not-look through its own silence, never fail the fleet's parse.\n */\nexport function readDeployment(model: unknown): DeploymentModel {\n const root = record(model);\n if (root === undefined) return NO_DEPLOYMENT;\n const deployment = record(root[\"deployment\"]);\n if (deployment === undefined) return NO_DEPLOYMENT;\n\n const nodes: DeployNode[] = [];\n for (const raw of iterate(deployment, \"nodes\")) {\n const n = record(raw);\n if (n === undefined) continue;\n const id = str(n, \"id\");\n if (id === \"\") continue;\n nodes.push({ id, kind: str(n, \"kind\"), title: str(n, \"title\"), tags: tags(n) });\n }\n\n const instances: DeployInstance[] = [];\n for (const raw of iterate(deployment, \"instances\")) {\n const i = record(raw);\n if (i === undefined) continue;\n const id = str(i, \"id\");\n // The logical element is the whole point of the record. An instance whose\n // element cannot be read joins to nothing, so reporting it would put a\n // deployed thing on the map that no requirement could ever cover.\n const element = record(i[\"element\"]);\n if (id === \"\" || element === undefined) continue;\n const elementId = str(element, \"id\");\n if (elementId === \"\") continue;\n instances.push({ id, element: elementId, title: str(i, \"title\"), tags: tags(i) });\n }\n\n const relationships: DeployRel[] = [];\n for (const raw of iterate(deployment, \"relationships\")) {\n const r = record(raw);\n if (r === undefined) continue;\n const source = record(r[\"source\"]);\n const target = record(r[\"target\"]);\n if (source === undefined || target === undefined) continue;\n const from = str(source, \"id\");\n const to = str(target, \"id\");\n if (from === \"\" || to === \"\") continue;\n // LikeC4 reports an untitled edge as `title: null` — normalized to the\n // declared optional exactly as `flattenModel` does for the logical model.\n const title = typeof r[\"title\"] === \"string\" ? r[\"title\"] : undefined;\n relationships.push({ source: from, target: to, ...(title === undefined ? {} : { title }), tags: tags(r) });\n }\n\n return { nodes, instances, relationships };\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `dynamic view`s a document DECLARES, read off LikeC4's parsed model.
|
|
3
|
+
*
|
|
4
|
+
* This is the only module in loam permitted to touch `$data`, and
|
|
5
|
+
* `scripts/arch-check.mjs` enforces that rather than trusting it (docs/DESIGN.md
|
|
6
|
+
* rule 26). The confinement is the point: `$data` is public and typed but thinly
|
|
7
|
+
* documented for this use, so an upstream shape change has a blast radius of one
|
|
8
|
+
* file, and `test/likec4-view-shape.test.ts` is the tripwire that fires before
|
|
9
|
+
* the change reaches a check.
|
|
10
|
+
*
|
|
11
|
+
* It takes the WHOLE model as `unknown` rather than a `$data` slice handed in by
|
|
12
|
+
* its caller, and that is not squeamishness — naming `$data` in `../likec4.ts`
|
|
13
|
+
* would violate the containment scan this module exists behind. Callers pass the
|
|
14
|
+
* model; every assumption about LikeC4's record shape lives here.
|
|
15
|
+
*
|
|
16
|
+
* Everything is defensive, in the same posture as `./specification.ts`: a shape
|
|
17
|
+
* this reader cannot make sense of degrades to ZERO views, never to a wrong one
|
|
18
|
+
* and never to a throw inside a validate run. That asymmetry is deliberate and
|
|
19
|
+
* is loam's standing rule for a suspended axis — a check with no views to grade
|
|
20
|
+
* reports could-not-look, while a check fed a half-read view would report
|
|
21
|
+
* nothing-wrong about a flow it never saw.
|
|
22
|
+
*/
|
|
23
|
+
import { descText } from "./values.js";
|
|
24
|
+
/** A record, or nothing — `v` is `unknown` off an untyped parse. */
|
|
25
|
+
function record(v) {
|
|
26
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : undefined;
|
|
27
|
+
}
|
|
28
|
+
/** The value at `key`, when it is a non-empty string. */
|
|
29
|
+
function str(rec, key) {
|
|
30
|
+
const v = rec[key];
|
|
31
|
+
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Every leaf step under `entries`, depth-first in author order.
|
|
35
|
+
*
|
|
36
|
+
* Steps NEST: a `loop 'until accepted' { ... }` arrives as an entry with
|
|
37
|
+
* `_type: "loop"`, a title, its own `steps[]`, and NO endpoints and NO `astPath`
|
|
38
|
+
* of its own (measured). A walk that treated every entry as a hop would read the
|
|
39
|
+
* bracket as a step and then fail to find a relationship backing it — inventing
|
|
40
|
+
* a finding out of a grouping the author drew for legibility.
|
|
41
|
+
*
|
|
42
|
+
* The test is structural rather than a list of group keywords (`loop`, `par`,
|
|
43
|
+
* ...): an entry with a nested `steps` array is a group whatever LikeC4 calls
|
|
44
|
+
* it, and an entry with two string endpoints is a hop. A future group kind
|
|
45
|
+
* therefore flattens correctly on the day it ships instead of on the day
|
|
46
|
+
* somebody notices.
|
|
47
|
+
*/
|
|
48
|
+
function leaves(entries, out) {
|
|
49
|
+
if (!Array.isArray(entries))
|
|
50
|
+
return;
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const rec = record(entry);
|
|
53
|
+
if (!rec)
|
|
54
|
+
continue;
|
|
55
|
+
if (Array.isArray(rec["steps"])) {
|
|
56
|
+
leaves(rec["steps"], out);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (typeof rec["source"] === "string" && typeof rec["target"] === "string")
|
|
60
|
+
out.push(rec);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** One leaf entry as a `ParsedStep`. Every leaf yields one; nothing is dropped. */
|
|
64
|
+
function step(rec, ordinal) {
|
|
65
|
+
const astPath = str(rec, "astPath");
|
|
66
|
+
const title = str(rec, "title");
|
|
67
|
+
const notes = descText(rec["notes"]);
|
|
68
|
+
return {
|
|
69
|
+
ordinal,
|
|
70
|
+
source: rec["source"],
|
|
71
|
+
target: rec["target"],
|
|
72
|
+
...(title === undefined ? {} : { title }),
|
|
73
|
+
...(notes === undefined ? {} : { notes }),
|
|
74
|
+
// Present-and-true is the only truthy form LikeC4 emits; absent means
|
|
75
|
+
// forward. Read as a boolean rather than carried as `true | undefined` so a
|
|
76
|
+
// caller cannot accidentally test `=== false` against a key that is never
|
|
77
|
+
// written.
|
|
78
|
+
isBackward: rec["isBackward"] === true,
|
|
79
|
+
...(astPath === undefined ? {} : { astPath }),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The dynamic views one parsed document declares, in the record's own order.
|
|
84
|
+
*
|
|
85
|
+
* `model` is the awaited `parsedModel()` result. The `await` matters and is the
|
|
86
|
+
* mistake every draft of this made: `$data` is `undefined` on the unresolved
|
|
87
|
+
* promise, so a reader handed the promise reports a document with views as
|
|
88
|
+
* having none — a silent zero, which is the one wrong answer this module is
|
|
89
|
+
* written to avoid.
|
|
90
|
+
*
|
|
91
|
+
* Two entries are dropped on the way out, for different reasons:
|
|
92
|
+
*
|
|
93
|
+
* - Anything whose `_type` is not `"dynamic"`. LikeC4 synthesises an `index`
|
|
94
|
+
* view into EVERY document, including one with no `views` block at all
|
|
95
|
+
* (measured), so reporting element views would be reporting a fiction the
|
|
96
|
+
* author never wrote. A census that must see authored element views wants the
|
|
97
|
+
* other filter rule 26 states — `sourcePath !== undefined` — and must not
|
|
98
|
+
* reuse this function to get it.
|
|
99
|
+
* - Anything with no `id`. There is nothing to name in a finding, and a view
|
|
100
|
+
* loam cannot name is a view it cannot ask anybody to fix.
|
|
101
|
+
*/
|
|
102
|
+
export function readDynamicViews(model) {
|
|
103
|
+
const data = record(record(model)?.["$data"]);
|
|
104
|
+
const views = record(data?.["views"]);
|
|
105
|
+
if (!views)
|
|
106
|
+
return [];
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const raw of Object.values(views)) {
|
|
109
|
+
const rec = record(raw);
|
|
110
|
+
if (!rec || rec["_type"] !== "dynamic")
|
|
111
|
+
continue;
|
|
112
|
+
const id = str(rec, "id");
|
|
113
|
+
if (id === undefined)
|
|
114
|
+
continue;
|
|
115
|
+
const found = [];
|
|
116
|
+
leaves(rec["steps"], found);
|
|
117
|
+
const steps = found.map((leaf, i) => step(leaf, i + 1));
|
|
118
|
+
const title = str(rec, "title");
|
|
119
|
+
const description = descText(rec["description"]);
|
|
120
|
+
const sourcePath = str(rec, "sourcePath");
|
|
121
|
+
out.push({
|
|
122
|
+
id,
|
|
123
|
+
...(sourcePath === undefined ? {} : { sourcePath }),
|
|
124
|
+
tags: Array.isArray(rec["tags"]) ? rec["tags"].filter((t) => typeof t === "string") : [],
|
|
125
|
+
...(title === undefined ? {} : { title }),
|
|
126
|
+
...(description === undefined ? {} : { description }),
|
|
127
|
+
steps,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=dynamic-views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-views.js","sourceRoot":"","sources":["../../../../src/core/c4/parsed/dynamic-views.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The `dynamic view`s a document DECLARES, read off LikeC4's parsed model.\n *\n * This is the only module in loam permitted to touch `$data`, and\n * `scripts/arch-check.mjs` enforces that rather than trusting it (docs/DESIGN.md\n * rule 26). The confinement is the point: `$data` is public and typed but thinly\n * documented for this use, so an upstream shape change has a blast radius of one\n * file, and `test/likec4-view-shape.test.ts` is the tripwire that fires before\n * the change reaches a check.\n *\n * It takes the WHOLE model as `unknown` rather than a `$data` slice handed in by\n * its caller, and that is not squeamishness — naming `$data` in `../likec4.ts`\n * would violate the containment scan this module exists behind. Callers pass the\n * model; every assumption about LikeC4's record shape lives here.\n *\n * Everything is defensive, in the same posture as `./specification.ts`: a shape\n * this reader cannot make sense of degrades to ZERO views, never to a wrong one\n * and never to a throw inside a validate run. That asymmetry is deliberate and\n * is loam's standing rule for a suspended axis — a check with no views to grade\n * reports could-not-look, while a check fed a half-read view would report\n * nothing-wrong about a flow it never saw.\n */\nimport { descText } from \"./values.js\";\n\n/** One hop of a declared use case: an ordered edge between two elements. */\nexport interface ParsedStep {\n /**\n * 1-based pre-order position among the view's LEAF steps — what lets a finding\n * say \"step 4 of Checkout\". Group wrappers do not consume an ordinal: a\n * `loop` is a bracket around hops, not a hop, and counting it would shift\n * every number after it away from what the author sees on the diagram.\n */\n ordinal: number;\n /**\n * The step's endpoints, ALREADY ORIENTED — see `isBackward`. Dotted FQN\n * strings naming elements, never relationship ids: a step says who talks to\n * whom, and which relationship backs that is a join loam performs later.\n */\n source: string;\n target: string;\n /**\n * The step's label, absent when the author wrote none. Carried verbatim,\n * because one join reads its opening characters: a title that opens with a\n * candidate relationship's operation id or message name, set off by\n * punctuation, picks that relationship where the map joins the pair by\n * several (`pickedByTitle` in `../resolve/steps.ts`).\n */\n title?: string;\n /** A `notes '...'` block on the step, decoded from LikeC4's rich-text shape. */\n notes?: string;\n /**\n * True when the author wrote the hop as a reply — `a <- b` rather than\n * `b -> a`. LOAD-BEARING, and measured: LikeC4 records `a <- b 'reply'` as\n * `{source: b, target: a, isBackward: true}` — already reversed AND flagged —\n * while a forward step carries no such key at all. `source`/`target` above are\n * therefore correct as they stand and need no flipping; the flag is carried so\n * a check can tell a return hop from a call, and so a message naming the\n * failing step can suggest the `<-` spelling to an author who wrote the arrow\n * the long way round.\n */\n isBackward: boolean;\n /**\n * LikeC4's own path to the step inside the view (`/steps@1/steps@0`), carried\n * verbatim. It is the only stable handle on a nested step — two hops between\n * the same pair inside different `loop` blocks are otherwise indistinguishable\n * — and it is message text, never identity: nothing joins on it.\n *\n * OPTIONAL, and that is a deliberate refusal to make it load-bearing. Every\n * leaf carries one at the 1.59.2 pin, so requiring it would look free — and\n * would mean that an upstream release which stopped emitting it turned every\n * use case in the fleet into a view with zero steps. That is the silent wrong\n * answer this module exists to avoid: a hop loam cannot cite is still a hop it\n * must grade.\n */\n astPath?: string;\n}\n\n/** One declared `dynamic view`, flattened to what rule 26 permits reading. */\nexport interface ParsedView {\n id: string;\n /**\n * The name LikeC4 knows the document by, and it is only a PATH under\n * `loadProject`: there it is relative to the project root, so\n * `usecases/checkout.likec4` inside `architecture/`. Under the per-file\n * loaders it is whatever that loader called the document — `source.c4` for\n * `loadSource`, the basename for `loadBatch` — because there is no project\n * for it to be relative to.\n *\n * So: name a file with it only when the views came from `loadProject`. That\n * is the only reader that has one, which is also the only reader that needs\n * one — a use case lives in a file of its own now, and a finding that cannot\n * name that file sends its reader to the landscape to look for something\n * that is not there.\n *\n * Absent for anything LikeC4 synthesized rather than read off a file, which\n * is how the census reader tells the two apart.\n */\n sourcePath?: string;\n /**\n * The view's declared tags, `[]` when it declares none. Normalized here\n * because LikeC4 reads an untagged view's tags as `null`, and a caller\n * testing `.length` on that would throw inside a validate run.\n *\n * Tags live on the VIEW and nowhere else: a step cannot carry tags, and\n * `metadata` on a step is a hard parse error. That is measured, and it is why\n * a use case is opted in as a whole rather than hop by hop.\n */\n tags: string[];\n title?: string;\n description?: string;\n /** The declared hops, in author order, groups flattened away. */\n steps: ParsedStep[];\n}\n\n/** A record, or nothing — `v` is `unknown` off an untyped parse. */\nfunction record(v: unknown): Record<string, unknown> | undefined {\n return v && typeof v === \"object\" && !Array.isArray(v) ? (v as Record<string, unknown>) : undefined;\n}\n\n/** The value at `key`, when it is a non-empty string. */\nfunction str(rec: Record<string, unknown>, key: string): string | undefined {\n const v = rec[key];\n return typeof v === \"string\" && v.length > 0 ? v : undefined;\n}\n\n/**\n * Every leaf step under `entries`, depth-first in author order.\n *\n * Steps NEST: a `loop 'until accepted' { ... }` arrives as an entry with\n * `_type: \"loop\"`, a title, its own `steps[]`, and NO endpoints and NO `astPath`\n * of its own (measured). A walk that treated every entry as a hop would read the\n * bracket as a step and then fail to find a relationship backing it — inventing\n * a finding out of a grouping the author drew for legibility.\n *\n * The test is structural rather than a list of group keywords (`loop`, `par`,\n * ...): an entry with a nested `steps` array is a group whatever LikeC4 calls\n * it, and an entry with two string endpoints is a hop. A future group kind\n * therefore flattens correctly on the day it ships instead of on the day\n * somebody notices.\n */\nfunction leaves(entries: unknown, out: Record<string, unknown>[]): void {\n if (!Array.isArray(entries)) return;\n for (const entry of entries) {\n const rec = record(entry);\n if (!rec) continue;\n if (Array.isArray(rec[\"steps\"])) {\n leaves(rec[\"steps\"], out);\n continue;\n }\n if (typeof rec[\"source\"] === \"string\" && typeof rec[\"target\"] === \"string\") out.push(rec);\n }\n}\n\n/** One leaf entry as a `ParsedStep`. Every leaf yields one; nothing is dropped. */\nfunction step(rec: Record<string, unknown>, ordinal: number): ParsedStep {\n const astPath = str(rec, \"astPath\");\n const title = str(rec, \"title\");\n const notes = descText(rec[\"notes\"]);\n return {\n ordinal,\n source: rec[\"source\"] as string,\n target: rec[\"target\"] as string,\n ...(title === undefined ? {} : { title }),\n ...(notes === undefined ? {} : { notes }),\n // Present-and-true is the only truthy form LikeC4 emits; absent means\n // forward. Read as a boolean rather than carried as `true | undefined` so a\n // caller cannot accidentally test `=== false` against a key that is never\n // written.\n isBackward: rec[\"isBackward\"] === true,\n ...(astPath === undefined ? {} : { astPath }),\n };\n}\n\n/**\n * The dynamic views one parsed document declares, in the record's own order.\n *\n * `model` is the awaited `parsedModel()` result. The `await` matters and is the\n * mistake every draft of this made: `$data` is `undefined` on the unresolved\n * promise, so a reader handed the promise reports a document with views as\n * having none — a silent zero, which is the one wrong answer this module is\n * written to avoid.\n *\n * Two entries are dropped on the way out, for different reasons:\n *\n * - Anything whose `_type` is not `\"dynamic\"`. LikeC4 synthesises an `index`\n * view into EVERY document, including one with no `views` block at all\n * (measured), so reporting element views would be reporting a fiction the\n * author never wrote. A census that must see authored element views wants the\n * other filter rule 26 states — `sourcePath !== undefined` — and must not\n * reuse this function to get it.\n * - Anything with no `id`. There is nothing to name in a finding, and a view\n * loam cannot name is a view it cannot ask anybody to fix.\n */\nexport function readDynamicViews(model: unknown): ParsedView[] {\n const data = record(record(model)?.[\"$data\"]);\n const views = record(data?.[\"views\"]);\n if (!views) return [];\n\n const out: ParsedView[] = [];\n for (const raw of Object.values(views)) {\n const rec = record(raw);\n if (!rec || rec[\"_type\"] !== \"dynamic\") continue;\n const id = str(rec, \"id\");\n if (id === undefined) continue;\n\n const found: Record<string, unknown>[] = [];\n leaves(rec[\"steps\"], found);\n const steps = found.map((leaf, i) => step(leaf, i + 1));\n\n const title = str(rec, \"title\");\n const description = descText(rec[\"description\"]);\n const sourcePath = str(rec, \"sourcePath\");\n out.push({\n id,\n ...(sourcePath === undefined ? {} : { sourcePath }),\n tags: Array.isArray(rec[\"tags\"]) ? rec[\"tags\"].filter((t): t is string => typeof t === \"string\") : [],\n ...(title === undefined ? {} : { title }),\n ...(description === undefined ? {} : { description }),\n steps,\n });\n }\n return out;\n}\n"]}
|