@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5992 -82
- package/COMPARISON.md +168 -63
- package/CONTRIBUTING.md +121 -0
- package/MIGRATING-from-OpenSpec.md +238 -55
- package/QUICKSTART.md +302 -0
- package/README.md +653 -144
- package/ROADMAP.md +1035 -0
- package/SCHEMA.md +3916 -263
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +927 -0
- package/dist/cli.js +133 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +204 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +309 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +74 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +193 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +319 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +298 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +106 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +318 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +30 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +355 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +166 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +305 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +367 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +221 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +6 -8
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +86 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +65 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +227 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +39 -28
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +152 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +66 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +105 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +262 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +146 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +72 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +142 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +63 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +155 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +358 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +344 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +108 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +238 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +75 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +175 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +18 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +62 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +328 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +279 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +199 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +300 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +221 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +278 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +174 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +182 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +53 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/show/service.js +239 -0
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +87 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +47 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +209 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +115 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +269 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +325 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +113 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +98 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +318 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +196 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +249 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +176 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/unarchive/restore.js +254 -0
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +59 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +245 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +204 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +58 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +264 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +85 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +222 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +93 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +371 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +118 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +266 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +71 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +75 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +52 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +89 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +145 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +252 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +241 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +177 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +310 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +279 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +148 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +363 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +178 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +81 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +263 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +278 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +206 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +328 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +220 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +266 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +141 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +230 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +111 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +155 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +169 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +299 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +46 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +44 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +78 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +104 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +138 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +273 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md.js +203 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +254 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +144 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +151 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +193 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +280 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +373 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +323 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +220 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +188 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +311 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +67 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +210 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +19 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +338 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +43 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +146 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +92 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +38 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +290 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +195 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +83 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/asyncapi/read.js +263 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +285 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +385 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +273 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +304 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +58 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +190 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +243 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +110 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +113 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +161 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +89 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +219 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +174 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +173 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +369 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +308 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +167 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +30 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +73 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +337 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +298 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +166 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +47 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +338 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +174 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +123 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +205 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +104 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +267 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +185 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +75 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +332 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +295 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +191 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +335 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +189 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +63 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +95 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +341 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +230 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +237 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +204 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +312 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/docs.js +37 -85
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +238 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +139 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +355 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +224 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +286 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +238 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +234 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +89 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +209 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +180 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +194 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +103 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/explore/explore.js +204 -0
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +174 -146
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +208 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +246 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +176 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +210 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +109 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +73 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/{records.js → kernel/records.js} +11 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +66 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +118 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +265 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +212 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +73 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +324 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +207 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +142 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +174 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +136 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +239 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +54 -108
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +199 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +16 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +204 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +232 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +110 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +220 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +78 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +70 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +241 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +191 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +304 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +116 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +157 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +120 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +244 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +201 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +139 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +280 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +220 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +322 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +308 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +61 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +90 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +255 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +146 -14
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +239 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +252 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +268 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +95 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +204 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/snapshot/snapshot.js +196 -0
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +181 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +60 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +126 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +214 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +163 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +216 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +302 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +216 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +166 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +140 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +101 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +76 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +296 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/grade/capability-tag.js +93 -0
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/core/usecases/grade/requirement-tag.js +94 -0
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/core/usecases/grade/steps.js +266 -0
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/core/usecases/grade/usecases.js +112 -0
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +123 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +180 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +170 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +259 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +158 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/read/shape.js +169 -0
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +165 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +99 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +61 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +59 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +216 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/vocabulary/report.js +90 -0
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +232 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +336 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +18 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +8 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +92 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +134 -0
- package/examples/docs/services/order-service/asyncapi.yaml +109 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +126 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +76 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +68 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
- package/examples/docs/services/platform/notification-service/health.yaml +40 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js +0 -320
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js +0 -317
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js +0 -253
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js +0 -225
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js +0 -47
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A service an active feature INTRODUCES, as `loam show` presents it: which
|
|
3
|
+
* feature carries it, the delta documents under that feature's
|
|
4
|
+
* `specs/<service>/`, what they add, and where a reader goes next.
|
|
5
|
+
*
|
|
6
|
+
* Its own view rather than a branch of `./service.ts`, because every line that
|
|
7
|
+
* view prints is a statement about the LIVING documents — artifact ticks under
|
|
8
|
+
* `services/<id>/`, a vouch, the fleet map's edges — and for this service each
|
|
9
|
+
* one would be a false "absent": the directory does not exist yet, by design,
|
|
10
|
+
* until the feature archives. Until this view existed `loam show` refused the
|
|
11
|
+
* name outright ("No service or feature"), on the same tree where `loam tasks`
|
|
12
|
+
* listed work for it, so the newest service in the fleet was the one a reader
|
|
13
|
+
* could not look up.
|
|
14
|
+
*
|
|
15
|
+
* The per-feature counts are `loam show <FEAT>`'s per-service row, read through
|
|
16
|
+
* the same core projections (`featureSpecPaths`, `apiChanges`, `eventChanges`),
|
|
17
|
+
* so the two views of one delta cannot disagree about what it adds.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync } from "node:fs";
|
|
20
|
+
import { emitJson, repoPath } from "../../core/envelope/json.js";
|
|
21
|
+
import { FleetContext } from "../../core/fleet-context.js";
|
|
22
|
+
import {} from "../../core/repo/entries.js";
|
|
23
|
+
import { featureSpecPaths } from "../../core/repo/paths.js";
|
|
24
|
+
import { apiChanges } from "../../core/projection/api.js";
|
|
25
|
+
import { eventChanges } from "../../core/projection/events.js";
|
|
26
|
+
import {} from "../../core/document/spec.js";
|
|
27
|
+
import { plural } from "../policy/format.js";
|
|
28
|
+
import { kindCounts, mark, requirementJson, requirementLine, scenarioCount } from "./marks.js";
|
|
29
|
+
export async function showIntroduced(docsDir, introduced, json, context) {
|
|
30
|
+
const { id } = introduced;
|
|
31
|
+
const rows = await Promise.all(introduced.features.map((f) => readIntroduction(f, id, context)));
|
|
32
|
+
const by = introduced.features.map((f) => f.id).join(", ");
|
|
33
|
+
if (json) {
|
|
34
|
+
emitJson({
|
|
35
|
+
command: "show",
|
|
36
|
+
type: "service",
|
|
37
|
+
id,
|
|
38
|
+
// The marker a consumer branches on, beside the id. It is absent from a
|
|
39
|
+
// living service's payload rather than `true` there, because that
|
|
40
|
+
// payload is published and stays byte-identical.
|
|
41
|
+
living: false,
|
|
42
|
+
introducedBy: introduced.features.map((f) => f.id),
|
|
43
|
+
introductions: rows.map((row) => ({
|
|
44
|
+
feature: row.feature.id,
|
|
45
|
+
path: repoPath(docsDir, row.paths.dir),
|
|
46
|
+
has: row.has,
|
|
47
|
+
// `show <FEAT> --json`'s per-service row, key for key, so a consumer
|
|
48
|
+
// that reads one reads the other.
|
|
49
|
+
...kindCounts(row.reqs),
|
|
50
|
+
operations: [...new Set(row.reqs.flatMap((r) => r.operations))],
|
|
51
|
+
api: row.api,
|
|
52
|
+
events: row.events,
|
|
53
|
+
// And the living payload's requirement entries, so the delta is
|
|
54
|
+
// listed exactly as the service will list it once it merges.
|
|
55
|
+
requirements: row.reqs.map(requirementJson),
|
|
56
|
+
archSpec: {
|
|
57
|
+
requirements: row.archReqs.length,
|
|
58
|
+
scenarios: scenarioCount(row.archReqs),
|
|
59
|
+
entries: row.archReqs.map(requirementJson),
|
|
60
|
+
},
|
|
61
|
+
next: nextCommands(row.feature, id),
|
|
62
|
+
})),
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(`${id} introduced by ${by} (in flight) — not in the living docs until it archives\n`);
|
|
67
|
+
rows.forEach((row, i) => {
|
|
68
|
+
if (i > 0)
|
|
69
|
+
console.log("");
|
|
70
|
+
printIntroduction(docsDir, row, id);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async function readIntroduction(feature, id, context) {
|
|
74
|
+
const paths = featureSpecPaths(feature.dir, id);
|
|
75
|
+
const has = {
|
|
76
|
+
spec: existsSync(paths.spec),
|
|
77
|
+
archSpec: existsSync(paths.archSpec),
|
|
78
|
+
openapi: existsSync(paths.openapi),
|
|
79
|
+
asyncapi: existsSync(paths.asyncapi),
|
|
80
|
+
};
|
|
81
|
+
// The contract projections carry their own readability, so a delta document
|
|
82
|
+
// that does not parse is said below rather than shown as "no operations".
|
|
83
|
+
const [reqs, archReqs, api, events] = await Promise.all([
|
|
84
|
+
has.spec ? context.readRequirements(paths.spec) : [],
|
|
85
|
+
has.archSpec ? context.readRequirements(paths.archSpec) : [],
|
|
86
|
+
apiChanges(paths.openapi),
|
|
87
|
+
eventChanges(paths.asyncapi),
|
|
88
|
+
]);
|
|
89
|
+
return { feature, paths, has, reqs, archReqs, api, events };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Where a reader goes next: the feature that carries the service, its delta
|
|
93
|
+
* over it, and the open work on it. Both interpolants are enumeration
|
|
94
|
+
* spellings — the canonical feature id and the feature's own directory name for
|
|
95
|
+
* the service — so the printed commands parse.
|
|
96
|
+
*/
|
|
97
|
+
function nextCommands(feature, id) {
|
|
98
|
+
return [
|
|
99
|
+
`loam show ${feature.id}`,
|
|
100
|
+
`loam delta ${feature.id} --service ${id}`,
|
|
101
|
+
`loam tasks ${feature.id} --service ${id}`,
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
function printIntroduction(docsDir, row, id) {
|
|
105
|
+
console.log(` ${row.feature.id} ${repoPath(docsDir, row.paths.dir)}`);
|
|
106
|
+
const specNote = (rs) => {
|
|
107
|
+
const k = kindCounts(rs);
|
|
108
|
+
return `+${k.added} ~${k.modified} -${k.removed} requirements · ${plural(scenarioCount(rs), "scenario")}`;
|
|
109
|
+
};
|
|
110
|
+
console.log(` ${mark(row.has.spec)} spec.md ${row.has.spec ? specNote(row.reqs) : ""}`.trimEnd());
|
|
111
|
+
console.log(` ${mark(row.has.archSpec)} arch.spec.md ${row.has.archSpec ? specNote(row.archReqs) : ""}`.trimEnd());
|
|
112
|
+
const apiNote = row.api.unreadable ? "does not parse" : plural(row.api.changes.length, "operation");
|
|
113
|
+
console.log(` ${mark(row.has.openapi)} openapi.yaml ${row.has.openapi ? apiNote : ""}`.trimEnd());
|
|
114
|
+
const eventNote = row.events.unreadable ? "does not read as AsyncAPI 3.0" : plural(row.events.changes.length, "message");
|
|
115
|
+
console.log(` ${mark(row.has.asyncapi)} asyncapi.yaml ${row.has.asyncapi ? eventNote : ""}`.trimEnd());
|
|
116
|
+
// The kind leads each line: in a delta it is the fact a reviewer reads first,
|
|
117
|
+
// and a requirement listed here without it would read as one already living.
|
|
118
|
+
if (row.reqs.length > 0) {
|
|
119
|
+
console.log("\n requirements");
|
|
120
|
+
for (const r of row.reqs)
|
|
121
|
+
console.log(` [${r.kind}] ${requirementLine(r)}`);
|
|
122
|
+
}
|
|
123
|
+
if (row.archReqs.length > 0) {
|
|
124
|
+
console.log("\n arch requirements");
|
|
125
|
+
for (const r of row.archReqs)
|
|
126
|
+
console.log(` [${r.kind}] ${requirementLine(r)}`);
|
|
127
|
+
}
|
|
128
|
+
if (row.api.unreadable) {
|
|
129
|
+
console.log("\n operations");
|
|
130
|
+
console.log(` ✗ openapi.yaml does not parse — nothing here lists what ${row.feature.id} adds to ${id}`);
|
|
131
|
+
if (row.api.error !== undefined)
|
|
132
|
+
console.log(` ${row.api.error}`);
|
|
133
|
+
}
|
|
134
|
+
else if (row.api.changes.length > 0) {
|
|
135
|
+
console.log("\n operations");
|
|
136
|
+
for (const op of row.api.changes) {
|
|
137
|
+
console.log(` ${op.remove ? "REMOVE " : ""}${op.method} ${op.path} ${op.operationId}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (row.events.unreadable) {
|
|
141
|
+
console.log("\n events");
|
|
142
|
+
console.log(` ✗ asyncapi.yaml does not read as AsyncAPI 3.0 — nothing here lists what ${row.feature.id} adds to ${id}`);
|
|
143
|
+
if (row.events.error !== undefined)
|
|
144
|
+
console.log(` ${row.events.error}`);
|
|
145
|
+
}
|
|
146
|
+
else if (row.events.changes.length > 0) {
|
|
147
|
+
console.log("\n events");
|
|
148
|
+
for (const m of row.events.changes) {
|
|
149
|
+
const direction = m.direction === null ? "" : `${m.direction.toUpperCase()} `;
|
|
150
|
+
console.log(` ${m.remove ? "REMOVE " : ""}${direction}${m.message} (${m.slot})`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
console.log("\n next");
|
|
154
|
+
for (const command of nextCommands(row.feature, id))
|
|
155
|
+
console.log(` ${command}`);
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=introduced.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introduced.js","sourceRoot":"","sources":["../../../src/commands/show/introduced.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A service an active feature INTRODUCES, as `loam show` presents it: which\n * feature carries it, the delta documents under that feature's\n * `specs/<service>/`, what they add, and where a reader goes next.\n *\n * Its own view rather than a branch of `./service.ts`, because every line that\n * view prints is a statement about the LIVING documents — artifact ticks under\n * `services/<id>/`, a vouch, the fleet map's edges — and for this service each\n * one would be a false \"absent\": the directory does not exist yet, by design,\n * until the feature archives. Until this view existed `loam show` refused the\n * name outright (\"No service or feature\"), on the same tree where `loam tasks`\n * listed work for it, so the newest service in the fleet was the one a reader\n * could not look up.\n *\n * The per-feature counts are `loam show <FEAT>`'s per-service row, read through\n * the same core projections (`featureSpecPaths`, `apiChanges`, `eventChanges`),\n * so the two views of one delta cannot disagree about what it adds.\n */\nimport { existsSync } from \"node:fs\";\nimport { emitJson, repoPath } from \"../../core/envelope/json.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { type FeatureEntry } from \"../../core/repo/entries.js\";\nimport { featureSpecPaths, type FeatureSpecPaths } from \"../../core/repo/paths.js\";\nimport { apiChanges, type ApiSlice } from \"../../core/projection/api.js\";\nimport { eventChanges, type EventSlice } from \"../../core/projection/events.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport type { RawServiceId } from \"../../core/kernel/ids/service.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { plural } from \"../policy/format.js\";\nimport { kindCounts, mark, requirementJson, requirementLine, scenarioCount } from \"./marks.js\";\n\nexport interface Introduced {\n /** The service, as the introducing feature's own `specs/` readdir spelled it. */\n id: RawServiceId;\n /** `introducingFeatures`' answer — never empty when this view is reached. */\n features: FeatureEntry[];\n}\n\n/** One introducing feature's delta over the service, read once for both renderings. */\ninterface Introduction {\n feature: FeatureEntry;\n paths: FeatureSpecPaths;\n has: { spec: boolean; archSpec: boolean; openapi: boolean; asyncapi: boolean };\n reqs: Requirement[];\n archReqs: Requirement[];\n api: ApiSlice;\n events: EventSlice;\n}\n\nexport async function showIntroduced(\n docsDir: DocsDir,\n introduced: Introduced,\n json: boolean,\n context: FleetContext,\n): Promise<void> {\n const { id } = introduced;\n const rows = await Promise.all(introduced.features.map((f) => readIntroduction(f, id, context)));\n const by = introduced.features.map((f) => f.id).join(\", \");\n\n if (json) {\n emitJson({\n command: \"show\",\n type: \"service\",\n id,\n // The marker a consumer branches on, beside the id. It is absent from a\n // living service's payload rather than `true` there, because that\n // payload is published and stays byte-identical.\n living: false,\n introducedBy: introduced.features.map((f) => f.id),\n introductions: rows.map((row) => ({\n feature: row.feature.id,\n path: repoPath(docsDir, row.paths.dir),\n has: row.has,\n // `show <FEAT> --json`'s per-service row, key for key, so a consumer\n // that reads one reads the other.\n ...kindCounts(row.reqs),\n operations: [...new Set(row.reqs.flatMap((r) => r.operations))],\n api: row.api,\n events: row.events,\n // And the living payload's requirement entries, so the delta is\n // listed exactly as the service will list it once it merges.\n requirements: row.reqs.map(requirementJson),\n archSpec: {\n requirements: row.archReqs.length,\n scenarios: scenarioCount(row.archReqs),\n entries: row.archReqs.map(requirementJson),\n },\n next: nextCommands(row.feature, id),\n })),\n });\n return;\n }\n\n console.log(`${id} introduced by ${by} (in flight) — not in the living docs until it archives\\n`);\n rows.forEach((row, i) => {\n if (i > 0) console.log(\"\");\n printIntroduction(docsDir, row, id);\n });\n}\n\nasync function readIntroduction(feature: FeatureEntry, id: RawServiceId, context: FleetContext): Promise<Introduction> {\n const paths = featureSpecPaths(feature.dir, id);\n const has = {\n spec: existsSync(paths.spec),\n archSpec: existsSync(paths.archSpec),\n openapi: existsSync(paths.openapi),\n asyncapi: existsSync(paths.asyncapi),\n };\n // The contract projections carry their own readability, so a delta document\n // that does not parse is said below rather than shown as \"no operations\".\n const [reqs, archReqs, api, events] = await Promise.all([\n has.spec ? context.readRequirements(paths.spec) : [],\n has.archSpec ? context.readRequirements(paths.archSpec) : [],\n apiChanges(paths.openapi),\n eventChanges(paths.asyncapi),\n ]);\n return { feature, paths, has, reqs, archReqs, api, events };\n}\n\n/**\n * Where a reader goes next: the feature that carries the service, its delta\n * over it, and the open work on it. Both interpolants are enumeration\n * spellings — the canonical feature id and the feature's own directory name for\n * the service — so the printed commands parse.\n */\nfunction nextCommands(feature: FeatureEntry, id: RawServiceId): string[] {\n return [\n `loam show ${feature.id}`,\n `loam delta ${feature.id} --service ${id}`,\n `loam tasks ${feature.id} --service ${id}`,\n ];\n}\n\nfunction printIntroduction(docsDir: DocsDir, row: Introduction, id: RawServiceId): void {\n console.log(` ${row.feature.id} ${repoPath(docsDir, row.paths.dir)}`);\n const specNote = (rs: Requirement[]): string => {\n const k = kindCounts(rs);\n return `+${k.added} ~${k.modified} -${k.removed} requirements · ${plural(scenarioCount(rs), \"scenario\")}`;\n };\n console.log(` ${mark(row.has.spec)} spec.md ${row.has.spec ? specNote(row.reqs) : \"\"}`.trimEnd());\n console.log(` ${mark(row.has.archSpec)} arch.spec.md ${row.has.archSpec ? specNote(row.archReqs) : \"\"}`.trimEnd());\n const apiNote = row.api.unreadable ? \"does not parse\" : plural(row.api.changes.length, \"operation\");\n console.log(` ${mark(row.has.openapi)} openapi.yaml ${row.has.openapi ? apiNote : \"\"}`.trimEnd());\n const eventNote = row.events.unreadable ? \"does not read as AsyncAPI 3.0\" : plural(row.events.changes.length, \"message\");\n console.log(` ${mark(row.has.asyncapi)} asyncapi.yaml ${row.has.asyncapi ? eventNote : \"\"}`.trimEnd());\n\n // The kind leads each line: in a delta it is the fact a reviewer reads first,\n // and a requirement listed here without it would read as one already living.\n if (row.reqs.length > 0) {\n console.log(\"\\n requirements\");\n for (const r of row.reqs) console.log(` [${r.kind}] ${requirementLine(r)}`);\n }\n if (row.archReqs.length > 0) {\n console.log(\"\\n arch requirements\");\n for (const r of row.archReqs) console.log(` [${r.kind}] ${requirementLine(r)}`);\n }\n\n if (row.api.unreadable) {\n console.log(\"\\n operations\");\n console.log(` ✗ openapi.yaml does not parse — nothing here lists what ${row.feature.id} adds to ${id}`);\n if (row.api.error !== undefined) console.log(` ${row.api.error}`);\n } else if (row.api.changes.length > 0) {\n console.log(\"\\n operations\");\n for (const op of row.api.changes) {\n console.log(` ${op.remove ? \"REMOVE \" : \"\"}${op.method} ${op.path} ${op.operationId}`);\n }\n }\n\n if (row.events.unreadable) {\n console.log(\"\\n events\");\n console.log(` ✗ asyncapi.yaml does not read as AsyncAPI 3.0 — nothing here lists what ${row.feature.id} adds to ${id}`);\n if (row.events.error !== undefined) console.log(` ${row.events.error}`);\n } else if (row.events.changes.length > 0) {\n console.log(\"\\n events\");\n for (const m of row.events.changes) {\n const direction = m.direction === null ? \"\" : `${m.direction.toUpperCase()} `;\n console.log(` ${m.remove ? \"REMOVE \" : \"\"}${direction}${m.message} (${m.slot})`);\n }\n }\n\n console.log(\"\\n next\");\n for (const command of nextCommands(row.feature, id)) console.log(` ${command}`);\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes every view of `loam show` is written in: a tick for a file that
|
|
3
|
+
* exists, a scenario count, an edge note, and one requirement as a line and as
|
|
4
|
+
* a `--json` entry. (The parse-error line is `errorText` in `core/c4/likec4.ts`,
|
|
5
|
+
* shared with validate.)
|
|
6
|
+
*
|
|
7
|
+
* A leaf of its own because the service view, the feature view and the view of
|
|
8
|
+
* a service a feature introduces all use them, and none should have to import
|
|
9
|
+
* another to reach a tick. The requirement shapes moved here from the service
|
|
10
|
+
* view when the introduced view arrived: a delta requirement is listed exactly
|
|
11
|
+
* as a living one is, and two spellings of one entry are two entries a
|
|
12
|
+
* consumer has to learn.
|
|
13
|
+
*/
|
|
14
|
+
import {} from "../../core/document/spec.js";
|
|
15
|
+
import { plural } from "../policy/format.js";
|
|
16
|
+
import {} from "./service.js";
|
|
17
|
+
export function mark(present) {
|
|
18
|
+
return present ? "✓" : "-";
|
|
19
|
+
}
|
|
20
|
+
export function scenarioCount(reqs) {
|
|
21
|
+
return reqs.reduce((n, r) => n + r.scenarios.length, 0);
|
|
22
|
+
}
|
|
23
|
+
export function edgeNote(e) {
|
|
24
|
+
if (e.op)
|
|
25
|
+
return ` ${e.op}`;
|
|
26
|
+
return e.title ? ` "${e.title}"` : "";
|
|
27
|
+
}
|
|
28
|
+
/** A requirement's `--json` entry — `requirements[]` and `archSpec.entries[]` alike. */
|
|
29
|
+
export function requirementJson(r) {
|
|
30
|
+
return {
|
|
31
|
+
id: r.id,
|
|
32
|
+
name: r.name,
|
|
33
|
+
kind: r.kind,
|
|
34
|
+
scenarios: r.scenarios.length,
|
|
35
|
+
operations: r.operations,
|
|
36
|
+
covers: r.covers,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** A requirement as one line, unindented: its name, its scenarios, what it governs and covers. */
|
|
40
|
+
export function requirementLine(r) {
|
|
41
|
+
const govern = r.operations.length > 0 ? ` → ${r.operations.join(", ")}` : "";
|
|
42
|
+
const covers = r.covers.length > 0 ? ` covers ${r.covers.join(", ")}` : "";
|
|
43
|
+
return `${r.name} (${plural(r.scenarios.length, "scenario")})${govern}${covers}`;
|
|
44
|
+
}
|
|
45
|
+
/** A requirement delta's ADDED / MODIFIED / REMOVED counts — one spelling for `show <FEAT>` and the introduced-service view. */
|
|
46
|
+
export function kindCounts(reqs) {
|
|
47
|
+
return {
|
|
48
|
+
added: reqs.filter((r) => r.kind === "ADDED").length,
|
|
49
|
+
modified: reqs.filter((r) => r.kind === "MODIFIED").length,
|
|
50
|
+
removed: reqs.filter((r) => r.kind === "REMOVED").length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=marks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marks.js","sourceRoot":"","sources":["../../../src/commands/show/marks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAoB,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,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,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,CAAc;IAC5C,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM;QAC7B,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM;KACjB,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,eAAe,CAAC,CAAc;IAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,OAAO,GAAG,CAAC,CAAC,IAAI,MAAM,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;AACpF,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,MAAM;QACpD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,MAAM;QAC1D,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM;KACzD,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The shapes every view of `loam show` is written in: a tick for a file that\n * exists, a scenario count, an edge note, and one requirement as a line and as\n * a `--json` entry. (The parse-error line is `errorText` in `core/c4/likec4.ts`,\n * shared with validate.)\n *\n * A leaf of its own because the service view, the feature view and the view of\n * a service a feature introduces all use them, and none should have to import\n * another to reach a tick. The requirement shapes moved here from the service\n * view when the introduced view arrived: a delta requirement is listed exactly\n * as a living one is, and two spellings of one entry are two entries a\n * consumer has to learn.\n */\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { plural } from \"../policy/format.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\n/** A requirement's `--json` entry — `requirements[]` and `archSpec.entries[]` alike. */\nexport function requirementJson(r: Requirement): Record<string, unknown> {\n return {\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\n/** A requirement as one line, unindented: its name, its scenarios, what it governs and covers. */\nexport function 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\n/** A requirement delta's ADDED / MODIFIED / REMOVED counts — one spelling for `show <FEAT>` and the introduced-service view. */\nexport function kindCounts(reqs: Requirement[]): { added: number; modified: number; removed: number } {\n return {\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 };\n}\n"]}
|
|
@@ -0,0 +1,239 @@
|
|
|
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
|
+
*/
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
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 { landscapeEvidence } from "../../core/vocabulary/maturity.js";
|
|
18
|
+
import { readOpenapi } from "../../core/openapi/doc.js";
|
|
19
|
+
import { landscapePath } from "../../core/repo/paths.js";
|
|
20
|
+
import { locateServicePaths } from "../../core/repo/service-target.js";
|
|
21
|
+
import { listServices } from "../../core/repo/repo.js";
|
|
22
|
+
import { countMarkdown } from "../../core/repo/tree/fs.js";
|
|
23
|
+
import { parseRequirements } from "../../core/document/parse.js";
|
|
24
|
+
import {} from "../../core/document/spec.js";
|
|
25
|
+
import { plural } from "../policy/format.js";
|
|
26
|
+
import { edgeNote, mark, requirementJson, requirementLine, scenarioCount } from "./marks.js";
|
|
27
|
+
import { errorText } from "../../core/c4/likec4.js";
|
|
28
|
+
export async function showService(docsDir, id, json, context) {
|
|
29
|
+
const paths = await locateServicePaths(docsDir, id, context);
|
|
30
|
+
const has = {
|
|
31
|
+
model: existsSync(paths.model),
|
|
32
|
+
spec: existsSync(paths.spec),
|
|
33
|
+
// The architecture-obligations axis. It was invisible here and in `list`,
|
|
34
|
+
// which made the whole axis unnavigable: a service could carry twenty arch
|
|
35
|
+
// requirements — the outbox, the retries, the alerts — and every command a
|
|
36
|
+
// reader uses to find out what a service documents showed none of them.
|
|
37
|
+
archSpec: existsSync(paths.archSpec),
|
|
38
|
+
openapi: existsSync(paths.openapi),
|
|
39
|
+
runbook: existsSync(paths.runbook),
|
|
40
|
+
health: existsSync(paths.health),
|
|
41
|
+
};
|
|
42
|
+
// Through the ONE reader of `model.likec4`, so the counts here are the counts
|
|
43
|
+
// `validate` prints: a model that EXTENDS the fleet map is a slice of the
|
|
44
|
+
// project it extends, and opening the file alone would show a screenful of
|
|
45
|
+
// parse errors for a document that is perfectly valid where it is read.
|
|
46
|
+
const read = has.model ? await context.serviceModel(docsDir, paths) : null;
|
|
47
|
+
const model = read === null
|
|
48
|
+
? { errors: [], elements: [], relationships: [] }
|
|
49
|
+
: read.mapUnreadable
|
|
50
|
+
? // The map did not parse, so an extending model could not be read at
|
|
51
|
+
// all. `show` must say that rather than print zeroes: "0 elements" is
|
|
52
|
+
// what a service with no architecture looks like, and this one may
|
|
53
|
+
// have plenty.
|
|
54
|
+
{
|
|
55
|
+
errors: [
|
|
56
|
+
{
|
|
57
|
+
message: "architecture/landscape.likec4 does not parse, and this model extends it — " +
|
|
58
|
+
"nothing here could be read. `loam validate --all` reports the map's own errors.",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
elements: [],
|
|
62
|
+
relationships: [],
|
|
63
|
+
}
|
|
64
|
+
: read.doc;
|
|
65
|
+
const reqs = has.spec ? parseRequirements(await readFile(paths.spec, "utf8")) : [];
|
|
66
|
+
const archReqs = has.archSpec ? parseRequirements(await readFile(paths.archSpec, "utf8")) : [];
|
|
67
|
+
const adrs = await countMarkdown(paths.adrsDir);
|
|
68
|
+
// `readOpenapi`, not `operationIds`: a contract that exists but does not parse
|
|
69
|
+
// came back from operationIds as an EMPTY operation list, indistinguishable
|
|
70
|
+
// from a service with no endpoints. `show` is what a reader opens to find out
|
|
71
|
+
// what a service offers, and answering "nothing" over a YAML error is the
|
|
72
|
+
// worst possible lie for that question. `x-loam-remove` entries are filtered
|
|
73
|
+
// out for the same reason validate filters them: they are deletion markers
|
|
74
|
+
// from a delta, not operations anybody can call.
|
|
75
|
+
const api = await readOpenapi(paths.openapi);
|
|
76
|
+
const ops = api.ops.filter((o) => !o.remove).map((o) => o.id);
|
|
77
|
+
// Both axes: the sample is per file, so an arch.spec.md read from a sample
|
|
78
|
+
// beside a fully-read spec.md still means part of this service's
|
|
79
|
+
// documentation was not read, and a badge derived from spec.md alone would
|
|
80
|
+
// not say so.
|
|
81
|
+
const [fm, archFm] = await Promise.all([readFrontmatter(paths.spec), readFrontmatter(paths.archSpec)]);
|
|
82
|
+
const scope = scopeText(fm);
|
|
83
|
+
const archScope = scopeText(archFm);
|
|
84
|
+
const provenance = {
|
|
85
|
+
status: stringField(fm, "status") ?? null,
|
|
86
|
+
owner: stringField(fm, "owner") ?? null,
|
|
87
|
+
last_verified: stringField(fm, "last_verified") ?? null,
|
|
88
|
+
sources: listField(fm, "sources"),
|
|
89
|
+
// Additive, under its frontmatter spelling like its siblings: `show` is
|
|
90
|
+
// where a person goes to find out what a service's documents claim, and a
|
|
91
|
+
// `status: verified` that a person reached by reading four sections of the
|
|
92
|
+
// spec is a materially different claim. Verbatim rather than decoded — an
|
|
93
|
+
// unreadable value is still a stamped partial read, and showing it as it
|
|
94
|
+
// stands is what lets a reader see the mangling.
|
|
95
|
+
vouch_scope: scope,
|
|
96
|
+
};
|
|
97
|
+
const governs = (op) => reqs.filter((r) => r.operations.includes(op)).map((r) => r.name);
|
|
98
|
+
const { inbound, outbound } = await landscapeEdges(docsDir, id, context);
|
|
99
|
+
if (json) {
|
|
100
|
+
emitJson({
|
|
101
|
+
command: "show",
|
|
102
|
+
type: "service",
|
|
103
|
+
id,
|
|
104
|
+
path: repoPath(docsDir, paths.dir),
|
|
105
|
+
has,
|
|
106
|
+
adrs,
|
|
107
|
+
frontmatter: provenance,
|
|
108
|
+
model: {
|
|
109
|
+
elements: model.elements.length,
|
|
110
|
+
relationships: model.relationships.length,
|
|
111
|
+
errors: model.errors.map(errorText),
|
|
112
|
+
},
|
|
113
|
+
requirements: reqs.map(requirementJson),
|
|
114
|
+
archSpec: {
|
|
115
|
+
requirements: archReqs.length,
|
|
116
|
+
scenarios: scenarioCount(archReqs),
|
|
117
|
+
entries: archReqs.map(requirementJson),
|
|
118
|
+
// The second axis carries its own scope: one `--sample` run can stamp
|
|
119
|
+
// one of the pair sampled and read the other in full, and the
|
|
120
|
+
// `frontmatter` block above is spec.md's alone.
|
|
121
|
+
vouch_scope: archScope,
|
|
122
|
+
},
|
|
123
|
+
openapi: {
|
|
124
|
+
unreadable: api.unreadable,
|
|
125
|
+
...(api.error === undefined ? {} : { error: api.error }),
|
|
126
|
+
},
|
|
127
|
+
operations: ops.map((op) => ({ id: op, governedBy: governs(op) })),
|
|
128
|
+
landscape: { inbound, outbound },
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// The badge qualifies the status rather than replacing it: the document
|
|
133
|
+
// still says `verified` and this screen still says so, with what that vouch
|
|
134
|
+
// actually covered attached. A bare `verified` over a sampled stamp is the
|
|
135
|
+
// one reading this whole feature exists to prevent — and either axis earns
|
|
136
|
+
// the qualifier, since either one is part of this service nobody read.
|
|
137
|
+
const shown = provenance.status === null || (scope === null && archScope === null)
|
|
138
|
+
? provenance.status
|
|
139
|
+
: `${provenance.status} (sampled)`;
|
|
140
|
+
const badge = [shown, provenance.owner].filter((s) => s !== null).join(" · ");
|
|
141
|
+
console.log(`${id} ${repoPath(docsDir, paths.dir)}${badge ? ` ${badge}` : ""}\n`);
|
|
142
|
+
if (provenance.sources.length > 0 || provenance.last_verified !== null || archScope !== null) {
|
|
143
|
+
console.log(" provenance");
|
|
144
|
+
if (provenance.last_verified !== null)
|
|
145
|
+
console.log(` verified ${provenance.last_verified}`);
|
|
146
|
+
// Per axis and named, because they can disagree: one file read in full,
|
|
147
|
+
// the other from a sample, is an ordinary outcome of one `--sample` run.
|
|
148
|
+
if (scope !== null)
|
|
149
|
+
console.log(` scope spec.md ${scope} — the rest of it was not read at that vouch`);
|
|
150
|
+
if (archScope !== null) {
|
|
151
|
+
console.log(` scope arch.spec.md ${archScope} — the rest of it was not read at that vouch`);
|
|
152
|
+
}
|
|
153
|
+
for (const s of provenance.sources)
|
|
154
|
+
console.log(` sources ${s}`);
|
|
155
|
+
console.log("");
|
|
156
|
+
}
|
|
157
|
+
console.log(" artifacts");
|
|
158
|
+
const modelNote = model.errors.length > 0
|
|
159
|
+
? `${model.errors.length} error(s)`
|
|
160
|
+
: `${plural(model.elements.length, "element")} · ${plural(model.relationships.length, "relationship")}`;
|
|
161
|
+
console.log(` ${mark(has.model)} model.likec4 ${has.model ? modelNote : ""}`.trimEnd());
|
|
162
|
+
const specNote = (rs) => `${plural(rs.length, "requirement")} · ${plural(scenarioCount(rs), "scenario")}`;
|
|
163
|
+
console.log(` ${mark(has.spec)} spec.md ${has.spec ? specNote(reqs) : ""}`.trimEnd());
|
|
164
|
+
console.log(` ${mark(has.archSpec)} arch.spec.md ${has.archSpec ? specNote(archReqs) : ""}`.trimEnd());
|
|
165
|
+
const apiNote = api.unreadable ? "does not parse" : plural(ops.length, "operation");
|
|
166
|
+
console.log(` ${mark(has.openapi)} openapi.yaml ${has.openapi ? apiNote : ""}`.trimEnd());
|
|
167
|
+
console.log(` ${mark(has.runbook)} runbook.md`);
|
|
168
|
+
console.log(` ${mark(has.health)} health.yaml`);
|
|
169
|
+
console.log(` ${mark(adrs > 0)} adrs/ ${adrs > 0 ? plural(adrs, "decision") : ""}`.trimEnd());
|
|
170
|
+
if (reqs.length > 0) {
|
|
171
|
+
console.log("\n requirements");
|
|
172
|
+
for (const r of reqs)
|
|
173
|
+
console.log(` ${requirementLine(r)}`);
|
|
174
|
+
}
|
|
175
|
+
if (archReqs.length > 0) {
|
|
176
|
+
console.log("\n arch requirements");
|
|
177
|
+
for (const r of archReqs)
|
|
178
|
+
console.log(` ${requirementLine(r)}`);
|
|
179
|
+
}
|
|
180
|
+
if (api.unreadable) {
|
|
181
|
+
console.log("\n operations");
|
|
182
|
+
console.log(` ✗ openapi.yaml does not parse — nothing here lists what ${id} offers`);
|
|
183
|
+
if (api.error !== undefined)
|
|
184
|
+
console.log(` ${api.error}`);
|
|
185
|
+
}
|
|
186
|
+
else if (ops.length > 0) {
|
|
187
|
+
console.log("\n operations");
|
|
188
|
+
for (const op of ops) {
|
|
189
|
+
const by = governs(op);
|
|
190
|
+
if (by.length > 0)
|
|
191
|
+
console.log(` ✓ ${op} governed by ${by.map((n) => `"${n}"`).join(", ")}`);
|
|
192
|
+
else
|
|
193
|
+
console.log(` ⚠ ${op} not governed by any requirement`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (inbound.length > 0 || outbound.length > 0) {
|
|
197
|
+
console.log("\n landscape");
|
|
198
|
+
for (const e of inbound)
|
|
199
|
+
console.log(` ← ${e.service}${edgeNote(e)}`);
|
|
200
|
+
for (const e of outbound)
|
|
201
|
+
console.log(` → ${e.service}${edgeNote(e)}`);
|
|
202
|
+
}
|
|
203
|
+
if (model.errors.length > 0) {
|
|
204
|
+
console.log("\n model errors");
|
|
205
|
+
for (const e of model.errors)
|
|
206
|
+
console.log(` ✗ ${errorText(e)}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** Inbound/outbound edges for a service, read off the living landscape. */
|
|
210
|
+
export async function landscapeEdges(docsDir, service, context) {
|
|
211
|
+
const path = landscapePath(docsDir);
|
|
212
|
+
if (!existsSync(path))
|
|
213
|
+
return { inbound: [], outbound: [] };
|
|
214
|
+
const land = await loadFile(path);
|
|
215
|
+
if (land.errors.length > 0)
|
|
216
|
+
return { inbound: [], outbound: [] };
|
|
217
|
+
// Edges are filed under the service an element is BOUND to, not under what the
|
|
218
|
+
// box is titled — otherwise renaming a box empties this list without a word —
|
|
219
|
+
// and an edge into a modelled container belongs to the service that owns it.
|
|
220
|
+
const known = new Set((await listServices(docsDir, context)).map((s) => s.id));
|
|
221
|
+
// The ONE shared partition (core/vocabulary/maturity.ts `landscapeEvidence`),
|
|
222
|
+
// not a fourth line-for-line copy of it. This loop was that copy, and it kept
|
|
223
|
+
// the rule the others have dropped: an edge whose two endpoints resolve to the
|
|
224
|
+
// same service is its own internal wiring, so `show` printed `← <id>` for a
|
|
225
|
+
// service nobody calls while `context` — which reads the shared derivation —
|
|
226
|
+
// printed nothing. `Edge` is that module's `LandscapeEdge` field for field.
|
|
227
|
+
const { inbound, outbound } = landscapeEvidence({
|
|
228
|
+
id: service,
|
|
229
|
+
parses: true,
|
|
230
|
+
relationships: land.relationships,
|
|
231
|
+
elementIds: land.elements.map((e) => e.id),
|
|
232
|
+
svcOf: serviceResolver(land.elements, known),
|
|
233
|
+
});
|
|
234
|
+
return { inbound, outbound };
|
|
235
|
+
}
|
|
236
|
+
/* ------------------------------------------------------------------ */
|
|
237
|
+
/* Feature */
|
|
238
|
+
/* ------------------------------------------------------------------ */
|
|
239
|
+
//# 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, type LoadedDoc } from \"../../core/c4/likec4.js\";\nimport { serviceResolver } from \"../../core/c4/resolve/service.js\";\nimport { landscapeEvidence } from \"../../core/vocabulary/maturity.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, mark, requirementJson, requirementLine, scenarioCount } from \"./marks.js\";\nimport { errorText } from \"../../core/c4/likec4.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 // Through the ONE reader of `model.likec4`, so the counts here are the counts\n // `validate` prints: a model that EXTENDS the fleet map is a slice of the\n // project it extends, and opening the file alone would show a screenful of\n // parse errors for a document that is perfectly valid where it is read.\n const read = has.model ? await context.serviceModel(docsDir, paths) : null;\n const model: LoadedDoc =\n read === null\n ? { errors: [], elements: [], relationships: [] }\n : read.mapUnreadable\n ? // The map did not parse, so an extending model could not be read at\n // all. `show` must say that rather than print zeroes: \"0 elements\" is\n // what a service with no architecture looks like, and this one may\n // have plenty.\n {\n errors: [\n {\n message:\n \"architecture/landscape.likec4 does not parse, and this model extends it — \" +\n \"nothing here could be read. `loam validate --all` reports the map's own errors.\",\n },\n ],\n elements: [],\n relationships: [],\n }\n : read.doc;\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 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 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 // The ONE shared partition (core/vocabulary/maturity.ts `landscapeEvidence`),\n // not a fourth line-for-line copy of it. This loop was that copy, and it kept\n // the rule the others have dropped: an edge whose two endpoints resolve to the\n // same service is its own internal wiring, so `show` printed `← <id>` for a\n // service nobody calls while `context` — which reads the shared derivation —\n // printed nothing. `Edge` is that module's `LandscapeEdge` field for field.\n const { inbound, outbound } = landscapeEvidence({\n id: service,\n parses: true,\n relationships: land.relationships,\n elementIds: land.elements.map((e) => e.id),\n svcOf: serviceResolver(land.elements, known),\n });\n return { inbound, outbound };\n}\n\n/* ------------------------------------------------------------------ */\n/* Feature */\n/* ------------------------------------------------------------------ */\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { FleetContext } from "../../core/fleet-context.js";
|
|
2
|
+
import { configOrRefuse, fail } from "../../core/envelope/json.js";
|
|
3
|
+
import { DocsRepoUnavailableError } from "../../core/repo/state.js";
|
|
4
|
+
import { listServices, resolveFeature } from "../../core/repo/repo.js";
|
|
5
|
+
import { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from "../policy/gate.js";
|
|
6
|
+
import { introducingFeatures } from "../../core/projection/introduced.js";
|
|
7
|
+
import { showFeature } from "./feature.js";
|
|
8
|
+
import { showIntroduced } from "./introduced.js";
|
|
9
|
+
import { showService } from "./service.js";
|
|
10
|
+
export function registerShow(program) {
|
|
11
|
+
program
|
|
12
|
+
.command("show")
|
|
13
|
+
.argument("<target>", "service id or feature id")
|
|
14
|
+
.description("Show everything loam knows about a service or a feature")
|
|
15
|
+
.option("--json", "emit the machine contract instead of the human view")
|
|
16
|
+
.option("--type <kind>", "force the reading: service | feature")
|
|
17
|
+
.action(async (target, opts) => {
|
|
18
|
+
const json = opts.json === true;
|
|
19
|
+
if (opts.type !== undefined && opts.type !== "service" && opts.type !== "feature") {
|
|
20
|
+
fail(json, "invalid-option", `Unknown --type '${opts.type}'. Expected: service | feature.`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const forced = opts.type;
|
|
24
|
+
const config = await configOrRefuse(json);
|
|
25
|
+
if (config === null)
|
|
26
|
+
return;
|
|
27
|
+
const { docsDir } = config;
|
|
28
|
+
// "No service or feature 'x' in <dir>" is a lie when <dir> is not a docs
|
|
29
|
+
// repo at all — the same refusal validate and list owe (docsRepoReady).
|
|
30
|
+
// `docs`, not `services`: a feature is readable from a repo whose
|
|
31
|
+
// services/ is missing, and if the target turns out to be a service the
|
|
32
|
+
// enumeration below refuses with `services-missing` anyway.
|
|
33
|
+
if (!docsRepoReady(json, docsDir, "docs"))
|
|
34
|
+
return;
|
|
35
|
+
// One read index for the invocation. Deciding the target is a service
|
|
36
|
+
// enumerates the fleet, and so does resolving the landscape's edges to the
|
|
37
|
+
// services that own them — `loam show <service>` walked services/ twice for
|
|
38
|
+
// one answer. The context memoises only within this invocation, so a later
|
|
39
|
+
// run still sees whatever is on disk then.
|
|
40
|
+
const context = new FleetContext();
|
|
41
|
+
try {
|
|
42
|
+
// A feature id is distinctive (FEAT-101); a service name is arbitrary. When
|
|
43
|
+
// both could match, the feature wins and --type forces the other reading.
|
|
44
|
+
const feature = forced === "service" ? null : await resolveFeature(docsDir, target, "include", context);
|
|
45
|
+
if (feature) {
|
|
46
|
+
await showFeature(docsDir, feature, json, context);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// The enumeration's own id travels on — `entry.id` rather than the raw
|
|
50
|
+
// argument (repo/service-target.ts's rule): equal as strings, and only
|
|
51
|
+
// one of them carries the fact that a readdir produced it.
|
|
52
|
+
const entry = forced === "feature" ? undefined : (await listServices(docsDir, context)).find((s) => s.id === target);
|
|
53
|
+
if (entry !== undefined) {
|
|
54
|
+
await showService(docsDir, entry.id, json, context);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Third, and still a service reading: a service an active feature
|
|
58
|
+
// INTRODUCES has no `services/` directory until that feature archives,
|
|
59
|
+
// so the enumeration above cannot answer for it — and "no such service"
|
|
60
|
+
// was the answer `show` gave for the newest service in the fleet while
|
|
61
|
+
// `loam tasks` listed work for it. The id that travels on is the
|
|
62
|
+
// feature's own readdir spelling, for the reason given above.
|
|
63
|
+
const introducing = forced === "feature" ? [] : await introducingFeatures(docsDir, target, context);
|
|
64
|
+
const introduced = introducing[0]?.services.find((s) => s === target);
|
|
65
|
+
if (introduced !== undefined) {
|
|
66
|
+
await showIntroduced(docsDir, { id: introduced, features: introducing }, json, context);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const looked = forced ? forced : "service or feature";
|
|
70
|
+
fail(json, "unknown-target", `No ${looked} '${target}' in ${docsDir}.`);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (err instanceof DocsRepoUnavailableError) {
|
|
74
|
+
reportDocsRepoError(json, err);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// An artifact that exists but cannot be read used to escape as a stack
|
|
78
|
+
// trace (`internal` in --json), naming nothing. `show` reads one target,
|
|
79
|
+
// so it has nothing to fall back on — but it can at least say WHICH file.
|
|
80
|
+
reportRepositoryUnavailable(json, err, `'${target}' cannot be shown`, docsDir);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/* ------------------------------------------------------------------ */
|
|
85
|
+
/* Service */
|
|
86
|
+
/* ------------------------------------------------------------------ */
|
|
87
|
+
//# sourceMappingURL=show.js.map
|