@ybotok/loam 0.1.0-beta.2 → 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 +2570 -61
- 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 +2362 -245
- 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 +82 -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/agent/agents-stamp.js +155 -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/read.js +239 -0
- 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 +59 -55
- 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 +132 -77
- 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 -291
- 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 -254
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1591
- 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 -343
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2065
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js +0 -68
- 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/brief.js +0 -733
- 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 -559
- 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 -479
- 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 -720
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -436
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -481
- 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 -1104
- 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,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fleet scorecard: ceiling-vs-actual aggregates for `validate --all`,
|
|
3
|
+
* recomputed per invocation from the same memoized FleetContext reads the run
|
|
4
|
+
* already paid for. loam stores no history — week-over-week tracking is the
|
|
5
|
+
* caller's pipeline's job: capture the `scorecard` payload key per run into a
|
|
6
|
+
* metrics store. Each axis is a pair of domain-named counts (`defined` vs
|
|
7
|
+
* `governed`) rather than abstract ceiling/actual keys, because payload keys
|
|
8
|
+
* freeze the moment they ship and the domain nouns survive axis nuance.
|
|
9
|
+
*
|
|
10
|
+
* This module derives and never prints; `./print.js` renders the one table
|
|
11
|
+
* the `--all` text report appends, and `./contracts.js` owns the per-service
|
|
12
|
+
* contract reads it sums.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { inOrder } from "../../../../core/kernel/concurrency.js";
|
|
16
|
+
import { coversElement } from "../../../../core/c4/arch.js";
|
|
17
|
+
import { serviceResolver } from "../../../../core/c4/resolve/service.js";
|
|
18
|
+
import {} from "../../../../core/fleet-context.js";
|
|
19
|
+
import {} from "../../../../core/kernel/ids/dirs.js";
|
|
20
|
+
import { landscapePath } from "../../../../core/repo/paths.js";
|
|
21
|
+
import { fleetStatus } from "../../../../core/status/fleet/fleet.js";
|
|
22
|
+
import { ARTIFACT_STATUSES } from "../../../../core/status/report.js";
|
|
23
|
+
import { ANSWERED_BY } from "../../../../core/verify/answers.js";
|
|
24
|
+
import { VERIFICATION_VERDICTS } from "../../../../core/verify/record.js";
|
|
25
|
+
import { maturityRollup } from "../../../../core/vocabulary/maturity.js";
|
|
26
|
+
import { subjectsWith } from "../../../../core/vocabulary/report.js";
|
|
27
|
+
import { featureVerification, serviceViews } from "../../../list/views.js";
|
|
28
|
+
import { drawnSystems } from "../census.js";
|
|
29
|
+
import { readLandscape } from "../load.js";
|
|
30
|
+
import { adoptionOf } from "./adoption.js";
|
|
31
|
+
import { contractCounts } from "./contracts.js";
|
|
32
|
+
/**
|
|
33
|
+
* Derive the scorecard, or decline. The failure story, per axis: a memoized
|
|
34
|
+
* read that FAILED rejects again on every await, so the per-service fan-out
|
|
35
|
+
* contains those per subject — an unreadable service contributes zeros while
|
|
36
|
+
* its own `service.unreadable` finding names the cause — and every landscape
|
|
37
|
+
* read goes through `../load.ts`'s containment, so an unreadable fleet map
|
|
38
|
+
* zeroes the map-derived axes on every platform instead of deleting the card.
|
|
39
|
+
* The catch is the last line of defence for the fleet-wide reads this module
|
|
40
|
+
* does not own (the verification cells, the fleet status): a rollup that can
|
|
41
|
+
* die must not take the graded report with it. No number rather than a wrong
|
|
42
|
+
* number.
|
|
43
|
+
*/
|
|
44
|
+
export async function buildScorecard(input) {
|
|
45
|
+
try {
|
|
46
|
+
return await derive(input);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Unreadable is not zero: the axes cannot be counted, so no claim is made.
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function derive(input) {
|
|
54
|
+
const { docsDir, targets, fleet, boundService } = input;
|
|
55
|
+
const services = await fleet.listServices(docsDir);
|
|
56
|
+
// The landscape, through the run's memo and the fleet target's containment:
|
|
57
|
+
// an unreadable file grades as one that did not parse, and a landscape that
|
|
58
|
+
// proves nothing contributes no inbound edges and no element census —
|
|
59
|
+
// fail-closed, exactly as the no-openapi grace reads the same absence.
|
|
60
|
+
// Loaded FIRST and handed to serviceViews below, so the maturity rollup
|
|
61
|
+
// costs no second parse of a document this run already holds.
|
|
62
|
+
const lp = landscapePath(docsDir);
|
|
63
|
+
const land = existsSync(lp) ? await readLandscape(() => fleet.loadLikeC4(lp)) : null;
|
|
64
|
+
const proven = land !== null && land.errors.length === 0;
|
|
65
|
+
const views = await serviceViews(docsDir, services, boundService, land);
|
|
66
|
+
const maturity = maturityRollup(views);
|
|
67
|
+
// Inbound op-linked edges per service, resolved exactly as the API axis
|
|
68
|
+
// resolves them (service/api.ts): the container-aware resolver, so an edge
|
|
69
|
+
// drawn into `paymentService.api` counts for the service that owns it.
|
|
70
|
+
const known = new Set(services.map((s) => s.id));
|
|
71
|
+
const inbound = new Map();
|
|
72
|
+
if (proven) {
|
|
73
|
+
const svcOf = serviceResolver(land.elements, known);
|
|
74
|
+
for (const r of land.relationships) {
|
|
75
|
+
if (r.op === undefined)
|
|
76
|
+
continue;
|
|
77
|
+
const owner = svcOf(r.target);
|
|
78
|
+
const ops = inbound.get(owner) ?? new Set();
|
|
79
|
+
ops.add(r.op);
|
|
80
|
+
inbound.set(owner, ops);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Every read in THIS fan-out is a memo hit — the service targets already
|
|
84
|
+
// parsed both requirement documents and both contracts — so it spawns no new
|
|
85
|
+
// filesystem work and needs no pool (unlike the verification fan-out below).
|
|
86
|
+
const perService = await Promise.all(services.map((svc) => contractCounts(svc, fleet, inbound.get(svc.id) ?? new Set())));
|
|
87
|
+
const sum = (pick) => perService.reduce((n, c) => n + pick(c), 0);
|
|
88
|
+
const operations = {
|
|
89
|
+
defined: sum((c) => c.operations.defined),
|
|
90
|
+
governed: sum((c) => c.operations.governed),
|
|
91
|
+
deprecated: sum((c) => c.operations.deprecated),
|
|
92
|
+
deprecatedStillConsumed: sum((c) => c.operations.deprecatedStillConsumed),
|
|
93
|
+
};
|
|
94
|
+
const messages = { defined: sum((c) => c.messages.defined), linked: sum((c) => c.messages.linked) };
|
|
95
|
+
const adoption = adoptionOf(perService);
|
|
96
|
+
// C4 coverage: the fleet map's own system census (`drawnSystems` — the set
|
|
97
|
+
// the undocumented pass walks) against every living arch.spec.md's `Covers:`
|
|
98
|
+
// entries. Element entries only — an edge entry names no element.
|
|
99
|
+
const covers = perService.flatMap((c) => c.covers);
|
|
100
|
+
const eligible = proven ? drawnSystems(land.elements, known) : [];
|
|
101
|
+
const covered = eligible.filter((e) => covers.some((c) => coversElement(c, e))).length;
|
|
102
|
+
// Verification: `list`'s own cells, so the two commands cannot disagree
|
|
103
|
+
// about a record's verdict. Active features only — an archived record is
|
|
104
|
+
// frozen history, not fleet debt. This fan-out is NOT memo hits:
|
|
105
|
+
// readVerification is one small file read per feature, and a recorded cell
|
|
106
|
+
// additionally derives its checklist (the same cost `list` pays for the same
|
|
107
|
+
// column) — real filesystem work, so it runs through the bounded pool.
|
|
108
|
+
const features = await fleet.listFeatures(docsDir);
|
|
109
|
+
const cells = await inOrder(features, (f) => featureVerification(docsDir, f));
|
|
110
|
+
const recorded = cells.filter((c) => c !== null);
|
|
111
|
+
const verdicts = Object.fromEntries(VERIFICATION_VERDICTS.map((v) => [v, 0]));
|
|
112
|
+
for (const cell of recorded)
|
|
113
|
+
verdicts[cell.verdict] += 1;
|
|
114
|
+
const confirmed = recorded.reduce((n, c) => n + c.confirmed, 0);
|
|
115
|
+
const answered = Object.fromEntries(ANSWERED_BY.map((who) => [who, recorded.reduce((n, c) => n + c.answered[who], 0)]));
|
|
116
|
+
// The fleet form of `status`, on this run's own snapshot: presence and
|
|
117
|
+
// dependency order, nothing graded — the stages an agent already branches on.
|
|
118
|
+
const status = await fleetStatus(docsDir, { context: fleet });
|
|
119
|
+
const stages = Object.fromEntries(ARTIFACT_STATUSES.map((s) => [s, 0]));
|
|
120
|
+
for (const f of status.features)
|
|
121
|
+
stages[f.stage] += 1;
|
|
122
|
+
return {
|
|
123
|
+
services: services.length,
|
|
124
|
+
maturity,
|
|
125
|
+
provenance: {
|
|
126
|
+
vouched: maturity.vouched,
|
|
127
|
+
// Both counts join through `subjectsWith` on the run's OWN findings, so
|
|
128
|
+
// each is structurally the same number as the report beside it — the
|
|
129
|
+
// unverifiable count is the footer's (unverifiableSubjects is the same
|
|
130
|
+
// call on the same code; this package cannot import the parent back).
|
|
131
|
+
// Both codes are LITERALS — provenance/sources.ts's own spellings —
|
|
132
|
+
// because the stable-code collector reads counting sites and refuses a
|
|
133
|
+
// slot it cannot read; the collector is also what convicts a typo here.
|
|
134
|
+
staleDigests: subjectsWith(targets, "sources.stale"),
|
|
135
|
+
unverifiableFromHere: subjectsWith(targets, "sources.unverifiable-from-here"),
|
|
136
|
+
// Doc-side, so unlike `staleDigests` this one is complete even from the
|
|
137
|
+
// docs repo: `sources.sampled-vouch` needs no service repo to fire.
|
|
138
|
+
sampledVouched: subjectsWith(targets, "sources.sampled-vouch"),
|
|
139
|
+
},
|
|
140
|
+
verification: {
|
|
141
|
+
recorded: recorded.length,
|
|
142
|
+
verdicts,
|
|
143
|
+
claims: {
|
|
144
|
+
total: recorded.reduce((n, c) => n + c.claims, 0),
|
|
145
|
+
confirmed,
|
|
146
|
+
answered,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
operations,
|
|
150
|
+
messages,
|
|
151
|
+
c4: { elements: eligible.length, covered },
|
|
152
|
+
adoption,
|
|
153
|
+
features: { active: status.features.length, stages },
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=scorecard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorecard.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/scorecard/scorecard.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The fleet scorecard: ceiling-vs-actual aggregates for `validate --all`,\n * recomputed per invocation from the same memoized FleetContext reads the run\n * already paid for. loam stores no history — week-over-week tracking is the\n * caller's pipeline's job: capture the `scorecard` payload key per run into a\n * metrics store. Each axis is a pair of domain-named counts (`defined` vs\n * `governed`) rather than abstract ceiling/actual keys, because payload keys\n * freeze the moment they ship and the domain nouns survive axis nuance.\n *\n * This module derives and never prints; `./print.js` renders the one table\n * the `--all` text report appends, and `./contracts.js` owns the per-service\n * contract reads it sums.\n */\nimport { existsSync } from \"node:fs\";\nimport { inOrder } from \"../../../../core/kernel/concurrency.js\";\nimport { coversElement } from \"../../../../core/c4/arch.js\";\nimport { serviceResolver } from \"../../../../core/c4/resolve/service.js\";\nimport { type FleetContext } from \"../../../../core/fleet-context.js\";\nimport { type DocsDir } from \"../../../../core/kernel/ids/dirs.js\";\nimport { landscapePath } from \"../../../../core/repo/paths.js\";\nimport { fleetStatus } from \"../../../../core/status/fleet/fleet.js\";\nimport { ARTIFACT_STATUSES, type ArtifactStatus } from \"../../../../core/status/report.js\";\nimport { ANSWERED_BY, type AnsweredBy } from \"../../../../core/verify/answers.js\";\nimport { VERIFICATION_VERDICTS, type VerificationVerdict } from \"../../../../core/verify/record.js\";\nimport { maturityRollup, type Maturity } from \"../../../../core/vocabulary/maturity.js\";\nimport { subjectsWith, type TargetReport } from \"../../../../core/vocabulary/report.js\";\nimport { featureVerification, serviceViews, type VerificationCell } from \"../../../list/views.js\";\nimport { drawnSystems } from \"../census.js\";\nimport { readLandscape } from \"../load.js\";\nimport { adoptionOf, type Adoption } from \"./adoption.js\";\nimport { contractCounts, type ContractCounts } from \"./contracts.js\";\n\n/** What `buildScorecard` needs of the run that is already in hand. */\nexport interface ScorecardInput {\n docsDir: DocsDir;\n /** The run's graded targets — the source for the one count only a repo-bound check can make (`sources.stale` walks the service's own repository, and must not run twice). */\n targets: TargetReport[];\n /** The run's memoized snapshot: every read below is a hit on it. */\n fleet: FleetContext;\n /** loam.json's `service` — the one repo whose `sources` are checkable from here (serviceViews' rule). */\n boundService: string | undefined;\n}\n\n/**\n * The additive `scorecard` payload key of `validate --all --json`, and the\n * `--all` text table. Shape frozen on ship, like every payload key: fields\n * may be added, never changed or removed.\n */\nexport interface Scorecard {\n /** Every `services/` directory the enumeration lists — the maturity rollup's denominator. */\n services: number;\n /** Counts per adoption-maturity rung, every rung present (core/vocabulary/maturity.ts). */\n maturity: Record<Maturity, number>;\n provenance: {\n /** Services at the `vouched` rung — a person stamped them. */\n vouched: number;\n /**\n * Of those, the ones where the person read a recorded SAMPLE of the\n * document rather than all of it, by subject off this run's\n * `sources.sampled-vouch` findings.\n *\n * Additive beside `vouched` rather than subtracted from it, because the\n * rung is real — a person did stamp it — but a dial reading\n * `vouched: 120` where 100 of them are sampled is exactly the\n * partial-trust-as-full-trust misreading the scope exists to prevent. A\n * dashboard that wants the stricter number subtracts this one knowingly.\n */\n sampledVouched: number;\n /**\n * Services whose stamped sources digest no longer matches the code, by\n * subject off this run's `sources.stale` findings — only what THIS run\n * could verify, so read it beside the count below, never alone.\n */\n staleDigests: number;\n /** Services whose declared `sources` only their own repos can check. */\n unverifiableFromHere: number;\n };\n verification: {\n /**\n * Active features with a verification record beside them. Its ceiling is\n * `features.active` — deliberately not repeated here: one denominator,\n * derived once, so the two axes cannot disagree about how many features\n * are in flight.\n */\n recorded: number;\n /** The recorded features' three-valued verdicts (core/verify/record.ts), every key present. */\n verdicts: Record<VerificationVerdict, number>;\n claims: {\n /** Questions asked across every recorded feature, `tallyRecord`'s counting. */\n total: number;\n confirmed: number;\n /**\n * Of the confirmed, one count per `answered_by` value (`ANSWERED_BY`),\n * every key present — the stable-shape rule `verdicts` and `stages`\n * follow, so a fourth provenance would appear rather than be absorbed.\n *\n * Read off the answers' own provenance, never by subtracting the\n * attested share: `attestedClaims` counts `scenario.tested` alone, so\n * `confirmed - attested` filed every OTHER kind an agent confirmed — a\n * permission, a capability, an exposed operation — under a test runner\n * that had not run. A record with four agent answers printed as three\n * runner and one agent, which is the reading this axis exists to give.\n */\n answered: Record<AnsweredBy, number>;\n };\n };\n /**\n * The HTTP axis, with a deliberate UNIT split: `defined`/`governed` count\n * contract SLOTS, exactly as the API axis's own findings count operations,\n * while `deprecated`/`deprecatedStillConsumed` count DISTINCT operationIds —\n * a duplicate-id slot pair (already its own warning) retires as ONE\n * operation, one migration owed.\n */\n operations: {\n /** Slots the living contracts define (removal markers are never operations). */\n defined: number;\n /** Slots (like `defined`) whose id a living requirement's `Operations:` line governs. */\n governed: number;\n /** Distinct deprecated operationIds. */\n deprecated: number;\n /** Distinct deprecated ids something still joins to — a living `Operations:` line, or an op-linked inbound landscape edge. */\n deprecatedStillConsumed: number;\n };\n messages: {\n /** Distinct message names the living async contracts declare. */\n defined: number;\n /** Of them, the ones a requirement's `Publishes:`/`Consumes:` line governs. */\n linked: number;\n };\n c4: {\n /** The drawn SYSTEMS — `drawnSystems`, the fleet map's own census, so the map's exemptions (actors, `#external`, groupings, containers) and this count cannot drift. */\n elements: number;\n /** Of them, the ones some living arch requirement's `Covers:` entry names. */\n covered: number;\n };\n /**\n * Services PARTICIPATING in each contract axis — how far the staged\n * adoption has spread, axis by axis. The denominator is `services`, carried\n * once above like every other denominator here. One mechanical rule per\n * axis, per service: `requirements` — spec.md holds at least one\n * `### Requirement:` block (content, not file presence, so a fleet of empty\n * adopt scaffolds honestly reads \"not started\"); `arch` — the same for\n * arch.spec.md; `openapi` / `asyncapi` — the contract file exists;\n * `permissions` / `capabilities` — at least one non-REMOVED requirement in\n * either spec document carries a `Requires:` / `Capability:` entry (the\n * used-set rule the fleet vocabulary checks apply). An axis at 0 is \"not\n * started\" — distinct from partially adopted — and is what licenses the\n * text report's per-axis warning banner (./adoption.js). An unreadable\n * service counts as participating in nothing, the same zeros doctrine as\n * every count here — read these beside the run's `service.unreadable`\n * findings, and note the text renderer refuses to group warnings on a run\n * that has any (report.ts).\n */\n adoption: Adoption;\n features: {\n active: number;\n /**\n * The fleet form's stage per active feature — all five ARTIFACT_STATUSES\n * keys even though that form never grades `draft` (the maturityRollup\n * rule: a stable shape a dashboard can diff).\n */\n stages: Record<ArtifactStatus, number>;\n };\n}\n\n/**\n * Derive the scorecard, or decline. The failure story, per axis: a memoized\n * read that FAILED rejects again on every await, so the per-service fan-out\n * contains those per subject — an unreadable service contributes zeros while\n * its own `service.unreadable` finding names the cause — and every landscape\n * read goes through `../load.ts`'s containment, so an unreadable fleet map\n * zeroes the map-derived axes on every platform instead of deleting the card.\n * The catch is the last line of defence for the fleet-wide reads this module\n * does not own (the verification cells, the fleet status): a rollup that can\n * die must not take the graded report with it. No number rather than a wrong\n * number.\n */\nexport async function buildScorecard(input: ScorecardInput): Promise<Scorecard | null> {\n try {\n return await derive(input);\n } catch {\n // Unreadable is not zero: the axes cannot be counted, so no claim is made.\n return null;\n }\n}\n\nasync function derive(input: ScorecardInput): Promise<Scorecard> {\n const { docsDir, targets, fleet, boundService } = input;\n const services = await fleet.listServices(docsDir);\n\n // The landscape, through the run's memo and the fleet target's containment:\n // an unreadable file grades as one that did not parse, and a landscape that\n // proves nothing contributes no inbound edges and no element census —\n // fail-closed, exactly as the no-openapi grace reads the same absence.\n // Loaded FIRST and handed to serviceViews below, so the maturity rollup\n // costs no second parse of a document this run already holds.\n const lp = landscapePath(docsDir);\n const land = existsSync(lp) ? await readLandscape(() => fleet.loadLikeC4(lp)) : null;\n const proven = land !== null && land.errors.length === 0;\n\n const views = await serviceViews(docsDir, services, boundService, land);\n const maturity = maturityRollup(views);\n\n // Inbound op-linked edges per service, resolved exactly as the API axis\n // resolves them (service/api.ts): the container-aware resolver, so an edge\n // drawn into `paymentService.api` counts for the service that owns it.\n const known: ReadonlySet<string> = new Set(services.map((s) => s.id));\n const inbound = new Map<string, Set<string>>();\n if (proven) {\n const svcOf = serviceResolver(land.elements, known);\n for (const r of land.relationships) {\n if (r.op === undefined) continue;\n const owner: string = svcOf(r.target);\n const ops = inbound.get(owner) ?? new Set<string>();\n ops.add(r.op);\n inbound.set(owner, ops);\n }\n }\n\n // Every read in THIS fan-out is a memo hit — the service targets already\n // parsed both requirement documents and both contracts — so it spawns no new\n // filesystem work and needs no pool (unlike the verification fan-out below).\n const perService = await Promise.all(\n services.map((svc) => contractCounts(svc, fleet, inbound.get(svc.id) ?? new Set<string>())),\n );\n const sum = (pick: (c: ContractCounts) => number): number =>\n perService.reduce((n, c) => n + pick(c), 0);\n const operations = {\n defined: sum((c) => c.operations.defined),\n governed: sum((c) => c.operations.governed),\n deprecated: sum((c) => c.operations.deprecated),\n deprecatedStillConsumed: sum((c) => c.operations.deprecatedStillConsumed),\n };\n const messages = { defined: sum((c) => c.messages.defined), linked: sum((c) => c.messages.linked) };\n const adoption = adoptionOf(perService);\n\n // C4 coverage: the fleet map's own system census (`drawnSystems` — the set\n // the undocumented pass walks) against every living arch.spec.md's `Covers:`\n // entries. Element entries only — an edge entry names no element.\n const covers = perService.flatMap((c) => c.covers);\n const eligible = proven ? drawnSystems(land.elements, known) : [];\n const covered = eligible.filter((e) => covers.some((c) => coversElement(c, e))).length;\n\n // Verification: `list`'s own cells, so the two commands cannot disagree\n // about a record's verdict. Active features only — an archived record is\n // frozen history, not fleet debt. This fan-out is NOT memo hits:\n // readVerification is one small file read per feature, and a recorded cell\n // additionally derives its checklist (the same cost `list` pays for the same\n // column) — real filesystem work, so it runs through the bounded pool.\n const features = await fleet.listFeatures(docsDir);\n const cells = await inOrder(features, (f) => featureVerification(docsDir, f));\n const recorded = cells.filter((c): c is VerificationCell => c !== null);\n const verdicts = Object.fromEntries(VERIFICATION_VERDICTS.map((v) => [v, 0])) as Record<VerificationVerdict, number>;\n for (const cell of recorded) verdicts[cell.verdict] += 1;\n const confirmed = recorded.reduce((n, c) => n + c.confirmed, 0);\n const answered = Object.fromEntries(\n ANSWERED_BY.map((who) => [who, recorded.reduce((n, c) => n + c.answered[who], 0)]),\n ) as Record<AnsweredBy, number>;\n\n // The fleet form of `status`, on this run's own snapshot: presence and\n // dependency order, nothing graded — the stages an agent already branches on.\n const status = await fleetStatus(docsDir, { context: fleet });\n const stages = Object.fromEntries(ARTIFACT_STATUSES.map((s) => [s, 0])) as Record<ArtifactStatus, number>;\n for (const f of status.features) stages[f.stage] += 1;\n\n return {\n services: services.length,\n maturity,\n provenance: {\n vouched: maturity.vouched,\n // Both counts join through `subjectsWith` on the run's OWN findings, so\n // each is structurally the same number as the report beside it — the\n // unverifiable count is the footer's (unverifiableSubjects is the same\n // call on the same code; this package cannot import the parent back).\n // Both codes are LITERALS — provenance/sources.ts's own spellings —\n // because the stable-code collector reads counting sites and refuses a\n // slot it cannot read; the collector is also what convicts a typo here.\n staleDigests: subjectsWith(targets, \"sources.stale\"),\n unverifiableFromHere: subjectsWith(targets, \"sources.unverifiable-from-here\"),\n // Doc-side, so unlike `staleDigests` this one is complete even from the\n // docs repo: `sources.sampled-vouch` needs no service repo to fire.\n sampledVouched: subjectsWith(targets, \"sources.sampled-vouch\"),\n },\n verification: {\n recorded: recorded.length,\n verdicts,\n claims: {\n total: recorded.reduce((n, c) => n + c.claims, 0),\n confirmed,\n answered,\n },\n },\n operations,\n messages,\n c4: { elements: eligible.length, covered },\n adoption,\n features: { active: status.features.length, stages },\n };\n}\n"]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `usecase.capability-unresolved` — the `#cap-` tag that names no declared
|
|
3
|
+
* capability, or more than one.
|
|
4
|
+
*
|
|
5
|
+
* The join itself lives in `core/capabilities/usecase-join.ts` and none of it is
|
|
6
|
+
* repeated here: this module owns the grade and the sentence, nothing else. That
|
|
7
|
+
* split is why the tag can answer "many" at all — the slug is not injective, so
|
|
8
|
+
* `payments/refunds` and `payments-refunds` both flatten to
|
|
9
|
+
* `payments-refunds` — and why the close candidates a message offers are real
|
|
10
|
+
* declared ids rather than loam's flattened spelling of them.
|
|
11
|
+
*
|
|
12
|
+
* ERROR, the same grade `capability.unknown` carries on a `Capability:` line and
|
|
13
|
+
* for its reason: an invented capability reads exactly like a real one. Here it
|
|
14
|
+
* reads that way at flow altitude — the tag is what files a whole business
|
|
15
|
+
* sequence under an owner, so a claim that resolves to nothing produces a use
|
|
16
|
+
* case nobody can find and a capability nobody can see is realized.
|
|
17
|
+
*
|
|
18
|
+
* SUPPRESSED ENTIRELY when the vocabulary is absent or unreadable: the caller
|
|
19
|
+
* resolves no claims at all in that case, so this answers with nothing. The
|
|
20
|
+
* claims are RESOLVED BY THE CALLER rather than here because the `#req-` grade
|
|
21
|
+
* beside this one is scoped by the very same verdicts, and two resolutions of
|
|
22
|
+
* one view's tags are two chances to disagree about which capability a flow is
|
|
23
|
+
* about. The ladder that produces the suppressing `null` is
|
|
24
|
+
* `gradableCapabilityIds` in `core/capabilities/findings.ts` — one function, called by every site that needs the graded id list, this module's
|
|
25
|
+
* caller in `../landscape.ts` included. The FILE is this axis's opt-in, so a
|
|
26
|
+
* fleet with no `architecture/capabilities.yaml` produces no capability finding
|
|
27
|
+
* at all, and an unreadable one is `capability.invalid` alone rather than one
|
|
28
|
+
* unresolved tag per use case in the fleet, which is a cascade and not a
|
|
29
|
+
* diagnosis. That rule is not re-decided here: a second reading of
|
|
30
|
+
* `CapabilityVocabulary` anywhere in this package is the copy that goes stale
|
|
31
|
+
* the day a fourth un-gradable state is added, so call the function.
|
|
32
|
+
*/
|
|
33
|
+
import { CAP_TAG_PREFIX, tagSlug, } from "../../../../core/capabilities/usecase-join.js";
|
|
34
|
+
import { viewPlace } from "./place.js";
|
|
35
|
+
/** A capability id as an author must write it in a tag: `identity/tokens (#cap-identity-tokens)`. */
|
|
36
|
+
function idAndTag(id) {
|
|
37
|
+
return `${id} (#${CAP_TAG_PREFIX}${tagSlug(id)})`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A tag nothing declares, with the close names spelled as TAGS as well as ids.
|
|
41
|
+
*
|
|
42
|
+
* Both spellings, because either alone sends the author somewhere wrong: the id
|
|
43
|
+
* is what `capabilities.yaml` holds and the tag is what the view must carry, and
|
|
44
|
+
* an author handed only `identity/tokens` writes `#cap-identity/tokens`, which
|
|
45
|
+
* LikeC4 refuses to parse. The flattening rule is stated in the same breath so
|
|
46
|
+
* the reader can derive the next one without being told again.
|
|
47
|
+
*/
|
|
48
|
+
function noneMessage(view, claim) {
|
|
49
|
+
const hint = claim.close.length > 0
|
|
50
|
+
? `Did you mean: ${claim.close.map(idAndTag).join(", ")}?`
|
|
51
|
+
: "Declare it there (`capabilities: {<id>: {description, owner}}`), or fix the tag.";
|
|
52
|
+
return (`${viewPlace(view)} is tagged #${claim.tag}, and no capability declared in ` +
|
|
53
|
+
`architecture/capabilities.yaml flattens to '${claim.slug}'. ${hint} ` +
|
|
54
|
+
"A tag spells the id with every character outside `[A-Za-z0-9_-]` flattened to `-`, because that is all a LikeC4 tag name accepts.");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A tag two or more declared ids answer to. Every colliding id is named — a
|
|
58
|
+
* message that stopped at the first would be reporting the ambiguity while
|
|
59
|
+
* hiding half of what makes it one.
|
|
60
|
+
*/
|
|
61
|
+
function manyMessage(view, claim) {
|
|
62
|
+
return (`${viewPlace(view)} is tagged #${claim.tag}, and ${claim.ids.length} declared capabilities flatten to ` +
|
|
63
|
+
`'${claim.slug}' (${claim.ids.join(", ")}) — nothing in the tag can say which one this use case realizes. ` +
|
|
64
|
+
"Rename one of them in architecture/capabilities.yaml: a guessed capability files every hop of the flow, " +
|
|
65
|
+
"and every rollup built over it, under an owner who never claimed it — and the wrong answer looks exactly " +
|
|
66
|
+
"like the right one.");
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One finding per `#cap-` tag that does not resolve — never one per view.
|
|
70
|
+
*
|
|
71
|
+
* A view may legitimately carry two capability tags (a checkout flow that also
|
|
72
|
+
* issues the identity token realizes both), and `resolveCapabilityTags` answers
|
|
73
|
+
* each on its own terms for that reason. Collapsing them here would either
|
|
74
|
+
* swallow a broken tag beside a working one or lose the capability the view
|
|
75
|
+
* genuinely does realize; one tag, one verdict, one finding keeps both facts.
|
|
76
|
+
*/
|
|
77
|
+
export function capabilityTagFindings(view, claims) {
|
|
78
|
+
const findings = [];
|
|
79
|
+
for (const claim of claims) {
|
|
80
|
+
if (claim.kind === "resolved")
|
|
81
|
+
continue;
|
|
82
|
+
findings.push({
|
|
83
|
+
severity: "error",
|
|
84
|
+
code: "usecase.capability-unresolved",
|
|
85
|
+
// The VIEW, not the tag: a subject is what a reader goes and opens, and
|
|
86
|
+
// `subjectsWith` counts one broken use case once however many of its tags
|
|
87
|
+
// are wrong.
|
|
88
|
+
subject: view.id,
|
|
89
|
+
message: claim.kind === "none" ? noneMessage(view, claim) : manyMessage(view, claim),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return findings;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=capability-tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-tag.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/usecases/capability-tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EACL,cAAc,EACd,OAAO,GAER,MAAM,+CAA+C,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,qGAAqG;AACrG,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO,GAAG,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,IAAgB,EAAE,KAAiD;IACtF,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACpB,CAAC,CAAC,iBAAiB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC1D,CAAC,CAAC,kFAAkF,CAAC;IACzF,OAAO,CACL,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,kCAAkC;QAC5E,+CAA+C,KAAK,CAAC,IAAI,MAAM,IAAI,GAAG;QACtE,mIAAmI,CACpI,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAgB,EAAE,KAAiD;IACtF,OAAO,CACL,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,CAAC,MAAM,oCAAoC;QACvG,IAAI,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,mEAAmE;QAC3G,0GAA0G;QAC1G,2GAA2G;QAC3G,qBAAqB,CACtB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAgB,EAAE,MAAkC;IACxF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACxC,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,+BAA+B;YACrC,wEAAwE;YACxE,0EAA0E;YAC1E,aAAa;YACb,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC;SACrF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * `usecase.capability-unresolved` — the `#cap-` tag that names no declared\n * capability, or more than one.\n *\n * The join itself lives in `core/capabilities/usecase-join.ts` and none of it is\n * repeated here: this module owns the grade and the sentence, nothing else. That\n * split is why the tag can answer \"many\" at all — the slug is not injective, so\n * `payments/refunds` and `payments-refunds` both flatten to\n * `payments-refunds` — and why the close candidates a message offers are real\n * declared ids rather than loam's flattened spelling of them.\n *\n * ERROR, the same grade `capability.unknown` carries on a `Capability:` line and\n * for its reason: an invented capability reads exactly like a real one. Here it\n * reads that way at flow altitude — the tag is what files a whole business\n * sequence under an owner, so a claim that resolves to nothing produces a use\n * case nobody can find and a capability nobody can see is realized.\n *\n * SUPPRESSED ENTIRELY when the vocabulary is absent or unreadable: the caller\n * resolves no claims at all in that case, so this answers with nothing. The\n * claims are RESOLVED BY THE CALLER rather than here because the `#req-` grade\n * beside this one is scoped by the very same verdicts, and two resolutions of\n * one view's tags are two chances to disagree about which capability a flow is\n * about. The ladder that produces the suppressing `null` is\n * `gradableCapabilityIds` in `core/capabilities/findings.ts` — one function, called by every site that needs the graded id list, this module's\n * caller in `../landscape.ts` included. The FILE is this axis's opt-in, so a\n * fleet with no `architecture/capabilities.yaml` produces no capability finding\n * at all, and an unreadable one is `capability.invalid` alone rather than one\n * unresolved tag per use case in the fleet, which is a cascade and not a\n * diagnosis. That rule is not re-decided here: a second reading of\n * `CapabilityVocabulary` anywhere in this package is the copy that goes stale\n * the day a fourth un-gradable state is added, so call the function.\n */\nimport {\n CAP_TAG_PREFIX,\n tagSlug,\n type CapabilityClaim,\n} from \"../../../../core/capabilities/usecase-join.js\";\nimport type { ParsedView } from \"../../../../core/c4/parsed/dynamic-views.js\";\nimport type { Finding } from \"../../../../core/vocabulary/report.js\";\nimport { viewPlace } from \"./place.js\";\n\n/** A capability id as an author must write it in a tag: `identity/tokens (#cap-identity-tokens)`. */\nfunction idAndTag(id: string): string {\n return `${id} (#${CAP_TAG_PREFIX}${tagSlug(id)})`;\n}\n\n/**\n * A tag nothing declares, with the close names spelled as TAGS as well as ids.\n *\n * Both spellings, because either alone sends the author somewhere wrong: the id\n * is what `capabilities.yaml` holds and the tag is what the view must carry, and\n * an author handed only `identity/tokens` writes `#cap-identity/tokens`, which\n * LikeC4 refuses to parse. The flattening rule is stated in the same breath so\n * the reader can derive the next one without being told again.\n */\nfunction noneMessage(view: ParsedView, claim: Extract<CapabilityClaim, { kind: \"none\" }>): string {\n const hint =\n claim.close.length > 0\n ? `Did you mean: ${claim.close.map(idAndTag).join(\", \")}?`\n : \"Declare it there (`capabilities: {<id>: {description, owner}}`), or fix the tag.\";\n return (\n `${viewPlace(view)} is tagged #${claim.tag}, and no capability declared in ` +\n `architecture/capabilities.yaml flattens to '${claim.slug}'. ${hint} ` +\n \"A tag spells the id with every character outside `[A-Za-z0-9_-]` flattened to `-`, because that is all a LikeC4 tag name accepts.\"\n );\n}\n\n/**\n * A tag two or more declared ids answer to. Every colliding id is named — a\n * message that stopped at the first would be reporting the ambiguity while\n * hiding half of what makes it one.\n */\nfunction manyMessage(view: ParsedView, claim: Extract<CapabilityClaim, { kind: \"many\" }>): string {\n return (\n `${viewPlace(view)} is tagged #${claim.tag}, and ${claim.ids.length} declared capabilities flatten to ` +\n `'${claim.slug}' (${claim.ids.join(\", \")}) — nothing in the tag can say which one this use case realizes. ` +\n \"Rename one of them in architecture/capabilities.yaml: a guessed capability files every hop of the flow, \" +\n \"and every rollup built over it, under an owner who never claimed it — and the wrong answer looks exactly \" +\n \"like the right one.\"\n );\n}\n\n/**\n * One finding per `#cap-` tag that does not resolve — never one per view.\n *\n * A view may legitimately carry two capability tags (a checkout flow that also\n * issues the identity token realizes both), and `resolveCapabilityTags` answers\n * each on its own terms for that reason. Collapsing them here would either\n * swallow a broken tag beside a working one or lose the capability the view\n * genuinely does realize; one tag, one verdict, one finding keeps both facts.\n */\nexport function capabilityTagFindings(view: ParsedView, claims: readonly CapabilityClaim[]): Finding[] {\n const findings: Finding[] = [];\n for (const claim of claims) {\n if (claim.kind === \"resolved\") continue;\n findings.push({\n severity: \"error\",\n code: \"usecase.capability-unresolved\",\n // The VIEW, not the tag: a subject is what a reader goes and opens, and\n // `subjectsWith` counts one broken use case once however many of its tags\n // are wrong.\n subject: view.id,\n message: claim.kind === \"none\" ? noneMessage(view, claim) : manyMessage(view, claim),\n });\n }\n return findings;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { viewFile } from "../../../../core/usecases/place.js";
|
|
2
|
+
/**
|
|
3
|
+
* The opening of every finding in this family:
|
|
4
|
+
* `landscape: architecture/usecases/checkout.likec4 — dynamic view 'uc_checkout'`.
|
|
5
|
+
*
|
|
6
|
+
* The `landscape:` prefix is the TARGET's name, not a file reference — every
|
|
7
|
+
* finding filed on the fleet target carries it, and `landscape.invalid` already
|
|
8
|
+
* sets the precedent of naming another document right after it.
|
|
9
|
+
*/
|
|
10
|
+
export function viewPlace(view) {
|
|
11
|
+
return `landscape: ${viewFile(view)} — dynamic view '${view.id}'`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=place.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/usecases/place.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,OAAO,cAAc,QAAQ,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,EAAE,GAAG,CAAC;AACpE,CAAC","sourcesContent":["/**\n * Where a use-case FINDING points: the validate target it is filed against, the\n * document the view was written in, and the view itself.\n *\n * A leaf module rather than another export on `./usecases.ts`, because both\n * graders in this package need it while the entry module imports both of them —\n * the leaf-helper-stranded-in-a-heavier-module shape docs/CODE-STYLE.md names as\n * the cause of every import cycle this repository has carried.\n *\n * NAMING THE FILE IS THE WHOLE SUBJECT. `validate --all` reads `architecture/`\n * as ONE LikeC4 project, so a `dynamic view` may have been written in\n * `architecture/landscape.likec4` or in any `architecture/usecases/*.likec4`,\n * and the project is what merges them. A message that named the landscape by\n * default would send its author to a file that does not contain the view — the\n * same defect `landscape.invalid`'s message was corrected for when the project\n * loader landed, arriving again one axis later.\n *\n * `viewFile` and `stepPlace` themselves moved to `core/usecases/place.ts` once\n * `loam diff`, `loam delta` and `loam context` became readers too; that module's\n * banner records why, and why the `landscape:` prefix below stayed here.\n */\nimport type { ParsedView } from \"../../../../core/c4/parsed/dynamic-views.js\";\nimport { viewFile } from \"../../../../core/usecases/place.js\";\n\n/**\n * The opening of every finding in this family:\n * `landscape: architecture/usecases/checkout.likec4 — dynamic view 'uc_checkout'`.\n *\n * The `landscape:` prefix is the TARGET's name, not a file reference — every\n * finding filed on the fleet target carries it, and `landscape.invalid` already\n * sets the precedent of naming another document right after it.\n */\nexport function viewPlace(view: ParsedView): string {\n return `landscape: ${viewFile(view)} — dynamic view '${view.id}'`;\n}\n"]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `usecase.requirement-unresolved` — the `#req-` tag that names no requirement
|
|
3
|
+
* of the capability the view is about.
|
|
4
|
+
*
|
|
5
|
+
* The join lives in `core/capabilities/usecase-join.ts` and none of it is
|
|
6
|
+
* repeated here: this module owns the grade and the sentences. Six arms, six
|
|
7
|
+
* fixes, and they are deliberately the same vocabulary
|
|
8
|
+
* `capability.realizes-unknown` uses for the OTHER carrier of this claim — an
|
|
9
|
+
* author who has learned one set of messages has learned both.
|
|
10
|
+
*
|
|
11
|
+
* ERROR, for `usecase.capability-unresolved`'s reason one join deeper: the tag
|
|
12
|
+
* is the architect's claim that a flow satisfies a named business promise, and a
|
|
13
|
+
* claim that resolves to nothing reads exactly like one that does — in the view,
|
|
14
|
+
* in review, and to anyone asking which flow keeps that promise.
|
|
15
|
+
*
|
|
16
|
+
* AN UNRESOLVED CLAIM SUPPRESSES NOTHING. `capability.requirement-unrealized`
|
|
17
|
+
* counts only RESOLVED claims, so a typo'd `#req-` tag leaves the requirement
|
|
18
|
+
* reported as realized by nobody — which is the truth, and is exactly what a
|
|
19
|
+
* broken claim should not be able to hide. The two findings arriving together is
|
|
20
|
+
* the intended reading: one says the tag is wrong, the other says the promise is
|
|
21
|
+
* still unkept.
|
|
22
|
+
*/
|
|
23
|
+
import { REQ_TAG_PREFIX, tagSlug, resolveRequirementTags, } from "../../../../core/capabilities/usecase-join.js";
|
|
24
|
+
import { viewPlace } from "./place.js";
|
|
25
|
+
/** A `Requirement-ID` as an author must write it in a tag: `CHK.ONCE (#req-CHK-ONCE)`. */
|
|
26
|
+
function idAndTag(id) {
|
|
27
|
+
return `${id} (#${REQ_TAG_PREFIX}${tagSlug(id)})`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The fix for one unresolved claim. The `unscoped` arm splits in two on the
|
|
31
|
+
* count, because none and several are opposite mistakes: one author forgot to
|
|
32
|
+
* say which capability, the other said two and left the id homeless.
|
|
33
|
+
*/
|
|
34
|
+
function advice(claim) {
|
|
35
|
+
switch (claim.kind) {
|
|
36
|
+
case "unscoped":
|
|
37
|
+
return claim.capabilities.length === 0
|
|
38
|
+
? "the view carries no `#cap-` tag that resolves to a declared capability, and a `Requirement-ID` is " +
|
|
39
|
+
"unique only inside its own document — so there is nothing for this id to be looked up in. " +
|
|
40
|
+
"Add the `#cap-<slug>` tag naming the capability this flow is about."
|
|
41
|
+
: `the view resolves ${claim.capabilities.length} capabilities (${claim.capabilities.join(", ")}), ` +
|
|
42
|
+
"so nothing says which document the id belongs to. A flow realizing promises from two capabilities " +
|
|
43
|
+
"needs one `#req-` tag per capability to be unambiguous, which the tag grammar cannot express — " +
|
|
44
|
+
"split the flow, or drop the `#req-` tag and let `Realizes:` on the service requirements carry it.";
|
|
45
|
+
case "undocumented":
|
|
46
|
+
return (`capability '${claim.capability}' is declared but has no capabilities/${claim.capability}/spec.md, ` +
|
|
47
|
+
"so it carries no requirements to satisfy. Write the document — a name alone can be claimed with " +
|
|
48
|
+
"`#cap-`, but only a document has promises a flow can keep.");
|
|
49
|
+
case "empty":
|
|
50
|
+
return (`capabilities/${claim.capability}/spec.md exists and declares no requirements yet — ` +
|
|
51
|
+
"add the `## Requirements` section, each requirement carrying its `Requirement-ID:`.");
|
|
52
|
+
case "none":
|
|
53
|
+
return claim.close.length > 0
|
|
54
|
+
? `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}'. ` +
|
|
55
|
+
`Did you mean: ${claim.close.map(idAndTag).join(", ")}?`
|
|
56
|
+
: `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}' — ` +
|
|
57
|
+
"check the `Requirement-ID:` lines in that document.";
|
|
58
|
+
default:
|
|
59
|
+
return (`${claim.ids.length} requirements of '${claim.capability}' flatten to '${claim.slug}' ` +
|
|
60
|
+
`(${claim.ids.join(", ")}) — nothing in the tag can say which promise this flow keeps. ` +
|
|
61
|
+
"Rename one of them: a guessed requirement reports the wrong promise as kept and the right one as " +
|
|
62
|
+
"unimplemented, and both answers look exactly like the truth.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One finding per `#req-` tag that does not resolve — never one per view.
|
|
67
|
+
*
|
|
68
|
+
* Several `#req-` tags on one view are legal and normal: a checkout flow that
|
|
69
|
+
* charges once AND honours the price keeps two promises, and there is no honest
|
|
70
|
+
* way to make its author pick one. So a broken tag beside a working one must
|
|
71
|
+
* neither swallow the break nor lose the promise the view genuinely does keep.
|
|
72
|
+
*
|
|
73
|
+
* `claims` is the view's OWN capability verdicts, already resolved by the
|
|
74
|
+
* caller — passed rather than recomputed so the scope this grade uses and the
|
|
75
|
+
* scope `capabilityTagFindings` graded are the same list, and an unresolved
|
|
76
|
+
* `#cap-` tag cannot silently scope a requirement lookup.
|
|
77
|
+
*/
|
|
78
|
+
export function requirementTagFindings(view, claims, requirementsOf) {
|
|
79
|
+
const scope = claims.flatMap((claim) => (claim.kind === "resolved" ? [claim.id] : []));
|
|
80
|
+
const findings = [];
|
|
81
|
+
for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {
|
|
82
|
+
if (claim.kind === "resolved")
|
|
83
|
+
continue;
|
|
84
|
+
findings.push({
|
|
85
|
+
severity: "error",
|
|
86
|
+
code: "usecase.requirement-unresolved",
|
|
87
|
+
// The VIEW, not the tag — a subject is what a reader goes and opens, and
|
|
88
|
+
// one broken use case counts once however many of its tags are wrong.
|
|
89
|
+
subject: view.id,
|
|
90
|
+
message: `${viewPlace(view)} is tagged #${claim.tag}, and it does not resolve: ${advice(claim)}`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return findings;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=requirement-tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirement-tag.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/usecases/requirement-tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,cAAc,EACd,OAAO,EACP,sBAAsB,GAGvB,MAAM,+CAA+C,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO,GAAG,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,MAAM,CAAC,KAAsD;IACpE,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;gBACpC,CAAC,CAAC,oGAAoG;oBAClG,4FAA4F;oBAC5F,qEAAqE;gBACzE,CAAC,CAAC,qBAAqB,KAAK,CAAC,YAAY,CAAC,MAAM,kBAAkB,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;oBAChG,oGAAoG;oBACpG,iGAAiG;oBACjG,mGAAmG,CAAC;QAC5G,KAAK,cAAc;YACjB,OAAO,CACL,eAAe,KAAK,CAAC,UAAU,yCAAyC,KAAK,CAAC,UAAU,YAAY;gBACpG,kGAAkG;gBAClG,4DAA4D,CAC7D,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,CACL,gBAAgB,KAAK,CAAC,UAAU,qDAAqD;gBACrF,qFAAqF,CACtF,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBAC3B,CAAC,CAAC,gBAAgB,KAAK,CAAC,UAAU,mDAAmD,KAAK,CAAC,IAAI,KAAK;oBAChG,iBAAiB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAC5D,CAAC,CAAC,gBAAgB,KAAK,CAAC,UAAU,mDAAmD,KAAK,CAAC,IAAI,MAAM;oBACjG,qDAAqD,CAAC;QAC9D;YACE,OAAO,CACL,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,qBAAqB,KAAK,CAAC,UAAU,iBAAiB,KAAK,CAAC,IAAI,IAAI;gBACvF,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,gEAAgE;gBACxF,mGAAmG;gBACnG,8DAA8D,CAC/D,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAgB,EAChB,MAAkC,EAClC,cAAuE;IAEvE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC;QAC7E,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACxC,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,gCAAgC;YACtC,yEAAyE;YACzE,sEAAsE;YACtE,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,8BAA8B,MAAM,CAAC,KAAK,CAAC,EAAE;SACjG,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * `usecase.requirement-unresolved` — the `#req-` tag that names no requirement\n * of the capability the view is about.\n *\n * The join lives in `core/capabilities/usecase-join.ts` and none of it is\n * repeated here: this module owns the grade and the sentences. Six arms, six\n * fixes, and they are deliberately the same vocabulary\n * `capability.realizes-unknown` uses for the OTHER carrier of this claim — an\n * author who has learned one set of messages has learned both.\n *\n * ERROR, for `usecase.capability-unresolved`'s reason one join deeper: the tag\n * is the architect's claim that a flow satisfies a named business promise, and a\n * claim that resolves to nothing reads exactly like one that does — in the view,\n * in review, and to anyone asking which flow keeps that promise.\n *\n * AN UNRESOLVED CLAIM SUPPRESSES NOTHING. `capability.requirement-unrealized`\n * counts only RESOLVED claims, so a typo'd `#req-` tag leaves the requirement\n * reported as realized by nobody — which is the truth, and is exactly what a\n * broken claim should not be able to hide. The two findings arriving together is\n * the intended reading: one says the tag is wrong, the other says the promise is\n * still unkept.\n */\nimport {\n REQ_TAG_PREFIX,\n tagSlug,\n resolveRequirementTags,\n type CapabilityClaim,\n type RequirementClaim,\n} from \"../../../../core/capabilities/usecase-join.js\";\nimport type { ParsedView } from \"../../../../core/c4/parsed/dynamic-views.js\";\nimport type { Finding } from \"../../../../core/vocabulary/report.js\";\nimport { viewPlace } from \"./place.js\";\n\n/** A `Requirement-ID` as an author must write it in a tag: `CHK.ONCE (#req-CHK-ONCE)`. */\nfunction idAndTag(id: string): string {\n return `${id} (#${REQ_TAG_PREFIX}${tagSlug(id)})`;\n}\n\n/**\n * The fix for one unresolved claim. The `unscoped` arm splits in two on the\n * count, because none and several are opposite mistakes: one author forgot to\n * say which capability, the other said two and left the id homeless.\n */\nfunction advice(claim: Exclude<RequirementClaim, { kind: \"resolved\" }>): string {\n switch (claim.kind) {\n case \"unscoped\":\n return claim.capabilities.length === 0\n ? \"the view carries no `#cap-` tag that resolves to a declared capability, and a `Requirement-ID` is \" +\n \"unique only inside its own document — so there is nothing for this id to be looked up in. \" +\n \"Add the `#cap-<slug>` tag naming the capability this flow is about.\"\n : `the view resolves ${claim.capabilities.length} capabilities (${claim.capabilities.join(\", \")}), ` +\n \"so nothing says which document the id belongs to. A flow realizing promises from two capabilities \" +\n \"needs one `#req-` tag per capability to be unambiguous, which the tag grammar cannot express — \" +\n \"split the flow, or drop the `#req-` tag and let `Realizes:` on the service requirements carry it.\";\n case \"undocumented\":\n return (\n `capability '${claim.capability}' is declared but has no capabilities/${claim.capability}/spec.md, ` +\n \"so it carries no requirements to satisfy. Write the document — a name alone can be claimed with \" +\n \"`#cap-`, but only a document has promises a flow can keep.\"\n );\n case \"empty\":\n return (\n `capabilities/${claim.capability}/spec.md exists and declares no requirements yet — ` +\n \"add the `## Requirements` section, each requirement carrying its `Requirement-ID:`.\"\n );\n case \"none\":\n return claim.close.length > 0\n ? `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}'. ` +\n `Did you mean: ${claim.close.map(idAndTag).join(\", \")}?`\n : `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}' — ` +\n \"check the `Requirement-ID:` lines in that document.\";\n default:\n return (\n `${claim.ids.length} requirements of '${claim.capability}' flatten to '${claim.slug}' ` +\n `(${claim.ids.join(\", \")}) — nothing in the tag can say which promise this flow keeps. ` +\n \"Rename one of them: a guessed requirement reports the wrong promise as kept and the right one as \" +\n \"unimplemented, and both answers look exactly like the truth.\"\n );\n }\n}\n\n/**\n * One finding per `#req-` tag that does not resolve — never one per view.\n *\n * Several `#req-` tags on one view are legal and normal: a checkout flow that\n * charges once AND honours the price keeps two promises, and there is no honest\n * way to make its author pick one. So a broken tag beside a working one must\n * neither swallow the break nor lose the promise the view genuinely does keep.\n *\n * `claims` is the view's OWN capability verdicts, already resolved by the\n * caller — passed rather than recomputed so the scope this grade uses and the\n * scope `capabilityTagFindings` graded are the same list, and an unresolved\n * `#cap-` tag cannot silently scope a requirement lookup.\n */\nexport function requirementTagFindings(\n view: ParsedView,\n claims: readonly CapabilityClaim[],\n requirementsOf: (capability: string) => ReadonlySet<string> | undefined,\n): Finding[] {\n const scope = claims.flatMap((claim) => (claim.kind === \"resolved\" ? [claim.id] : []));\n const findings: Finding[] = [];\n for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {\n if (claim.kind === \"resolved\") continue;\n findings.push({\n severity: \"error\",\n code: \"usecase.requirement-unresolved\",\n // The VIEW, not the tag — a subject is what a reader goes and opens, and\n // one broken use case counts once however many of its tags are wrong.\n subject: view.id,\n message: `${viewPlace(view)} is tagged #${claim.tag}, and it does not resolve: ${advice(claim)}`,\n });\n }\n return findings;\n}\n"]}
|