@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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A service an active feature INTRODUCES, as `loam validate` meets it — named
|
|
3
|
+
* by the repository's own binding, or named on the command line.
|
|
4
|
+
*
|
|
5
|
+
* Until the feature archives, such a service's only documents are the
|
|
6
|
+
* feature's `specs/<service>/`: `services/` learns the name at the merge
|
|
7
|
+
* (`core/projection/introduced.ts`, the one answer to "introduces" every
|
|
8
|
+
* command reads). `validate` looked only under `services/`, so in that
|
|
9
|
+
* service's own repository a bare `loam validate` refused with
|
|
10
|
+
* `service.unknown` and "Did you mean: payment-service?" — it read the newest
|
|
11
|
+
* service in the fleet as a typo, while `loam status` and `loam doctor` in the
|
|
12
|
+
* same repository named the feature that introduces it.
|
|
13
|
+
*
|
|
14
|
+
* Two readings, two answers:
|
|
15
|
+
*
|
|
16
|
+
* the binding (a bare `loam validate`) → the introducing features are
|
|
17
|
+
* validated in the service's place. They hold every document the service
|
|
18
|
+
* has, so theirs is the grade there is to give, and it is `--feature`'s
|
|
19
|
+
* grade target for target — never a slice of it, which would be a green
|
|
20
|
+
* over whatever the slice left out. The run says first which features it
|
|
21
|
+
* validated and why, in `show`'s words for the same fact, so a reader never
|
|
22
|
+
* takes a feature's findings for the service's own.
|
|
23
|
+
* a name (`--service <id>`, the positional) → still a service target, which
|
|
24
|
+
* does not exist, so still `service.unknown` at error: `--service` forces
|
|
25
|
+
* the service reading by contract. Only the prose changes — it names the
|
|
26
|
+
* feature and the command that validates its documents, where it used to
|
|
27
|
+
* offer the nearest living id as the correction.
|
|
28
|
+
*
|
|
29
|
+
* A name nothing introduces keeps the near-miss refusal, byte for byte.
|
|
30
|
+
*/
|
|
31
|
+
import { closeIds } from "../../../core/c4/arch.js";
|
|
32
|
+
import { introducingFeatures } from "../../../core/projection/introduced.js";
|
|
33
|
+
import { listServices } from "../../../core/repo/repo.js";
|
|
34
|
+
/**
|
|
35
|
+
* The features a bare run validates in place of the bound service — or null
|
|
36
|
+
* when the binding names a living service, or a name nothing introduces, and
|
|
37
|
+
* the run grades it as a service (`service.unknown` and all) exactly as before.
|
|
38
|
+
*/
|
|
39
|
+
export async function introducedBinding(docsDir, resolved, fleet) {
|
|
40
|
+
// An enumerated directory is living. `introducingFeatures` would say so too,
|
|
41
|
+
// after reading every feature to learn it.
|
|
42
|
+
if (resolved.dir !== undefined)
|
|
43
|
+
return null;
|
|
44
|
+
const features = await introducingFeatures(docsDir, resolved.id, fleet);
|
|
45
|
+
return features.length === 0 ? null : { service: resolved.id, features };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The two lines a bare run prints above the report: the first is `loam show
|
|
49
|
+
* <service>`'s header for the same state, the second says what was validated
|
|
50
|
+
* instead and why those features.
|
|
51
|
+
*/
|
|
52
|
+
export function introducedLead({ service, features }) {
|
|
53
|
+
const ids = features.map((f) => f.id);
|
|
54
|
+
const several = ids.length > 1;
|
|
55
|
+
const listed = several ? `${ids.slice(0, -1).join(", ")} and ${ids.slice(-1).join("")}` : ids.join("");
|
|
56
|
+
return [
|
|
57
|
+
`${service} introduced by ${ids.join(", ")} (in flight) — not in the living docs until ${several ? "one of them" : "it"} archives`,
|
|
58
|
+
` validating ${listed} instead: ${several ? "their" : "its"} specs/${service}/ are this service's documents until then`,
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The `--json` payload's `boundService`: why `targets` holds features and no
|
|
63
|
+
* service. The keys are `show`'s and `steps`' for the same fact — `living:
|
|
64
|
+
* false` and `introducedBy` — so a consumer that reads one reads them all.
|
|
65
|
+
*/
|
|
66
|
+
export function introducedJson({ service, features }) {
|
|
67
|
+
return { id: service, living: false, introducedBy: features.map((f) => f.id) };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* `service.unknown`: no directory under `services/` answers to the name. The
|
|
71
|
+
* hint depends on why. A feature in flight introduces it → name the feature
|
|
72
|
+
* and the command that validates its documents, in `loam doctor`'s words for
|
|
73
|
+
* the same state. Something close is living → the near-miss, which is what
|
|
74
|
+
* makes a typo diagnosable. Neither → where to look. Never `loam adopt`, in any
|
|
75
|
+
* branch: adopting a typo would document the misspelling, and adopting an
|
|
76
|
+
* introduced service would write `services/<id>/` ahead of the merge.
|
|
77
|
+
*/
|
|
78
|
+
export async function unknownServiceFinding(docsDir, service, treePath, fleet) {
|
|
79
|
+
const ids = (await introducingFeatures(docsDir, service, fleet)).map((f) => f.id);
|
|
80
|
+
const [lead, ...others] = ids;
|
|
81
|
+
if (lead !== undefined) {
|
|
82
|
+
const several = others.length > 0;
|
|
83
|
+
return {
|
|
84
|
+
severity: "error",
|
|
85
|
+
code: "service.unknown",
|
|
86
|
+
message: `No service directory at ${treePath}: ${lead} introduces it${several ? ` (so does ${others.join(", ")})` : ""}, ` +
|
|
87
|
+
`and it is not in the living docs until ${several ? "one of them" : lead} archives. Until then its documents are ` +
|
|
88
|
+
`${several ? `the specs/${service}/ of ${ids.join(", ")}` : `${lead}'s specs/${service}/`} — run ` +
|
|
89
|
+
`\`loam validate --feature ${lead}\`${several ? `, and likewise for ${others.join(", ")},` : ""} to validate them.`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const close = closeIds(service, (await listServices(docsDir, fleet)).map((s) => s.id));
|
|
93
|
+
return {
|
|
94
|
+
severity: "error",
|
|
95
|
+
code: "service.unknown",
|
|
96
|
+
message: `No service directory at ${treePath}.` +
|
|
97
|
+
(close.length > 0
|
|
98
|
+
? ` Did you mean: ${close.join(", ")}?`
|
|
99
|
+
: " `loam list services` shows what exists."),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=introduced.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introduced.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/introduced.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A service an active feature INTRODUCES, as `loam validate` meets it — named\n * by the repository's own binding, or named on the command line.\n *\n * Until the feature archives, such a service's only documents are the\n * feature's `specs/<service>/`: `services/` learns the name at the merge\n * (`core/projection/introduced.ts`, the one answer to \"introduces\" every\n * command reads). `validate` looked only under `services/`, so in that\n * service's own repository a bare `loam validate` refused with\n * `service.unknown` and \"Did you mean: payment-service?\" — it read the newest\n * service in the fleet as a typo, while `loam status` and `loam doctor` in the\n * same repository named the feature that introduces it.\n *\n * Two readings, two answers:\n *\n * the binding (a bare `loam validate`) → the introducing features are\n * validated in the service's place. They hold every document the service\n * has, so theirs is the grade there is to give, and it is `--feature`'s\n * grade target for target — never a slice of it, which would be a green\n * over whatever the slice left out. The run says first which features it\n * validated and why, in `show`'s words for the same fact, so a reader never\n * takes a feature's findings for the service's own.\n * a name (`--service <id>`, the positional) → still a service target, which\n * does not exist, so still `service.unknown` at error: `--service` forces\n * the service reading by contract. Only the prose changes — it names the\n * feature and the command that validates its documents, where it used to\n * offer the nearest living id as the correction.\n *\n * A name nothing introduces keeps the near-miss refusal, byte for byte.\n */\nimport { closeIds } from \"../../../core/c4/arch.js\";\nimport type { FleetContext } from \"../../../core/fleet-context.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { introducingFeatures } from \"../../../core/projection/introduced.js\";\nimport type { FeatureEntry } from \"../../../core/repo/entries.js\";\nimport { listServices } from \"../../../core/repo/repo.js\";\nimport type { ServiceTarget } from \"../../../core/repo/service-target.js\";\nimport type { Finding } from \"../../../core/vocabulary/report.js\";\n\n/** A bound service a bare run validates through the features that introduce it. */\nexport interface IntroducedBinding {\n /** The service loam.json names. */\n service: string;\n /** `introducingFeatures`' answer, ordered by id — never empty. */\n features: FeatureEntry[];\n}\n\n/**\n * The features a bare run validates in place of the bound service — or null\n * when the binding names a living service, or a name nothing introduces, and\n * the run grades it as a service (`service.unknown` and all) exactly as before.\n */\nexport async function introducedBinding(\n docsDir: DocsDir,\n resolved: Extract<ServiceTarget, { ok: true }>,\n fleet: FleetContext,\n): Promise<IntroducedBinding | null> {\n // An enumerated directory is living. `introducingFeatures` would say so too,\n // after reading every feature to learn it.\n if (resolved.dir !== undefined) return null;\n const features = await introducingFeatures(docsDir, resolved.id, fleet);\n return features.length === 0 ? null : { service: resolved.id, features };\n}\n\n/**\n * The two lines a bare run prints above the report: the first is `loam show\n * <service>`'s header for the same state, the second says what was validated\n * instead and why those features.\n */\nexport function introducedLead({ service, features }: IntroducedBinding): string[] {\n const ids = features.map((f) => f.id);\n const several = ids.length > 1;\n const listed = several ? `${ids.slice(0, -1).join(\", \")} and ${ids.slice(-1).join(\"\")}` : ids.join(\"\");\n return [\n `${service} introduced by ${ids.join(\", \")} (in flight) — not in the living docs until ${several ? \"one of them\" : \"it\"} archives`,\n ` validating ${listed} instead: ${several ? \"their\" : \"its\"} specs/${service}/ are this service's documents until then`,\n ];\n}\n\n/**\n * The `--json` payload's `boundService`: why `targets` holds features and no\n * service. The keys are `show`'s and `steps`' for the same fact — `living:\n * false` and `introducedBy` — so a consumer that reads one reads them all.\n */\nexport function introducedJson({ service, features }: IntroducedBinding): {\n id: string;\n living: false;\n introducedBy: string[];\n} {\n return { id: service, living: false, introducedBy: features.map((f) => f.id) };\n}\n\n/**\n * `service.unknown`: no directory under `services/` answers to the name. The\n * hint depends on why. A feature in flight introduces it → name the feature\n * and the command that validates its documents, in `loam doctor`'s words for\n * the same state. Something close is living → the near-miss, which is what\n * makes a typo diagnosable. Neither → where to look. Never `loam adopt`, in any\n * branch: adopting a typo would document the misspelling, and adopting an\n * introduced service would write `services/<id>/` ahead of the merge.\n */\nexport async function unknownServiceFinding(\n docsDir: DocsDir,\n service: string,\n treePath: string,\n fleet: FleetContext,\n): Promise<Finding> {\n const ids = (await introducingFeatures(docsDir, service, fleet)).map((f) => f.id);\n const [lead, ...others] = ids;\n if (lead !== undefined) {\n const several = others.length > 0;\n return {\n severity: \"error\",\n code: \"service.unknown\",\n message:\n `No service directory at ${treePath}: ${lead} introduces it${several ? ` (so does ${others.join(\", \")})` : \"\"}, ` +\n `and it is not in the living docs until ${several ? \"one of them\" : lead} archives. Until then its documents are ` +\n `${several ? `the specs/${service}/ of ${ids.join(\", \")}` : `${lead}'s specs/${service}/`} — run ` +\n `\\`loam validate --feature ${lead}\\`${several ? `, and likewise for ${others.join(\", \")},` : \"\"} to validate them.`,\n };\n }\n const close = closeIds(service, (await listServices(docsDir, fleet)).map((s) => s.id));\n return {\n severity: \"error\",\n code: \"service.unknown\",\n message:\n `No service directory at ${treePath}.` +\n (close.length > 0\n ? ` Did you mean: ${close.join(\", \")}?`\n : \" `loam list services` shows what exists.\"),\n };\n}\n"]}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a requirement document owes, checked the same way wherever it lives.
|
|
3
|
+
*
|
|
4
|
+
* The same `### Requirement:` grammar is authored in four places — a service's
|
|
5
|
+
* spec.md and arch.spec.md, and a feature's per-service deltas of both — and
|
|
6
|
+
* every breach below carries from a delta into the living document through the
|
|
7
|
+
* archive merge. So the checks are one set called from both target kinds
|
|
8
|
+
* (`service/` and `feature/`): grading a delta more leniently than the file it
|
|
9
|
+
* is about to become is how a defect acquires a signature saying it was
|
|
10
|
+
* reviewed.
|
|
11
|
+
*
|
|
12
|
+
* None of these read the filesystem and none of them print — they take parsed
|
|
13
|
+
* requirements and answer in findings.
|
|
14
|
+
*/
|
|
15
|
+
import {} from "../../../core/vocabulary/report.js";
|
|
16
|
+
import { assertionlessFindings, examplesFindings, missingScenariosFinding, requirementsMissingScenarios, steplessFindings, } from "../../../core/document/scenarios.js";
|
|
17
|
+
import { requirementIdProblems } from "../../../core/document/spec.js";
|
|
18
|
+
import { closeIds, coversCandidates, entryResolves, parseCoversEntry, } from "../../../core/c4/arch.js";
|
|
19
|
+
import {} from "../../../core/permissions/permissions.js";
|
|
20
|
+
import {} from "../../../core/openapi/doc.js";
|
|
21
|
+
/** The parsed Covers entries of every requirement that will live (REMOVED covers nothing). */
|
|
22
|
+
export function coversEntries(reqs) {
|
|
23
|
+
return reqs.filter((r) => r.kind !== "REMOVED").flatMap((r) => r.covers.map(parseCoversEntry));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `spec.duplicate-requirement` — two `### Requirement:` blocks with one name in
|
|
27
|
+
* one LIVING document. Nothing else catches it, and the merge algebra
|
|
28
|
+
* (applyRequirementDelta) matches by name and edits only the FIRST match: a
|
|
29
|
+
* later archive rewrites one copy and the other survives as a stale snapshot
|
|
30
|
+
* of whatever the requirement used to say. Per file on purpose — spec.md and
|
|
31
|
+
* arch.spec.md are separate requirement namespaces (their merges never cross
|
|
32
|
+
* files), so one name appearing in both is legal and unflagged.
|
|
33
|
+
*/
|
|
34
|
+
export function duplicateRequirementFindings(reqs, where, subject) {
|
|
35
|
+
const counts = new Map();
|
|
36
|
+
for (const r of reqs)
|
|
37
|
+
counts.set(r.name, (counts.get(r.name) ?? 0) + 1);
|
|
38
|
+
return [...counts]
|
|
39
|
+
.filter(([, n]) => n > 1)
|
|
40
|
+
.map(([name, n]) => ({
|
|
41
|
+
severity: "error",
|
|
42
|
+
code: "spec.duplicate-requirement",
|
|
43
|
+
subject,
|
|
44
|
+
message: `${where}: requirement '${name}' is defined ${n} times — a merge edits only the first, every other copy lives on stale; keep exactly one`,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
/** Stable IDs are optional, but once authored they must select exactly one requirement. */
|
|
48
|
+
export function requirementIdFindings(reqs, where, subject) {
|
|
49
|
+
return requirementIdProblems(reqs).map((problem) => {
|
|
50
|
+
if (problem.kind === "invalid") {
|
|
51
|
+
return {
|
|
52
|
+
severity: "error",
|
|
53
|
+
code: "spec.requirement-id-invalid",
|
|
54
|
+
subject,
|
|
55
|
+
message: `${where}: requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}' — use 1-128 characters matching [A-Za-z][A-Za-z0-9._-]*`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (problem.kind === "repeated") {
|
|
59
|
+
return {
|
|
60
|
+
severity: "error",
|
|
61
|
+
code: "spec.requirement-id-repeated",
|
|
62
|
+
subject,
|
|
63
|
+
message: `${where}: requirement '${problem.requirement}' declares Requirement-ID ${problem.values.length} times — identity must be declared exactly once`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
severity: "error",
|
|
68
|
+
code: "spec.requirement-id-duplicate",
|
|
69
|
+
subject,
|
|
70
|
+
message: `${where}: Requirement-ID '${problem.id}' is shared by ${problem.requirements.map((name) => `'${name}'`).join(", ")} — one ID may identify only one requirement`,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The two list lines of the requirement grammar, exactly as core/document/spec.ts spells
|
|
76
|
+
* them (mirrored here, not exported from there, because the parser's grammar is
|
|
77
|
+
* its own; a drift shows up as this check counting differently than the parser
|
|
78
|
+
* assigns). A SECOND matching line in one requirement body REPLACES the first —
|
|
79
|
+
* assignment, not append, the documented keep-last quirk — so the author's
|
|
80
|
+
* "long list in two lines" pattern silently loses its first line.
|
|
81
|
+
*/
|
|
82
|
+
const OPERATIONS_LINE_RE = /^\s*Operations?:\s*(.+?)\s*$/i;
|
|
83
|
+
const COVERS_LINE_RE = /^\s*Covers?:\s*(.+?)\s*$/i;
|
|
84
|
+
/**
|
|
85
|
+
* `spec.repeated-operations` / `spec.repeated-covers` — warn on the silent
|
|
86
|
+
* loss, keep the keep-last semantics (changing them would re-read every spec
|
|
87
|
+
* in the fleet). Scenario bodies never count: the parser only assigns from the
|
|
88
|
+
* requirement's own body lines, and `Requirement.text` is exactly those.
|
|
89
|
+
* REMOVED requirements are exempt the way coversEntries exempts them — content
|
|
90
|
+
* on its way out obliges nothing.
|
|
91
|
+
*/
|
|
92
|
+
export function repeatedListLineFindings(reqs, where, subject) {
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const r of reqs) {
|
|
95
|
+
if (r.kind === "REMOVED")
|
|
96
|
+
continue;
|
|
97
|
+
for (const { re, label, code } of [
|
|
98
|
+
{ re: OPERATIONS_LINE_RE, label: "Operations:", code: "spec.repeated-operations" },
|
|
99
|
+
{ re: COVERS_LINE_RE, label: "Covers:", code: "spec.repeated-covers" },
|
|
100
|
+
]) {
|
|
101
|
+
const n = r.text.filter((line) => re.test(line)).length;
|
|
102
|
+
if (n < 2)
|
|
103
|
+
continue;
|
|
104
|
+
out.push({
|
|
105
|
+
severity: "warn",
|
|
106
|
+
code,
|
|
107
|
+
subject,
|
|
108
|
+
message: `${where}: requirement '${r.name}' has ${n} '${label}' lines — the last REPLACES the others (assignment, not append), the earlier list is silently lost; merge them into one comma-separated line`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
export function coversUnknownFindings(reqs, target, scope, healthUnreadable = false) {
|
|
115
|
+
const { where, subject } = target;
|
|
116
|
+
const out = [];
|
|
117
|
+
for (const r of reqs) {
|
|
118
|
+
if (r.kind === "REMOVED")
|
|
119
|
+
continue;
|
|
120
|
+
for (const raw of r.covers) {
|
|
121
|
+
const entry = parseCoversEntry(raw);
|
|
122
|
+
if (healthUnreadable && (entry.form === "alert" || entry.form === "sli"))
|
|
123
|
+
continue;
|
|
124
|
+
if (entryResolves(entry, scope))
|
|
125
|
+
continue;
|
|
126
|
+
const close = coversCandidates(entry, scope);
|
|
127
|
+
out.push({
|
|
128
|
+
severity: "warn",
|
|
129
|
+
code: "covers.unknown",
|
|
130
|
+
subject,
|
|
131
|
+
message: `${where}: requirement '${r.name}' — Covers: '${raw}' resolves to nothing` +
|
|
132
|
+
(close.length > 0
|
|
133
|
+
? `. Did you mean: ${close.join(", ")}?`
|
|
134
|
+
: " in the model, the landscape or health.yaml"),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* `permissions.unknown` — the typo guard on the `Requires:` line, and an ERROR
|
|
142
|
+
* where its `Covers:` sibling is a warning.
|
|
143
|
+
*
|
|
144
|
+
* The two differ because what they promise differs. `Covers:` is advisory end
|
|
145
|
+
* to end: a wrong id costs its author the coverage they wrote the line for and
|
|
146
|
+
* nothing else. `Requires:` names authorization the service actually enforces,
|
|
147
|
+
* and the failure it guards is the one an unaided reader cannot see — an
|
|
148
|
+
* invented permission reads exactly like a real one, in the requirement, in the
|
|
149
|
+
* generated scenario, and in the test somebody then writes against it. Its
|
|
150
|
+
* grade is `Operations:`', not `Covers:`'.
|
|
151
|
+
*
|
|
152
|
+
* Silent on ONE case only: an unreadable vocabulary, where
|
|
153
|
+
* `permissions.invalid` is the honest finding and grading every entry against a
|
|
154
|
+
* file nobody could parse is the false cascade `healthUnreadable` exists to
|
|
155
|
+
* stop one axis over. A MISSING vocabulary is not that case — the `Requires:`
|
|
156
|
+
* line is itself the opt-in, and a line that resolves against nothing while
|
|
157
|
+
* reading like a join is the failure this whole axis exists to prevent.
|
|
158
|
+
*/
|
|
159
|
+
export function requiresUnknownFindings(reqs, target, vocabulary) {
|
|
160
|
+
const { where, subject } = target;
|
|
161
|
+
if (vocabulary.invalid !== undefined)
|
|
162
|
+
return [];
|
|
163
|
+
const known = [...vocabulary.byId.keys()];
|
|
164
|
+
const out = [];
|
|
165
|
+
for (const r of reqs) {
|
|
166
|
+
if (r.kind === "REMOVED")
|
|
167
|
+
continue;
|
|
168
|
+
for (const raw of r.requires) {
|
|
169
|
+
if (vocabulary.byId.has(raw))
|
|
170
|
+
continue;
|
|
171
|
+
const close = closeIds(raw, known);
|
|
172
|
+
out.push({
|
|
173
|
+
severity: "error",
|
|
174
|
+
code: "permissions.unknown",
|
|
175
|
+
subject,
|
|
176
|
+
message: `${where}: requirement '${r.name}' — Requires: '${raw}' is not declared in architecture/permissions.yaml` +
|
|
177
|
+
(!vocabulary.present
|
|
178
|
+
? ", which does not exist. The `Requires:` line is the opt-in: create the fleet vocabulary with this permission under its subject kind, or drop the line"
|
|
179
|
+
: close.length > 0
|
|
180
|
+
? `. Did you mean: ${close.join(", ")}?`
|
|
181
|
+
: ". Entries are '<subject>/<permission>'; declare it there, or fix the spelling"),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return out;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* `api.response-ungoverned` — a declared 4xx/5xx response no scenario reaches.
|
|
189
|
+
*
|
|
190
|
+
* The gap this closes is the one a whole adoption can fall into: `api.ungoverned`
|
|
191
|
+
* grades OPERATIONS against requirements, so an endpoint with one happy-path
|
|
192
|
+
* requirement and twelve declared failure codes is fully governed by every
|
|
193
|
+
* check loam had. The refusals are where a service's decision layer surfaces —
|
|
194
|
+
* a permission denied, a field combination rejected, a state that forbids the
|
|
195
|
+
* transition — and the contract is the only artifact in the corpus that already
|
|
196
|
+
* enumerates them.
|
|
197
|
+
*
|
|
198
|
+
* A scenario "reaches" a code when the code appears as a standalone number
|
|
199
|
+
* anywhere in its body, `Examples` rows included — which is why this arrived
|
|
200
|
+
* with outline support and not before: a status column is exactly where a
|
|
201
|
+
* matrix puts its codes, and before it those rows were prose in a description.
|
|
202
|
+
* The match is textual and therefore generous by design. It answers "did
|
|
203
|
+
* anybody write this case down", not "is this scenario correct", and the
|
|
204
|
+
* failure it is built to catch is the code nobody mentioned at all. Warn, like
|
|
205
|
+
* its sibling: a service may legitimately declare a code its scenarios describe
|
|
206
|
+
* in words, and an error would teach authors to paste numbers into prose.
|
|
207
|
+
*
|
|
208
|
+
* Operations no requirement governs are skipped: `api.ungoverned` already
|
|
209
|
+
* names those, and reporting each of their codes as well is one defect
|
|
210
|
+
* counted twice.
|
|
211
|
+
*/
|
|
212
|
+
export function responseGovernanceFindings(service, ops, livingReqs) {
|
|
213
|
+
const ungoverned = [];
|
|
214
|
+
for (const op of ops) {
|
|
215
|
+
if (op.failureCodes.length === 0)
|
|
216
|
+
continue;
|
|
217
|
+
const governing = livingReqs.filter((r) => r.kind !== "REMOVED" && r.operations.includes(op.id));
|
|
218
|
+
if (governing.length === 0)
|
|
219
|
+
continue;
|
|
220
|
+
const body = governing.flatMap((r) => r.scenarios.flatMap((s) => s.lines)).join("\n");
|
|
221
|
+
const missing = op.failureCodes.filter((code) => !new RegExp(`(?<!\\d)${code}(?!\\d)`).test(body));
|
|
222
|
+
if (missing.length > 0)
|
|
223
|
+
ungoverned.push(`${op.id}: ${missing.join(", ")}`);
|
|
224
|
+
}
|
|
225
|
+
if (ungoverned.length === 0)
|
|
226
|
+
return [];
|
|
227
|
+
return [
|
|
228
|
+
{
|
|
229
|
+
severity: "warn",
|
|
230
|
+
code: "api.response-ungoverned",
|
|
231
|
+
subject: service,
|
|
232
|
+
message: `${service}: ${ungoverned.length} operation(s) declare a failure response no scenario reaches — write the refusal as a scenario, or as a row in one`,
|
|
233
|
+
details: ungoverned,
|
|
234
|
+
},
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
export function coverageFinding(label, reqs) {
|
|
238
|
+
const missing = requirementsMissingScenarios(reqs);
|
|
239
|
+
if (missing.length === 0) {
|
|
240
|
+
return {
|
|
241
|
+
severity: "ok",
|
|
242
|
+
code: "requirements.covered",
|
|
243
|
+
message: `${label} covered (${reqs.length} requirement${reqs.length === 1 ? "" : "s"}, all with scenarios)`,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return { ...missingScenariosFinding(label, missing), text: { detailPrefix: "- " } };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The scenario-shape run of the battery every requirement document gets, in
|
|
250
|
+
* report order — stepless, assertionless, examples — spelled once for the four
|
|
251
|
+
* documents the header names, so they cannot drift apart. What differs between
|
|
252
|
+
* the four stays at each call site: a delta's coverage finding carries its
|
|
253
|
+
* service as `subject`, a living spec.md with no requirements reports
|
|
254
|
+
* `spec.no-requirements` in coverage's place, and duplicate names and
|
|
255
|
+
* requirement ids are graded on LIVING documents (`duplicateRequirementFindings`).
|
|
256
|
+
*/
|
|
257
|
+
export function scenarioShapeFindings(label, subject, reqs) {
|
|
258
|
+
return [
|
|
259
|
+
...steplessFindings(label, subject, reqs),
|
|
260
|
+
...assertionlessFindings(label, subject, reqs),
|
|
261
|
+
...examplesFindings(label, subject, reqs),
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/requirements.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a requirement document owes, checked the same way wherever it lives.\n *\n * The same `### Requirement:` grammar is authored in four places — a service's\n * spec.md and arch.spec.md, and a feature's per-service deltas of both — and\n * every breach below carries from a delta into the living document through the\n * archive merge. So the checks are one set called from both target kinds\n * (`service/` and `feature/`): grading a delta more leniently than the file it\n * is about to become is how a defect acquires a signature saying it was\n * reviewed.\n *\n * None of these read the filesystem and none of them print — they take parsed\n * requirements and answer in findings.\n */\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport {\n assertionlessFindings,\n examplesFindings,\n missingScenariosFinding,\n requirementsMissingScenarios,\n steplessFindings,\n} from \"../../../core/document/scenarios.js\";\nimport { requirementIdProblems, type Requirement } from \"../../../core/document/spec.js\";\nimport {\n closeIds,\n coversCandidates,\n entryResolves,\n parseCoversEntry,\n type CoverageScope,\n type CoversEntry,\n} from \"../../../core/c4/arch.js\";\nimport { type Vocabulary } from \"../../../core/permissions/permissions.js\";\nimport { type Operation } from \"../../../core/openapi/doc.js\";\n\n/** The parsed Covers entries of every requirement that will live (REMOVED covers nothing). */\nexport function coversEntries(reqs: Requirement[]): CoversEntry[] {\n return reqs.filter((r) => r.kind !== \"REMOVED\").flatMap((r) => r.covers.map(parseCoversEntry));\n}\n\n/**\n * `spec.duplicate-requirement` — two `### Requirement:` blocks with one name in\n * one LIVING document. Nothing else catches it, and the merge algebra\n * (applyRequirementDelta) matches by name and edits only the FIRST match: a\n * later archive rewrites one copy and the other survives as a stale snapshot\n * of whatever the requirement used to say. Per file on purpose — spec.md and\n * arch.spec.md are separate requirement namespaces (their merges never cross\n * files), so one name appearing in both is legal and unflagged.\n */\nexport function duplicateRequirementFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n const counts = new Map<string, number>();\n for (const r of reqs) counts.set(r.name, (counts.get(r.name) ?? 0) + 1);\n return [...counts]\n .filter(([, n]) => n > 1)\n .map(([name, n]) => ({\n severity: \"error\" as const,\n code: \"spec.duplicate-requirement\",\n subject,\n message: `${where}: requirement '${name}' is defined ${n} times — a merge edits only the first, every other copy lives on stale; keep exactly one`,\n }));\n}\n\n/** Stable IDs are optional, but once authored they must select exactly one requirement. */\nexport function requirementIdFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n return requirementIdProblems(reqs).map((problem) => {\n if (problem.kind === \"invalid\") {\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-invalid\",\n subject,\n message: `${where}: requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}' — use 1-128 characters matching [A-Za-z][A-Za-z0-9._-]*`,\n };\n }\n if (problem.kind === \"repeated\") {\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-repeated\",\n subject,\n message: `${where}: requirement '${problem.requirement}' declares Requirement-ID ${problem.values.length} times — identity must be declared exactly once`,\n };\n }\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-duplicate\",\n subject,\n message: `${where}: Requirement-ID '${problem.id}' is shared by ${problem.requirements.map((name) => `'${name}'`).join(\", \")} — one ID may identify only one requirement`,\n };\n });\n}\n\n/**\n * The two list lines of the requirement grammar, exactly as core/document/spec.ts spells\n * them (mirrored here, not exported from there, because the parser's grammar is\n * its own; a drift shows up as this check counting differently than the parser\n * assigns). A SECOND matching line in one requirement body REPLACES the first —\n * assignment, not append, the documented keep-last quirk — so the author's\n * \"long list in two lines\" pattern silently loses its first line.\n */\nconst OPERATIONS_LINE_RE = /^\\s*Operations?:\\s*(.+?)\\s*$/i;\nconst COVERS_LINE_RE = /^\\s*Covers?:\\s*(.+?)\\s*$/i;\n\n/**\n * `spec.repeated-operations` / `spec.repeated-covers` — warn on the silent\n * loss, keep the keep-last semantics (changing them would re-read every spec\n * in the fleet). Scenario bodies never count: the parser only assigns from the\n * requirement's own body lines, and `Requirement.text` is exactly those.\n * REMOVED requirements are exempt the way coversEntries exempts them — content\n * on its way out obliges nothing.\n */\nexport function repeatedListLineFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const { re, label, code } of [\n { re: OPERATIONS_LINE_RE, label: \"Operations:\", code: \"spec.repeated-operations\" },\n { re: COVERS_LINE_RE, label: \"Covers:\", code: \"spec.repeated-covers\" },\n ]) {\n const n = r.text.filter((line) => re.test(line)).length;\n if (n < 2) continue;\n out.push({\n severity: \"warn\",\n code,\n subject,\n message: `${where}: requirement '${r.name}' has ${n} '${label}' lines — the last REPLACES the others (assignment, not append), the earlier list is silently lost; merge them into one comma-separated line`,\n });\n }\n }\n return out;\n}\n\n/**\n * `covers.unknown` — the typo guard on the Covers: line. Warn, not error: the\n * axis is advisory end to end, and a wrong id already costs its author the\n * coverage they wrote the line for. The hint offers only real ids (closeIds's\n * rule), and says where resolution looked when there is nothing close.\n * `healthUnreadable` mutes the alert:/sli: forms only: against a health.yaml\n * nobody could read, \"did you mean\" is a false diagnosis of a typo —\n * health.invalid (emitted by the service target) is the honest one.\n */\n/** Which document is being graded, and under whose name the finding is filed. */\nexport interface CoverageTarget {\n where: string;\n subject: string;\n}\n\nexport function coversUnknownFindings(\n reqs: Requirement[],\n target: CoverageTarget,\n scope: CoverageScope,\n healthUnreadable = false,\n): Finding[] {\n const { where, subject } = target;\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const raw of r.covers) {\n const entry = parseCoversEntry(raw);\n if (healthUnreadable && (entry.form === \"alert\" || entry.form === \"sli\")) continue;\n if (entryResolves(entry, scope)) continue;\n const close = coversCandidates(entry, scope);\n out.push({\n severity: \"warn\",\n code: \"covers.unknown\",\n subject,\n message:\n `${where}: requirement '${r.name}' — Covers: '${raw}' resolves to nothing` +\n (close.length > 0\n ? `. Did you mean: ${close.join(\", \")}?`\n : \" in the model, the landscape or health.yaml\"),\n });\n }\n }\n return out;\n}\n\n/**\n * `permissions.unknown` — the typo guard on the `Requires:` line, and an ERROR\n * where its `Covers:` sibling is a warning.\n *\n * The two differ because what they promise differs. `Covers:` is advisory end\n * to end: a wrong id costs its author the coverage they wrote the line for and\n * nothing else. `Requires:` names authorization the service actually enforces,\n * and the failure it guards is the one an unaided reader cannot see — an\n * invented permission reads exactly like a real one, in the requirement, in the\n * generated scenario, and in the test somebody then writes against it. Its\n * grade is `Operations:`', not `Covers:`'.\n *\n * Silent on ONE case only: an unreadable vocabulary, where\n * `permissions.invalid` is the honest finding and grading every entry against a\n * file nobody could parse is the false cascade `healthUnreadable` exists to\n * stop one axis over. A MISSING vocabulary is not that case — the `Requires:`\n * line is itself the opt-in, and a line that resolves against nothing while\n * reading like a join is the failure this whole axis exists to prevent.\n */\nexport function requiresUnknownFindings(\n reqs: Requirement[],\n target: CoverageTarget,\n vocabulary: Vocabulary,\n): Finding[] {\n const { where, subject } = target;\n if (vocabulary.invalid !== undefined) return [];\n const known = [...vocabulary.byId.keys()];\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const raw of r.requires) {\n if (vocabulary.byId.has(raw)) continue;\n const close = closeIds(raw, known);\n out.push({\n severity: \"error\",\n code: \"permissions.unknown\",\n subject,\n message:\n `${where}: requirement '${r.name}' — Requires: '${raw}' is not declared in architecture/permissions.yaml` +\n (!vocabulary.present\n ? \", which does not exist. The `Requires:` line is the opt-in: create the fleet vocabulary with this permission under its subject kind, or drop the line\"\n : close.length > 0\n ? `. Did you mean: ${close.join(\", \")}?`\n : \". Entries are '<subject>/<permission>'; declare it there, or fix the spelling\"),\n });\n }\n }\n return out;\n}\n\n/**\n * `api.response-ungoverned` — a declared 4xx/5xx response no scenario reaches.\n *\n * The gap this closes is the one a whole adoption can fall into: `api.ungoverned`\n * grades OPERATIONS against requirements, so an endpoint with one happy-path\n * requirement and twelve declared failure codes is fully governed by every\n * check loam had. The refusals are where a service's decision layer surfaces —\n * a permission denied, a field combination rejected, a state that forbids the\n * transition — and the contract is the only artifact in the corpus that already\n * enumerates them.\n *\n * A scenario \"reaches\" a code when the code appears as a standalone number\n * anywhere in its body, `Examples` rows included — which is why this arrived\n * with outline support and not before: a status column is exactly where a\n * matrix puts its codes, and before it those rows were prose in a description.\n * The match is textual and therefore generous by design. It answers \"did\n * anybody write this case down\", not \"is this scenario correct\", and the\n * failure it is built to catch is the code nobody mentioned at all. Warn, like\n * its sibling: a service may legitimately declare a code its scenarios describe\n * in words, and an error would teach authors to paste numbers into prose.\n *\n * Operations no requirement governs are skipped: `api.ungoverned` already\n * names those, and reporting each of their codes as well is one defect\n * counted twice.\n */\nexport function responseGovernanceFindings(\n service: string,\n ops: Operation[],\n livingReqs: Requirement[],\n): Finding[] {\n const ungoverned: string[] = [];\n for (const op of ops) {\n if (op.failureCodes.length === 0) continue;\n const governing = livingReqs.filter((r) => r.kind !== \"REMOVED\" && r.operations.includes(op.id));\n if (governing.length === 0) continue;\n const body = governing.flatMap((r) => r.scenarios.flatMap((s) => s.lines)).join(\"\\n\");\n const missing = op.failureCodes.filter((code) => !new RegExp(`(?<!\\\\d)${code}(?!\\\\d)`).test(body));\n if (missing.length > 0) ungoverned.push(`${op.id}: ${missing.join(\", \")}`);\n }\n if (ungoverned.length === 0) return [];\n return [\n {\n severity: \"warn\",\n code: \"api.response-ungoverned\",\n subject: service,\n message: `${service}: ${ungoverned.length} operation(s) declare a failure response no scenario reaches — write the refusal as a scenario, or as a row in one`,\n details: ungoverned,\n },\n ];\n}\n\nexport function coverageFinding(label: string, reqs: Requirement[]): Finding {\n const missing = requirementsMissingScenarios(reqs);\n if (missing.length === 0) {\n return {\n severity: \"ok\",\n code: \"requirements.covered\",\n message: `${label} covered (${reqs.length} requirement${reqs.length === 1 ? \"\" : \"s\"}, all with scenarios)`,\n };\n }\n return { ...missingScenariosFinding(label, missing), text: { detailPrefix: \"- \" } };\n}\n\n/**\n * The scenario-shape run of the battery every requirement document gets, in\n * report order — stepless, assertionless, examples — spelled once for the four\n * documents the header names, so they cannot drift apart. What differs between\n * the four stays at each call site: a delta's coverage finding carries its\n * service as `subject`, a living spec.md with no requirements reports\n * `spec.no-requirements` in coverage's place, and duplicate names and\n * requirement ids are graded on LIVING documents (`duplicateRequirementFindings`).\n */\nexport function scenarioShapeFindings(label: string, subject: string, reqs: Requirement[]): Finding[] {\n return [\n ...steplessFindings(label, subject, reqs),\n ...assertionlessFindings(label, subject, reqs),\n ...examplesFindings(label, subject, reqs),\n ];\n}\n"]}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import {} from "../../../core/kernel/ids/service.js";
|
|
3
|
+
import { SPEC_AXES } from "../../../core/repo/paths.js";
|
|
4
|
+
import { locateServicePaths } from "../../../core/repo/service-target.js";
|
|
5
|
+
import { listField, readFrontmatter } from "../../../core/document/frontmatter.js";
|
|
6
|
+
import {} from "../../../core/vocabulary/report.js";
|
|
7
|
+
import { missingSources, patternSources, unsafeSources } from "../../../core/provenance/sources.js";
|
|
8
|
+
import { emptySourcesMessage, expandSourceFiles } from "../../../core/provenance/stamp.js";
|
|
9
|
+
/**
|
|
10
|
+
* The two things a `sources` list can be that `serviceProvenance` cannot say.
|
|
11
|
+
*
|
|
12
|
+
* `sources.unverifiable-from-here` — the spec names sources and loam is NOT in
|
|
13
|
+
* that service's repository, so every sources check (existence, digest,
|
|
14
|
+
* staleness) is skipped. serviceProvenance returns an empty list in that case
|
|
15
|
+
* and the silence read as "checked and fine". It used to be counted only under
|
|
16
|
+
* `--all` and printed as one rollup line, which meant `validate --service X`
|
|
17
|
+
* run from the docs repo — the single most common way anyone looks at one
|
|
18
|
+
* service — reported nothing at all about its own blind spot. Severity `ok`,
|
|
19
|
+
* deliberately: nothing is WRONG with the docs, the check simply cannot run
|
|
20
|
+
* here, and grading it a warning would make a fully documented fleet
|
|
21
|
+
* permanently yellow and `--strict` permanently red in the docs repo's CI.
|
|
22
|
+
*
|
|
23
|
+
* `sources.empty` — the paths exist, and expand to no files at all: an empty
|
|
24
|
+
* directory, or a tree the repository itself ignores. A digest over nothing
|
|
25
|
+
* never changes, so the stamp would read as current forever. `loam vouch`
|
|
26
|
+
* already refuses to stamp it; until now `validate` said nothing, so an author
|
|
27
|
+
* got a green run followed by a refusal, two commands contradicting each other
|
|
28
|
+
* about one document. The sentence comes from `emptySourcesMessage`, the same
|
|
29
|
+
* definition vouch refuses with, under the label vouch uses.
|
|
30
|
+
*/
|
|
31
|
+
export async function sourceScopeFindings(docsDir, service, repoDir, fleet) {
|
|
32
|
+
const paths = await locateServicePaths(docsDir, service, fleet);
|
|
33
|
+
const out = [];
|
|
34
|
+
// The axis pair is SPEC_AXES', not this function's: `serviceProvenance` grades
|
|
35
|
+
// the same two files from the same list, and a scope check that walked a
|
|
36
|
+
// shorter list than the grading would go quiet on the axis it forgot.
|
|
37
|
+
for (const { path, file } of SPEC_AXES.map((axis) => ({ path: paths[axis.key], file: axis.file }))) {
|
|
38
|
+
if (!existsSync(path))
|
|
39
|
+
continue;
|
|
40
|
+
const sources = listField(await readFrontmatter(path), "sources");
|
|
41
|
+
if (sources.length === 0)
|
|
42
|
+
continue;
|
|
43
|
+
// vouch's own labelling: a bare service id for spec.md, qualified for the
|
|
44
|
+
// arch axis. The refusal and the finding must be the same sentence.
|
|
45
|
+
const label = file === "spec.md" ? service : `${service}: ${file}`;
|
|
46
|
+
if (repoDir === undefined) {
|
|
47
|
+
// A literal, as at the rollup's counting site (../report.ts), and for
|
|
48
|
+
// the reason given there: the stable-code collector reads only literal
|
|
49
|
+
// `code:` slots. This used to be a shared constant, which kept the two
|
|
50
|
+
// spellings equal but hid the emission itself from the collector — the
|
|
51
|
+
// code was guarded only because the rollup's text marker spelled it.
|
|
52
|
+
//
|
|
53
|
+
// `ok` still, but never PRINTED as ✓: the check above did not run, and
|
|
54
|
+
// a check mark beside "nothing here can resolve them" read as a pass.
|
|
55
|
+
// The hint changes the glyph and nothing a machine or an exit code reads.
|
|
56
|
+
out.push({
|
|
57
|
+
severity: "ok",
|
|
58
|
+
code: "sources.unverifiable-from-here",
|
|
59
|
+
subject: service,
|
|
60
|
+
message: `${label}: ${sources.length} source(s) declared, but this is not ${service}'s repository — nothing here can resolve them. Run \`loam validate --service ${service}\` from inside it.`,
|
|
61
|
+
text: { marker: "not-checked" },
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Every other shape of broken list is serviceProvenance's to grade, and
|
|
66
|
+
// grading them twice would send an author fixing one thing from two
|
|
67
|
+
// findings. "Covers no files" is only meaningful once the paths are real.
|
|
68
|
+
if (patternSources(sources).length > 0 ||
|
|
69
|
+
unsafeSources(repoDir, sources).length > 0 ||
|
|
70
|
+
missingSources(repoDir, sources).length > 0) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const expansion = await expandSourceFiles(repoDir, sources, label);
|
|
74
|
+
if (expansion.files.length > 0)
|
|
75
|
+
continue;
|
|
76
|
+
out.push({
|
|
77
|
+
severity: "warn",
|
|
78
|
+
code: "sources.empty",
|
|
79
|
+
subject: service,
|
|
80
|
+
message: expansion.empty ?? emptySourcesMessage(label, sources),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/sources.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { type PathableService } from \"../../../core/kernel/ids/service.js\";\nimport { SPEC_AXES } from \"../../../core/repo/paths.js\";\nimport type { FleetContext } from \"../../../core/fleet-context.js\";\nimport { locateServicePaths } from \"../../../core/repo/service-target.js\";\nimport { listField, readFrontmatter } from \"../../../core/document/frontmatter.js\";\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport { missingSources, patternSources, unsafeSources } from \"../../../core/provenance/sources.js\";\nimport { emptySourcesMessage, expandSourceFiles } from \"../../../core/provenance/stamp.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\n/**\n * The two things a `sources` list can be that `serviceProvenance` cannot say.\n *\n * `sources.unverifiable-from-here` — the spec names sources and loam is NOT in\n * that service's repository, so every sources check (existence, digest,\n * staleness) is skipped. serviceProvenance returns an empty list in that case\n * and the silence read as \"checked and fine\". It used to be counted only under\n * `--all` and printed as one rollup line, which meant `validate --service X`\n * run from the docs repo — the single most common way anyone looks at one\n * service — reported nothing at all about its own blind spot. Severity `ok`,\n * deliberately: nothing is WRONG with the docs, the check simply cannot run\n * here, and grading it a warning would make a fully documented fleet\n * permanently yellow and `--strict` permanently red in the docs repo's CI.\n *\n * `sources.empty` — the paths exist, and expand to no files at all: an empty\n * directory, or a tree the repository itself ignores. A digest over nothing\n * never changes, so the stamp would read as current forever. `loam vouch`\n * already refuses to stamp it; until now `validate` said nothing, so an author\n * got a green run followed by a refusal, two commands contradicting each other\n * about one document. The sentence comes from `emptySourcesMessage`, the same\n * definition vouch refuses with, under the label vouch uses.\n */\nexport async function sourceScopeFindings(\n docsDir: DocsDir,\n service: PathableService,\n repoDir: string | undefined,\n fleet: FleetContext,\n): Promise<Finding[]> {\n const paths = await locateServicePaths(docsDir, service, fleet);\n const out: Finding[] = [];\n // The axis pair is SPEC_AXES', not this function's: `serviceProvenance` grades\n // the same two files from the same list, and a scope check that walked a\n // shorter list than the grading would go quiet on the axis it forgot.\n for (const { path, file } of SPEC_AXES.map((axis) => ({ path: paths[axis.key], file: axis.file }))) {\n if (!existsSync(path)) continue;\n const sources = listField(await readFrontmatter(path), \"sources\");\n if (sources.length === 0) continue;\n // vouch's own labelling: a bare service id for spec.md, qualified for the\n // arch axis. The refusal and the finding must be the same sentence.\n const label = file === \"spec.md\" ? service : `${service}: ${file}`;\n if (repoDir === undefined) {\n // A literal, as at the rollup's counting site (../report.ts), and for\n // the reason given there: the stable-code collector reads only literal\n // `code:` slots. This used to be a shared constant, which kept the two\n // spellings equal but hid the emission itself from the collector — the\n // code was guarded only because the rollup's text marker spelled it.\n //\n // `ok` still, but never PRINTED as ✓: the check above did not run, and\n // a check mark beside \"nothing here can resolve them\" read as a pass.\n // The hint changes the glyph and nothing a machine or an exit code reads.\n out.push({\n severity: \"ok\",\n code: \"sources.unverifiable-from-here\",\n subject: service,\n message: `${label}: ${sources.length} source(s) declared, but this is not ${service}'s repository — nothing here can resolve them. Run \\`loam validate --service ${service}\\` from inside it.`,\n text: { marker: \"not-checked\" },\n });\n continue;\n }\n // Every other shape of broken list is serviceProvenance's to grade, and\n // grading them twice would send an author fixing one thing from two\n // findings. \"Covers no files\" is only meaningful once the paths are real.\n if (\n patternSources(sources).length > 0 ||\n unsafeSources(repoDir, sources).length > 0 ||\n missingSources(repoDir, sources).length > 0\n ) {\n continue;\n }\n const expansion = await expandSourceFiles(repoDir, sources, label);\n if (expansion.files.length > 0) continue;\n out.push({\n severity: \"warn\",\n code: \"sources.empty\",\n subject: service,\n message: expansion.empty ?? emptySourcesMessage(label, sources),\n });\n }\n return out;\n}\n"]}
|