@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.1
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 +2548 -86
- package/COMPARISON.md +80 -63
- package/CONTRIBUTING.md +84 -0
- package/MIGRATING-from-OpenSpec.md +213 -54
- package/QUICKSTART.md +125 -0
- package/README.md +450 -150
- package/ROADMAP.md +494 -0
- package/SCHEMA.md +2355 -256
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +701 -0
- package/dist/cli.js +113 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +209 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +268 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +77 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +159 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +317 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +161 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +111 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +237 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +27 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +251 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/context/context.js +99 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +283 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +279 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +205 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +9 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +93 -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 +5 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +151 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +29 -24
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +115 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +54 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +146 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +246 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +149 -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 +28 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +146 -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 +65 -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 +157 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +343 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +301 -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/views.js +105 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +183 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +34 -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 +170 -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 +142 -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 +91 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +19 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +43 -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/commit.js +76 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/new.js +283 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +355 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +203 -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} +11 -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 +275 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +192 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +133 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +172 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +178 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/marks.js +24 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/{show.js → show/service.js} +63 -152
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +77 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/json.js +45 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +157 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +119 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +189 -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 +265 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +115 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +101 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +103 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +94 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +70 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +160 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +67 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +194 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +296 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +55 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +254 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +76 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/checks/vocabulary.js +31 -0
- package/dist/commands/validate/checks/vocabulary.js.map +1 -0
- package/dist/commands/validate/feature.js +216 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +69 -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 +353 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +52 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +236 -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 +63 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.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/usecases/requirement-tag.js +95 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/steps.js +197 -0
- package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +40 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +59 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +92 -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/report.js +269 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/service/api.js +338 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +219 -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 +131 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/service.js +250 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +219 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +113 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/validate.js +338 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +182 -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 +72 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +241 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +226 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +223 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +246 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +217 -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 +271 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +142 -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 +285 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +125 -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 +123 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +176 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/artifacts.js +220 -0
- package/dist/core/agent/agents-md/artifacts.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +324 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/cycle.js +165 -0
- package/dist/core/agent/agents-md/cycle.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +34 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +41 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +62 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +32 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +60 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +246 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
- package/dist/core/agent/agents-md/spine.js +40 -0
- package/dist/core/agent/agents-md/spine.js.map +1 -0
- package/dist/core/agent/agents-md.js +170 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -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 +259 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +103 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +150 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +228 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +133 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +334 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +262 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +105 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +105 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +209 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +65 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +188 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +16 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +297 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +110 -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 +141 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +91 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +33 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +308 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +215 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +107 -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.js → asyncapi/read.js} +95 -109
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +225 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +250 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +194 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/targets.js +226 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +47 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +282 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +88 -0
- package/dist/core/c4/likec4.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 +57 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +75 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/project/architecture.js +45 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/documents.js +58 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +183 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/resolve/service.js +113 -0
- package/dist/core/c4/resolve/service.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 +109 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/source-mask.js +82 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +227 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +101 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +10 -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/edges.js +36 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +269 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +194 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/workspace.js +172 -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 +50 -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 +342 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +181 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +143 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +199 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +126 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +277 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +177 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +74 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/coherence.js +251 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/declared.js +269 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +206 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +204 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +166 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +122 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/merged.js +40 -0
- package/dist/core/coherence/events/merged.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 +155 -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/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.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 +296 -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/diff/base-git.js +148 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +209 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/current-state.js +96 -0
- package/dist/core/diff/current-state.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +188 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/semantic.js +243 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/diff/victims.js +247 -0
- package/dist/core/diff/victims.js.map +1 -0
- package/dist/core/docs.js +7 -64
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +222 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +135 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +275 -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/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +77 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -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 +263 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +221 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +241 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +79 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +175 -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 +175 -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 +181 -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.js +144 -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.js → explore/explore.js} +50 -101
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +120 -78
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +201 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +205 -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 +113 -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 +234 -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 +106 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +86 -0
- package/dist/core/glossary/tree.js.map +1 -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/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} +18 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +68 -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 +104 -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 +236 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +111 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +72 -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 +314 -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 +166 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +112 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +175 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/depth.js +122 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +189 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +44 -106
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +234 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +26 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +208 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +256 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +128 -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 +221 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +76 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +65 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +235 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +200 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +260 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +133 -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 +118 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +76 -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/provenance/findings.js +208 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +225 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +182 -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 +263 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +232 -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 +192 -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 +236 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +248 -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 +52 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +64 -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/views.js +172 -0
- package/dist/core/repo/tree/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +234 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +99 -2
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +131 -0
- package/dist/core/scaffold/landscape.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 +241 -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 +206 -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 +98 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +126 -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.js +202 -0
- package/dist/core/staging/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +171 -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 +49 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +102 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +171 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +207 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +150 -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/fleet/fleet.js +187 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +207 -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 +201 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/usecases/capability.js +169 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +116 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +103 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +235 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +137 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/operations.js +111 -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/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +173 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +150 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +201 -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/file.js +257 -0
- package/dist/core/verify/file.js.map +1 -0
- package/dist/core/verify/pins/lint.js +157 -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/record.js +142 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +89 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +57 -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 +55 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +145 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/{report.js → vocabulary/report.js} +30 -2
- 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 +189 -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 +280 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/subsystems.likec4 +11 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +65 -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 +129 -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 +28 -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 +70 -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 +9 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +109 -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 +127 -0
- package/examples/docs/services/order-service/asyncapi.yaml +108 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +138 -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 +73 -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 +67 -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 +117 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +83 -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 +199 -0
- package/examples/docs/services/platform/notification-service/health.yaml +35 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +118 -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.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- 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.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.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.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
- /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
- /package/dist/core/{records.js → kernel/records.js} +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
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 { requirementsMissingScenarios } 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 {
|
|
247
|
+
severity: "error",
|
|
248
|
+
code: "requirements.missing-scenarios",
|
|
249
|
+
message: `${label}: ${missing.length} requirement(s) without a scenario`,
|
|
250
|
+
details: missing.map((r) => r.name),
|
|
251
|
+
text: { detailPrefix: "- " },
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
//# 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 { requirementsMissingScenarios } 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 {\n severity: \"error\",\n code: \"requirements.missing-scenarios\",\n message: `${label}: ${missing.length} requirement(s) without a scenario`,\n details: missing.map((r) => r.name),\n text: { detailPrefix: \"- \" },\n };\n}\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
import { UNVERIFIABLE } from "./vocabulary.js";
|
|
10
|
+
/**
|
|
11
|
+
* The two things a `sources` list can be that `serviceProvenance` cannot say.
|
|
12
|
+
*
|
|
13
|
+
* `sources.unverifiable-from-here` — the spec names sources and loam is NOT in
|
|
14
|
+
* that service's repository, so every sources check (existence, digest,
|
|
15
|
+
* staleness) is skipped. serviceProvenance returns an empty list in that case
|
|
16
|
+
* and the silence read as "checked and fine". It used to be counted only under
|
|
17
|
+
* `--all` and printed as one rollup line, which meant `validate --service X`
|
|
18
|
+
* run from the docs repo — the single most common way anyone looks at one
|
|
19
|
+
* service — reported nothing at all about its own blind spot. Severity `ok`,
|
|
20
|
+
* deliberately: nothing is WRONG with the docs, the check simply cannot run
|
|
21
|
+
* here, and grading it a warning would make a fully documented fleet
|
|
22
|
+
* permanently yellow and `--strict` permanently red in the docs repo's CI.
|
|
23
|
+
*
|
|
24
|
+
* `sources.empty` — the paths exist, and expand to no files at all: an empty
|
|
25
|
+
* directory, or a tree the repository itself ignores. A digest over nothing
|
|
26
|
+
* never changes, so the stamp would read as current forever. `loam vouch`
|
|
27
|
+
* already refuses to stamp it; until now `validate` said nothing, so an author
|
|
28
|
+
* got a green run followed by a refusal, two commands contradicting each other
|
|
29
|
+
* about one document. The sentence comes from `emptySourcesMessage`, the same
|
|
30
|
+
* definition vouch refuses with, under the label vouch uses.
|
|
31
|
+
*/
|
|
32
|
+
export async function sourceScopeFindings(docsDir, service, repoDir, fleet) {
|
|
33
|
+
const paths = await locateServicePaths(docsDir, service, fleet);
|
|
34
|
+
const out = [];
|
|
35
|
+
// The axis pair is SPEC_AXES', not this function's: `serviceProvenance` grades
|
|
36
|
+
// the same two files from the same list, and a scope check that walked a
|
|
37
|
+
// shorter list than the grading would go quiet on the axis it forgot.
|
|
38
|
+
for (const { path, file } of SPEC_AXES.map((axis) => ({ path: paths[axis.key], file: axis.file }))) {
|
|
39
|
+
if (!existsSync(path))
|
|
40
|
+
continue;
|
|
41
|
+
const sources = listField(await readFrontmatter(path), "sources");
|
|
42
|
+
if (sources.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
// vouch's own labelling: a bare service id for spec.md, qualified for the
|
|
45
|
+
// arch axis. The refusal and the finding must be the same sentence.
|
|
46
|
+
const label = file === "spec.md" ? service : `${service}: ${file}`;
|
|
47
|
+
if (repoDir === undefined) {
|
|
48
|
+
out.push({
|
|
49
|
+
severity: "ok",
|
|
50
|
+
code: UNVERIFIABLE,
|
|
51
|
+
subject: service,
|
|
52
|
+
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.`,
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Every other shape of broken list is serviceProvenance's to grade, and
|
|
57
|
+
// grading them twice would send an author fixing one thing from two
|
|
58
|
+
// findings. "Covers no files" is only meaningful once the paths are real.
|
|
59
|
+
if (patternSources(sources).length > 0 ||
|
|
60
|
+
unsafeSources(repoDir, sources).length > 0 ||
|
|
61
|
+
missingSources(repoDir, sources).length > 0) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const expansion = await expandSourceFiles(repoDir, sources, label);
|
|
65
|
+
if (expansion.files.length > 0)
|
|
66
|
+
continue;
|
|
67
|
+
out.push({
|
|
68
|
+
severity: "warn",
|
|
69
|
+
code: "sources.empty",
|
|
70
|
+
subject: service,
|
|
71
|
+
message: expansion.empty ?? emptySourcesMessage(label, sources),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/sources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAwB,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAgB,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAgB,EAChB,OAAwB,EACxB,OAA2B,EAC3B,KAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAChE,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,yEAAyE;IACzE,sEAAsE;IACtE,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACnG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,0EAA0E;QAC1E,oEAAoE;QACpE,MAAM,KAAK,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,IAAI,EAAE,CAAC;QACnE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC;gBACP,QAAQ,EAAE,IAAI;gBACd,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,OAAO;gBAChB,OAAO,EAAE,GAAG,KAAK,KAAK,OAAO,CAAC,MAAM,wCAAwC,OAAO,gFAAgF,OAAO,oBAAoB;aAC/L,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,wEAAwE;QACxE,oEAAoE;QACpE,0EAA0E;QAC1E,IACE,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;YAClC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;YAC1C,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAC3C,CAAC;YACD,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACnE,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QACzC,GAAG,CAAC,IAAI,CAAC;YACP,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,SAAS,CAAC,KAAK,IAAI,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","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 { UNVERIFIABLE } from \"./vocabulary.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 out.push({\n severity: \"ok\",\n code: UNVERIFIABLE,\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 });\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"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The handful of facts every validate check speaks, and none of them owns.
|
|
3
|
+
*
|
|
4
|
+
* A leaf module rather than a paragraph beside its first caller, because the
|
|
5
|
+
* checks are spread across packages and each of these is read from more than
|
|
6
|
+
* one of them: the dispatcher's rollup and the service target's sources check
|
|
7
|
+
* both name one finding code, and several targets render parser diagnostics
|
|
8
|
+
* the same way. ACTOR_KINDS and EXTERNAL_TAG lived here too, until they
|
|
9
|
+
* reached a third copy (`core/gate/partners.ts`, `core/verify/checklist.ts`);
|
|
10
|
+
* their shared spelling is now `core/vocabulary/maturity.ts`, beside the
|
|
11
|
+
* landscape evidence that asks the same questions.
|
|
12
|
+
*/
|
|
13
|
+
import {} from "../../../core/c4/likec4.js";
|
|
14
|
+
/** The one code the rollup line counts; spelled once so the two cannot drift. */
|
|
15
|
+
export const UNVERIFIABLE = "sources.unverifiable-from-here";
|
|
16
|
+
/**
|
|
17
|
+
* One parser diagnostic as a finding's evidence line: `L12:` when the parser
|
|
18
|
+
* knew a line, because that lets a reader open the file at the fault instead of
|
|
19
|
+
* searching for it.
|
|
20
|
+
*
|
|
21
|
+
* Three other modules hand-roll the same ternary (`commands/show.ts`,
|
|
22
|
+
* `commands/delta.ts`, `core/c4/splice/landscape-merge.ts`). All four belong
|
|
23
|
+
* beside `LikeC4Error` in `core/c4/likec4.ts`. That used to be blocked by the
|
|
24
|
+
* file limit — nine lines of headroom — and is not any more: moving the resolver
|
|
25
|
+
* out to `core/c4/resolve/service.ts` left the loader around 100 lines under.
|
|
26
|
+
* The consolidation is now unblocked and simply owed.
|
|
27
|
+
*/
|
|
28
|
+
export function errorText(e) {
|
|
29
|
+
return typeof e.line === "number" ? `L${e.line}: ${e.message}` : e.message;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=vocabulary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAoB,MAAM,4BAA4B,CAAC;AAE9D,iFAAiF;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG,gCAAgC,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,CAAc;IACtC,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7E,CAAC","sourcesContent":["/**\n * The handful of facts every validate check speaks, and none of them owns.\n *\n * A leaf module rather than a paragraph beside its first caller, because the\n * checks are spread across packages and each of these is read from more than\n * one of them: the dispatcher's rollup and the service target's sources check\n * both name one finding code, and several targets render parser diagnostics\n * the same way. ACTOR_KINDS and EXTERNAL_TAG lived here too, until they\n * reached a third copy (`core/gate/partners.ts`, `core/verify/checklist.ts`);\n * their shared spelling is now `core/vocabulary/maturity.ts`, beside the\n * landscape evidence that asks the same questions.\n */\nimport { type LikeC4Error } from \"../../../core/c4/likec4.js\";\n\n/** The one code the rollup line counts; spelled once so the two cannot drift. */\nexport const UNVERIFIABLE = \"sources.unverifiable-from-here\";\n\n/**\n * One parser diagnostic as a finding's evidence line: `L12:` when the parser\n * knew a line, because that lets a reader open the file at the fault instead of\n * searching for it.\n *\n * Three other modules hand-roll the same ternary (`commands/show.ts`,\n * `commands/delta.ts`, `core/c4/splice/landscape-merge.ts`). All four belong\n * beside `LikeC4Error` in `core/c4/likec4.ts`. That used to be blocked by the\n * file limit — nine lines of headroom — and is not any more: moving the resolver\n * out to `core/c4/resolve/service.ts` left the loader around 100 lines under.\n * The consolidation is now unblocked and simply owed.\n */\nexport function errorText(e: LikeC4Error): string {\n return typeof e.line === \"number\" ? `L${e.line}: ${e.message}` : e.message;\n}\n"]}
|