@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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch loader: many self-contained `.likec4` documents through ONE
|
|
3
|
+
* LikeC4/Langium workspace.
|
|
4
|
+
*
|
|
5
|
+
* `loadFile` pays a fresh workspace per call — ~100ms even warm — which is what
|
|
6
|
+
* made `validate --all` O(documents) workspace spins (13.7s median over the
|
|
7
|
+
* 120-service benchmark fixture, docs/BENCHMARKS.md). This module copies every
|
|
8
|
+
* document into a mkdtemp workspace as one single-file PROJECT each (a
|
|
9
|
+
* `likec4.config.json` per folder), calls `LikeC4.fromWorkspace` once, splits
|
|
10
|
+
* `getErrors()` per document, and reads each clean project through the same
|
|
11
|
+
* `cleanDoc` the per-file path uses. Parity — byte-identical error
|
|
12
|
+
* messages/lines and identical elements/relationships — is pinned by
|
|
13
|
+
* test/likec4-batch-parity.test.ts, which is also the tripwire for the exact
|
|
14
|
+
* likec4 version pin: multi-project workspaces are public API, but this use of
|
|
15
|
+
* them is not documented, so an upgrade must fail that suite before it lands.
|
|
16
|
+
*
|
|
17
|
+
* Isolation is load-bearing, not cosmetic: `fromSource` gives each document a
|
|
18
|
+
* workspace of its own, so an author-written `import ... from 'name'` can never
|
|
19
|
+
* resolve. In a shared workspace it COULD — a sibling project is one lucky name
|
|
20
|
+
* away — so every folder carries one crypto-random per-invocation hex token in
|
|
21
|
+
* its project name. A document cannot import what it cannot name, and the
|
|
22
|
+
* parity suite pins that a guessed sibling name errors identically in both
|
|
23
|
+
* modes.
|
|
24
|
+
*
|
|
25
|
+
* Callers own the failure story: a document that cannot be staged (unreadable,
|
|
26
|
+
* missing) is silently DROPPED from the result so the caller's ordinary
|
|
27
|
+
* per-path load reproduces today's error, and a batch-infrastructure failure
|
|
28
|
+
* (tmpdir denied — the sandboxed-runner class ROADMAP documents) rejects the
|
|
29
|
+
* whole call for the caller to catch and degrade. FleetContext.prefetchLikeC4
|
|
30
|
+
* does exactly that: findings can never change because a workspace could not be
|
|
31
|
+
* created, only the speed can.
|
|
32
|
+
*
|
|
33
|
+
* This file took core/c4/ to exactly five files, and the seam that note
|
|
34
|
+
* predicted is now open: `./project/load.ts` loads a DIRECTORY as one project,
|
|
35
|
+
* which is the opposite isolation contract and belongs beside this one rather
|
|
36
|
+
* than inside it.
|
|
37
|
+
*/
|
|
38
|
+
import { randomBytes } from "node:crypto";
|
|
39
|
+
import { inOrder } from "../kernel/concurrency.js";
|
|
40
|
+
import { copyFile, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
41
|
+
import { tmpdir } from "node:os";
|
|
42
|
+
import { basename, join, resolve } from "node:path";
|
|
43
|
+
import { LikeC4 } from "likec4";
|
|
44
|
+
import { cleanDoc, distinctErrors } from "./likec4.js";
|
|
45
|
+
/**
|
|
46
|
+
* Stage every readable document as its own single-file project. A copy failure
|
|
47
|
+
* removes the half-made folder and drops the path — an empty project must not
|
|
48
|
+
* reach the workspace scan, and the caller's per-path load owns the error. The
|
|
49
|
+
* copy is `copyFile` (raw bytes), not read/decode/write: BOM, CRLF and even
|
|
50
|
+
* non-UTF-8 bytes reach LikeC4's own reader exactly as they would from the
|
|
51
|
+
* original file on disk.
|
|
52
|
+
*/
|
|
53
|
+
async function stage(root, targets) {
|
|
54
|
+
const token = randomBytes(8).toString("hex");
|
|
55
|
+
// Concurrent, capped, in input order (kernel/concurrency's contract): the
|
|
56
|
+
// per-document folders share nothing, and on a network-mounted docs repo
|
|
57
|
+
// the sequential form paid three round-trips per document. Nulls mark the
|
|
58
|
+
// drops so indices — and with them the p<i> project names — stay aligned.
|
|
59
|
+
const results = await inOrder([...targets.entries()], async ([i, path]) => {
|
|
60
|
+
const project = `p${i}_${token}`;
|
|
61
|
+
const folder = join(root, project);
|
|
62
|
+
try {
|
|
63
|
+
await mkdir(folder);
|
|
64
|
+
await writeFile(join(folder, "likec4.config.json"), JSON.stringify({ name: project }), "utf8");
|
|
65
|
+
await copyFile(path, join(folder, basename(path)));
|
|
66
|
+
return { path, project };
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
await rm(folder, { recursive: true, force: true });
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return results.filter((r) => r !== null);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* `getErrors()` split per document, each error's `sourceFsPath` rewritten from
|
|
77
|
+
* the workspace copy to the document's real absolute path.
|
|
78
|
+
*
|
|
79
|
+
* Grouping keys on the unique `p<i>_<token>` path SEGMENT, never on a
|
|
80
|
+
* tmp-root prefix compare: darwin hands back realpathed workspace paths
|
|
81
|
+
* (`/var/...` becomes `/private/var/...`) in some environments and the literal
|
|
82
|
+
* mkdtemp path in others, and a prefix compare silently attributes every error
|
|
83
|
+
* to nobody in exactly one of those two worlds. The segment survives both.
|
|
84
|
+
*
|
|
85
|
+
* Read through `distinctErrors` exactly as `loadSource` reads them, so a
|
|
86
|
+
* document's list is the same one in both modes.
|
|
87
|
+
*/
|
|
88
|
+
function groupErrors(likec4, staged) {
|
|
89
|
+
const pathOf = new Map(staged.map((doc) => [doc.project, doc.path]));
|
|
90
|
+
const grouped = new Map();
|
|
91
|
+
for (const err of distinctErrors(likec4.getErrors())) {
|
|
92
|
+
const project = err.sourceFsPath.split(/[\\/]/).find((segment) => pathOf.has(segment));
|
|
93
|
+
if (project === undefined) {
|
|
94
|
+
// An error this walk cannot attribute would otherwise be DROPPED — and a
|
|
95
|
+
// dropped error grades its document clean, which is failing open in the
|
|
96
|
+
// fleet gate. Unreachable at the pinned likec4 version (every corpus
|
|
97
|
+
// error carries its project folder in sourceFsPath), so the one place a
|
|
98
|
+
// dependency upgrade could break the attribution is the one place that
|
|
99
|
+
// must reject the whole batch: the caller degrades to per-path loads,
|
|
100
|
+
// where the error reappears.
|
|
101
|
+
throw new Error(`unattributable LikeC4 error in batch workspace: ${err.message}`);
|
|
102
|
+
}
|
|
103
|
+
const list = grouped.get(project) ?? [];
|
|
104
|
+
list.push({ ...err, sourceFsPath: pathOf.get(project) });
|
|
105
|
+
grouped.set(project, list);
|
|
106
|
+
}
|
|
107
|
+
return grouped;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Load and validate many self-contained `.likec4` documents in one workspace.
|
|
111
|
+
* Returns `resolve(path)` → LoadedDoc; paths are deduped through the same
|
|
112
|
+
* resolution, and a path that could not be staged is absent from the result.
|
|
113
|
+
*
|
|
114
|
+
* A document with errors keeps `loadSource`'s exact rule — empty elements and
|
|
115
|
+
* relationships, WITHOUT calling `parsedModel`: the parsed stage succeeds even
|
|
116
|
+
* over unresolved references, so the "errors mean no model" boundary is loam's
|
|
117
|
+
* to apply, not LikeC4's. A clean document is flattened from
|
|
118
|
+
* `parsedModel(project)` — parsed, never computed: the computed stage RESOLVES
|
|
119
|
+
* every view against the model — which loam never wants, because it reads a
|
|
120
|
+
* view's DECLARATIONS and never a view's resolved contents (docs/DESIGN.md
|
|
121
|
+
* rule 26) — and which is superlinear in edge count (see loadSource).
|
|
122
|
+
*/
|
|
123
|
+
export async function loadBatch(paths) {
|
|
124
|
+
const targets = [...new Set(paths.map((path) => resolve(path)))];
|
|
125
|
+
const out = new Map();
|
|
126
|
+
if (targets.length === 0)
|
|
127
|
+
return out;
|
|
128
|
+
const root = await mkdtemp(join(tmpdir(), "loam-c4-"));
|
|
129
|
+
try {
|
|
130
|
+
const staged = await stage(root, targets);
|
|
131
|
+
if (staged.length === 0)
|
|
132
|
+
return out;
|
|
133
|
+
// One workspace for the whole batch — the entire point. The logger is
|
|
134
|
+
// disabled exactly as in loadSource: diagnostics are returned per document,
|
|
135
|
+
// not written out-of-band to stderr (core never prints).
|
|
136
|
+
const likec4 = await LikeC4.fromWorkspace(root, { logger: false });
|
|
137
|
+
try {
|
|
138
|
+
const grouped = groupErrors(likec4, staged);
|
|
139
|
+
for (const { path, project } of staged) {
|
|
140
|
+
const errors = grouped.get(project) ?? [];
|
|
141
|
+
if (errors.length > 0) {
|
|
142
|
+
out.set(path, { errors, elements: [], relationships: [] });
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Through `cleanDoc`, the one assembly `loadSource` uses too. The
|
|
146
|
+
// specification travels with the batch loader and must: this is the
|
|
147
|
+
// loader `validate --all` reads the landscape through, so a kind-tag
|
|
148
|
+
// check wired only into `loadSource` would be a check the fleet gate
|
|
149
|
+
// — the one run it exists for — never actually ran.
|
|
150
|
+
out.set(path, cleanDoc((await likec4.parsedModel(project))));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
await likec4.dispose();
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
// The workspace is this invocation's alone; nothing else may observe it.
|
|
161
|
+
// A kill between mkdtemp and here can strand a loam-c4-* dir in OS tmp —
|
|
162
|
+
// never in the docs repo — which docs/DESIGN.md records as accepted.
|
|
163
|
+
await rm(root, { recursive: true, force: true });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/core/c4/workspace.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Batch loader: many self-contained `.likec4` documents through ONE\n * LikeC4/Langium workspace.\n *\n * `loadFile` pays a fresh workspace per call — ~100ms even warm — which is what\n * made `validate --all` O(documents) workspace spins (13.7s median over the\n * 120-service benchmark fixture, docs/BENCHMARKS.md). This module copies every\n * document into a mkdtemp workspace as one single-file PROJECT each (a\n * `likec4.config.json` per folder), calls `LikeC4.fromWorkspace` once, splits\n * `getErrors()` per document, and reads each clean project through the same\n * `cleanDoc` the per-file path uses. Parity — byte-identical error\n * messages/lines and identical elements/relationships — is pinned by\n * test/likec4-batch-parity.test.ts, which is also the tripwire for the exact\n * likec4 version pin: multi-project workspaces are public API, but this use of\n * them is not documented, so an upgrade must fail that suite before it lands.\n *\n * Isolation is load-bearing, not cosmetic: `fromSource` gives each document a\n * workspace of its own, so an author-written `import ... from 'name'` can never\n * resolve. In a shared workspace it COULD — a sibling project is one lucky name\n * away — so every folder carries one crypto-random per-invocation hex token in\n * its project name. A document cannot import what it cannot name, and the\n * parity suite pins that a guessed sibling name errors identically in both\n * modes.\n *\n * Callers own the failure story: a document that cannot be staged (unreadable,\n * missing) is silently DROPPED from the result so the caller's ordinary\n * per-path load reproduces today's error, and a batch-infrastructure failure\n * (tmpdir denied — the sandboxed-runner class ROADMAP documents) rejects the\n * whole call for the caller to catch and degrade. FleetContext.prefetchLikeC4\n * does exactly that: findings can never change because a workspace could not be\n * created, only the speed can.\n *\n * This file took core/c4/ to exactly five files, and the seam that note\n * predicted is now open: `./project/load.ts` loads a DIRECTORY as one project,\n * which is the opposite isolation contract and belongs beside this one rather\n * than inside it.\n */\nimport { randomBytes } from \"node:crypto\";\nimport { inOrder } from \"../kernel/concurrency.js\";\nimport { copyFile, mkdir, mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { LikeC4 } from \"likec4\";\nimport { cleanDoc, distinctErrors, type LikeC4Error, type LoadedDoc, type ReadableModel } from \"./likec4.js\";\n\n/** A staged document: the real path it came from, and its workspace project. */\ninterface StagedDoc {\n path: string;\n project: string;\n}\n\n/**\n * Stage every readable document as its own single-file project. A copy failure\n * removes the half-made folder and drops the path — an empty project must not\n * reach the workspace scan, and the caller's per-path load owns the error. The\n * copy is `copyFile` (raw bytes), not read/decode/write: BOM, CRLF and even\n * non-UTF-8 bytes reach LikeC4's own reader exactly as they would from the\n * original file on disk.\n */\nasync function stage(root: string, targets: string[]): Promise<StagedDoc[]> {\n const token = randomBytes(8).toString(\"hex\");\n // Concurrent, capped, in input order (kernel/concurrency's contract): the\n // per-document folders share nothing, and on a network-mounted docs repo\n // the sequential form paid three round-trips per document. Nulls mark the\n // drops so indices — and with them the p<i> project names — stay aligned.\n const results = await inOrder([...targets.entries()], async ([i, path]) => {\n const project = `p${i}_${token}`;\n const folder = join(root, project);\n try {\n await mkdir(folder);\n await writeFile(join(folder, \"likec4.config.json\"), JSON.stringify({ name: project }), \"utf8\");\n await copyFile(path, join(folder, basename(path)));\n return { path, project };\n } catch {\n await rm(folder, { recursive: true, force: true });\n return null;\n }\n });\n return results.filter((r): r is StagedDoc => r !== null);\n}\n\n/**\n * `getErrors()` split per document, each error's `sourceFsPath` rewritten from\n * the workspace copy to the document's real absolute path.\n *\n * Grouping keys on the unique `p<i>_<token>` path SEGMENT, never on a\n * tmp-root prefix compare: darwin hands back realpathed workspace paths\n * (`/var/...` becomes `/private/var/...`) in some environments and the literal\n * mkdtemp path in others, and a prefix compare silently attributes every error\n * to nobody in exactly one of those two worlds. The segment survives both.\n *\n * Read through `distinctErrors` exactly as `loadSource` reads them, so a\n * document's list is the same one in both modes.\n */\nfunction groupErrors(likec4: LikeC4, staged: StagedDoc[]): Map<string, LikeC4Error[]> {\n const pathOf = new Map(staged.map((doc) => [doc.project, doc.path]));\n const grouped = new Map<string, LikeC4Error[]>();\n for (const err of distinctErrors(likec4.getErrors())) {\n const project = err.sourceFsPath.split(/[\\\\/]/).find((segment) => pathOf.has(segment));\n if (project === undefined) {\n // An error this walk cannot attribute would otherwise be DROPPED — and a\n // dropped error grades its document clean, which is failing open in the\n // fleet gate. Unreachable at the pinned likec4 version (every corpus\n // error carries its project folder in sourceFsPath), so the one place a\n // dependency upgrade could break the attribution is the one place that\n // must reject the whole batch: the caller degrades to per-path loads,\n // where the error reappears.\n throw new Error(`unattributable LikeC4 error in batch workspace: ${err.message}`);\n }\n const list = grouped.get(project) ?? [];\n list.push({ ...err, sourceFsPath: pathOf.get(project) });\n grouped.set(project, list);\n }\n return grouped;\n}\n\n/**\n * Load and validate many self-contained `.likec4` documents in one workspace.\n * Returns `resolve(path)` → LoadedDoc; paths are deduped through the same\n * resolution, and a path that could not be staged is absent from the result.\n *\n * A document with errors keeps `loadSource`'s exact rule — empty elements and\n * relationships, WITHOUT calling `parsedModel`: the parsed stage succeeds even\n * over unresolved references, so the \"errors mean no model\" boundary is loam's\n * to apply, not LikeC4's. A clean document is flattened from\n * `parsedModel(project)` — parsed, never computed: the computed stage RESOLVES\n * every view against the model — which loam never wants, because it reads a\n * view's DECLARATIONS and never a view's resolved contents (docs/DESIGN.md\n * rule 26) — and which is superlinear in edge count (see loadSource).\n */\nexport async function loadBatch(paths: string[]): Promise<Map<string, LoadedDoc>> {\n const targets = [...new Set(paths.map((path) => resolve(path)))];\n const out = new Map<string, LoadedDoc>();\n if (targets.length === 0) return out;\n const root = await mkdtemp(join(tmpdir(), \"loam-c4-\"));\n try {\n const staged = await stage(root, targets);\n if (staged.length === 0) return out;\n // One workspace for the whole batch — the entire point. The logger is\n // disabled exactly as in loadSource: diagnostics are returned per document,\n // not written out-of-band to stderr (core never prints).\n const likec4 = await LikeC4.fromWorkspace(root, { logger: false });\n try {\n const grouped = groupErrors(likec4, staged);\n for (const { path, project } of staged) {\n const errors = grouped.get(project) ?? [];\n if (errors.length > 0) {\n out.set(path, { errors, elements: [], relationships: [] });\n } else {\n // Through `cleanDoc`, the one assembly `loadSource` uses too. The\n // specification travels with the batch loader and must: this is the\n // loader `validate --all` reads the landscape through, so a kind-tag\n // check wired only into `loadSource` would be a check the fleet gate\n // — the one run it exists for — never actually ran.\n out.set(path, cleanDoc((await likec4.parsedModel(project)) as ReadableModel));\n }\n }\n } finally {\n await likec4.dispose();\n }\n return out;\n } finally {\n // The workspace is this invocation's alone; nothing else may observe it.\n // A kill between mkdtemp and here can strand a loam-c4-* dir in OS tmp —\n // never in the docs repo — which docs/DESIGN.md records as accepted.\n await rm(root, { recursive: true, force: true });\n }\n}\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `loam new --capability <id>` says about the capability it just scaffolded
|
|
3
|
+
* a delta for.
|
|
4
|
+
*
|
|
5
|
+
* NOTES, NEVER REFUSALS, and the whole judgement is in that word. A capability
|
|
6
|
+
* the fleet has never named is exactly what an analyst opening a new business
|
|
7
|
+
* area types, and it is the case the flag exists for: `--touches <services>`
|
|
8
|
+
* asks for the services before the business change is written, and inverting
|
|
9
|
+
* that only works if naming a new promise is the ordinary path rather than the
|
|
10
|
+
* refused one. The archive that lands this feature is what creates
|
|
11
|
+
* `capabilities/<id>/spec.md` (`commands/archive/plan/specs.ts`), so there is
|
|
12
|
+
* nothing to declare first.
|
|
13
|
+
*
|
|
14
|
+
* THE OTHER READING STAYS AVAILABLE IN THE MESSAGE. The failure a refusal would
|
|
15
|
+
* have caught is the typo — `payments/refund` against a living
|
|
16
|
+
* `payments/refunds` is a second capability created out of nothing, with the
|
|
17
|
+
* promise filed where nobody looks — so the close names are spelled out
|
|
18
|
+
* alongside, exactly as `--touches`' own near-miss note spells them, together
|
|
19
|
+
* with the way back out. That is the same trade `unknownServiceNotes` makes in
|
|
20
|
+
* `commands/new/new.ts`, and it is deliberate that the two flags behave alike:
|
|
21
|
+
* "names something that does not exist yet" is legitimate on both.
|
|
22
|
+
*
|
|
23
|
+
* THE NEAR-MISS RULE IS `nearestIds`, NOT `closeIds`, and on this axis the two
|
|
24
|
+
* disagree loudly. `closeIds` matches on substring either way, so
|
|
25
|
+
* `payments/refunds` reports its own PARENT `payments` as a candidate — nesting
|
|
26
|
+
* spelled by the tree is the axis's headline shape, and a note telling an author
|
|
27
|
+
* their new sub-capability is a misspelling of the group it sits in is worse
|
|
28
|
+
* than no note. `nearestIds` is the edit-distance "did you misspell a directory"
|
|
29
|
+
* rule, which is the question actually being asked here, and
|
|
30
|
+
* `core/repo/entries.ts` states that division at its own definition.
|
|
31
|
+
*
|
|
32
|
+
* THE WAY OUT NAMES THIS FEATURE'S DIRECTORY, never `features/`. loam ships
|
|
33
|
+
* instructions people and agents type back; `features/` holds every in-flight
|
|
34
|
+
* feature in a SHARED docs repo, so an instruction to delete it is an
|
|
35
|
+
* instruction to destroy other authors' work. `dirName` is threaded in for that
|
|
36
|
+
* one sentence — the same care `validate/feature.ts` takes to spell
|
|
37
|
+
* `features/FEAT-1-split/` rather than `features/FEAT-1/`.
|
|
38
|
+
*
|
|
39
|
+
* WHAT IT DOES NOT SAY, and why not: which services realize this capability
|
|
40
|
+
* today. `capabilityRollup` knows, and the line would be useful, but it walks
|
|
41
|
+
* every service's `spec.md` AND `arch.spec.md` across the whole fleet — a cost
|
|
42
|
+
* proportional to the service tree, paid by a command whose job is to create
|
|
43
|
+
* four files, and `loam new` sits in the authoring hot path. `loam list
|
|
44
|
+
* capabilities` already computes exactly that answer and the note points at it.
|
|
45
|
+
* The half that IS read here is the one an author cannot write the delta
|
|
46
|
+
* without — the living document's own requirement ids, which is what a MODIFIED
|
|
47
|
+
* section addresses and what an ADDED section must not repeat — and that is one
|
|
48
|
+
* file, the very file this delta diffs against.
|
|
49
|
+
*
|
|
50
|
+
* IN CORE, not beside the command, for the rule the command layer is held to:
|
|
51
|
+
* `commands/` parses arguments, calls core and prints. Which of a fleet's two
|
|
52
|
+
* vocabularies declared an id, and which of a capability's requirements are
|
|
53
|
+
* addressable, are questions about the DOCUMENTS — the same questions
|
|
54
|
+
* `../findings.ts` answers as findings — and the only thing this module does
|
|
55
|
+
* differently is answer them for a person who has not written anything yet.
|
|
56
|
+
*/
|
|
57
|
+
import { readFile } from "node:fs/promises";
|
|
58
|
+
import { compareIds, nearestIds } from "../../repo/entries.js";
|
|
59
|
+
import { parseRequirements } from "../../document/parse.js";
|
|
60
|
+
import { readCapabilityVocabulary } from "../capabilities.js";
|
|
61
|
+
/**
|
|
62
|
+
* One note per `--capability` id: is this promise already declared, and if so
|
|
63
|
+
* what does it already say?
|
|
64
|
+
*
|
|
65
|
+
* The vocabulary read is the UNION of `architecture/capabilities.yaml` and the
|
|
66
|
+
* `capabilities/` tree, never one side, for the reason `capabilities.ts` states:
|
|
67
|
+
* a second spelling of "the vocabulary" is a second answer to whether an id is
|
|
68
|
+
* known, and this note and `capability.unknown` must not be able to disagree.
|
|
69
|
+
*/
|
|
70
|
+
export async function capabilityNotes(docsDir, scope) {
|
|
71
|
+
if (scope.ids.length === 0)
|
|
72
|
+
return [];
|
|
73
|
+
const vocab = await readCapabilityVocabulary(docsDir);
|
|
74
|
+
const declared = [...vocab.byId.keys()].sort(compareIds);
|
|
75
|
+
const notes = [];
|
|
76
|
+
for (const id of scope.ids) {
|
|
77
|
+
const known = vocab.byId.get(id);
|
|
78
|
+
if (known === undefined) {
|
|
79
|
+
const near = nearestIds(id, declared);
|
|
80
|
+
notes.push(`--capability '${id}' is a capability this fleet has not named yet — nothing declares it in ` +
|
|
81
|
+
`architecture/capabilities.yaml or capabilities/${id}/spec.md. That is legal and often the point: ` +
|
|
82
|
+
`archiving this feature CREATES capabilities/${id}/spec.md from the delta just scaffolded` +
|
|
83
|
+
(near.length === 0
|
|
84
|
+
? "."
|
|
85
|
+
: `. If you meant an existing one — ${near.map((n) => `'${n}'`).join(" or ")} — rename ` +
|
|
86
|
+
`features/${scope.dirName}/capabilities/${id}/ to that spelling, or delete features/${scope.dirName}/ and re-run \`loam new\`.`));
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (known.spec === undefined) {
|
|
90
|
+
// Declared in the YAML with no document behind it: the ordinary
|
|
91
|
+
// mid-adoption state, and the one case where this feature is writing the
|
|
92
|
+
// fleet's first prose for a word it already had.
|
|
93
|
+
notes.push(`--capability '${id}' is declared in architecture/capabilities.yaml but has no capabilities/${id}/spec.md yet — ` +
|
|
94
|
+
"this feature's delta is the first prose behind that word, and archiving it writes the document.");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
notes.push(livingNote(id, await requirementIds(known.spec)));
|
|
98
|
+
}
|
|
99
|
+
return notes;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The living document's requirement ids, in document order.
|
|
103
|
+
*
|
|
104
|
+
* A requirement WITHOUT a `Requirement-ID:` is skipped rather than named by its
|
|
105
|
+
* heading, matching every other reader on this axis: nothing can address it, so
|
|
106
|
+
* offering the heading as an address would teach exactly the identity-by-heading
|
|
107
|
+
* `capability.requirement-unidentified` refuses.
|
|
108
|
+
*
|
|
109
|
+
* An unreadable document is NOT fatal here. This is a note printed after the
|
|
110
|
+
* scaffold has already committed, and the alternative — throwing out of a
|
|
111
|
+
* successful `loam new` — would report the write as a failure. `loam validate`
|
|
112
|
+
* owns the diagnosis of a living document nobody can read.
|
|
113
|
+
*/
|
|
114
|
+
async function requirementIds(spec) {
|
|
115
|
+
try {
|
|
116
|
+
return parseRequirements(await readFile(spec, "utf8")).flatMap((r) => r.kind === "REMOVED" || r.id === undefined ? [] : [r.id]);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** The note for a capability that already has a document — what the delta is a diff against. */
|
|
123
|
+
function livingNote(id, ids) {
|
|
124
|
+
const head = `--capability '${id}' already has capabilities/${id}/spec.md`;
|
|
125
|
+
if (ids === null)
|
|
126
|
+
return `${head}, which could not be read — run \`loam validate --all\` before authoring against it.`;
|
|
127
|
+
if (ids.length === 0) {
|
|
128
|
+
return (`${head}, and it declares no identified requirements yet — everything in this delta is an ADDED promise. ` +
|
|
129
|
+
"`loam list capabilities` shows what the fleet already realizes.");
|
|
130
|
+
}
|
|
131
|
+
// The ids, not a count: a MODIFIED section addresses one of these and an
|
|
132
|
+
// ADDED one must not repeat it, so the list IS the thing the author needs in
|
|
133
|
+
// front of them. Capped, because a long-lived capability can carry dozens and
|
|
134
|
+
// a note that scrolls is a note nobody reads.
|
|
135
|
+
const shown = ids.slice(0, 8);
|
|
136
|
+
return (`${head}, declaring ${ids.length} identified requirement(s): ${shown.join(", ")}` +
|
|
137
|
+
(ids.length > shown.length ? `, … (\`loam show\` for the rest)` : "") +
|
|
138
|
+
". A MODIFIED section addresses one of those ids; an ADDED one must not repeat it. " +
|
|
139
|
+
"`loam list capabilities` shows which services realize them today.");
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../../../../src/core/capabilities/authoring/notes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What `loam new --capability <id>` says about the capability it just scaffolded\n * a delta for.\n *\n * NOTES, NEVER REFUSALS, and the whole judgement is in that word. A capability\n * the fleet has never named is exactly what an analyst opening a new business\n * area types, and it is the case the flag exists for: `--touches <services>`\n * asks for the services before the business change is written, and inverting\n * that only works if naming a new promise is the ordinary path rather than the\n * refused one. The archive that lands this feature is what creates\n * `capabilities/<id>/spec.md` (`commands/archive/plan/specs.ts`), so there is\n * nothing to declare first.\n *\n * THE OTHER READING STAYS AVAILABLE IN THE MESSAGE. The failure a refusal would\n * have caught is the typo — `payments/refund` against a living\n * `payments/refunds` is a second capability created out of nothing, with the\n * promise filed where nobody looks — so the close names are spelled out\n * alongside, exactly as `--touches`' own near-miss note spells them, together\n * with the way back out. That is the same trade `unknownServiceNotes` makes in\n * `commands/new/new.ts`, and it is deliberate that the two flags behave alike:\n * \"names something that does not exist yet\" is legitimate on both.\n *\n * THE NEAR-MISS RULE IS `nearestIds`, NOT `closeIds`, and on this axis the two\n * disagree loudly. `closeIds` matches on substring either way, so\n * `payments/refunds` reports its own PARENT `payments` as a candidate — nesting\n * spelled by the tree is the axis's headline shape, and a note telling an author\n * their new sub-capability is a misspelling of the group it sits in is worse\n * than no note. `nearestIds` is the edit-distance \"did you misspell a directory\"\n * rule, which is the question actually being asked here, and\n * `core/repo/entries.ts` states that division at its own definition.\n *\n * THE WAY OUT NAMES THIS FEATURE'S DIRECTORY, never `features/`. loam ships\n * instructions people and agents type back; `features/` holds every in-flight\n * feature in a SHARED docs repo, so an instruction to delete it is an\n * instruction to destroy other authors' work. `dirName` is threaded in for that\n * one sentence — the same care `validate/feature.ts` takes to spell\n * `features/FEAT-1-split/` rather than `features/FEAT-1/`.\n *\n * WHAT IT DOES NOT SAY, and why not: which services realize this capability\n * today. `capabilityRollup` knows, and the line would be useful, but it walks\n * every service's `spec.md` AND `arch.spec.md` across the whole fleet — a cost\n * proportional to the service tree, paid by a command whose job is to create\n * four files, and `loam new` sits in the authoring hot path. `loam list\n * capabilities` already computes exactly that answer and the note points at it.\n * The half that IS read here is the one an author cannot write the delta\n * without — the living document's own requirement ids, which is what a MODIFIED\n * section addresses and what an ADDED section must not repeat — and that is one\n * file, the very file this delta diffs against.\n *\n * IN CORE, not beside the command, for the rule the command layer is held to:\n * `commands/` parses arguments, calls core and prints. Which of a fleet's two\n * vocabularies declared an id, and which of a capability's requirements are\n * addressable, are questions about the DOCUMENTS — the same questions\n * `../findings.ts` answers as findings — and the only thing this module does\n * differently is answer them for a person who has not written anything yet.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { compareIds, nearestIds } from \"../../repo/entries.js\";\nimport { parseRequirements } from \"../../document/parse.js\";\nimport { readCapabilityVocabulary } from \"../capabilities.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\n\n/** Which feature was just scaffolded, and which promises it named. */\nexport interface CapabilityNoteScope {\n /** The feature's directory NAME (`FEAT-1-split`) — what the way-out sentence spells. */\n dirName: string;\n /** The `--capability` ids, in the order they were given. */\n ids: readonly string[];\n}\n\n/**\n * One note per `--capability` id: is this promise already declared, and if so\n * what does it already say?\n *\n * The vocabulary read is the UNION of `architecture/capabilities.yaml` and the\n * `capabilities/` tree, never one side, for the reason `capabilities.ts` states:\n * a second spelling of \"the vocabulary\" is a second answer to whether an id is\n * known, and this note and `capability.unknown` must not be able to disagree.\n */\nexport async function capabilityNotes(docsDir: DocsDir, scope: CapabilityNoteScope): Promise<string[]> {\n if (scope.ids.length === 0) return [];\n const vocab = await readCapabilityVocabulary(docsDir);\n const declared = [...vocab.byId.keys()].sort(compareIds);\n const notes: string[] = [];\n for (const id of scope.ids) {\n const known = vocab.byId.get(id);\n if (known === undefined) {\n const near = nearestIds(id, declared);\n notes.push(\n `--capability '${id}' is a capability this fleet has not named yet — nothing declares it in ` +\n `architecture/capabilities.yaml or capabilities/${id}/spec.md. That is legal and often the point: ` +\n `archiving this feature CREATES capabilities/${id}/spec.md from the delta just scaffolded` +\n (near.length === 0\n ? \".\"\n : `. If you meant an existing one — ${near.map((n) => `'${n}'`).join(\" or \")} — rename ` +\n `features/${scope.dirName}/capabilities/${id}/ to that spelling, or delete features/${scope.dirName}/ and re-run \\`loam new\\`.`),\n );\n continue;\n }\n if (known.spec === undefined) {\n // Declared in the YAML with no document behind it: the ordinary\n // mid-adoption state, and the one case where this feature is writing the\n // fleet's first prose for a word it already had.\n notes.push(\n `--capability '${id}' is declared in architecture/capabilities.yaml but has no capabilities/${id}/spec.md yet — ` +\n \"this feature's delta is the first prose behind that word, and archiving it writes the document.\",\n );\n continue;\n }\n notes.push(livingNote(id, await requirementIds(known.spec)));\n }\n return notes;\n}\n\n/**\n * The living document's requirement ids, in document order.\n *\n * A requirement WITHOUT a `Requirement-ID:` is skipped rather than named by its\n * heading, matching every other reader on this axis: nothing can address it, so\n * offering the heading as an address would teach exactly the identity-by-heading\n * `capability.requirement-unidentified` refuses.\n *\n * An unreadable document is NOT fatal here. This is a note printed after the\n * scaffold has already committed, and the alternative — throwing out of a\n * successful `loam new` — would report the write as a failure. `loam validate`\n * owns the diagnosis of a living document nobody can read.\n */\nasync function requirementIds(spec: string): Promise<string[] | null> {\n try {\n return parseRequirements(await readFile(spec, \"utf8\")).flatMap((r) =>\n r.kind === \"REMOVED\" || r.id === undefined ? [] : [r.id],\n );\n } catch {\n return null;\n }\n}\n\n/** The note for a capability that already has a document — what the delta is a diff against. */\nfunction livingNote(id: string, ids: string[] | null): string {\n const head = `--capability '${id}' already has capabilities/${id}/spec.md`;\n if (ids === null) return `${head}, which could not be read — run \\`loam validate --all\\` before authoring against it.`;\n if (ids.length === 0) {\n return (\n `${head}, and it declares no identified requirements yet — everything in this delta is an ADDED promise. ` +\n \"`loam list capabilities` shows what the fleet already realizes.\"\n );\n }\n // The ids, not a count: a MODIFIED section addresses one of these and an\n // ADDED one must not repeat it, so the list IS the thing the author needs in\n // front of them. Capped, because a long-lived capability can carry dozens and\n // a note that scrolls is a note nobody reads.\n const shown = ids.slice(0, 8);\n return (\n `${head}, declaring ${ids.length} identified requirement(s): ${shown.join(\", \")}` +\n (ids.length > shown.length ? `, … (\\`loam show\\` for the rest)` : \"\") +\n \". A MODIFIED section addresses one of those ids; an ADDED one must not repeat it. \" +\n \"`loam list capabilities` shows which services realize them today.\"\n );\n}\n"]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fleet's capability vocabulary: which business capabilities exist, by
|
|
3
|
+
* declared name, so a requirement's `Capability:` line resolves or refuses
|
|
4
|
+
* instead of silently labelling.
|
|
5
|
+
*
|
|
6
|
+
* It is a fleet document (`architecture/capabilities.yaml`, beside the
|
|
7
|
+
* landscape and the permissions vocabulary) because a capability crosses
|
|
8
|
+
* services by definition — "registration" is realized by requirements in four
|
|
9
|
+
* repositories, and a per-service copy would be N spellings of one word.
|
|
10
|
+
*
|
|
11
|
+
* What this is NOT, deliberately: a domain model, and not an authored prose
|
|
12
|
+
* layer either. SCHEMA.md rejected a free-text `capability:` label because
|
|
13
|
+
* nothing could check it; a DECLARED name is different in exactly the way that
|
|
14
|
+
* mattered there — the id exists in this file or it does not, so an unknown
|
|
15
|
+
* name is an error with close candidates, a declaration nothing realizes is a
|
|
16
|
+
* warning, and the vocabulary cannot drift while looking authoritative. The
|
|
17
|
+
* long-lived capability documents themselves (one page per capability, revised
|
|
18
|
+
* by features) stay outside loam — that is the roadmap's evidence-gated Later
|
|
19
|
+
* item, and the rollup built over these names is the evidence that decides it.
|
|
20
|
+
*
|
|
21
|
+
* The OPT-IN also differs from the authorization axis, on purpose: there the
|
|
22
|
+
* `Requires:` line is the opt-in and a missing permissions.yaml is an error at
|
|
23
|
+
* the line; here the FILE is the opt-in — a fleet with no capabilities.yaml
|
|
24
|
+
* produces no capability findings at all (`core/capabilities/findings.ts`
|
|
25
|
+
* holds the rule and the reason).
|
|
26
|
+
*/
|
|
27
|
+
import { readFile } from "node:fs/promises";
|
|
28
|
+
import { existsSync } from "node:fs";
|
|
29
|
+
import { parse as parseYaml } from "yaml";
|
|
30
|
+
import { isRecord } from "../kernel/records.js";
|
|
31
|
+
import { capabilitiesPath } from "../repo/paths.js";
|
|
32
|
+
import { capabilityDocsDir } from "../repo/authored/paths.js";
|
|
33
|
+
import { readCapabilityTree } from "./tree.js";
|
|
34
|
+
const NO_TREE = { present: false, docs: [], undocumented: [] };
|
|
35
|
+
const EMPTY = { present: false, byId: new Map(), tree: NO_TREE };
|
|
36
|
+
/**
|
|
37
|
+
* Read the vocabulary — exactly `permissions.ts`'s defensive ladder, because
|
|
38
|
+
* the two files fail the same ways: a missing file is silence, a YAML error or
|
|
39
|
+
* a non-mapping shape is `invalid` (one finding for the whole run, the family
|
|
40
|
+
* suppressed behind it), an empty document is a present-and-empty vocabulary,
|
|
41
|
+
* and a declaration whose body is not a mapping is treated as `{}` rather than
|
|
42
|
+
* refusing the whole file over one leaf.
|
|
43
|
+
*/
|
|
44
|
+
async function readCapabilities(path) {
|
|
45
|
+
if (!existsSync(path))
|
|
46
|
+
return EMPTY;
|
|
47
|
+
let doc;
|
|
48
|
+
try {
|
|
49
|
+
doc = parseYaml(await readFile(path, "utf8"));
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
return { ...EMPTY, present: true, invalid: e instanceof Error ? e.message : String(e) };
|
|
53
|
+
}
|
|
54
|
+
if (doc === null || doc === undefined)
|
|
55
|
+
return { ...EMPTY, present: true };
|
|
56
|
+
if (!isRecord(doc))
|
|
57
|
+
return { ...EMPTY, present: true, invalid: "the document is not a mapping" };
|
|
58
|
+
const block = doc["capabilities"];
|
|
59
|
+
if (block === undefined)
|
|
60
|
+
return { ...EMPTY, present: true };
|
|
61
|
+
if (!isRecord(block)) {
|
|
62
|
+
return { ...EMPTY, present: true, invalid: "`capabilities` is not a mapping of capability id to its declaration" };
|
|
63
|
+
}
|
|
64
|
+
const byId = new Map();
|
|
65
|
+
for (const [id, body] of Object.entries(block)) {
|
|
66
|
+
const decl = isRecord(body) ? body : {};
|
|
67
|
+
byId.set(id, {
|
|
68
|
+
id,
|
|
69
|
+
source: "yaml",
|
|
70
|
+
...(typeof decl["description"] === "string" ? { description: decl["description"] } : {}),
|
|
71
|
+
...(typeof decl["owner"] === "string" ? { owner: decl["owner"] } : {}),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return { ...EMPTY, present: true, byId };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* THE vocabulary — both sides read and merged, and the only shape a grader
|
|
78
|
+
* should ever be handed.
|
|
79
|
+
*
|
|
80
|
+
* `readCapabilities` above is the file alone, and it is private to this
|
|
81
|
+
* module because nothing that grades a fleet may use it: a `Capability:` line
|
|
82
|
+
* naming an id the tree declares and the YAML does not would resolve through
|
|
83
|
+
* the union and fail through the file, so a second spelling of "the
|
|
84
|
+
* vocabulary" is a second answer to `capability.unknown`.
|
|
85
|
+
*
|
|
86
|
+
* WHERE AN ID SITS ON BOTH SIDES THE YAML'S METADATA SURVIVES, and not by
|
|
87
|
+
* precedence — the document has nothing to overwrite it with. `description` and
|
|
88
|
+
* `owner` are fields, and this axis's own rule is that an entry without prose
|
|
89
|
+
* stays a line in YAML; the document's contribution is the narrative and the
|
|
90
|
+
* requirements, which are prose, and loam reads frontmatter, never prose. So a
|
|
91
|
+
* capability declared only in the tree has no owner in `loam list
|
|
92
|
+
* capabilities`, and that is the honest reading rather than a gap: nobody wrote
|
|
93
|
+
* one down. What the merge adds on that side is `spec` and `source`.
|
|
94
|
+
*
|
|
95
|
+
* An UNREADABLE YAML suspends the whole family (`gradableCapabilityIds` in
|
|
96
|
+
* `./findings.ts` is the one statement of that ladder), and the tree is still
|
|
97
|
+
* walked and still carried: `capability.doc-missing` is a fact about
|
|
98
|
+
* directories that no YAML failure makes untrue, and suppressing it behind an
|
|
99
|
+
* unrelated broken file would hide a half-created capability until somebody
|
|
100
|
+
* fixed a document it has nothing to do with.
|
|
101
|
+
*/
|
|
102
|
+
export async function readCapabilityVocabulary(docsDir) {
|
|
103
|
+
const [yaml, tree] = await Promise.all([
|
|
104
|
+
readCapabilities(capabilitiesPath(docsDir)),
|
|
105
|
+
readCapabilityTree(capabilityDocsDir(docsDir)),
|
|
106
|
+
]);
|
|
107
|
+
const byId = new Map(yaml.byId);
|
|
108
|
+
for (const doc of tree.docs) {
|
|
109
|
+
const declared = byId.get(doc.id);
|
|
110
|
+
byId.set(doc.id, {
|
|
111
|
+
...declared,
|
|
112
|
+
id: doc.id,
|
|
113
|
+
source: declared === undefined ? "tree" : "both",
|
|
114
|
+
spec: doc.spec,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
...yaml,
|
|
119
|
+
present: yaml.present || tree.present,
|
|
120
|
+
byId,
|
|
121
|
+
tree,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../../src/core/capabilities/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAuB,MAAM,WAAW,CAAC;AAwDpE,MAAM,OAAO,GAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;AAC/E,MAAM,KAAK,GAAyB,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAEvF;;;;;;;GAOG;AACH,KAAK,UAAU,gBAAgB,CAAC,IAAY;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,SAAS,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1F,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC;IAEjG,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,qEAAqE,EAAE,CAAC;IACrH,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC3C,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,EAAE;YACF,MAAM,EAAE,MAAM;YACd,GAAG,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxF,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,OAAgB;IAC7D,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACrC,gBAAgB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC3C,kBAAkB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;KAC/C,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE;YACf,GAAG,QAAQ;YACX,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,MAAM,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAChD,IAAI,EAAE,GAAG,CAAC,IAAI;SACf,CAAC,CAAC;IACL,CAAC;IACD,OAAO;QACL,GAAG,IAAI;QACP,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;QACrC,IAAI;QACJ,IAAI;KACL,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The fleet's capability vocabulary: which business capabilities exist, by\n * declared name, so a requirement's `Capability:` line resolves or refuses\n * instead of silently labelling.\n *\n * It is a fleet document (`architecture/capabilities.yaml`, beside the\n * landscape and the permissions vocabulary) because a capability crosses\n * services by definition — \"registration\" is realized by requirements in four\n * repositories, and a per-service copy would be N spellings of one word.\n *\n * What this is NOT, deliberately: a domain model, and not an authored prose\n * layer either. SCHEMA.md rejected a free-text `capability:` label because\n * nothing could check it; a DECLARED name is different in exactly the way that\n * mattered there — the id exists in this file or it does not, so an unknown\n * name is an error with close candidates, a declaration nothing realizes is a\n * warning, and the vocabulary cannot drift while looking authoritative. The\n * long-lived capability documents themselves (one page per capability, revised\n * by features) stay outside loam — that is the roadmap's evidence-gated Later\n * item, and the rollup built over these names is the evidence that decides it.\n *\n * The OPT-IN also differs from the authorization axis, on purpose: there the\n * `Requires:` line is the opt-in and a missing permissions.yaml is an error at\n * the line; here the FILE is the opt-in — a fleet with no capabilities.yaml\n * produces no capability findings at all (`core/capabilities/findings.ts`\n * holds the rule and the reason).\n */\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { parse as parseYaml } from \"yaml\";\nimport { isRecord } from \"../kernel/records.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\nimport { capabilitiesPath } from \"../repo/paths.js\";\nimport { capabilityDocsDir } from \"../repo/authored/paths.js\";\nimport { readCapabilityTree, type CapabilityTree } from \"./tree.js\";\n\n/** One declared capability. The id is the full key, slashes preserved. */\nexport interface Capability {\n /**\n * The token a requirement's `Capability:` line writes. Nesting is spelled\n * INSIDE the id (`payments/refunds`) and never collapsed — the key is\n * exactly the string a requirement names, greppable as written.\n */\n id: string;\n description?: string;\n /**\n * A team or a person — deliberately `owner:`, not permissions' `owned_by:`,\n * because that field carries \"defining service\" semantics a capability does\n * not have. Never resolved against anything; a blank is a worse answer than\n * an unverified one.\n */\n owner?: string;\n /**\n * Which side declared this id. `yaml` is a name in\n * `architecture/capabilities.yaml` with no document; `tree` is a\n * `capabilities/<id>/spec.md` the YAML does not name; `both` is the same id\n * on both sides, which is normal rather than a duplicate — the YAML declared\n * the word first and somebody has since written the document for it.\n *\n * Recorded rather than derived at each reader, because the two sides carry\n * different fixes: a `yaml`-only capability is fixed by writing the document,\n * a `tree`-only one needs no fix at all, and a message that could not tell\n * them apart would advise editing a file that may not exist.\n */\n source: \"yaml\" | \"tree\" | \"both\";\n /** `capabilities/<id>/spec.md`, absolute, when the tree declares this id. */\n spec?: string;\n}\n\nexport interface CapabilityVocabulary {\n /**\n * False when NEITHER `architecture/capabilities.yaml` nor `capabilities/`\n * exists. Either one is the axis's opt-in, so a fleet holding neither\n * produces no capability finding at all, however many `Capability:` lines its\n * requirements already carry.\n */\n present: boolean;\n /**\n * Why `architecture/capabilities.yaml` could not be read as a vocabulary,\n * when it could not. The TREE has no such state: a directory either lists or\n * it does not, and an unreadable one is a filesystem failure the walk lets\n * throw rather than a document loam misread.\n */\n invalid?: string;\n /** Declared capabilities, keyed by the full id — the union of both sides. */\n byId: Map<string, Capability>;\n /** What the `capabilities/` walk found, for the graders that need the paths. */\n tree: CapabilityTree;\n}\n\nconst NO_TREE: CapabilityTree = { present: false, docs: [], undocumented: [] };\nconst EMPTY: CapabilityVocabulary = { present: false, byId: new Map(), tree: NO_TREE };\n\n/**\n * Read the vocabulary — exactly `permissions.ts`'s defensive ladder, because\n * the two files fail the same ways: a missing file is silence, a YAML error or\n * a non-mapping shape is `invalid` (one finding for the whole run, the family\n * suppressed behind it), an empty document is a present-and-empty vocabulary,\n * and a declaration whose body is not a mapping is treated as `{}` rather than\n * refusing the whole file over one leaf.\n */\nasync function readCapabilities(path: string): Promise<CapabilityVocabulary> {\n if (!existsSync(path)) return EMPTY;\n let doc: unknown;\n try {\n doc = parseYaml(await readFile(path, \"utf8\"));\n } catch (e) {\n return { ...EMPTY, present: true, invalid: e instanceof Error ? e.message : String(e) };\n }\n if (doc === null || doc === undefined) return { ...EMPTY, present: true };\n if (!isRecord(doc)) return { ...EMPTY, present: true, invalid: \"the document is not a mapping\" };\n\n const block = doc[\"capabilities\"];\n if (block === undefined) return { ...EMPTY, present: true };\n if (!isRecord(block)) {\n return { ...EMPTY, present: true, invalid: \"`capabilities` is not a mapping of capability id to its declaration\" };\n }\n\n const byId = new Map<string, Capability>();\n for (const [id, body] of Object.entries(block)) {\n const decl = isRecord(body) ? body : {};\n byId.set(id, {\n id,\n source: \"yaml\",\n ...(typeof decl[\"description\"] === \"string\" ? { description: decl[\"description\"] } : {}),\n ...(typeof decl[\"owner\"] === \"string\" ? { owner: decl[\"owner\"] } : {}),\n });\n }\n return { ...EMPTY, present: true, byId };\n}\n\n/**\n * THE vocabulary — both sides read and merged, and the only shape a grader\n * should ever be handed.\n *\n * `readCapabilities` above is the file alone, and it is private to this\n * module because nothing that grades a fleet may use it: a `Capability:` line\n * naming an id the tree declares and the YAML does not would resolve through\n * the union and fail through the file, so a second spelling of \"the\n * vocabulary\" is a second answer to `capability.unknown`.\n *\n * WHERE AN ID SITS ON BOTH SIDES THE YAML'S METADATA SURVIVES, and not by\n * precedence — the document has nothing to overwrite it with. `description` and\n * `owner` are fields, and this axis's own rule is that an entry without prose\n * stays a line in YAML; the document's contribution is the narrative and the\n * requirements, which are prose, and loam reads frontmatter, never prose. So a\n * capability declared only in the tree has no owner in `loam list\n * capabilities`, and that is the honest reading rather than a gap: nobody wrote\n * one down. What the merge adds on that side is `spec` and `source`.\n *\n * An UNREADABLE YAML suspends the whole family (`gradableCapabilityIds` in\n * `./findings.ts` is the one statement of that ladder), and the tree is still\n * walked and still carried: `capability.doc-missing` is a fact about\n * directories that no YAML failure makes untrue, and suppressing it behind an\n * unrelated broken file would hide a half-created capability until somebody\n * fixed a document it has nothing to do with.\n */\nexport async function readCapabilityVocabulary(docsDir: DocsDir): Promise<CapabilityVocabulary> {\n const [yaml, tree] = await Promise.all([\n readCapabilities(capabilitiesPath(docsDir)),\n readCapabilityTree(capabilityDocsDir(docsDir)),\n ]);\n const byId = new Map(yaml.byId);\n for (const doc of tree.docs) {\n const declared = byId.get(doc.id);\n byId.set(doc.id, {\n ...declared,\n id: doc.id,\n source: declared === undefined ? \"tree\" : \"both\",\n spec: doc.spec,\n });\n }\n return {\n ...yaml,\n present: yaml.present || tree.present,\n byId,\n tree,\n };\n}\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The capability document's own three grades, applied to a FEATURE'S DELTA.
|
|
3
|
+
*
|
|
4
|
+
* `../findings.ts` grades the living `capabilities/<id>/spec.md` and files
|
|
5
|
+
* Findings for `loam validate`. This is the same three rules filed as archive
|
|
6
|
+
* Issues — the split `capabilityUnknownIssues` one directory over makes
|
|
7
|
+
* between its two commands, and for the identical reason: severity says
|
|
8
|
+
* whether the DOCUMENT is valid, gating says whether the MERGE is safe, and the
|
|
9
|
+
* two questions are asked by two different commands about the same text. A grade
|
|
10
|
+
* is already an Issue in shape (its return type pins severity and code), so
|
|
11
|
+
* the rules' own objects are returned, not copied field by field.
|
|
12
|
+
*
|
|
13
|
+
* WITHOUT THIS THE DELTA PATH IS A HOLE THROUGH THE RULE. A capability
|
|
14
|
+
* requirement carrying `Operations:` is a service requirement filed at the
|
|
15
|
+
* business altitude — the one thing that makes a second requirements corpus
|
|
16
|
+
* worth having is that it does not become a second place to write the first
|
|
17
|
+
* one. Graded only on the living document, that requirement merges cleanly and
|
|
18
|
+
* earns its error afterwards, against a file whoever reads the finding did not
|
|
19
|
+
* write and cannot un-merge. So the delta is graded BEFORE the merge, where the
|
|
20
|
+
* author is still holding the document.
|
|
21
|
+
*
|
|
22
|
+
* ADDED AND MODIFIED ONLY. A REMOVED requirement is being retired: demanding a
|
|
23
|
+
* `Requirement-ID:` on it, or refusing the `Operations:` line it is deleting,
|
|
24
|
+
* would ask for an edit to text that is about to stop existing. A BASE
|
|
25
|
+
* requirement is a delta quoting living context, already named by
|
|
26
|
+
* `delta.requirement-not-merged`, and it merges nothing — two findings for one
|
|
27
|
+
* mistake is the failure to avoid.
|
|
28
|
+
*
|
|
29
|
+
* NO CODES OF ITS OWN, and no message of its own. Every sentence comes from
|
|
30
|
+
* `capabilityDocFindings`, whose `where` parameter is what points them at the
|
|
31
|
+
* feature's copy of the document.
|
|
32
|
+
*/
|
|
33
|
+
import { capabilityDocFindings } from "../findings.js";
|
|
34
|
+
/**
|
|
35
|
+
* The three grades, as archive-gating Issues, over the requirements a
|
|
36
|
+
* capability delta would actually merge.
|
|
37
|
+
*
|
|
38
|
+
* `target.where` is the delta's repo-relative path so a reader is sent to the
|
|
39
|
+
* file they wrote, and `target.subject` is the capability id so a `--json`
|
|
40
|
+
* consumer groups by promise rather than by path — the same split every other
|
|
41
|
+
* capability grade uses.
|
|
42
|
+
*/
|
|
43
|
+
export function capabilityDocIssues(reqs, target) {
|
|
44
|
+
const merging = reqs.filter((r) => r.kind === "ADDED" || r.kind === "MODIFIED");
|
|
45
|
+
return capabilityDocFindings(merging, target.subject, target.where);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=doc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc.js","sourceRoot":"","sources":["../../../../src/core/capabilities/delta/doc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,qBAAqB,EAAyB,MAAM,gBAAgB,CAAC;AAI9E;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAmB,EAAE,MAAwB;IAC/E,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAChF,OAAO,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC","sourcesContent":["/**\n * The capability document's own three grades, applied to a FEATURE'S DELTA.\n *\n * `../findings.ts` grades the living `capabilities/<id>/spec.md` and files\n * Findings for `loam validate`. This is the same three rules filed as archive\n * Issues — the split `capabilityUnknownIssues` one directory over makes\n * between its two commands, and for the identical reason: severity says\n * whether the DOCUMENT is valid, gating says whether the MERGE is safe, and the\n * two questions are asked by two different commands about the same text. A grade\n * is already an Issue in shape (its return type pins severity and code), so\n * the rules' own objects are returned, not copied field by field.\n *\n * WITHOUT THIS THE DELTA PATH IS A HOLE THROUGH THE RULE. A capability\n * requirement carrying `Operations:` is a service requirement filed at the\n * business altitude — the one thing that makes a second requirements corpus\n * worth having is that it does not become a second place to write the first\n * one. Graded only on the living document, that requirement merges cleanly and\n * earns its error afterwards, against a file whoever reads the finding did not\n * write and cannot un-merge. So the delta is graded BEFORE the merge, where the\n * author is still holding the document.\n *\n * ADDED AND MODIFIED ONLY. A REMOVED requirement is being retired: demanding a\n * `Requirement-ID:` on it, or refusing the `Operations:` line it is deleting,\n * would ask for an edit to text that is about to stop existing. A BASE\n * requirement is a delta quoting living context, already named by\n * `delta.requirement-not-merged`, and it merges nothing — two findings for one\n * mistake is the failure to avoid.\n *\n * NO CODES OF ITS OWN, and no message of its own. Every sentence comes from\n * `capabilityDocFindings`, whose `where` parameter is what points them at the\n * feature's copy of the document.\n */\nimport { capabilityDocFindings, type CapabilityTarget } from \"../findings.js\";\nimport type { Requirement } from \"../../document/spec.js\";\nimport type { Issue } from \"../../vocabulary/issue.js\";\n\n/**\n * The three grades, as archive-gating Issues, over the requirements a\n * capability delta would actually merge.\n *\n * `target.where` is the delta's repo-relative path so a reader is sent to the\n * file they wrote, and `target.subject` is the capability id so a `--json`\n * consumer groups by promise rather than by path — the same split every other\n * capability grade uses.\n */\nexport function capabilityDocIssues(reqs: Requirement[], target: CapabilityTarget): Issue[] {\n const merging = reqs.filter((r) => r.kind === \"ADDED\" || r.kind === \"MODIFIED\");\n return capabilityDocFindings(merging, target.subject, target.where);\n}\n"]}
|