@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,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a service's `model.likec4` is GRADED, once `c4/service-model/` has
|
|
3
|
+
* decided how to read it.
|
|
4
|
+
*
|
|
5
|
+
* A package of its own beside `../service.ts` because that module is the ORDER
|
|
6
|
+
* — it reads what more than one axis joins through and pushes findings in the
|
|
7
|
+
* sequence the report is read in — and this is one axis's verdicts. Splitting it
|
|
8
|
+
* out is what let the model gain three arms without the order module gaining
|
|
9
|
+
* any: the four states below are the loader's four, and each one has exactly one
|
|
10
|
+
* right answer here.
|
|
11
|
+
*
|
|
12
|
+
* - the map is unreadable (an extending model only): NOTHING. The model could
|
|
13
|
+
* not be read, so neither `c4.invalid` nor `c4.valid` is a claim anybody may
|
|
14
|
+
* make about it, and blaming N services for one broken document is the
|
|
15
|
+
* report. `spine.landscape-invalid` already fires per service and gains a
|
|
16
|
+
* clause saying the model went unread with it (`../spine.ts`).
|
|
17
|
+
* - errors: `c4.invalid`, exactly as before. For an extending model the details
|
|
18
|
+
* name the FILE as well as the line, because a duplicate declaration is
|
|
19
|
+
* reported against the map as well as the model, and a bare `L8:` then points
|
|
20
|
+
* at somebody else's text.
|
|
21
|
+
* - clean, and nothing in the map resolves to this directory:
|
|
22
|
+
* `landscape.service-unmodelled` on the SERVICE target. An extending model
|
|
23
|
+
* says what is inside an element the map binds; with no such element there is
|
|
24
|
+
* nothing to be inside, and every count below would be zero for a file full
|
|
25
|
+
* of architecture.
|
|
26
|
+
* - clean: `c4.valid`, and one `c4.element-unowned` per element the model
|
|
27
|
+
* declared outside its own.
|
|
28
|
+
*/
|
|
29
|
+
import { readFile } from "node:fs/promises";
|
|
30
|
+
import { relative } from "node:path";
|
|
31
|
+
import { maskSource } from "../../../../core/c4/source-mask.js";
|
|
32
|
+
import { serviceResolver } from "../../../../core/c4/resolve/service.js";
|
|
33
|
+
import { ARTIFACT_FILES } from "../../../../core/repo/paths.js";
|
|
34
|
+
import { errorText } from "../../../../core/c4/likec4.js";
|
|
35
|
+
export async function modelFindings(grade) {
|
|
36
|
+
const { service, model } = grade;
|
|
37
|
+
// The map did not parse, so the model was never read. Silence here is the
|
|
38
|
+
// whole point: `spine.landscape-invalid` is the one finding, and it names the
|
|
39
|
+
// map rather than blaming a file nobody opened.
|
|
40
|
+
if (model.mapUnreadable)
|
|
41
|
+
return [];
|
|
42
|
+
if (model.doc.errors.length > 0) {
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
severity: "error",
|
|
46
|
+
code: "c4.invalid",
|
|
47
|
+
message: `${service}: C4 model has ${model.doc.errors.length} error(s)`,
|
|
48
|
+
// The hint FIRST, the errors after it: `capDetails` keeps the first ten
|
|
49
|
+
// lines and drops the rest, and a model written in both shapes at once
|
|
50
|
+
// stops resolving every kind and every reference in the file — dozens of
|
|
51
|
+
// cascading errors — so appending the one line that diagnoses it put it
|
|
52
|
+
// past the cap in exactly the case it exists for (verification
|
|
53
|
+
// 2026-09-04). It is the diagnosis; the errors are the evidence.
|
|
54
|
+
details: [...(await extendHint(grade)), ...model.doc.errors.map((err) => detail(err, grade))],
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
if (model.shape === "extending" && !mapBindsAnElement(grade)) {
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
severity: "error",
|
|
62
|
+
code: "landscape.service-unmodelled",
|
|
63
|
+
subject: service,
|
|
64
|
+
message: `${service}: ${ARTIFACT_FILES.model} extends the fleet map, and no element in ` +
|
|
65
|
+
`architecture/landscape.likec4 resolves to ${grade.treePath}/ — nothing in the model can be graded ` +
|
|
66
|
+
`until the map binds one (metadata { service '${service}' })`,
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
const findings = [
|
|
71
|
+
{
|
|
72
|
+
severity: "ok",
|
|
73
|
+
code: "c4.valid",
|
|
74
|
+
message: `${service}: C4 model valid (` +
|
|
75
|
+
(model.shape === "extending" ? "extends the fleet map — " : "") +
|
|
76
|
+
`${model.doc.elements.length} elements · ${model.doc.relationships.length} relationships)` +
|
|
77
|
+
// Outside the parentheses because the counts inside are facts about
|
|
78
|
+
// model.likec4 alone and the flows are read from the whole project.
|
|
79
|
+
(grade.gradedFlows === 0 ? "" : ` · ${grade.gradedFlows} tagged flow(s) graded`),
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
for (const element of model.unowned) {
|
|
83
|
+
findings.push({
|
|
84
|
+
severity: "warn",
|
|
85
|
+
code: "c4.element-unowned",
|
|
86
|
+
subject: service,
|
|
87
|
+
message: `${service}: ${ARTIFACT_FILES.model} declares '${element.id}' (${element.kind}) outside this service's ` +
|
|
88
|
+
"own element — an extending model adds elements under the element that resolves to " +
|
|
89
|
+
`${service} only. Three remedies, and the FIRST is the one a store or a component usually ` +
|
|
90
|
+
// The nested arm led the other two from 2026-09-04: a private store's own
|
|
91
|
+
// remedy was missing here, so following what this printed moved a store
|
|
92
|
+
// to fleet level and earned `landscape.service-undocumented` (#01/W8).
|
|
93
|
+
`wants: a store or component this service owns goes INSIDE the \`extend <fqn> { }\` block, ` +
|
|
94
|
+
"where its id becomes `<fqn>.<name>`; a system this service reaches belongs in " +
|
|
95
|
+
"architecture/landscape.likec4, declared once; and another service's internals belong in " +
|
|
96
|
+
"that service's model",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return findings;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Does anything in the per-service project resolve to this service?
|
|
103
|
+
*
|
|
104
|
+
* The same question `sliceForService` asks to build `own`, asked again rather
|
|
105
|
+
* than carried on the `ServiceModel`: the slice publishes what a check READS
|
|
106
|
+
* (the elements, the edges, the strays), and "was the set empty" is a fact
|
|
107
|
+
* about the map's bindings rather than a fourth list. Resolved over the
|
|
108
|
+
* PROJECT's elements, because that is the index the slice used and a
|
|
109
|
+
* nearest-ancestor binding must win here exactly as it does there.
|
|
110
|
+
*
|
|
111
|
+
* A standalone model never reaches this: it declares its own elements and
|
|
112
|
+
* answers for them whether or not the map has heard of the directory — the
|
|
113
|
+
* fleet target's own `landscape.service-unmodelled` is where that is said.
|
|
114
|
+
*/
|
|
115
|
+
function mapBindsAnElement(grade) {
|
|
116
|
+
const project = grade.model.project;
|
|
117
|
+
if (project === null)
|
|
118
|
+
return true;
|
|
119
|
+
const resolve = serviceResolver(project.elements, grade.known);
|
|
120
|
+
return project.elements.some((e) => resolve(e.id) === grade.service);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* One parse error, spelled for the shape it came from.
|
|
124
|
+
*
|
|
125
|
+
* A standalone model is one file, so its errors keep the bare `L8: …` form they
|
|
126
|
+
* have always had — every fixture and every reader of that message is pinned to
|
|
127
|
+
* it. An extending model is a PROJECT, and LikeC4 reports a duplicate
|
|
128
|
+
* declaration against BOTH documents: without the file name the reader is sent
|
|
129
|
+
* to a line number in a file they were never told about, which is the exact
|
|
130
|
+
* failure `landscape.invalid` fixed one altitude up.
|
|
131
|
+
*/
|
|
132
|
+
function detail(err, grade) {
|
|
133
|
+
if (grade.model.shape === "standalone" || err.sourceFsPath === undefined)
|
|
134
|
+
return errorText(err);
|
|
135
|
+
return `${relative(grade.docsDir, err.sourceFsPath).split(/[\\/]/).join("/")} ${errorText(err)}`;
|
|
136
|
+
}
|
|
137
|
+
/** An `extend` in a masked model — the bytes, not a parse, because the parse is what failed. */
|
|
138
|
+
const EXTENDS = /\bextend\s+[A-Za-z_][\w.-]*\s*\{/;
|
|
139
|
+
/**
|
|
140
|
+
* The one line that explains a model written in BOTH shapes at once.
|
|
141
|
+
*
|
|
142
|
+
* A file declaring an element kind is standalone (SCHEMA.md, "Two shapes of a
|
|
143
|
+
* service model"), so it is parsed alone — and every `extend <fqn>` in it then
|
|
144
|
+
* resolves nothing, because the fqn belongs to a map this load never opened.
|
|
145
|
+
* LikeC4 says `Could not resolve reference to Element named '<fqn>'`, which
|
|
146
|
+
* reads as a typo; nothing said which of the two lines the author has to drop
|
|
147
|
+
* (verification 2026-09-04, D10). Emitted only for the standalone shape, where
|
|
148
|
+
* the diagnosis is certain; an unreadable file adds nothing, since the loader
|
|
149
|
+
* already answered `standalone` for the same reason and `c4.invalid` names it.
|
|
150
|
+
*/
|
|
151
|
+
async function extendHint(grade) {
|
|
152
|
+
if (grade.model.shape !== "standalone")
|
|
153
|
+
return [];
|
|
154
|
+
const text = await readFile(grade.modelPath, "utf8").catch(() => null);
|
|
155
|
+
if (text === null || !EXTENDS.test(maskSource(text).code))
|
|
156
|
+
return [];
|
|
157
|
+
return [
|
|
158
|
+
`${ARTIFACT_FILES.model} declares an element kind in \`specification { }\`, so it is read as the ` +
|
|
159
|
+
"standalone shape — parsed alone, where `extend` resolves nothing. Drop the kind declaration to " +
|
|
160
|
+
"extend the fleet map, or drop the `extend` and declare the elements here",
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=grade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grade.js","sourceRoot":"","sources":["../../../../../src/commands/validate/service/model/grade.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * How a service's `model.likec4` is GRADED, once `c4/service-model/` has\n * decided how to read it.\n *\n * A package of its own beside `../service.ts` because that module is the ORDER\n * — it reads what more than one axis joins through and pushes findings in the\n * sequence the report is read in — and this is one axis's verdicts. Splitting it\n * out is what let the model gain three arms without the order module gaining\n * any: the four states below are the loader's four, and each one has exactly one\n * right answer here.\n *\n * - the map is unreadable (an extending model only): NOTHING. The model could\n * not be read, so neither `c4.invalid` nor `c4.valid` is a claim anybody may\n * make about it, and blaming N services for one broken document is the\n * report. `spine.landscape-invalid` already fires per service and gains a\n * clause saying the model went unread with it (`../spine.ts`).\n * - errors: `c4.invalid`, exactly as before. For an extending model the details\n * name the FILE as well as the line, because a duplicate declaration is\n * reported against the map as well as the model, and a bare `L8:` then points\n * at somebody else's text.\n * - clean, and nothing in the map resolves to this directory:\n * `landscape.service-unmodelled` on the SERVICE target. An extending model\n * says what is inside an element the map binds; with no such element there is\n * nothing to be inside, and every count below would be zero for a file full\n * of architecture.\n * - clean: `c4.valid`, and one `c4.element-unowned` per element the model\n * declared outside its own.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\nimport { maskSource } from \"../../../../core/c4/source-mask.js\";\nimport type { ServiceModel } from \"../../../../core/c4/service-model/load.js\";\nimport { serviceResolver } from \"../../../../core/c4/resolve/service.js\";\nimport type { LikeC4Error } from \"../../../../core/c4/likec4.js\";\nimport type { DocsDir } from \"../../../../core/kernel/ids/dirs.js\";\nimport type { PathableService } from \"../../../../core/kernel/ids/service.js\";\nimport { ARTIFACT_FILES } from \"../../../../core/repo/paths.js\";\nimport type { Finding } from \"../../../../core/vocabulary/report.js\";\nimport { errorText } from \"../../../../core/c4/likec4.js\";\n\nexport interface ModelGrade {\n service: PathableService;\n /** Repo-relative, `/`-separated — the directory the map has to bind, named in the unmodelled arm. */\n treePath: string;\n docsDir: DocsDir;\n model: ServiceModel;\n /** Absolute path of `model.likec4` — read only to explain a parse error, see `extendHint`. */\n modelPath: string;\n /** Every service directory that exists — the resolver's positive evidence, exactly as the slice used it. */\n known: ReadonlySet<string>;\n /**\n * How many of this service's own `dynamic view`s carried a reserved tag and\n * were graded (`core/usecases/service/flows.ts`), counted by the caller\n * because the scan is the use-case axis's and this is the model's.\n *\n * It rides on `c4.valid` and nowhere else. A healthy intra-service flow used\n * to be invisible on every loam surface — the axis reports only what is wrong\n * with one — so a team that wrote the slot correctly could not tell it from a\n * team whose views were never read (verification 2026-09-04, D10).\n */\n gradedFlows: number;\n}\n\nexport async function modelFindings(grade: ModelGrade): Promise<Finding[]> {\n const { service, model } = grade;\n // The map did not parse, so the model was never read. Silence here is the\n // whole point: `spine.landscape-invalid` is the one finding, and it names the\n // map rather than blaming a file nobody opened.\n if (model.mapUnreadable) return [];\n\n if (model.doc.errors.length > 0) {\n return [\n {\n severity: \"error\",\n code: \"c4.invalid\",\n message: `${service}: C4 model has ${model.doc.errors.length} error(s)`,\n // The hint FIRST, the errors after it: `capDetails` keeps the first ten\n // lines and drops the rest, and a model written in both shapes at once\n // stops resolving every kind and every reference in the file — dozens of\n // cascading errors — so appending the one line that diagnoses it put it\n // past the cap in exactly the case it exists for (verification\n // 2026-09-04). It is the diagnosis; the errors are the evidence.\n details: [...(await extendHint(grade)), ...model.doc.errors.map((err) => detail(err, grade))],\n },\n ];\n }\n\n if (model.shape === \"extending\" && !mapBindsAnElement(grade)) {\n return [\n {\n severity: \"error\",\n code: \"landscape.service-unmodelled\",\n subject: service,\n message:\n `${service}: ${ARTIFACT_FILES.model} extends the fleet map, and no element in ` +\n `architecture/landscape.likec4 resolves to ${grade.treePath}/ — nothing in the model can be graded ` +\n `until the map binds one (metadata { service '${service}' })`,\n },\n ];\n }\n\n const findings: Finding[] = [\n {\n severity: \"ok\",\n code: \"c4.valid\",\n message:\n `${service}: C4 model valid (` +\n (model.shape === \"extending\" ? \"extends the fleet map — \" : \"\") +\n `${model.doc.elements.length} elements · ${model.doc.relationships.length} relationships)` +\n // Outside the parentheses because the counts inside are facts about\n // model.likec4 alone and the flows are read from the whole project.\n (grade.gradedFlows === 0 ? \"\" : ` · ${grade.gradedFlows} tagged flow(s) graded`),\n },\n ];\n for (const element of model.unowned) {\n findings.push({\n severity: \"warn\",\n code: \"c4.element-unowned\",\n subject: service,\n message:\n `${service}: ${ARTIFACT_FILES.model} declares '${element.id}' (${element.kind}) outside this service's ` +\n \"own element — an extending model adds elements under the element that resolves to \" +\n `${service} only. Three remedies, and the FIRST is the one a store or a component usually ` +\n // The nested arm led the other two from 2026-09-04: a private store's own\n // remedy was missing here, so following what this printed moved a store\n // to fleet level and earned `landscape.service-undocumented` (#01/W8).\n `wants: a store or component this service owns goes INSIDE the \\`extend <fqn> { }\\` block, ` +\n \"where its id becomes `<fqn>.<name>`; a system this service reaches belongs in \" +\n \"architecture/landscape.likec4, declared once; and another service's internals belong in \" +\n \"that service's model\",\n });\n }\n return findings;\n}\n\n/**\n * Does anything in the per-service project resolve to this service?\n *\n * The same question `sliceForService` asks to build `own`, asked again rather\n * than carried on the `ServiceModel`: the slice publishes what a check READS\n * (the elements, the edges, the strays), and \"was the set empty\" is a fact\n * about the map's bindings rather than a fourth list. Resolved over the\n * PROJECT's elements, because that is the index the slice used and a\n * nearest-ancestor binding must win here exactly as it does there.\n *\n * A standalone model never reaches this: it declares its own elements and\n * answers for them whether or not the map has heard of the directory — the\n * fleet target's own `landscape.service-unmodelled` is where that is said.\n */\nfunction mapBindsAnElement(grade: ModelGrade): boolean {\n const project = grade.model.project;\n if (project === null) return true;\n const resolve = serviceResolver(project.elements, grade.known);\n return project.elements.some((e) => resolve(e.id) === (grade.service as string));\n}\n\n/**\n * One parse error, spelled for the shape it came from.\n *\n * A standalone model is one file, so its errors keep the bare `L8: …` form they\n * have always had — every fixture and every reader of that message is pinned to\n * it. An extending model is a PROJECT, and LikeC4 reports a duplicate\n * declaration against BOTH documents: without the file name the reader is sent\n * to a line number in a file they were never told about, which is the exact\n * failure `landscape.invalid` fixed one altitude up.\n */\nfunction detail(err: LikeC4Error, grade: ModelGrade): string {\n if (grade.model.shape === \"standalone\" || err.sourceFsPath === undefined) return errorText(err);\n return `${relative(grade.docsDir, err.sourceFsPath).split(/[\\\\/]/).join(\"/\")} ${errorText(err)}`;\n}\n\n/** An `extend` in a masked model — the bytes, not a parse, because the parse is what failed. */\nconst EXTENDS = /\\bextend\\s+[A-Za-z_][\\w.-]*\\s*\\{/;\n\n/**\n * The one line that explains a model written in BOTH shapes at once.\n *\n * A file declaring an element kind is standalone (SCHEMA.md, \"Two shapes of a\n * service model\"), so it is parsed alone — and every `extend <fqn>` in it then\n * resolves nothing, because the fqn belongs to a map this load never opened.\n * LikeC4 says `Could not resolve reference to Element named '<fqn>'`, which\n * reads as a typo; nothing said which of the two lines the author has to drop\n * (verification 2026-09-04, D10). Emitted only for the standalone shape, where\n * the diagnosis is certain; an unreadable file adds nothing, since the loader\n * already answered `standalone` for the same reason and `c4.invalid` names it.\n */\nasync function extendHint(grade: ModelGrade): Promise<string[]> {\n if (grade.model.shape !== \"standalone\") return [];\n const text = await readFile(grade.modelPath, \"utf8\").catch(() => null);\n if (text === null || !EXTENDS.test(maskSource(text).code)) return [];\n return [\n `${ARTIFACT_FILES.model} declares an element kind in \\`specification { }\\`, so it is read as the ` +\n \"standalone shape — parsed alone, where `extend` resolves nothing. Drop the kind declaration to \" +\n \"extend the fleet map, or drop the `extend` and declare the elements here\",\n ];\n}\n"]}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The service target: one adopted service graded across every axis it owns.
|
|
3
|
+
*
|
|
4
|
+
* This module is the ORDER, not the checks. It reads what more than one axis
|
|
5
|
+
* joins through — the C4 model, the living landscape and its resolver, the two
|
|
6
|
+
* requirement documents — hands each of those to the axis that grades it, and
|
|
7
|
+
* pushes the findings in the sequence the report is read in. The axes
|
|
8
|
+
* themselves cannot see each other, which is the point: `./api.js` decides once
|
|
9
|
+
* whether there is a contract to read, and `./spine.js` is handed the answer
|
|
10
|
+
* instead of re-deriving it against a file it would open a second time.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { relative } from "node:path";
|
|
14
|
+
import {} from "../../../core/c4/likec4.js";
|
|
15
|
+
import {} from "../../../core/c4/service-model/load.js";
|
|
16
|
+
import { serviceResolver } from "../../../core/c4/resolve/service.js";
|
|
17
|
+
import {} from "../../../core/kernel/ids/service.js";
|
|
18
|
+
import { landscapePath as landscapeFile, permissionsPath } from "../../../core/repo/paths.js";
|
|
19
|
+
import { locateServicePaths } from "../../../core/repo/service-target.js";
|
|
20
|
+
import { readVocabulary } from "../../../core/permissions/permissions.js";
|
|
21
|
+
import { capabilityRequirementIndex, capabilityUnknownIssues } from "../../../core/capabilities/findings.js";
|
|
22
|
+
import { realizesStaleFindings, realizesUnknownIssues } from "../../../core/capabilities/realizes/findings.js";
|
|
23
|
+
import { requiresUnknownFindings } from "../checks/requirements.js";
|
|
24
|
+
import { listServices } from "../../../core/repo/repo.js";
|
|
25
|
+
import {} from "../../../core/vocabulary/report.js";
|
|
26
|
+
import { serviceProvenance } from "../../../core/provenance/findings.js";
|
|
27
|
+
import { gherkinFindings } from "../../../core/gherkin/stale.js";
|
|
28
|
+
import { gherkinRoot } from "../../../core/gherkin/stamp.js";
|
|
29
|
+
import { UnsafePathError } from "../../../core/kernel/path-safety.js";
|
|
30
|
+
import { repoPath } from "../../../core/envelope/json.js";
|
|
31
|
+
import { interruptedCommitFinding } from "../../../core/staging/recovery/finding.js";
|
|
32
|
+
import { FleetContext } from "../../../core/fleet-context.js";
|
|
33
|
+
import { serviceLinkFindings } from "../links/corpus.js";
|
|
34
|
+
import { sourceScopeFindings } from "../checks/sources.js";
|
|
35
|
+
import { unknownServiceFinding } from "../checks/introduced.js";
|
|
36
|
+
import { apiAxisFindings } from "./api.js";
|
|
37
|
+
import { generatedContractFindings } from "./contracts/generated.js";
|
|
38
|
+
import { evidencePinFindings } from "./evidence-pins.js";
|
|
39
|
+
import { spineFindings } from "./spine.js";
|
|
40
|
+
import { eventAxisFindings } from "./events/events.js";
|
|
41
|
+
import { archAxisFindings, readServiceSpecs } from "./specs.js";
|
|
42
|
+
import { modelFindings } from "./model/grade.js";
|
|
43
|
+
import { divergedFindings } from "./model/diverged.js";
|
|
44
|
+
import { requirementIdsOf, serviceUseCaseFindings } from "./usecases/usecases.js";
|
|
45
|
+
import { readServiceFlows } from "../../../core/usecases/service/flows.js";
|
|
46
|
+
import { unknownDirectiveFindings } from "../../../core/document/grammar/directives.js";
|
|
47
|
+
export async function validateService(check) {
|
|
48
|
+
const { docsDir, service, repoDir, preloaded, gherkinDir, contracts, fleet } = check;
|
|
49
|
+
// The spine and event joins below all ask the landscape's resolver one
|
|
50
|
+
// question: does this edge's endpoint resolve into the directory being
|
|
51
|
+
// validated? The resolver answers with DOCUMENT text and `service` is the
|
|
52
|
+
// repository's own name — disjoint brands, so `===` between them is TS2367.
|
|
53
|
+
// Widening to `string` is not a cast: membership questions cross the
|
|
54
|
+
// provenance line through plain-string containers by design (kernel/ids/service.ts),
|
|
55
|
+
// and nothing pathable ever comes back out of a comparison.
|
|
56
|
+
const me = service;
|
|
57
|
+
const findings = [];
|
|
58
|
+
const paths = await locateServicePaths(docsDir, service, fleet);
|
|
59
|
+
// Repo-relative, `/`-separated: the report's own scope, and the spelling
|
|
60
|
+
// every service-local use-case finding opens with.
|
|
61
|
+
const treePath = relative(docsDir, paths.dir).replaceAll("\\", "/");
|
|
62
|
+
const report = {
|
|
63
|
+
kind: "service",
|
|
64
|
+
id: service,
|
|
65
|
+
path: treePath,
|
|
66
|
+
findings,
|
|
67
|
+
};
|
|
68
|
+
// A directory that does not exist is a different fact from a directory with
|
|
69
|
+
// everything missing: validating a typo must say "typo", not "unadopted" —
|
|
70
|
+
// and a service a feature in flight introduces is neither (checks/introduced.ts).
|
|
71
|
+
if (!existsSync(paths.dir)) {
|
|
72
|
+
findings.push(await unknownServiceFinding(docsDir, service, treePath, fleet));
|
|
73
|
+
return report;
|
|
74
|
+
}
|
|
75
|
+
// Which service directories actually exist — the positive evidence
|
|
76
|
+
// `serviceOf` needs to resolve an edge drawn into a modelled CONTAINER
|
|
77
|
+
// (`paymentService.api`) back to the service that owns it. Without it every
|
|
78
|
+
// such edge resolves to the container's own title, i.e. to a service nobody
|
|
79
|
+
// has ever adopted, and drops out of the spine unnoticed.
|
|
80
|
+
//
|
|
81
|
+
// Read before the model rather than after it, because the model is now read
|
|
82
|
+
// through the same resolver: an extending model's own slice is exactly the
|
|
83
|
+
// elements this set makes resolvable.
|
|
84
|
+
const known = new Set((await listServices(docsDir, fleet)).map((s) => s.id));
|
|
85
|
+
// C4 model. Its absence is an error — this is where `adopt` comes in — but it
|
|
86
|
+
// must NOT silence the rest of the gate stack: `loam archive` of a feature
|
|
87
|
+
// introducing a new service creates exactly this state (spec.md, arch.spec.md,
|
|
88
|
+
// openapi.yaml, no model.likec4), and an early return here suspended arch
|
|
89
|
+
// coverage, health.uncovered, provenance (content_digest included) and the
|
|
90
|
+
// gherkin staleness chain for the very services vouch had just promised them
|
|
91
|
+
// to. So the finding is emitted and the walk CONTINUES; only the checks that
|
|
92
|
+
// read the model itself are guarded.
|
|
93
|
+
const hasModel = existsSync(paths.model);
|
|
94
|
+
let elements = [];
|
|
95
|
+
let relationships = [];
|
|
96
|
+
// The model as its own SHAPE demands it be read — a file parsed alone, or a
|
|
97
|
+
// slice of the project it extends (`core/c4/service-model/load.ts`). Kept for
|
|
98
|
+
// the service's own use cases below, which need both its views and which
|
|
99
|
+
// shape produced them.
|
|
100
|
+
let model = null;
|
|
101
|
+
// The service's OWN use cases, scanned here rather than beside the grades it
|
|
102
|
+
// feeds: `c4.valid` reports how many were graded, and that count is the only
|
|
103
|
+
// surface a HEALTHY flow appears on. Null means no scan was made — the model
|
|
104
|
+
// does not parse (`c4.invalid` owns that, and a second load repeats its
|
|
105
|
+
// cascade under a use-case code) or its map does not (an extending model then
|
|
106
|
+
// comes back with no errors AND no model, and the flow project would be
|
|
107
|
+
// staged over the same broken map).
|
|
108
|
+
let flows = null;
|
|
109
|
+
if (!hasModel) {
|
|
110
|
+
findings.push({
|
|
111
|
+
severity: "error",
|
|
112
|
+
code: "service.no-model",
|
|
113
|
+
message: `No C4 model at ${repoPath(docsDir, paths.model)}. Run \`loam adopt\` for '${service}' first.`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
model = await fleet.serviceModel(docsDir, paths);
|
|
118
|
+
elements = model.doc.elements;
|
|
119
|
+
relationships = model.doc.relationships;
|
|
120
|
+
if (!model.mapUnreadable && model.doc.errors.length === 0) {
|
|
121
|
+
flows = await readServiceFlows({
|
|
122
|
+
paths,
|
|
123
|
+
model: model.doc,
|
|
124
|
+
known,
|
|
125
|
+
// An extending model's siblings resolve against the fleet map, so their
|
|
126
|
+
// project is the docs root's, never the service directory. The project
|
|
127
|
+
// the model was READ in travels with it because that is the scope of a
|
|
128
|
+
// view written inside model.likec4: `model.doc` is the service's own
|
|
129
|
+
// slice, and a hop backed by one of the map's edges is backed wherever
|
|
130
|
+
// the view sits.
|
|
131
|
+
...(model.shape === "extending" && model.project !== null
|
|
132
|
+
? { extending: { docsDir, project: model.project } }
|
|
133
|
+
: {}),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
findings.push(...(await modelFindings({
|
|
137
|
+
service,
|
|
138
|
+
treePath,
|
|
139
|
+
docsDir,
|
|
140
|
+
model,
|
|
141
|
+
modelPath: paths.model,
|
|
142
|
+
known,
|
|
143
|
+
gradedFlows: flows?.kind === "read" ? flows.views.length : 0,
|
|
144
|
+
})));
|
|
145
|
+
}
|
|
146
|
+
// The fleet map as the PROJECT it is, in EVERY mode — landscape plus every
|
|
147
|
+
// `architecture/**/*.likec4` minus the generated views file. Single-service
|
|
148
|
+
// runs used to read `landscape.likec4` alone, which made three answers depend
|
|
149
|
+
// on which flag the caller happened to pass: a use-case file that does not
|
|
150
|
+
// parse was `spine.landscape-invalid` under `--all` and silence under
|
|
151
|
+
// `--service`, an extending model was readable under one and not the other,
|
|
152
|
+
// and `c4.declaration-diverged` would have compared against a different
|
|
153
|
+
// document. Under `--all` the caller hands in the doc it already loaded.
|
|
154
|
+
//
|
|
155
|
+
// Still gated on the landscape FILE existing: `land === null` means "this repo
|
|
156
|
+
// draws no fleet", and a repo with an `architecture/usecases/` and no map is
|
|
157
|
+
// that state, not a map that loaded empty.
|
|
158
|
+
const land = preloaded ?? (existsSync(landscapeFile(docsDir)) ? await fleet.architecture(docsDir) : null);
|
|
159
|
+
// Where a standalone model's copies of the map's elements have drifted. After
|
|
160
|
+
// `c4.valid` because it is a claim about a model that parsed, and silent for
|
|
161
|
+
// an extending model, which has no copy to diverge.
|
|
162
|
+
if (model !== null)
|
|
163
|
+
findings.push(...divergedFindings({ service, model, architecture: land, known }));
|
|
164
|
+
// The living landscape's element→service resolver, container-aware and
|
|
165
|
+
// memoized. Every question below that asks "does this edge point at me?"
|
|
166
|
+
// asks it through this one function, so the no-openapi grace, the HTTP spine
|
|
167
|
+
// and the event spine can never disagree about which edges are inbound.
|
|
168
|
+
const landSvcOf = land === null ? null : serviceResolver(land.elements, known);
|
|
169
|
+
const specs = await readServiceSpecs({ docsDir, service, paths, fleet });
|
|
170
|
+
findings.push(...specs.findings);
|
|
171
|
+
const { reqs, livingReqs, archText, archReqs } = specs;
|
|
172
|
+
const api = await apiAxisFindings({
|
|
173
|
+
docsDir,
|
|
174
|
+
service,
|
|
175
|
+
me,
|
|
176
|
+
paths,
|
|
177
|
+
reqs,
|
|
178
|
+
livingReqs,
|
|
179
|
+
land,
|
|
180
|
+
landSvcOf,
|
|
181
|
+
fleet,
|
|
182
|
+
});
|
|
183
|
+
findings.push(...api.findings);
|
|
184
|
+
findings.push(...spineFindings({
|
|
185
|
+
service,
|
|
186
|
+
docsDir,
|
|
187
|
+
treePath,
|
|
188
|
+
me,
|
|
189
|
+
land,
|
|
190
|
+
landSvcOf,
|
|
191
|
+
contract: api.contract,
|
|
192
|
+
landscapeReported: check.landscapeReported,
|
|
193
|
+
// An unreadable map takes an extending model with it, and the spine
|
|
194
|
+
// finding is where that is said — see `Spine.modelExtends`.
|
|
195
|
+
modelExtends: model?.shape === "extending",
|
|
196
|
+
}));
|
|
197
|
+
findings.push(...(await eventAxisFindings({
|
|
198
|
+
docsDir,
|
|
199
|
+
service,
|
|
200
|
+
me,
|
|
201
|
+
paths,
|
|
202
|
+
reqs,
|
|
203
|
+
livingReqs,
|
|
204
|
+
archReqs,
|
|
205
|
+
land,
|
|
206
|
+
landSvcOf,
|
|
207
|
+
known,
|
|
208
|
+
fleet,
|
|
209
|
+
})));
|
|
210
|
+
findings.push(...(await archAxisFindings({
|
|
211
|
+
service,
|
|
212
|
+
paths,
|
|
213
|
+
archText,
|
|
214
|
+
archReqs,
|
|
215
|
+
elements,
|
|
216
|
+
relationships,
|
|
217
|
+
// The one fact that tells "this service models nothing" apart from "this
|
|
218
|
+
// service's model could not be read" — its map does not parse, or it does
|
|
219
|
+
// not itself (`c4.invalid` above): both arrive here as empty lists, and
|
|
220
|
+
// only the second one must silence `covers.unknown`.
|
|
221
|
+
modelUnreadable: model !== null && (model.mapUnreadable || model.doc.errors.length > 0),
|
|
222
|
+
land,
|
|
223
|
+
known,
|
|
224
|
+
docsDir,
|
|
225
|
+
fleet,
|
|
226
|
+
})));
|
|
227
|
+
// The service's own use cases, GRADED — scanned beside the model above. Here
|
|
228
|
+
// rather than on the fleet target because the hops name this service's
|
|
229
|
+
// containers, which only its project resolves; after the arch axis because a
|
|
230
|
+
// `#req-` tag resolves against the ids both spec documents declare.
|
|
231
|
+
if (flows !== null) {
|
|
232
|
+
findings.push(...serviceUseCaseFindings({
|
|
233
|
+
service,
|
|
234
|
+
treePath,
|
|
235
|
+
docsDir,
|
|
236
|
+
scan: flows,
|
|
237
|
+
services: known,
|
|
238
|
+
requirementIds: requirementIdsOf(paths, livingReqs, archReqs),
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
// The authorization axis. Both requirement documents are graded against one
|
|
242
|
+
// fleet vocabulary — a permission is a fleet fact, and an arch requirement
|
|
243
|
+
// gates on one exactly as a business requirement does. The capability axis
|
|
244
|
+
// rides the same loop against ITS fleet vocabulary; under --all the fleet
|
|
245
|
+
// memo makes that one parse for the whole run.
|
|
246
|
+
const vocabulary = await readVocabulary(permissionsPath(docsDir));
|
|
247
|
+
const capabilities = await fleet.capabilities(docsDir);
|
|
248
|
+
// The requirement-level index behind `Realizes:`. Built once for both axes,
|
|
249
|
+
// and behind the same ladder `capabilityUnknownIssues` applies — an absent
|
|
250
|
+
// or unreadable vocabulary means no reads and no grades at all, so a fleet
|
|
251
|
+
// that has not adopted the axis pays nothing for a line it never wrote.
|
|
252
|
+
const capabilityReqs = await capabilityRequirementIndex(capabilities, (p) => fleet.readRequirements(p));
|
|
253
|
+
for (const [label, docReqs] of [
|
|
254
|
+
["spec.md", reqs],
|
|
255
|
+
["arch.spec.md", archReqs],
|
|
256
|
+
]) {
|
|
257
|
+
const target = { where: `${service}: ${label}`, subject: service };
|
|
258
|
+
findings.push(...requiresUnknownFindings(docReqs, target, vocabulary));
|
|
259
|
+
findings.push(...capabilityUnknownIssues(docReqs, target, capabilities));
|
|
260
|
+
findings.push(...realizesUnknownIssues(docReqs, target, capabilityReqs));
|
|
261
|
+
findings.push(...realizesStaleFindings(docReqs, target, capabilityReqs));
|
|
262
|
+
// The grammar guard, last in the loop: it grades the KEYS the three checks
|
|
263
|
+
// above resolve values from, so a line none of them saw is reported here
|
|
264
|
+
// rather than staying invisible for having produced nothing to check.
|
|
265
|
+
findings.push(...unknownDirectiveFindings(docReqs, target));
|
|
266
|
+
}
|
|
267
|
+
// The links this service's own documents write. Its place in the order is
|
|
268
|
+
// deliberate: every axis above joins through a LINE loam defined, and this one
|
|
269
|
+
// grades the join an author writes in prose — so it reads last among the
|
|
270
|
+
// document checks and adds no input any of them depend on.
|
|
271
|
+
findings.push(...(await serviceLinkFindings({ docsDir, subject: service, fleet }, paths)));
|
|
272
|
+
// Provenance last: who vouched for this, and what code it was written from.
|
|
273
|
+
findings.push(...(await serviceProvenance(docsDir, service, { repoDir, loamOwned: check.loamOwned, fleet })));
|
|
274
|
+
findings.push(...(await sourceScopeFindings(docsDir, service, repoDir, fleet)));
|
|
275
|
+
// The build's own contract against the committed copy. Service-repo only:
|
|
276
|
+
// from the docs repo there is no build output to read, and the family stays
|
|
277
|
+
// silent rather than guessing — the same rule `sources` provenance follows.
|
|
278
|
+
if (repoDir !== undefined) {
|
|
279
|
+
findings.push(...(await generatedContractFindings(service, repoDir, contracts?.openapi, paths.openapi)));
|
|
280
|
+
}
|
|
281
|
+
// The generated-gherkin freshness chain, service-repo-scoped like sources.*:
|
|
282
|
+
// it needs the repo (the suite lives there), and it stays quiet until
|
|
283
|
+
// <gherkinDir>/loam/ exists — a service that never generated has not opted in.
|
|
284
|
+
findings.push(...(await gherkinFindings({ docsDir, service, repoDir, gherkinDir, fleet })));
|
|
285
|
+
// The evidence-pin re-check, the same service-repo-scoped family: recorded
|
|
286
|
+
// verification citations graded against THIS working tree, quiet from the
|
|
287
|
+
// docs repo — sources.unverifiable-from-here already names that blind spot.
|
|
288
|
+
findings.push(...(await evidencePinFindings(docsDir, service, repoDir, fleet)));
|
|
289
|
+
// The one journal that does NOT live in the docs repo: gherkin commits into
|
|
290
|
+
// the service repo's emission root. A half-committed suite graded by the
|
|
291
|
+
// freshness chain above reads as merely stale — warn-severity, which never
|
|
292
|
+
// gates — while doctor calls the same state a blocker. Same finding, same
|
|
293
|
+
// code, led rather than appended, exactly as validate leads with the docs
|
|
294
|
+
// repo's own journal.
|
|
295
|
+
if (repoDir !== undefined) {
|
|
296
|
+
try {
|
|
297
|
+
const interrupted = await interruptedCommitFinding(gherkinRoot(repoDir, gherkinDir));
|
|
298
|
+
if (interrupted !== null)
|
|
299
|
+
findings.unshift(interrupted);
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
// An unsafe gherkinDir is `loam gherkin`'s refusal to make, with its
|
|
303
|
+
// own sentence; grading declines to scan what it cannot trust.
|
|
304
|
+
if (!(err instanceof UnsafePathError))
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return report;
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../src/commands/validate/service/service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The service target: one adopted service graded across every axis it owns.\n *\n * This module is the ORDER, not the checks. It reads what more than one axis\n * joins through — the C4 model, the living landscape and its resolver, the two\n * requirement documents — hands each of those to the axis that grades it, and\n * pushes the findings in the sequence the report is read in. The axes\n * themselves cannot see each other, which is the point: `./api.js` decides once\n * whether there is a contract to read, and `./spine.js` is handed the answer\n * instead of re-deriving it against a file it would open a second time.\n */\nimport { existsSync } from \"node:fs\";\nimport { relative } from \"node:path\";\nimport { type Elem, type LoadedDoc, type Rel } from \"../../../core/c4/likec4.js\";\nimport { type ServiceModel } from \"../../../core/c4/service-model/load.js\";\nimport { serviceResolver } from \"../../../core/c4/resolve/service.js\";\nimport { type PathableService } from \"../../../core/kernel/ids/service.js\";\nimport { landscapePath as landscapeFile, permissionsPath } from \"../../../core/repo/paths.js\";\nimport { locateServicePaths } from \"../../../core/repo/service-target.js\";\nimport { readVocabulary } from \"../../../core/permissions/permissions.js\";\nimport { capabilityRequirementIndex, capabilityUnknownIssues } from \"../../../core/capabilities/findings.js\";\nimport { realizesStaleFindings, realizesUnknownIssues } from \"../../../core/capabilities/realizes/findings.js\";\nimport { requiresUnknownFindings } from \"../checks/requirements.js\";\nimport { listServices } from \"../../../core/repo/repo.js\";\nimport { type Finding, type TargetReport } from \"../../../core/vocabulary/report.js\";\nimport { serviceProvenance } from \"../../../core/provenance/findings.js\";\nimport { gherkinFindings } from \"../../../core/gherkin/stale.js\";\nimport { gherkinRoot } from \"../../../core/gherkin/stamp.js\";\nimport { UnsafePathError } from \"../../../core/kernel/path-safety.js\";\nimport { repoPath } from \"../../../core/envelope/json.js\";\nimport { interruptedCommitFinding } from \"../../../core/staging/recovery/finding.js\";\nimport { FleetContext } from \"../../../core/fleet-context.js\";\nimport { serviceLinkFindings } from \"../links/corpus.js\";\nimport { sourceScopeFindings } from \"../checks/sources.js\";\nimport { unknownServiceFinding } from \"../checks/introduced.js\";\nimport { apiAxisFindings } from \"./api.js\";\nimport { generatedContractFindings } from \"./contracts/generated.js\";\nimport { evidencePinFindings } from \"./evidence-pins.js\";\nimport { spineFindings } from \"./spine.js\";\nimport { eventAxisFindings } from \"./events/events.js\";\nimport { archAxisFindings, readServiceSpecs } from \"./specs.js\";\nimport { modelFindings } from \"./model/grade.js\";\nimport { divergedFindings } from \"./model/diverged.js\";\nimport { requirementIdsOf, serviceUseCaseFindings } from \"./usecases/usecases.js\";\nimport { readServiceFlows, type ServiceFlowScan } from \"../../../core/usecases/service/flows.js\";\nimport { unknownDirectiveFindings } from \"../../../core/document/grammar/directives.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\n/**\n * A service's absences are graded by what each one proves.\n *\n * `service.unknown` (error): the directory itself does not exist — the id is a\n * typo until proven otherwise, so the hint names ids that DO exist and never\n * `loam adopt`, which would faithfully document the misspelling. The proof\n * otherwise is a feature in flight that introduces it; the hint then names\n * that feature instead (`../checks/introduced.ts`).\n * `service.no-model` (error): the directory is real but the C4 center is not —\n * adopt is the right hint. Every check that does not read the model still runs\n * (spec coverage, the arch axis, provenance, gherkin staleness): archive\n * creates exactly this state for a new service, and those signals must not go\n * quiet there.\n * `service.no-spec` / `service.no-openapi` (warn): the adopt brief marks both\n * required, but a fleet mid-rollout legitimately has part-adopted services —\n * the absence must stay visible without gating CI for months. The openapi warn\n * keeps quiet when the landscape proves nobody calls an operation on this\n * service: a worker with no API is not missing one.\n * `api.ops-unlinked` (warn): an OpenAPI and requirements that never name each\n * other pass every cross-axis check vacuously — a repo migrated from OpenSpec\n * does exactly that by default, and vacuous is not the same as checked.\n */\ninterface ServiceCheck {\n docsDir: DocsDir;\n service: PathableService;\n /** The service's own repo, when loam is standing in it. Undefined from the docs repo. */\n repoDir?: string;\n /** loam's own files in `repoDir` (`loamOwnedFiles`) — outside the walk check's denominator. */\n loamOwned?: readonly string[];\n /** The build outputs `loam.json` names, when this repo declares any. */\n contracts?: { openapi?: string };\n /** The living landscape under --all; undefined means \"load it if you need it\", null means \"there is none\". */\n preloaded?: LoadedDoc | null;\n gherkinDir?: string;\n /**\n * The read index this target reads the fleet map and the model through.\n *\n * Required, and every validate mode builds one before it grades anything —\n * the single-service run included (`validate.ts`) — rather than this target\n * keeping a second reading rule for a run that arrived without one:\n * `serviceModel` needs the enumeration and a document memo to answer at\n * all, and both live there. Request-scoped like every other `FleetContext`\n * — created for the invocation, dropped with it.\n */\n fleet: FleetContext;\n /**\n * True when this run ALSO emits a `landscape` target. It decides one thing:\n * whether a landscape parse error's details are repeated here. Under --all\n * they are not — the landscape target already carries them once, and N copies\n * of one parser's cascade is the whole report. Under --all --base the\n * landscape is a target only when the branch changed `architecture/`, so the\n * caller states this per run (`validate.ts`'s `serviceTarget`) rather than\n * inferring it from `preloaded`: a map handed in is not a map reported.\n */\n landscapeReported?: boolean;\n}\n\nexport async function validateService(check: ServiceCheck): Promise<TargetReport> {\n const { docsDir, service, repoDir, preloaded, gherkinDir, contracts, fleet } = check;\n // The spine and event joins below all ask the landscape's resolver one\n // question: does this edge's endpoint resolve into the directory being\n // validated? The resolver answers with DOCUMENT text and `service` is the\n // repository's own name — disjoint brands, so `===` between them is TS2367.\n // Widening to `string` is not a cast: membership questions cross the\n // provenance line through plain-string containers by design (kernel/ids/service.ts),\n // and nothing pathable ever comes back out of a comparison.\n const me: string = service;\n const findings: Finding[] = [];\n const paths = await locateServicePaths(docsDir, service, fleet);\n // Repo-relative, `/`-separated: the report's own scope, and the spelling\n // every service-local use-case finding opens with.\n const treePath = relative(docsDir, paths.dir).replaceAll(\"\\\\\", \"/\");\n const report: TargetReport = {\n kind: \"service\",\n id: service,\n path: treePath,\n findings,\n };\n\n // A directory that does not exist is a different fact from a directory with\n // everything missing: validating a typo must say \"typo\", not \"unadopted\" —\n // and a service a feature in flight introduces is neither (checks/introduced.ts).\n if (!existsSync(paths.dir)) {\n findings.push(await unknownServiceFinding(docsDir, service, treePath, fleet));\n return report;\n }\n\n // Which service directories actually exist — the positive evidence\n // `serviceOf` needs to resolve an edge drawn into a modelled CONTAINER\n // (`paymentService.api`) back to the service that owns it. Without it every\n // such edge resolves to the container's own title, i.e. to a service nobody\n // has ever adopted, and drops out of the spine unnoticed.\n //\n // Read before the model rather than after it, because the model is now read\n // through the same resolver: an extending model's own slice is exactly the\n // elements this set makes resolvable.\n const known = new Set((await listServices(docsDir, fleet)).map((s) => s.id));\n\n // C4 model. Its absence is an error — this is where `adopt` comes in — but it\n // must NOT silence the rest of the gate stack: `loam archive` of a feature\n // introducing a new service creates exactly this state (spec.md, arch.spec.md,\n // openapi.yaml, no model.likec4), and an early return here suspended arch\n // coverage, health.uncovered, provenance (content_digest included) and the\n // gherkin staleness chain for the very services vouch had just promised them\n // to. So the finding is emitted and the walk CONTINUES; only the checks that\n // read the model itself are guarded.\n const hasModel = existsSync(paths.model);\n let elements: Elem[] = [];\n let relationships: Rel[] = [];\n // The model as its own SHAPE demands it be read — a file parsed alone, or a\n // slice of the project it extends (`core/c4/service-model/load.ts`). Kept for\n // the service's own use cases below, which need both its views and which\n // shape produced them.\n let model: ServiceModel | null = null;\n // The service's OWN use cases, scanned here rather than beside the grades it\n // feeds: `c4.valid` reports how many were graded, and that count is the only\n // surface a HEALTHY flow appears on. Null means no scan was made — the model\n // does not parse (`c4.invalid` owns that, and a second load repeats its\n // cascade under a use-case code) or its map does not (an extending model then\n // comes back with no errors AND no model, and the flow project would be\n // staged over the same broken map).\n let flows: ServiceFlowScan | null = null;\n if (!hasModel) {\n findings.push({\n severity: \"error\",\n code: \"service.no-model\",\n message: `No C4 model at ${repoPath(docsDir, paths.model)}. Run \\`loam adopt\\` for '${service}' first.`,\n });\n } else {\n model = await fleet.serviceModel(docsDir, paths);\n elements = model.doc.elements;\n relationships = model.doc.relationships;\n if (!model.mapUnreadable && model.doc.errors.length === 0) {\n flows = await readServiceFlows({\n paths,\n model: model.doc,\n known,\n // An extending model's siblings resolve against the fleet map, so their\n // project is the docs root's, never the service directory. The project\n // the model was READ in travels with it because that is the scope of a\n // view written inside model.likec4: `model.doc` is the service's own\n // slice, and a hop backed by one of the map's edges is backed wherever\n // the view sits.\n ...(model.shape === \"extending\" && model.project !== null\n ? { extending: { docsDir, project: model.project } }\n : {}),\n });\n }\n findings.push(\n ...(await modelFindings({\n service,\n treePath,\n docsDir,\n model,\n modelPath: paths.model,\n known,\n gradedFlows: flows?.kind === \"read\" ? flows.views.length : 0,\n })),\n );\n }\n\n // The fleet map as the PROJECT it is, in EVERY mode — landscape plus every\n // `architecture/**/*.likec4` minus the generated views file. Single-service\n // runs used to read `landscape.likec4` alone, which made three answers depend\n // on which flag the caller happened to pass: a use-case file that does not\n // parse was `spine.landscape-invalid` under `--all` and silence under\n // `--service`, an extending model was readable under one and not the other,\n // and `c4.declaration-diverged` would have compared against a different\n // document. Under `--all` the caller hands in the doc it already loaded.\n //\n // Still gated on the landscape FILE existing: `land === null` means \"this repo\n // draws no fleet\", and a repo with an `architecture/usecases/` and no map is\n // that state, not a map that loaded empty.\n const land =\n preloaded ?? (existsSync(landscapeFile(docsDir)) ? await fleet.architecture(docsDir) : null);\n\n // Where a standalone model's copies of the map's elements have drifted. After\n // `c4.valid` because it is a claim about a model that parsed, and silent for\n // an extending model, which has no copy to diverge.\n if (model !== null) findings.push(...divergedFindings({ service, model, architecture: land, known }));\n\n\n // The living landscape's element→service resolver, container-aware and\n // memoized. Every question below that asks \"does this edge point at me?\"\n // asks it through this one function, so the no-openapi grace, the HTTP spine\n // and the event spine can never disagree about which edges are inbound.\n const landSvcOf = land === null ? null : serviceResolver(land.elements, known);\n\n const specs = await readServiceSpecs({ docsDir, service, paths, fleet });\n findings.push(...specs.findings);\n const { reqs, livingReqs, archText, archReqs } = specs;\n\n const api = await apiAxisFindings({\n docsDir,\n service,\n me,\n paths,\n reqs,\n livingReqs,\n land,\n landSvcOf,\n fleet,\n });\n findings.push(...api.findings);\n findings.push(\n ...spineFindings({\n service,\n docsDir,\n treePath,\n me,\n land,\n landSvcOf,\n contract: api.contract,\n landscapeReported: check.landscapeReported,\n // An unreadable map takes an extending model with it, and the spine\n // finding is where that is said — see `Spine.modelExtends`.\n modelExtends: model?.shape === \"extending\",\n }),\n );\n findings.push(\n ...(await eventAxisFindings({\n docsDir,\n service,\n me,\n paths,\n reqs,\n livingReqs,\n archReqs,\n land,\n landSvcOf,\n known,\n fleet,\n })),\n );\n findings.push(\n ...(await archAxisFindings({\n service,\n paths,\n archText,\n archReqs,\n elements,\n relationships,\n // The one fact that tells \"this service models nothing\" apart from \"this\n // service's model could not be read\" — its map does not parse, or it does\n // not itself (`c4.invalid` above): both arrive here as empty lists, and\n // only the second one must silence `covers.unknown`.\n modelUnreadable: model !== null && (model.mapUnreadable || model.doc.errors.length > 0),\n land,\n known,\n docsDir,\n fleet,\n })),\n );\n\n // The service's own use cases, GRADED — scanned beside the model above. Here\n // rather than on the fleet target because the hops name this service's\n // containers, which only its project resolves; after the arch axis because a\n // `#req-` tag resolves against the ids both spec documents declare.\n if (flows !== null) {\n findings.push(\n ...serviceUseCaseFindings({\n service,\n treePath,\n docsDir,\n scan: flows,\n services: known,\n requirementIds: requirementIdsOf(paths, livingReqs, archReqs),\n }),\n );\n }\n\n // The authorization axis. Both requirement documents are graded against one\n // fleet vocabulary — a permission is a fleet fact, and an arch requirement\n // gates on one exactly as a business requirement does. The capability axis\n // rides the same loop against ITS fleet vocabulary; under --all the fleet\n // memo makes that one parse for the whole run.\n const vocabulary = await readVocabulary(permissionsPath(docsDir));\n const capabilities = await fleet.capabilities(docsDir);\n // The requirement-level index behind `Realizes:`. Built once for both axes,\n // and behind the same ladder `capabilityUnknownIssues` applies — an absent\n // or unreadable vocabulary means no reads and no grades at all, so a fleet\n // that has not adopted the axis pays nothing for a line it never wrote.\n const capabilityReqs = await capabilityRequirementIndex(capabilities, (p) => fleet.readRequirements(p));\n for (const [label, docReqs] of [\n [\"spec.md\", reqs],\n [\"arch.spec.md\", archReqs],\n ] as const) {\n const target = { where: `${service}: ${label}`, subject: service };\n findings.push(...requiresUnknownFindings(docReqs, target, vocabulary));\n findings.push(...capabilityUnknownIssues(docReqs, target, capabilities));\n findings.push(...realizesUnknownIssues(docReqs, target, capabilityReqs));\n findings.push(...realizesStaleFindings(docReqs, target, capabilityReqs));\n // The grammar guard, last in the loop: it grades the KEYS the three checks\n // above resolve values from, so a line none of them saw is reported here\n // rather than staying invisible for having produced nothing to check.\n findings.push(...unknownDirectiveFindings(docReqs, target));\n }\n\n // The links this service's own documents write. Its place in the order is\n // deliberate: every axis above joins through a LINE loam defined, and this one\n // grades the join an author writes in prose — so it reads last among the\n // document checks and adds no input any of them depend on.\n findings.push(...(await serviceLinkFindings({ docsDir, subject: service, fleet }, paths)));\n\n // Provenance last: who vouched for this, and what code it was written from.\n findings.push(...(await serviceProvenance(docsDir, service, { repoDir, loamOwned: check.loamOwned, fleet })));\n findings.push(...(await sourceScopeFindings(docsDir, service, repoDir, fleet)));\n // The build's own contract against the committed copy. Service-repo only:\n // from the docs repo there is no build output to read, and the family stays\n // silent rather than guessing — the same rule `sources` provenance follows.\n if (repoDir !== undefined) {\n findings.push(...(await generatedContractFindings(service, repoDir, contracts?.openapi, paths.openapi)));\n }\n\n // The generated-gherkin freshness chain, service-repo-scoped like sources.*:\n // it needs the repo (the suite lives there), and it stays quiet until\n // <gherkinDir>/loam/ exists — a service that never generated has not opted in.\n findings.push(...(await gherkinFindings({ docsDir, service, repoDir, gherkinDir, fleet })));\n\n // The evidence-pin re-check, the same service-repo-scoped family: recorded\n // verification citations graded against THIS working tree, quiet from the\n // docs repo — sources.unverifiable-from-here already names that blind spot.\n findings.push(...(await evidencePinFindings(docsDir, service, repoDir, fleet)));\n\n // The one journal that does NOT live in the docs repo: gherkin commits into\n // the service repo's emission root. A half-committed suite graded by the\n // freshness chain above reads as merely stale — warn-severity, which never\n // gates — while doctor calls the same state a blocker. Same finding, same\n // code, led rather than appended, exactly as validate leads with the docs\n // repo's own journal.\n if (repoDir !== undefined) {\n try {\n const interrupted = await interruptedCommitFinding(gherkinRoot(repoDir, gherkinDir));\n if (interrupted !== null) findings.unshift(interrupted);\n } catch (err) {\n // An unsafe gherkinDir is `loam gherkin`'s refusal to make, with its\n // own sentence; grading declines to scan what it cannot trust.\n if (!(err instanceof UnsafePathError)) throw err;\n }\n }\n\n return report;\n}\n"]}
|