@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,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One feature as `loam show` presents it: its intent, its delta, the
|
|
3
|
+
* per-service specs under it, and the business promises it changes.
|
|
4
|
+
*
|
|
5
|
+
* Split from `./service.ts` because a service and a feature answer different
|
|
6
|
+
* questions — what a repository holds now, against what a change proposes —
|
|
7
|
+
* and only the service view has to reach the landscape for its edges. The
|
|
8
|
+
* one-line shapes both write in are in `./marks.ts`.
|
|
9
|
+
*
|
|
10
|
+
* THE CAPABILITY SECTION IS NOT DECORATION. Without it a feature carrying only
|
|
11
|
+
* a `features/<FEAT>/capabilities/<id>/spec.md` — a business change with no
|
|
12
|
+
* service touched yet, which is the first thing an analyst writes and what
|
|
13
|
+
* `loam new --capability` scaffolds — displayed as a feature that carries
|
|
14
|
+
* nothing at all, from the command a person runs to find out what a feature
|
|
15
|
+
* carries. The archive would then refuse it (`capability.uncovered`,
|
|
16
|
+
* `scaffold.placeholder`) over documents this view said were not there.
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync } from "node:fs";
|
|
19
|
+
import { readFile } from "node:fs/promises";
|
|
20
|
+
import { emitJson, repoPath } from "../../core/envelope/json.js";
|
|
21
|
+
import {} from "../../core/c4/likec4.js";
|
|
22
|
+
import { FleetContext } from "../../core/fleet-context.js";
|
|
23
|
+
import {} from "../../core/repo/entries.js";
|
|
24
|
+
import { featurePaths, featureSpecPaths } from "../../core/repo/paths.js";
|
|
25
|
+
import { parseRequirements } from "../../core/document/parse.js";
|
|
26
|
+
import { featureCapabilityDeltas } from "../../core/capabilities/delta/tree.js";
|
|
27
|
+
import { capabilityDeltaSummaries } from "../../core/capabilities/delta/summary.js";
|
|
28
|
+
import { apiChanges } from "../../core/projection/api.js";
|
|
29
|
+
import { eventChanges } from "../../core/projection/events.js";
|
|
30
|
+
import { featureStatus } from "../../core/status/feature/feature.js";
|
|
31
|
+
import { executableNext } from "../../core/status/actions/execution.js";
|
|
32
|
+
import { findingJson } from "../../core/vocabulary/report.js";
|
|
33
|
+
import { plural } from "../policy/format.js";
|
|
34
|
+
import { errorText, mark } from "./marks.js";
|
|
35
|
+
const REVIEW_INTENT_LIMIT = 1_200;
|
|
36
|
+
function intentSummary(text) {
|
|
37
|
+
const withoutFrontmatter = text.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, "");
|
|
38
|
+
const prose = withoutFrontmatter
|
|
39
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
40
|
+
.split(/\r?\n/)
|
|
41
|
+
.map((line) => line.trim())
|
|
42
|
+
.filter((line) => line.length > 0 && !line.startsWith("#"))
|
|
43
|
+
.join(" ");
|
|
44
|
+
return prose.length <= REVIEW_INTENT_LIMIT
|
|
45
|
+
? prose
|
|
46
|
+
: `${prose.slice(0, REVIEW_INTENT_LIMIT - 1).trimEnd()}…`;
|
|
47
|
+
}
|
|
48
|
+
export async function showFeature(docsDir, feature, json, context = new FleetContext()) {
|
|
49
|
+
const paths = featurePaths(feature.dir);
|
|
50
|
+
const delta = feature.has.delta
|
|
51
|
+
? await context.loadLikeC4(paths.delta)
|
|
52
|
+
: { errors: [], elements: [], relationships: [] };
|
|
53
|
+
const taggedEls = delta.elements.filter((e) => e.tags.includes(feature.id));
|
|
54
|
+
const taggedRels = delta.relationships.filter((r) => r.tags.includes(feature.id));
|
|
55
|
+
const services = [];
|
|
56
|
+
for (const svc of feature.services) {
|
|
57
|
+
const servicePaths = featureSpecPaths(feature.dir, svc);
|
|
58
|
+
const specPath = servicePaths.spec;
|
|
59
|
+
const reqs = existsSync(specPath) ? parseRequirements(await readFile(specPath, "utf8")) : [];
|
|
60
|
+
services.push({
|
|
61
|
+
id: svc,
|
|
62
|
+
added: reqs.filter((r) => r.kind === "ADDED").length,
|
|
63
|
+
modified: reqs.filter((r) => r.kind === "MODIFIED").length,
|
|
64
|
+
removed: reqs.filter((r) => r.kind === "REMOVED").length,
|
|
65
|
+
operations: [...new Set(reqs.flatMap((r) => r.operations))],
|
|
66
|
+
api: await apiChanges(servicePaths.openapi),
|
|
67
|
+
events: await eventChanges(servicePaths.asyncapi),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// One `existsSync` for a feature with no capability delta, which is every
|
|
71
|
+
// feature in a fleet that has not adopted the business axis — the walk's own
|
|
72
|
+
// short-circuit, and the whole cost such a fleet pays for this section.
|
|
73
|
+
const capabilities = await capabilityDeltaSummaries((await featureCapabilityDeltas(feature.dir)).docs, async (path) => parseRequirements(await readFile(path, "utf8")));
|
|
74
|
+
if (json) {
|
|
75
|
+
const status = await featureStatus(docsDir, feature, { context });
|
|
76
|
+
const issues = status.checks.issues.map((finding) => findingJson(finding, { path: status.feature.path, role: "scope" }));
|
|
77
|
+
const blockers = issues.filter((finding) => finding["severity"] === "error" || finding["gates"] === true);
|
|
78
|
+
const intent = existsSync(paths.intent) ? intentSummary(await readFile(paths.intent, "utf8")) : "";
|
|
79
|
+
emitJson({
|
|
80
|
+
command: "show",
|
|
81
|
+
type: "feature",
|
|
82
|
+
id: feature.id,
|
|
83
|
+
dirName: feature.dirName,
|
|
84
|
+
path: repoPath(docsDir, feature.dir),
|
|
85
|
+
archived: feature.archived,
|
|
86
|
+
has: feature.has,
|
|
87
|
+
delta: {
|
|
88
|
+
elements: taggedEls.length,
|
|
89
|
+
relationships: taggedRels.length,
|
|
90
|
+
errors: delta.errors.map(errorText),
|
|
91
|
+
},
|
|
92
|
+
services,
|
|
93
|
+
// Additive, which the envelope permits (core/envelope/json.ts), and an
|
|
94
|
+
// EMPTY ARRAY rather than an omitted key for a feature that carries none:
|
|
95
|
+
// a consumer indexing it must not have to tell "no capability delta" from
|
|
96
|
+
// "this loam does not report them", and the two would be the same absence.
|
|
97
|
+
capabilities: capabilities.map((c) => ({
|
|
98
|
+
id: c.id,
|
|
99
|
+
path: repoPath(docsDir, c.spec),
|
|
100
|
+
added: c.added,
|
|
101
|
+
modified: c.modified,
|
|
102
|
+
removed: c.removed,
|
|
103
|
+
promises: c.promises,
|
|
104
|
+
})),
|
|
105
|
+
review: {
|
|
106
|
+
readyToArchive: !feature.archived && status.feature.stage === "done" && blockers.length === 0,
|
|
107
|
+
intent: {
|
|
108
|
+
path: repoPath(docsDir, paths.intent),
|
|
109
|
+
summary: intent,
|
|
110
|
+
},
|
|
111
|
+
architecture: {
|
|
112
|
+
path: repoPath(docsDir, paths.delta),
|
|
113
|
+
elements: taggedEls.map((element) => ({
|
|
114
|
+
id: element.id,
|
|
115
|
+
kind: element.kind,
|
|
116
|
+
title: element.title,
|
|
117
|
+
})),
|
|
118
|
+
relationships: taggedRels.map((relationship) => ({
|
|
119
|
+
source: relationship.source,
|
|
120
|
+
target: relationship.target,
|
|
121
|
+
title: relationship.title ?? null,
|
|
122
|
+
operation: relationship.op ?? null,
|
|
123
|
+
})),
|
|
124
|
+
errors: delta.errors.map(errorText),
|
|
125
|
+
},
|
|
126
|
+
services,
|
|
127
|
+
dependencies: { blockedBy: status.feature.blockedBy },
|
|
128
|
+
artifacts: status.artifacts,
|
|
129
|
+
verification: status.verification,
|
|
130
|
+
blockers,
|
|
131
|
+
advisories: issues.filter((finding) => finding["severity"] === "warn" && finding["gates"] !== true),
|
|
132
|
+
useCases: status.useCases,
|
|
133
|
+
next: status.next.map(executableNext),
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const state = feature.archived ? "archived" : "active";
|
|
139
|
+
console.log(`${feature.id} ${repoPath(docsDir, feature.dir)} ${state}\n`);
|
|
140
|
+
console.log(" artifacts");
|
|
141
|
+
console.log(` ${mark(feature.has.intent)} intent.md`);
|
|
142
|
+
const deltaNote = delta.errors.length > 0
|
|
143
|
+
? `${delta.errors.length} error(s)`
|
|
144
|
+
: `${plural(taggedEls.length, "element")} · ${plural(taggedRels.length, "relationship")} tagged ${feature.id}`;
|
|
145
|
+
console.log(` ${mark(feature.has.delta)} delta.likec4 ${feature.has.delta ? deltaNote : ""}`.trimEnd());
|
|
146
|
+
if (services.length > 0) {
|
|
147
|
+
console.log("\n services");
|
|
148
|
+
const width = Math.max(...services.map((s) => s.id.length));
|
|
149
|
+
for (const s of services) {
|
|
150
|
+
const ops = s.operations.length > 0 ? ` · ${s.operations.join(", ")}` : "";
|
|
151
|
+
console.log(` ${s.id.padEnd(width)} +${s.added} ~${s.modified} -${s.removed} requirements${ops}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Printed only when the feature carries one: a fleet that has not adopted the
|
|
155
|
+
// business axis must see nothing, and an empty "capabilities" heading over
|
|
156
|
+
// every feature in every such fleet is exactly the noise that teaches people
|
|
157
|
+
// to stop reading the output.
|
|
158
|
+
if (capabilities.length > 0) {
|
|
159
|
+
console.log("\n capabilities");
|
|
160
|
+
const width = Math.max(...capabilities.map((c) => c.id.length));
|
|
161
|
+
for (const c of capabilities) {
|
|
162
|
+
// The promise ids, not just the counts: `Realizes: <capability>#<id>` is
|
|
163
|
+
// the line somebody has to write next, and the id is the half of it a
|
|
164
|
+
// reader cannot guess.
|
|
165
|
+
const ids = c.promises.flatMap((p) => (p.id === null ? [] : [p.id]));
|
|
166
|
+
console.log(` ${c.id.padEnd(width)} +${c.added} ~${c.modified} -${c.removed} promises` +
|
|
167
|
+
(ids.length === 0 ? "" : ` · ${ids.join(", ")}`));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (delta.errors.length > 0) {
|
|
171
|
+
console.log("\n delta errors");
|
|
172
|
+
for (const e of delta.errors)
|
|
173
|
+
console.log(` ✗ ${errorText(e)}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/* ------------------------------------------------------------------ */
|
|
177
|
+
/** "-" for absent, matching `list`: ✗ is the error glyph here, and a missing runbook is not an error. */
|
|
178
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../src/commands/show/feature.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One feature as `loam show` presents it: its intent, its delta, the\n * per-service specs under it, and the business promises it changes.\n *\n * Split from `./service.ts` because a service and a feature answer different\n * questions — what a repository holds now, against what a change proposes —\n * and only the service view has to reach the landscape for its edges. The\n * one-line shapes both write in are in `./marks.ts`.\n *\n * THE CAPABILITY SECTION IS NOT DECORATION. Without it a feature carrying only\n * a `features/<FEAT>/capabilities/<id>/spec.md` — a business change with no\n * service touched yet, which is the first thing an analyst writes and what\n * `loam new --capability` scaffolds — displayed as a feature that carries\n * nothing at all, from the command a person runs to find out what a feature\n * carries. The archive would then refuse it (`capability.uncovered`,\n * `scaffold.placeholder`) over documents this view said were not there.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { emitJson, repoPath } from \"../../core/envelope/json.js\";\nimport { type Elem } from \"../../core/c4/likec4.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { type FeatureEntry } from \"../../core/repo/entries.js\";\nimport { featurePaths, featureSpecPaths } from \"../../core/repo/paths.js\";\nimport { parseRequirements } from \"../../core/document/parse.js\";\nimport { featureCapabilityDeltas } from \"../../core/capabilities/delta/tree.js\";\nimport { capabilityDeltaSummaries } from \"../../core/capabilities/delta/summary.js\";\nimport { apiChanges } from \"../../core/projection/api.js\";\nimport { eventChanges } from \"../../core/projection/events.js\";\nimport { featureStatus } from \"../../core/status/feature/feature.js\";\nimport { executableNext } from \"../../core/status/actions/execution.js\";\nimport { findingJson } from \"../../core/vocabulary/report.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { plural } from \"../policy/format.js\";\nimport { errorText, mark } from \"./marks.js\";\n\nconst REVIEW_INTENT_LIMIT = 1_200;\n\nfunction intentSummary(text: string): string {\n const withoutFrontmatter = text.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/, \"\");\n const prose = withoutFrontmatter\n .replace(/<!--[\\s\\S]*?-->/g, \"\")\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"))\n .join(\" \");\n return prose.length <= REVIEW_INTENT_LIMIT\n ? prose\n : `${prose.slice(0, REVIEW_INTENT_LIMIT - 1).trimEnd()}…`;\n}\n\nexport async function showFeature(\n docsDir: DocsDir,\n feature: FeatureEntry,\n json: boolean,\n context = new FleetContext(),\n): Promise<void> {\n const paths = featurePaths(feature.dir);\n const delta = feature.has.delta\n ? await context.loadLikeC4(paths.delta)\n : { errors: [], elements: [] as Elem[], relationships: [] };\n const taggedEls = delta.elements.filter((e) => e.tags.includes(feature.id));\n const taggedRels = delta.relationships.filter((r) => r.tags.includes(feature.id));\n\n const services = [];\n for (const svc of feature.services) {\n const servicePaths = featureSpecPaths(feature.dir, svc);\n const specPath = servicePaths.spec;\n const reqs = existsSync(specPath) ? parseRequirements(await readFile(specPath, \"utf8\")) : [];\n services.push({\n id: svc,\n added: reqs.filter((r) => r.kind === \"ADDED\").length,\n modified: reqs.filter((r) => r.kind === \"MODIFIED\").length,\n removed: reqs.filter((r) => r.kind === \"REMOVED\").length,\n operations: [...new Set(reqs.flatMap((r) => r.operations))],\n api: await apiChanges(servicePaths.openapi),\n events: await eventChanges(servicePaths.asyncapi),\n });\n }\n\n // One `existsSync` for a feature with no capability delta, which is every\n // feature in a fleet that has not adopted the business axis — the walk's own\n // short-circuit, and the whole cost such a fleet pays for this section.\n const capabilities = await capabilityDeltaSummaries(\n (await featureCapabilityDeltas(feature.dir)).docs,\n async (path) => parseRequirements(await readFile(path, \"utf8\")),\n );\n\n if (json) {\n const status = await featureStatus(docsDir, feature, { context });\n const issues = status.checks.issues.map((finding) =>\n findingJson(finding, { path: status.feature.path, role: \"scope\" }),\n );\n const blockers = issues.filter(\n (finding) => finding[\"severity\"] === \"error\" || finding[\"gates\"] === true,\n );\n const intent = existsSync(paths.intent) ? intentSummary(await readFile(paths.intent, \"utf8\")) : \"\";\n emitJson({\n command: \"show\",\n type: \"feature\",\n id: feature.id,\n dirName: feature.dirName,\n path: repoPath(docsDir, feature.dir),\n archived: feature.archived,\n has: feature.has,\n delta: {\n elements: taggedEls.length,\n relationships: taggedRels.length,\n errors: delta.errors.map(errorText),\n },\n services,\n // Additive, which the envelope permits (core/envelope/json.ts), and an\n // EMPTY ARRAY rather than an omitted key for a feature that carries none:\n // a consumer indexing it must not have to tell \"no capability delta\" from\n // \"this loam does not report them\", and the two would be the same absence.\n capabilities: capabilities.map((c) => ({\n id: c.id,\n path: repoPath(docsDir, c.spec),\n added: c.added,\n modified: c.modified,\n removed: c.removed,\n promises: c.promises,\n })),\n review: {\n readyToArchive: !feature.archived && status.feature.stage === \"done\" && blockers.length === 0,\n intent: {\n path: repoPath(docsDir, paths.intent),\n summary: intent,\n },\n architecture: {\n path: repoPath(docsDir, paths.delta),\n elements: taggedEls.map((element) => ({\n id: element.id,\n kind: element.kind,\n title: element.title,\n })),\n relationships: taggedRels.map((relationship) => ({\n source: relationship.source,\n target: relationship.target,\n title: relationship.title ?? null,\n operation: relationship.op ?? null,\n })),\n errors: delta.errors.map(errorText),\n },\n services,\n dependencies: { blockedBy: status.feature.blockedBy },\n artifacts: status.artifacts,\n verification: status.verification,\n blockers,\n advisories: issues.filter(\n (finding) => finding[\"severity\"] === \"warn\" && finding[\"gates\"] !== true,\n ),\n useCases: status.useCases,\n next: status.next.map(executableNext),\n },\n });\n return;\n }\n\n const state = feature.archived ? \"archived\" : \"active\";\n console.log(`${feature.id} ${repoPath(docsDir, feature.dir)} ${state}\\n`);\n\n console.log(\" artifacts\");\n console.log(` ${mark(feature.has.intent)} intent.md`);\n const deltaNote =\n delta.errors.length > 0\n ? `${delta.errors.length} error(s)`\n : `${plural(taggedEls.length, \"element\")} · ${plural(taggedRels.length, \"relationship\")} tagged ${feature.id}`;\n console.log(` ${mark(feature.has.delta)} delta.likec4 ${feature.has.delta ? deltaNote : \"\"}`.trimEnd());\n\n if (services.length > 0) {\n console.log(\"\\n services\");\n const width = Math.max(...services.map((s) => s.id.length));\n for (const s of services) {\n const ops = s.operations.length > 0 ? ` · ${s.operations.join(\", \")}` : \"\";\n console.log(\n ` ${s.id.padEnd(width)} +${s.added} ~${s.modified} -${s.removed} requirements${ops}`,\n );\n }\n }\n\n // Printed only when the feature carries one: a fleet that has not adopted the\n // business axis must see nothing, and an empty \"capabilities\" heading over\n // every feature in every such fleet is exactly the noise that teaches people\n // to stop reading the output.\n if (capabilities.length > 0) {\n console.log(\"\\n capabilities\");\n const width = Math.max(...capabilities.map((c) => c.id.length));\n for (const c of capabilities) {\n // The promise ids, not just the counts: `Realizes: <capability>#<id>` is\n // the line somebody has to write next, and the id is the half of it a\n // reader cannot guess.\n const ids = c.promises.flatMap((p) => (p.id === null ? [] : [p.id]));\n console.log(\n ` ${c.id.padEnd(width)} +${c.added} ~${c.modified} -${c.removed} promises` +\n (ids.length === 0 ? \"\" : ` · ${ids.join(\", \")}`),\n );\n }\n }\n\n if (delta.errors.length > 0) {\n console.log(\"\\n delta errors\");\n for (const e of delta.errors) console.log(` ✗ ${errorText(e)}`);\n }\n}\n\n/* ------------------------------------------------------------------ */\n\n/** \"-\" for absent, matching `list`: ✗ is the error glyph here, and a missing runbook is not an error. */\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The four one-line shapes both halves of `loam show` are written in: a tick
|
|
3
|
+
* for a file that exists, a scenario count, an edge note, a parse error.
|
|
4
|
+
*
|
|
5
|
+
* A leaf of its own because the service view and the feature view both use
|
|
6
|
+
* them, and neither should have to import the other to reach a tick.
|
|
7
|
+
*/
|
|
8
|
+
import {} from "../../core/document/spec.js";
|
|
9
|
+
import {} from "./service.js";
|
|
10
|
+
export function mark(present) {
|
|
11
|
+
return present ? "✓" : "-";
|
|
12
|
+
}
|
|
13
|
+
export function scenarioCount(reqs) {
|
|
14
|
+
return reqs.reduce((n, r) => n + r.scenarios.length, 0);
|
|
15
|
+
}
|
|
16
|
+
export function edgeNote(e) {
|
|
17
|
+
if (e.op)
|
|
18
|
+
return ` ${e.op}`;
|
|
19
|
+
return e.title ? ` "${e.title}"` : "";
|
|
20
|
+
}
|
|
21
|
+
export function errorText(e) {
|
|
22
|
+
return typeof e.line === "number" ? `L${e.line}: ${e.message}` : e.message;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=marks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marks.js","sourceRoot":"","sources":["../../../src/commands/show/marks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAoB,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAa,MAAM,cAAc,CAAC;AAEzC,MAAM,UAAU,IAAI,CAAC,OAAgB;IACnC,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAO;IAC9B,IAAI,CAAC,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;IAC7B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAqC;IAC7D,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAC7E,CAAC","sourcesContent":["/**\n * The four one-line shapes both halves of `loam show` are written in: a tick\n * for a file that exists, a scenario count, an edge note, a parse error.\n *\n * A leaf of its own because the service view and the feature view both use\n * them, and neither should have to import the other to reach a tick.\n */\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { type Edge } from \"./service.js\";\n\nexport function mark(present: boolean): string {\n return present ? \"✓\" : \"-\";\n}\n\nexport function scenarioCount(reqs: Requirement[]): number {\n return reqs.reduce((n, r) => n + r.scenarios.length, 0);\n}\n\nexport function edgeNote(e: Edge): string {\n if (e.op) return ` ${e.op}`;\n return e.title ? ` \"${e.title}\"` : \"\";\n}\n\nexport function errorText(e: { message: string; line?: number }): string {\n return typeof e.line === \"number\" ? `L${e.line}: ${e.message}` : e.message;\n}\n"]}
|
|
@@ -1,78 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One service as `loam show` presents it: its spec, its contract, and the
|
|
3
|
+
* fleet edges into and out of it.
|
|
4
|
+
*
|
|
5
|
+
* Split from `./feature.ts` because a service and a feature answer different
|
|
6
|
+
* questions — what a repository holds now, against what a change proposes —
|
|
7
|
+
* and only the service view has to reach the landscape for its edges.
|
|
8
|
+
*/
|
|
1
9
|
import { existsSync } from "node:fs";
|
|
2
10
|
import { readFile } from "node:fs/promises";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { loadFile
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.action(async (target, opts) => {
|
|
21
|
-
const json = opts.json === true;
|
|
22
|
-
if (opts.type !== undefined && opts.type !== "service" && opts.type !== "feature") {
|
|
23
|
-
fail(json, "invalid-option", `Unknown --type '${opts.type}'. Expected: service | feature.`);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const forced = opts.type;
|
|
27
|
-
const config = await loadConfig();
|
|
28
|
-
if (!config) {
|
|
29
|
-
reportNoConfig(json);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const { docsDir } = config;
|
|
33
|
-
// "No service or feature 'x' in <dir>" is a lie when <dir> is not a docs
|
|
34
|
-
// repo at all — the same refusal validate and list owe (docsRepoReady).
|
|
35
|
-
// `docs`, not `services`: a feature is readable from a repo whose
|
|
36
|
-
// services/ is missing, and if the target turns out to be a service the
|
|
37
|
-
// enumeration below refuses with `services-missing` anyway.
|
|
38
|
-
if (!docsRepoReady(json, docsDir, "docs"))
|
|
39
|
-
return;
|
|
40
|
-
// One read index for the invocation. Deciding the target is a service
|
|
41
|
-
// enumerates the fleet, and so does resolving the landscape's edges to the
|
|
42
|
-
// services that own them — `loam show <service>` walked services/ twice for
|
|
43
|
-
// one answer. The context memoises only within this invocation, so a later
|
|
44
|
-
// run still sees whatever is on disk then.
|
|
45
|
-
const context = new FleetContext();
|
|
46
|
-
try {
|
|
47
|
-
// A feature id is distinctive (FEAT-101); a service name is arbitrary. When
|
|
48
|
-
// both could match, the feature wins and --type forces the other reading.
|
|
49
|
-
const feature = forced === "service" ? null : await resolveFeature(docsDir, target, "include", context);
|
|
50
|
-
if (feature) {
|
|
51
|
-
await showFeature(docsDir, feature, json);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const isService = forced !== "feature" && (await listServices(docsDir, context)).some((s) => s.id === target);
|
|
55
|
-
if (isService) {
|
|
56
|
-
await showService(docsDir, target, json, context);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const looked = forced ? forced : "service or feature";
|
|
60
|
-
fail(json, "unknown-target", `No ${looked} '${target}' in ${docsDir}.`);
|
|
61
|
-
}
|
|
62
|
-
catch (err) {
|
|
63
|
-
if (err instanceof DocsRepoUnavailableError) {
|
|
64
|
-
reportDocsRepoError(json, err);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
// An artifact that exists but cannot be read used to escape as a stack
|
|
68
|
-
// trace (`internal` in --json), naming nothing. `show` reads one target,
|
|
69
|
-
// so it has nothing to fall back on — but it can at least say WHICH file.
|
|
70
|
-
reportRepositoryUnavailable(json, err, `'${target}' cannot be shown`, docsDir);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
async function showService(docsDir, id, json, context) {
|
|
75
|
-
const paths = servicePaths(docsDir, id);
|
|
11
|
+
import { FleetContext } from "../../core/fleet-context.js";
|
|
12
|
+
import { emitJson, repoPath } from "../../core/envelope/json.js";
|
|
13
|
+
import { listField, readFrontmatter, stringField } from "../../core/document/frontmatter.js";
|
|
14
|
+
import { scopeText } from "../../core/provenance/sample/scope.js";
|
|
15
|
+
import { loadFile } from "../../core/c4/likec4.js";
|
|
16
|
+
import { serviceResolver } from "../../core/c4/resolve/service.js";
|
|
17
|
+
import { readOpenapi } from "../../core/openapi/doc.js";
|
|
18
|
+
import { landscapePath } from "../../core/repo/paths.js";
|
|
19
|
+
import { locateServicePaths } from "../../core/repo/service-target.js";
|
|
20
|
+
import { listServices } from "../../core/repo/repo.js";
|
|
21
|
+
import { countMarkdown } from "../../core/repo/tree/fs.js";
|
|
22
|
+
import { parseRequirements } from "../../core/document/parse.js";
|
|
23
|
+
import {} from "../../core/document/spec.js";
|
|
24
|
+
import { plural } from "../policy/format.js";
|
|
25
|
+
import { edgeNote, errorText, mark, scenarioCount } from "./marks.js";
|
|
26
|
+
export async function showService(docsDir, id, json, context) {
|
|
27
|
+
const paths = await locateServicePaths(docsDir, id, context);
|
|
76
28
|
const has = {
|
|
77
29
|
model: existsSync(paths.model),
|
|
78
30
|
spec: existsSync(paths.spec),
|
|
@@ -100,12 +52,25 @@ async function showService(docsDir, id, json, context) {
|
|
|
100
52
|
// from a delta, not operations anybody can call.
|
|
101
53
|
const api = await readOpenapi(paths.openapi);
|
|
102
54
|
const ops = api.ops.filter((o) => !o.remove).map((o) => o.id);
|
|
103
|
-
|
|
55
|
+
// Both axes: the sample is per file, so an arch.spec.md read from a sample
|
|
56
|
+
// beside a fully-read spec.md still means part of this service's
|
|
57
|
+
// documentation was not read, and a badge derived from spec.md alone would
|
|
58
|
+
// not say so.
|
|
59
|
+
const [fm, archFm] = await Promise.all([readFrontmatter(paths.spec), readFrontmatter(paths.archSpec)]);
|
|
60
|
+
const scope = scopeText(fm);
|
|
61
|
+
const archScope = scopeText(archFm);
|
|
104
62
|
const provenance = {
|
|
105
63
|
status: stringField(fm, "status") ?? null,
|
|
106
64
|
owner: stringField(fm, "owner") ?? null,
|
|
107
65
|
last_verified: stringField(fm, "last_verified") ?? null,
|
|
108
66
|
sources: listField(fm, "sources"),
|
|
67
|
+
// Additive, under its frontmatter spelling like its siblings: `show` is
|
|
68
|
+
// where a person goes to find out what a service's documents claim, and a
|
|
69
|
+
// `status: verified` that a person reached by reading four sections of the
|
|
70
|
+
// spec is a materially different claim. Verbatim rather than decoded — an
|
|
71
|
+
// unreadable value is still a stamped partial read, and showing it as it
|
|
72
|
+
// stands is what lets a reader see the mangling.
|
|
73
|
+
vouch_scope: scope,
|
|
109
74
|
};
|
|
110
75
|
const governs = (op) => reqs.filter((r) => r.operations.includes(op)).map((r) => r.name);
|
|
111
76
|
const { inbound, outbound } = await landscapeEdges(docsDir, id, context);
|
|
@@ -119,6 +84,7 @@ async function showService(docsDir, id, json, context) {
|
|
|
119
84
|
});
|
|
120
85
|
if (json) {
|
|
121
86
|
emitJson({
|
|
87
|
+
command: "show",
|
|
122
88
|
type: "service",
|
|
123
89
|
id,
|
|
124
90
|
path: repoPath(docsDir, paths.dir),
|
|
@@ -135,6 +101,10 @@ async function showService(docsDir, id, json, context) {
|
|
|
135
101
|
requirements: archReqs.length,
|
|
136
102
|
scenarios: scenarioCount(archReqs),
|
|
137
103
|
entries: archReqs.map(requirementJson),
|
|
104
|
+
// The second axis carries its own scope: one `--sample` run can stamp
|
|
105
|
+
// one of the pair sampled and read the other in full, and the
|
|
106
|
+
// `frontmatter` block above is spec.md's alone.
|
|
107
|
+
vouch_scope: archScope,
|
|
138
108
|
},
|
|
139
109
|
openapi: {
|
|
140
110
|
unreadable: api.unreadable,
|
|
@@ -145,12 +115,27 @@ async function showService(docsDir, id, json, context) {
|
|
|
145
115
|
});
|
|
146
116
|
return;
|
|
147
117
|
}
|
|
148
|
-
|
|
118
|
+
// The badge qualifies the status rather than replacing it: the document
|
|
119
|
+
// still says `verified` and this screen still says so, with what that vouch
|
|
120
|
+
// actually covered attached. A bare `verified` over a sampled stamp is the
|
|
121
|
+
// one reading this whole feature exists to prevent — and either axis earns
|
|
122
|
+
// the qualifier, since either one is part of this service nobody read.
|
|
123
|
+
const shown = provenance.status === null || (scope === null && archScope === null)
|
|
124
|
+
? provenance.status
|
|
125
|
+
: `${provenance.status} (sampled)`;
|
|
126
|
+
const badge = [shown, provenance.owner].filter((s) => s !== null).join(" · ");
|
|
149
127
|
console.log(`${id} ${repoPath(docsDir, paths.dir)}${badge ? ` ${badge}` : ""}\n`);
|
|
150
|
-
if (provenance.sources.length > 0 || provenance.last_verified !== null) {
|
|
128
|
+
if (provenance.sources.length > 0 || provenance.last_verified !== null || archScope !== null) {
|
|
151
129
|
console.log(" provenance");
|
|
152
130
|
if (provenance.last_verified !== null)
|
|
153
131
|
console.log(` verified ${provenance.last_verified}`);
|
|
132
|
+
// Per axis and named, because they can disagree: one file read in full,
|
|
133
|
+
// the other from a sample, is an ordinary outcome of one `--sample` run.
|
|
134
|
+
if (scope !== null)
|
|
135
|
+
console.log(` scope spec.md ${scope} — the rest of it was not read at that vouch`);
|
|
136
|
+
if (archScope !== null) {
|
|
137
|
+
console.log(` scope arch.spec.md ${archScope} — the rest of it was not read at that vouch`);
|
|
138
|
+
}
|
|
154
139
|
for (const s of provenance.sources)
|
|
155
140
|
console.log(` sources ${s}`);
|
|
156
141
|
console.log("");
|
|
@@ -213,7 +198,7 @@ async function showService(docsDir, id, json, context) {
|
|
|
213
198
|
}
|
|
214
199
|
}
|
|
215
200
|
/** Inbound/outbound edges for a service, read off the living landscape. */
|
|
216
|
-
async function landscapeEdges(docsDir, service, context) {
|
|
201
|
+
export async function landscapeEdges(docsDir, service, context) {
|
|
217
202
|
const path = landscapePath(docsDir);
|
|
218
203
|
if (!existsSync(path))
|
|
219
204
|
return { inbound: [], outbound: [] };
|
|
@@ -243,78 +228,4 @@ async function landscapeEdges(docsDir, service, context) {
|
|
|
243
228
|
/* ------------------------------------------------------------------ */
|
|
244
229
|
/* Feature */
|
|
245
230
|
/* ------------------------------------------------------------------ */
|
|
246
|
-
|
|
247
|
-
const paths = featurePaths(feature.dir);
|
|
248
|
-
const delta = feature.has.delta
|
|
249
|
-
? await loadFile(paths.delta)
|
|
250
|
-
: { errors: [], elements: [], relationships: [] };
|
|
251
|
-
const taggedEls = delta.elements.filter((e) => e.tags.includes(feature.id));
|
|
252
|
-
const taggedRels = delta.relationships.filter((r) => r.tags.includes(feature.id));
|
|
253
|
-
const services = [];
|
|
254
|
-
for (const svc of feature.services) {
|
|
255
|
-
const specPath = featureSpecPaths(feature.dir, svc).spec;
|
|
256
|
-
const reqs = existsSync(specPath) ? parseRequirements(await readFile(specPath, "utf8")) : [];
|
|
257
|
-
services.push({
|
|
258
|
-
id: svc,
|
|
259
|
-
added: reqs.filter((r) => r.kind === "ADDED").length,
|
|
260
|
-
modified: reqs.filter((r) => r.kind === "MODIFIED").length,
|
|
261
|
-
removed: reqs.filter((r) => r.kind === "REMOVED").length,
|
|
262
|
-
operations: [...new Set(reqs.flatMap((r) => r.operations))],
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
if (json) {
|
|
266
|
-
emitJson({
|
|
267
|
-
type: "feature",
|
|
268
|
-
id: feature.id,
|
|
269
|
-
dirName: feature.dirName,
|
|
270
|
-
path: repoPath(docsDir, feature.dir),
|
|
271
|
-
archived: feature.archived,
|
|
272
|
-
has: feature.has,
|
|
273
|
-
delta: {
|
|
274
|
-
elements: taggedEls.length,
|
|
275
|
-
relationships: taggedRels.length,
|
|
276
|
-
errors: delta.errors.map(errorText),
|
|
277
|
-
},
|
|
278
|
-
services,
|
|
279
|
-
});
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const state = feature.archived ? "archived" : "active";
|
|
283
|
-
console.log(`${feature.id} ${repoPath(docsDir, feature.dir)} ${state}\n`);
|
|
284
|
-
console.log(" artifacts");
|
|
285
|
-
console.log(` ${mark(feature.has.intent)} intent.md`);
|
|
286
|
-
const deltaNote = delta.errors.length > 0
|
|
287
|
-
? `${delta.errors.length} error(s)`
|
|
288
|
-
: `${plural(taggedEls.length, "element")} · ${plural(taggedRels.length, "relationship")} tagged ${feature.id}`;
|
|
289
|
-
console.log(` ${mark(feature.has.delta)} delta.likec4 ${feature.has.delta ? deltaNote : ""}`.trimEnd());
|
|
290
|
-
if (services.length > 0) {
|
|
291
|
-
console.log("\n services");
|
|
292
|
-
const width = Math.max(...services.map((s) => s.id.length));
|
|
293
|
-
for (const s of services) {
|
|
294
|
-
const ops = s.operations.length > 0 ? ` · ${s.operations.join(", ")}` : "";
|
|
295
|
-
console.log(` ${s.id.padEnd(width)} +${s.added} ~${s.modified} -${s.removed} requirements${ops}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
if (delta.errors.length > 0) {
|
|
299
|
-
console.log("\n delta errors");
|
|
300
|
-
for (const e of delta.errors)
|
|
301
|
-
console.log(` ✗ ${errorText(e)}`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
/* ------------------------------------------------------------------ */
|
|
305
|
-
/** "-" for absent, matching `list`: ✗ is the error glyph here, and a missing runbook is not an error. */
|
|
306
|
-
function mark(present) {
|
|
307
|
-
return present ? "✓" : "-";
|
|
308
|
-
}
|
|
309
|
-
function scenarioCount(reqs) {
|
|
310
|
-
return reqs.reduce((n, r) => n + r.scenarios.length, 0);
|
|
311
|
-
}
|
|
312
|
-
function edgeNote(e) {
|
|
313
|
-
if (e.op)
|
|
314
|
-
return ` ${e.op}`;
|
|
315
|
-
return e.title ? ` "${e.title}"` : "";
|
|
316
|
-
}
|
|
317
|
-
function errorText(e) {
|
|
318
|
-
return typeof e.line === "number" ? `L${e.line}: ${e.message}` : e.message;
|
|
319
|
-
}
|
|
320
|
-
//# sourceMappingURL=show.js.map
|
|
231
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/commands/show/service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One service as `loam show` presents it: its spec, its contract, and the\n * fleet edges into and out of it.\n *\n * Split from `./feature.ts` because a service and a feature answer different\n * questions — what a repository holds now, against what a change proposes —\n * and only the service view has to reach the landscape for its edges.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { emitJson, repoPath } from \"../../core/envelope/json.js\";\nimport { listField, readFrontmatter, stringField } from \"../../core/document/frontmatter.js\";\nimport { scopeText } from \"../../core/provenance/sample/scope.js\";\nimport { loadFile } from \"../../core/c4/likec4.js\";\nimport { serviceResolver } from \"../../core/c4/resolve/service.js\";\nimport { readOpenapi } from \"../../core/openapi/doc.js\";\nimport type { PathableService } from \"../../core/kernel/ids/service.js\";\nimport { landscapePath } from \"../../core/repo/paths.js\";\nimport { locateServicePaths } from \"../../core/repo/service-target.js\";\nimport { listServices } from \"../../core/repo/repo.js\";\nimport { countMarkdown } from \"../../core/repo/tree/fs.js\";\nimport { parseRequirements } from \"../../core/document/parse.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { plural } from \"../policy/format.js\";\nimport { edgeNote, errorText, mark, scenarioCount } from \"./marks.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\nexport interface Edge {\n service: string;\n op: string | null;\n title: string | null;\n}\n\nexport async function showService(\n docsDir: DocsDir,\n id: PathableService,\n json: boolean,\n context: FleetContext,\n): Promise<void> {\n const paths = await locateServicePaths(docsDir, id, context);\n const has = {\n model: existsSync(paths.model),\n spec: existsSync(paths.spec),\n // The architecture-obligations axis. It was invisible here and in `list`,\n // which made the whole axis unnavigable: a service could carry twenty arch\n // requirements — the outbox, the retries, the alerts — and every command a\n // reader uses to find out what a service documents showed none of them.\n archSpec: existsSync(paths.archSpec),\n openapi: existsSync(paths.openapi),\n runbook: existsSync(paths.runbook),\n health: existsSync(paths.health),\n };\n\n const model = has.model\n ? await loadFile(paths.model)\n : { errors: [], elements: [], relationships: [] };\n const reqs = has.spec ? parseRequirements(await readFile(paths.spec, \"utf8\")) : [];\n const archReqs = has.archSpec ? parseRequirements(await readFile(paths.archSpec, \"utf8\")) : [];\n const adrs = await countMarkdown(paths.adrsDir);\n // `readOpenapi`, not `operationIds`: a contract that exists but does not parse\n // came back from operationIds as an EMPTY operation list, indistinguishable\n // from a service with no endpoints. `show` is what a reader opens to find out\n // what a service offers, and answering \"nothing\" over a YAML error is the\n // worst possible lie for that question. `x-loam-remove` entries are filtered\n // out for the same reason validate filters them: they are deletion markers\n // from a delta, not operations anybody can call.\n const api = await readOpenapi(paths.openapi);\n const ops = api.ops.filter((o) => !o.remove).map((o) => o.id);\n\n // Both axes: the sample is per file, so an arch.spec.md read from a sample\n // beside a fully-read spec.md still means part of this service's\n // documentation was not read, and a badge derived from spec.md alone would\n // not say so.\n const [fm, archFm] = await Promise.all([readFrontmatter(paths.spec), readFrontmatter(paths.archSpec)]);\n const scope = scopeText(fm);\n const archScope = scopeText(archFm);\n const provenance = {\n status: stringField(fm, \"status\") ?? null,\n owner: stringField(fm, \"owner\") ?? null,\n last_verified: stringField(fm, \"last_verified\") ?? null,\n sources: listField(fm, \"sources\"),\n // Additive, under its frontmatter spelling like its siblings: `show` is\n // where a person goes to find out what a service's documents claim, and a\n // `status: verified` that a person reached by reading four sections of the\n // spec is a materially different claim. Verbatim rather than decoded — an\n // unreadable value is still a stamped partial read, and showing it as it\n // stands is what lets a reader see the mangling.\n vouch_scope: scope,\n };\n\n const governs = (op: string): string[] =>\n reqs.filter((r) => r.operations.includes(op)).map((r) => r.name);\n\n const { inbound, outbound } = await landscapeEdges(docsDir, id, context);\n\n const requirementJson = (r: Requirement): Record<string, unknown> => ({\n id: r.id,\n name: r.name,\n kind: r.kind,\n scenarios: r.scenarios.length,\n operations: r.operations,\n covers: r.covers,\n });\n\n if (json) {\n emitJson({\n command: \"show\",\n type: \"service\",\n id,\n path: repoPath(docsDir, paths.dir),\n has,\n adrs,\n frontmatter: provenance,\n model: {\n elements: model.elements.length,\n relationships: model.relationships.length,\n errors: model.errors.map(errorText),\n },\n requirements: reqs.map(requirementJson),\n archSpec: {\n requirements: archReqs.length,\n scenarios: scenarioCount(archReqs),\n entries: archReqs.map(requirementJson),\n // The second axis carries its own scope: one `--sample` run can stamp\n // one of the pair sampled and read the other in full, and the\n // `frontmatter` block above is spec.md's alone.\n vouch_scope: archScope,\n },\n openapi: {\n unreadable: api.unreadable,\n ...(api.error === undefined ? {} : { error: api.error }),\n },\n operations: ops.map((op) => ({ id: op, governedBy: governs(op) })),\n landscape: { inbound, outbound },\n });\n return;\n }\n\n // The badge qualifies the status rather than replacing it: the document\n // still says `verified` and this screen still says so, with what that vouch\n // actually covered attached. A bare `verified` over a sampled stamp is the\n // one reading this whole feature exists to prevent — and either axis earns\n // the qualifier, since either one is part of this service nobody read.\n const shown =\n provenance.status === null || (scope === null && archScope === null)\n ? provenance.status\n : `${provenance.status} (sampled)`;\n const badge = [shown, provenance.owner].filter((s) => s !== null).join(\" · \");\n console.log(`${id} ${repoPath(docsDir, paths.dir)}${badge ? ` ${badge}` : \"\"}\\n`);\n\n if (provenance.sources.length > 0 || provenance.last_verified !== null || archScope !== null) {\n console.log(\" provenance\");\n if (provenance.last_verified !== null) console.log(` verified ${provenance.last_verified}`);\n // Per axis and named, because they can disagree: one file read in full,\n // the other from a sample, is an ordinary outcome of one `--sample` run.\n if (scope !== null) console.log(` scope spec.md ${scope} — the rest of it was not read at that vouch`);\n if (archScope !== null) {\n console.log(` scope arch.spec.md ${archScope} — the rest of it was not read at that vouch`);\n }\n for (const s of provenance.sources) console.log(` sources ${s}`);\n console.log(\"\");\n }\n\n console.log(\" artifacts\");\n const modelNote =\n model.errors.length > 0\n ? `${model.errors.length} error(s)`\n : `${plural(model.elements.length, \"element\")} · ${plural(model.relationships.length, \"relationship\")}`;\n console.log(` ${mark(has.model)} model.likec4 ${has.model ? modelNote : \"\"}`.trimEnd());\n const specNote = (rs: Requirement[]): string =>\n `${plural(rs.length, \"requirement\")} · ${plural(scenarioCount(rs), \"scenario\")}`;\n console.log(` ${mark(has.spec)} spec.md ${has.spec ? specNote(reqs) : \"\"}`.trimEnd());\n console.log(\n ` ${mark(has.archSpec)} arch.spec.md ${has.archSpec ? specNote(archReqs) : \"\"}`.trimEnd(),\n );\n const apiNote = api.unreadable ? \"does not parse\" : plural(ops.length, \"operation\");\n console.log(` ${mark(has.openapi)} openapi.yaml ${has.openapi ? apiNote : \"\"}`.trimEnd());\n console.log(` ${mark(has.runbook)} runbook.md`);\n console.log(` ${mark(has.health)} health.yaml`);\n console.log(` ${mark(adrs > 0)} adrs/ ${adrs > 0 ? plural(adrs, \"decision\") : \"\"}`.trimEnd());\n\n const requirementLine = (r: Requirement): string => {\n const govern = r.operations.length > 0 ? ` → ${r.operations.join(\", \")}` : \"\";\n const covers = r.covers.length > 0 ? ` covers ${r.covers.join(\", \")}` : \"\";\n return ` ${r.name} (${plural(r.scenarios.length, \"scenario\")})${govern}${covers}`;\n };\n if (reqs.length > 0) {\n console.log(\"\\n requirements\");\n for (const r of reqs) console.log(requirementLine(r));\n }\n if (archReqs.length > 0) {\n console.log(\"\\n arch requirements\");\n for (const r of archReqs) console.log(requirementLine(r));\n }\n\n if (api.unreadable) {\n console.log(\"\\n operations\");\n console.log(` ✗ openapi.yaml does not parse — nothing here lists what ${id} offers`);\n if (api.error !== undefined) console.log(` ${api.error}`);\n } else if (ops.length > 0) {\n console.log(\"\\n operations\");\n for (const op of ops) {\n const by = governs(op);\n if (by.length > 0) console.log(` ✓ ${op} governed by ${by.map((n) => `\"${n}\"`).join(\", \")}`);\n else console.log(` ⚠ ${op} not governed by any requirement`);\n }\n }\n\n if (inbound.length > 0 || outbound.length > 0) {\n console.log(\"\\n landscape\");\n for (const e of inbound) console.log(` ← ${e.service}${edgeNote(e)}`);\n for (const e of outbound) console.log(` → ${e.service}${edgeNote(e)}`);\n }\n\n if (model.errors.length > 0) {\n console.log(\"\\n model errors\");\n for (const e of model.errors) console.log(` ✗ ${errorText(e)}`);\n }\n}\n\n/** Inbound/outbound edges for a service, read off the living landscape. */\nexport async function landscapeEdges(\n docsDir: DocsDir,\n service: string,\n context: FleetContext,\n): Promise<{ inbound: Edge[]; outbound: Edge[] }> {\n const path = landscapePath(docsDir);\n if (!existsSync(path)) return { inbound: [], outbound: [] };\n const land = await loadFile(path);\n if (land.errors.length > 0) return { inbound: [], outbound: [] };\n // Edges are filed under the service an element is BOUND to, not under what the\n // box is titled — otherwise renaming a box empties this list without a word —\n // and an edge into a modelled container belongs to the service that owns it.\n const known = new Set((await listServices(docsDir, context)).map((s) => s.id));\n const svcOf = serviceResolver(land.elements, known);\n\n const inbound: Edge[] = [];\n const outbound: Edge[] = [];\n for (const r of land.relationships) {\n const edge = (service: string): Edge => ({\n service,\n op: r.op ?? null,\n title: r.title ?? null,\n });\n if (svcOf(r.target) === service) inbound.push(edge(svcOf(r.source)));\n else if (svcOf(r.source) === service) outbound.push(edge(svcOf(r.target)));\n }\n return { inbound, outbound };\n}\n\n/* ------------------------------------------------------------------ */\n/* Feature */\n/* ------------------------------------------------------------------ */\n"]}
|