@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,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a person is shown before they answer a sampled vouch's question, and
|
|
3
|
+
* the additive `--json` shape of what it stamped.
|
|
4
|
+
*
|
|
5
|
+
* The reading list is the whole interface of `--sample <n>`: the sections
|
|
6
|
+
* picked, where they start, the preamble that is always read, and — said
|
|
7
|
+
* plainly, before the prompt rather than after the stamp — that the sections
|
|
8
|
+
* NOT listed will have been read by nobody, and what every later surface will
|
|
9
|
+
* say about that. A flag that quietly reduces assurance would be a bad trade;
|
|
10
|
+
* one that states the reduction to the person making it is the trade this
|
|
11
|
+
* feature is.
|
|
12
|
+
*
|
|
13
|
+
* Kept out of `vouch.ts` because that file is the flag boundary and is at its
|
|
14
|
+
* line limit, and out of `plan.ts` because a derivation that prints cannot be
|
|
15
|
+
* called by the reading pack, which renders the same sample its own way.
|
|
16
|
+
*/
|
|
17
|
+
import { plural } from "../../policy/format.js";
|
|
18
|
+
/** `spec.md:42` — a body-relative section line put back on the file it came from. */
|
|
19
|
+
function sectionAt(axis, line) {
|
|
20
|
+
return `${axis.file}:${line + axis.lineOffset}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The sampled claim in one sentence, for the reading list and the prompt: what
|
|
24
|
+
* will be stamped, and what every later reader will therefore say.
|
|
25
|
+
*/
|
|
26
|
+
function claim(axis, service) {
|
|
27
|
+
return (`${axis.file} will be stamped \`vouch_scope: sampled ${axis.picked.length}/${axis.of} seed=${axis.seed}\` — ` +
|
|
28
|
+
`the other ${plural(axis.of - axis.picked.length, "section")} will have been read by nobody. \`loam list\` shows ` +
|
|
29
|
+
`it as \`vouched (sampled)\` and \`loam validate\` reports \`sources.sampled-vouch\` until a person runs a full ` +
|
|
30
|
+
`\`loam vouch --service ${service}\`.`);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The reading list, printed before the confirmation. Text mode only — a
|
|
34
|
+
* `--json` run cannot be asked a question at all (`vouch-unattended`), so
|
|
35
|
+
* there is nobody on the other end of this list.
|
|
36
|
+
*/
|
|
37
|
+
export function printReadingList(plan, service) {
|
|
38
|
+
console.log(`\n${service} — sampled vouch: ${plural(plan.n, "section")} per spec file. Read what is listed here.\n`);
|
|
39
|
+
for (const axis of plan.axes) {
|
|
40
|
+
if (axis.mode === "full") {
|
|
41
|
+
// Said, not skipped: somebody who asked for a sample of four and got the
|
|
42
|
+
// whole document needs to know which of the two they are vouching for.
|
|
43
|
+
console.log(` ${axis.file} — ${plural(axis.of, "section")}, at or under the sample: the whole file is the read, ` +
|
|
44
|
+
`and it is stamped as an ordinary vouch with no scope.\n`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
console.log(` ${axis.file} — ${axis.picked.length} of ${plural(axis.of, "section")}, seed=${axis.seed}`);
|
|
48
|
+
console.log(` the preamble above the first heading — always read, never part of the count`);
|
|
49
|
+
for (const section of axis.picked)
|
|
50
|
+
console.log(` ${sectionAt(axis, section.line)} ${section.heading}`);
|
|
51
|
+
// The FULL declared sources, deliberately not a sample of them: nothing in
|
|
52
|
+
// loam maps a source file to a doc section, and inventing that mapping
|
|
53
|
+
// ("these files back those sections") is exactly the meaning-derivation
|
|
54
|
+
// this tool refuses to do. The sample is of sections; the digest still
|
|
55
|
+
// covers every source, and so does the claim.
|
|
56
|
+
console.log(` sources — ${axis.sources.entries.length} entr${axis.sources.entries.length === 1 ? "y" : "ies"}, ${plural(axis.sources.files, "file")}, all of them under the stamp:`);
|
|
57
|
+
for (const entry of axis.sources.entries)
|
|
58
|
+
console.log(` ${entry}`);
|
|
59
|
+
console.log("");
|
|
60
|
+
}
|
|
61
|
+
for (const axis of plan.axes)
|
|
62
|
+
if (axis.mode === "sampled")
|
|
63
|
+
console.log(` ${claim(axis, service)}\n`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The sampled half of the confirmation's own text, so the question a person
|
|
67
|
+
* answers names the same sections the list above it did.
|
|
68
|
+
*/
|
|
69
|
+
export function promptClaim(plan, service) {
|
|
70
|
+
// A type predicate, not a bare `.filter`: TypeScript does not narrow a union
|
|
71
|
+
// through `filter`, and the alternative at the two use sites below is a cast
|
|
72
|
+
// or a second impossible branch — both of which are a way to be wrong about
|
|
73
|
+
// which arm this is.
|
|
74
|
+
const sampled = plan.axes.filter((axis) => axis.mode === "sampled");
|
|
75
|
+
if (sampled.length === 0) {
|
|
76
|
+
return ("You asked for a sample, and it covers every section of every file — so this is an ordinary full vouch " +
|
|
77
|
+
"and nothing will record a partial read.");
|
|
78
|
+
}
|
|
79
|
+
return [
|
|
80
|
+
`You are vouching for a SAMPLE: ${sampled
|
|
81
|
+
.map((axis) => `${axis.file} ${axis.picked.length}/${axis.of}`)
|
|
82
|
+
.join(", ")}. Everything else stays unread, and the document will say so.`,
|
|
83
|
+
...sampled.map((axis) => claim(axis, service)),
|
|
84
|
+
].join("\n");
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The additive `vouchScope` payload — the stamped scope plus the headings it
|
|
88
|
+
* chose, so a consumer never has to re-derive the sample to find out what was
|
|
89
|
+
* read. Null for a file vouched in full, because that IS the whole answer for
|
|
90
|
+
* one, and a consumer that omitted the key could not tell it from an older
|
|
91
|
+
* loam that never wrote one.
|
|
92
|
+
*/
|
|
93
|
+
export function scopeJson(scope, axis) {
|
|
94
|
+
if (scope === null)
|
|
95
|
+
return null;
|
|
96
|
+
return {
|
|
97
|
+
mode: "sampled",
|
|
98
|
+
sections: scope.sections,
|
|
99
|
+
of: scope.of,
|
|
100
|
+
seed: scope.seed,
|
|
101
|
+
// Joined by file at the call site; an axis that does not answer leaves the
|
|
102
|
+
// headings out rather than inventing them — the seed and the counts are
|
|
103
|
+
// still enough to recompute the list.
|
|
104
|
+
...(axis === undefined || axis.mode !== "sampled"
|
|
105
|
+
? {}
|
|
106
|
+
: { headings: axis.picked.map((section) => section.heading) }),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=print.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print.js","sourceRoot":"","sources":["../../../../src/commands/vouch/sample/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a person is shown before they answer a sampled vouch's question, and\n * the additive `--json` shape of what it stamped.\n *\n * The reading list is the whole interface of `--sample <n>`: the sections\n * picked, where they start, the preamble that is always read, and — said\n * plainly, before the prompt rather than after the stamp — that the sections\n * NOT listed will have been read by nobody, and what every later surface will\n * say about that. A flag that quietly reduces assurance would be a bad trade;\n * one that states the reduction to the person making it is the trade this\n * feature is.\n *\n * Kept out of `vouch.ts` because that file is the flag boundary and is at its\n * line limit, and out of `plan.ts` because a derivation that prints cannot be\n * called by the reading pack, which renders the same sample its own way.\n */\nimport { plural } from \"../../policy/format.js\";\nimport type { VouchScope } from \"../../../core/provenance/sample/scope.js\";\nimport type { PlannedAxis, SamplePlan } from \"./plan.js\";\n\n/** `spec.md:42` — a body-relative section line put back on the file it came from. */\nfunction sectionAt(axis: PlannedAxis, line: number): string {\n return `${axis.file}:${line + axis.lineOffset}`;\n}\n\n/**\n * The sampled claim in one sentence, for the reading list and the prompt: what\n * will be stamped, and what every later reader will therefore say.\n */\nfunction claim(axis: PlannedAxis & { mode: \"sampled\" }, service: string): string {\n return (\n `${axis.file} will be stamped \\`vouch_scope: sampled ${axis.picked.length}/${axis.of} seed=${axis.seed}\\` — ` +\n `the other ${plural(axis.of - axis.picked.length, \"section\")} will have been read by nobody. \\`loam list\\` shows ` +\n `it as \\`vouched (sampled)\\` and \\`loam validate\\` reports \\`sources.sampled-vouch\\` until a person runs a full ` +\n `\\`loam vouch --service ${service}\\`.`\n );\n}\n\n/**\n * The reading list, printed before the confirmation. Text mode only — a\n * `--json` run cannot be asked a question at all (`vouch-unattended`), so\n * there is nobody on the other end of this list.\n */\nexport function printReadingList(plan: SamplePlan, service: string): void {\n console.log(`\\n${service} — sampled vouch: ${plural(plan.n, \"section\")} per spec file. Read what is listed here.\\n`);\n for (const axis of plan.axes) {\n if (axis.mode === \"full\") {\n // Said, not skipped: somebody who asked for a sample of four and got the\n // whole document needs to know which of the two they are vouching for.\n console.log(\n ` ${axis.file} — ${plural(axis.of, \"section\")}, at or under the sample: the whole file is the read, ` +\n `and it is stamped as an ordinary vouch with no scope.\\n`,\n );\n continue;\n }\n console.log(` ${axis.file} — ${axis.picked.length} of ${plural(axis.of, \"section\")}, seed=${axis.seed}`);\n console.log(` the preamble above the first heading — always read, never part of the count`);\n for (const section of axis.picked) console.log(` ${sectionAt(axis, section.line)} ${section.heading}`);\n // The FULL declared sources, deliberately not a sample of them: nothing in\n // loam maps a source file to a doc section, and inventing that mapping\n // (\"these files back those sections\") is exactly the meaning-derivation\n // this tool refuses to do. The sample is of sections; the digest still\n // covers every source, and so does the claim.\n console.log(\n ` sources — ${axis.sources.entries.length} entr${axis.sources.entries.length === 1 ? \"y\" : \"ies\"}, ${plural(axis.sources.files, \"file\")}, all of them under the stamp:`,\n );\n for (const entry of axis.sources.entries) console.log(` ${entry}`);\n console.log(\"\");\n }\n for (const axis of plan.axes) if (axis.mode === \"sampled\") console.log(` ${claim(axis, service)}\\n`);\n}\n\n/**\n * The sampled half of the confirmation's own text, so the question a person\n * answers names the same sections the list above it did.\n */\nexport function promptClaim(plan: SamplePlan, service: string): string {\n // A type predicate, not a bare `.filter`: TypeScript does not narrow a union\n // through `filter`, and the alternative at the two use sites below is a cast\n // or a second impossible branch — both of which are a way to be wrong about\n // which arm this is.\n const sampled = plan.axes.filter((axis): axis is PlannedAxis & { mode: \"sampled\" } => axis.mode === \"sampled\");\n if (sampled.length === 0) {\n return (\n \"You asked for a sample, and it covers every section of every file — so this is an ordinary full vouch \" +\n \"and nothing will record a partial read.\"\n );\n }\n return [\n `You are vouching for a SAMPLE: ${sampled\n .map((axis) => `${axis.file} ${axis.picked.length}/${axis.of}`)\n .join(\", \")}. Everything else stays unread, and the document will say so.`,\n ...sampled.map((axis) => claim(axis, service)),\n ].join(\"\\n\");\n}\n\n/**\n * The additive `vouchScope` payload — the stamped scope plus the headings it\n * chose, so a consumer never has to re-derive the sample to find out what was\n * read. Null for a file vouched in full, because that IS the whole answer for\n * one, and a consumer that omitted the key could not tell it from an older\n * loam that never wrote one.\n */\nexport function scopeJson(scope: VouchScope | null, axis: PlannedAxis | undefined): Record<string, unknown> | null {\n if (scope === null) return null;\n return {\n mode: \"sampled\",\n sections: scope.sections,\n of: scope.of,\n seed: scope.seed,\n // Joined by file at the call site; an axis that does not answer leaves the\n // headings out rather than inventing them — the seed and the counts are\n // still enough to recompute the list.\n ...(axis === undefined || axis.mode !== \"sampled\"\n ? {}\n : { headings: axis.picked.map((section) => section.heading) }),\n };\n}\n"]}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does this spec still describe the code it points at?
|
|
3
|
+
*
|
|
4
|
+
* One spec, read against the sources it declares. It answers only about what it
|
|
5
|
+
* could check, and says which sources it skipped — a vouch over a spec whose
|
|
6
|
+
* sources could not be read would be the claim this command exists to prevent.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { listField, parseFrontmatter } from "../../../core/document/frontmatter.js";
|
|
10
|
+
import { missingSources, patternSources, unsafeSources } from "../../../core/provenance/sources.js";
|
|
11
|
+
import { emptySourcesMessage, sourcesDigest } from "../../../core/provenance/stamp.js";
|
|
12
|
+
import { SPEC_AXES } from "../../../core/repo/paths.js";
|
|
13
|
+
import { locateServicePaths } from "../../../core/repo/service-target.js";
|
|
14
|
+
import { NotUtf8Error, readUtf8 } from "../../../core/staging/writes.js";
|
|
15
|
+
/**
|
|
16
|
+
* "There is no living spec here", in one sentence.
|
|
17
|
+
*
|
|
18
|
+
* Three callers reach this state independently — the stamp (`../run.ts`), the
|
|
19
|
+
* reading list (`../sample/plan.ts`), both now through `verifyAxes` below, and
|
|
20
|
+
* the reading pack (`../pack/pack.ts`) — and two of them carried a comment
|
|
21
|
+
* promising to keep the wording identical to the third, which is a promise
|
|
22
|
+
* nothing could enforce. It lives in the leaf all three already import,
|
|
23
|
+
* because the failure this repo has actually shipped is four copies of an
|
|
24
|
+
* enumeration `catch` that looked identical for years while a fix landed in
|
|
25
|
+
* one of them: a `--sample` run refusing a missing spec with older advice than
|
|
26
|
+
* a bare run gives is the same defect, one flag wide.
|
|
27
|
+
*/
|
|
28
|
+
export function noLivingSpecMessage(specPath, service) {
|
|
29
|
+
return `No living spec at ${specPath}. Run \`loam adopt\` for '${service}' first.`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The axis walk the stamp (`../run.ts`) and the reading list
|
|
33
|
+
* (`../sample/plan.ts`) both make, spelled once: spec.md is required,
|
|
34
|
+
* arch.spec.md rides when it exists, and one file that cannot be verified
|
|
35
|
+
* refuses the walk before the next is read — so a stamp writes nothing and a
|
|
36
|
+
* person is asked to read nothing.
|
|
37
|
+
*
|
|
38
|
+
* Walked by name rather than accumulated in a loop, because every caller
|
|
39
|
+
* needs to know WHICH file it is holding — the required one or the optional
|
|
40
|
+
* one — and a loop can only say that positionally. Sequential, not
|
|
41
|
+
* Promise.all: each verification hashes a whole source tree through the
|
|
42
|
+
* batched digest, and two of those in flight at once doubles the file
|
|
43
|
+
* descriptors that batching exists to bound. Two files.
|
|
44
|
+
*/
|
|
45
|
+
export async function verifyAxes(req) {
|
|
46
|
+
const paths = await locateServicePaths(req.docsDir, req.service);
|
|
47
|
+
if (!existsSync(paths.spec)) {
|
|
48
|
+
return { ok: false, code: "unknown-target", message: noLivingSpecMessage(paths.spec, req.service) };
|
|
49
|
+
}
|
|
50
|
+
const [specAxis, archAxis] = SPEC_AXES;
|
|
51
|
+
const spec = await verifySpec(req, paths[specAxis.key], specAxis.file);
|
|
52
|
+
if (!spec.ok)
|
|
53
|
+
return spec;
|
|
54
|
+
if (!existsSync(paths[archAxis.key]))
|
|
55
|
+
return { ok: true, spec, arch: null };
|
|
56
|
+
const arch = await verifySpec(req, paths[archAxis.key], archAxis.file);
|
|
57
|
+
return arch.ok ? { ok: true, spec, arch } : arch;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The per-file half of the refusal discipline: everything vouch cannot verify
|
|
61
|
+
* about ONE spec file, checked the same way for spec.md and arch.spec.md.
|
|
62
|
+
*/
|
|
63
|
+
export async function verifySpec(req, path, file) {
|
|
64
|
+
// Through readUtf8, so the round trip below is exact: the stamp is computed
|
|
65
|
+
// from `raw` and the race check compares `Buffer.from(raw)` against the bytes
|
|
66
|
+
// on disk, which only agree if the file decoded without substitutions. A
|
|
67
|
+
// non-UTF-8 spec is refused by name rather than stamped as verified with
|
|
68
|
+
// every undecodable byte replaced. Refused HERE rather than left to the CLI's
|
|
69
|
+
// top-level handler, which would report a diagnosable state as `internal`.
|
|
70
|
+
// What it replaces is a diagnosis that was worse than none: a UTF-16 spec
|
|
71
|
+
// decoded to a document with no frontmatter loam could find, so vouch refused
|
|
72
|
+
// it as `sources-absent` — "names no sources" — over a file whose `sources:`
|
|
73
|
+
// line is right there.
|
|
74
|
+
let raw;
|
|
75
|
+
try {
|
|
76
|
+
raw = await readUtf8(path);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (!(err instanceof NotUtf8Error))
|
|
80
|
+
throw err;
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
code: "repository-unavailable",
|
|
84
|
+
message: `${req.service}: ${file} cannot be vouched for — ${err.message}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const fm = parseFrontmatter(raw);
|
|
88
|
+
// Before any sources reasoning: a header that does not parse hides whatever
|
|
89
|
+
// fields the author wrote, so "names no sources" would be a false diagnosis —
|
|
90
|
+
// and if the file ever reached the stamp, withFrontmatterFields' rule for
|
|
91
|
+
// unreadable headers is replace-don't-merge, which would silently discard the
|
|
92
|
+
// author's owner/service/sources lines. Refuse before the write path can see
|
|
93
|
+
// the file. The code stays `sources-absent` — for vouch's purposes the
|
|
94
|
+
// sources ARE unreadable-hence-absent, and the message carries the real
|
|
95
|
+
// diagnosis — rather than minting a new ErrorCode for one refusal.
|
|
96
|
+
if (fm.malformed) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
code: "sources-absent",
|
|
100
|
+
message: `${req.service}: ${file} has a frontmatter block that cannot be read as YAML — ` +
|
|
101
|
+
`its fields (\`sources\` included) are unreadable, and stamping would rewrite the header wholesale, ` +
|
|
102
|
+
`losing what the author wrote. Fix the YAML between the \`---\` fences ` +
|
|
103
|
+
`(\`loam validate\` reports it as \`frontmatter.malformed\`), then re-run.`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const sources = listField(fm, "sources");
|
|
107
|
+
if (sources.length === 0) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
code: "sources-absent",
|
|
111
|
+
message: `${req.service}: ${file} names no sources — there is nothing to vouch it against. Add \`sources:\` naming the code it was written from.`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// spec.md's refusals predate the second axis and keep their exact wording;
|
|
115
|
+
// where they did not name the file, only the newer axis adds it.
|
|
116
|
+
const label = file === "spec.md" ? req.service : `${req.service}: ${file}`;
|
|
117
|
+
// Before the existence check: a pattern is not a path that "does not exist",
|
|
118
|
+
// it is an entry loam no longer reads at all, and the refusal has to say so.
|
|
119
|
+
const patterns = patternSources(sources);
|
|
120
|
+
if (patterns.length > 0) {
|
|
121
|
+
return {
|
|
122
|
+
ok: false,
|
|
123
|
+
code: "sources-path-missing",
|
|
124
|
+
message: `${label}: ${patterns.length} source(s) are glob patterns — ${patterns.join(", ")}. Patterns are no longer supported: name files or directories (a directory already covers everything beneath it). A stamp over a pattern would vouch for a file set nobody can be sure of.`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const unsafe = unsafeSources(req.repoDir, sources);
|
|
128
|
+
if (unsafe.length > 0) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
code: "sources-path-missing",
|
|
132
|
+
message: `${label}: ${unsafe.length} source(s) escape the service repo — ${unsafe.join(", ")}. Sources must be relative paths contained by this repository, including through symlinks; vouch will not hash files outside it.`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const missing = missingSources(req.repoDir, sources);
|
|
136
|
+
if (missing.length > 0) {
|
|
137
|
+
return {
|
|
138
|
+
ok: false,
|
|
139
|
+
code: "sources-path-missing",
|
|
140
|
+
message: `${label}: ${missing.length} source(s) do not exist — ${missing.join(", ")}. Vouching now would stamp a claim about code that is not there.`,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const { digest, index, skipped } = await sourcesDigest(req.repoDir, sources);
|
|
144
|
+
if (index.length === 0) {
|
|
145
|
+
// A directory that exists but holds no files — or only ones the walk leaves
|
|
146
|
+
// out: dot-entries, `node_modules`, anything the repository itself ignores.
|
|
147
|
+
// The paths "resolve", but a digest over nothing never changes, so the stamp
|
|
148
|
+
// would read as current forever. The sentence comes from provenance/stamp.ts so
|
|
149
|
+
// that `loam validate` can grade the same state in the same words instead of
|
|
150
|
+
// going green on a document this command refuses.
|
|
151
|
+
return { ok: false, code: "sources-absent", message: emptySourcesMessage(label, sources) };
|
|
152
|
+
}
|
|
153
|
+
return { ok: true, path, file, raw, sources, digest, index, skipped };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../../src/commands/vouch/vet/verify.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Does this spec still describe the code it points at?\n *\n * One spec, read against the sources it declares. It answers only about what it\n * could check, and says which sources it skipped — a vouch over a spec whose\n * sources could not be read would be the claim this command exists to prevent.\n */\nimport { existsSync } from \"node:fs\";\nimport { listField, parseFrontmatter } from \"../../../core/document/frontmatter.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport type { PathableService } from \"../../../core/kernel/ids/service.js\";\nimport { missingSources, patternSources, unsafeSources } from \"../../../core/provenance/sources.js\";\nimport { emptySourcesMessage, sourcesDigest, type SourceIndexEntry } from \"../../../core/provenance/stamp.js\";\nimport type { SkippedSource } from \"../../../core/provenance/walk.js\";\nimport { SPEC_AXES } from \"../../../core/repo/paths.js\";\nimport { locateServicePaths } from \"../../../core/repo/service-target.js\";\nimport { NotUtf8Error, readUtf8 } from \"../../../core/staging/writes.js\";\n\n/** A spec-axis file whose sources all check out, carrying what the stamp needs. */\nexport interface VerifiedSpec {\n ok: true;\n path: string;\n file: string;\n /** The file exactly as read — what the stamp is applied to. */\n raw: string;\n sources: string[];\n digest: string;\n /** Per-file shas, in digest order — what `sources_files` is stamped from. */\n index: SourceIndexEntry[];\n skipped: SkippedSource[];\n}\n\n/**\n * The two facts the vetting reads — not the whole VouchRequest, because the\n * reading pack (`../pack/pack.ts`) asks the same questions with no date or\n * identity to offer: a pack stamps nothing.\n */\nexport interface SpecVetting {\n service: PathableService;\n repoDir: string;\n}\n\n/**\n * The refusal half, spelled here rather than imported from `../contract.ts`:\n * this module is a LEAF two sibling consumers share — `run.ts` (the stamp) and\n * `pack/pack.ts` (the worklist) — which is why it lives in its own package,\n * and an import from the vouch package above it would close the exact\n * package-graph cycle the move exists to avoid. The codes are a subset of\n * VouchOutcome's refusal codes, so run.ts returns one of these unchanged.\n */\nexport interface SpecRefusal {\n ok: false;\n code: \"sources-absent\" | \"sources-path-missing\" | \"repository-unavailable\";\n message: string;\n}\n\n/**\n * \"There is no living spec here\", in one sentence.\n *\n * Three callers reach this state independently — the stamp (`../run.ts`), the\n * reading list (`../sample/plan.ts`), both now through `verifyAxes` below, and\n * the reading pack (`../pack/pack.ts`) — and two of them carried a comment\n * promising to keep the wording identical to the third, which is a promise\n * nothing could enforce. It lives in the leaf all three already import,\n * because the failure this repo has actually shipped is four copies of an\n * enumeration `catch` that looked identical for years while a fix landed in\n * one of them: a `--sample` run refusing a missing spec with older advice than\n * a bare run gives is the same defect, one flag wide.\n */\nexport function noLivingSpecMessage(specPath: string, service: string): string {\n return `No living spec at ${specPath}. Run \\`loam adopt\\` for '${service}' first.`;\n}\n\n/** Every spec-axis file of one service, verified: spec.md always, arch.spec.md when it exists. */\nexport interface VerifiedAxes {\n ok: true;\n spec: VerifiedSpec;\n arch: VerifiedSpec | null;\n}\n\n/** The walk's refusals: one file's vetting, or no spec.md to vet at all. */\nexport type AxesRefusal = SpecRefusal | { ok: false; code: \"unknown-target\"; message: string };\n\n/**\n * The axis walk the stamp (`../run.ts`) and the reading list\n * (`../sample/plan.ts`) both make, spelled once: spec.md is required,\n * arch.spec.md rides when it exists, and one file that cannot be verified\n * refuses the walk before the next is read — so a stamp writes nothing and a\n * person is asked to read nothing.\n *\n * Walked by name rather than accumulated in a loop, because every caller\n * needs to know WHICH file it is holding — the required one or the optional\n * one — and a loop can only say that positionally. Sequential, not\n * Promise.all: each verification hashes a whole source tree through the\n * batched digest, and two of those in flight at once doubles the file\n * descriptors that batching exists to bound. Two files.\n */\nexport async function verifyAxes(req: SpecVetting & { docsDir: DocsDir }): Promise<VerifiedAxes | AxesRefusal> {\n const paths = await locateServicePaths(req.docsDir, req.service);\n if (!existsSync(paths.spec)) {\n return { ok: false, code: \"unknown-target\", message: noLivingSpecMessage(paths.spec, req.service) };\n }\n const [specAxis, archAxis] = SPEC_AXES;\n const spec = await verifySpec(req, paths[specAxis.key], specAxis.file);\n if (!spec.ok) return spec;\n if (!existsSync(paths[archAxis.key])) return { ok: true, spec, arch: null };\n const arch = await verifySpec(req, paths[archAxis.key], archAxis.file);\n return arch.ok ? { ok: true, spec, arch } : arch;\n}\n\n/**\n * The per-file half of the refusal discipline: everything vouch cannot verify\n * about ONE spec file, checked the same way for spec.md and arch.spec.md.\n */\nexport async function verifySpec(\n req: SpecVetting,\n path: string,\n file: string,\n): Promise<VerifiedSpec | SpecRefusal> {\n // Through readUtf8, so the round trip below is exact: the stamp is computed\n // from `raw` and the race check compares `Buffer.from(raw)` against the bytes\n // on disk, which only agree if the file decoded without substitutions. A\n // non-UTF-8 spec is refused by name rather than stamped as verified with\n // every undecodable byte replaced. Refused HERE rather than left to the CLI's\n // top-level handler, which would report a diagnosable state as `internal`.\n // What it replaces is a diagnosis that was worse than none: a UTF-16 spec\n // decoded to a document with no frontmatter loam could find, so vouch refused\n // it as `sources-absent` — \"names no sources\" — over a file whose `sources:`\n // line is right there.\n let raw: string;\n try {\n raw = await readUtf8(path);\n } catch (err) {\n if (!(err instanceof NotUtf8Error)) throw err;\n return {\n ok: false,\n code: \"repository-unavailable\",\n message: `${req.service}: ${file} cannot be vouched for — ${err.message}`,\n };\n }\n const fm = parseFrontmatter(raw);\n // Before any sources reasoning: a header that does not parse hides whatever\n // fields the author wrote, so \"names no sources\" would be a false diagnosis —\n // and if the file ever reached the stamp, withFrontmatterFields' rule for\n // unreadable headers is replace-don't-merge, which would silently discard the\n // author's owner/service/sources lines. Refuse before the write path can see\n // the file. The code stays `sources-absent` — for vouch's purposes the\n // sources ARE unreadable-hence-absent, and the message carries the real\n // diagnosis — rather than minting a new ErrorCode for one refusal.\n if (fm.malformed) {\n return {\n ok: false,\n code: \"sources-absent\",\n message:\n `${req.service}: ${file} has a frontmatter block that cannot be read as YAML — ` +\n `its fields (\\`sources\\` included) are unreadable, and stamping would rewrite the header wholesale, ` +\n `losing what the author wrote. Fix the YAML between the \\`---\\` fences ` +\n `(\\`loam validate\\` reports it as \\`frontmatter.malformed\\`), then re-run.`,\n };\n }\n const sources = listField(fm, \"sources\");\n if (sources.length === 0) {\n return {\n ok: false,\n code: \"sources-absent\",\n message: `${req.service}: ${file} names no sources — there is nothing to vouch it against. Add \\`sources:\\` naming the code it was written from.`,\n };\n }\n\n // spec.md's refusals predate the second axis and keep their exact wording;\n // where they did not name the file, only the newer axis adds it.\n const label = file === \"spec.md\" ? req.service : `${req.service}: ${file}`;\n\n // Before the existence check: a pattern is not a path that \"does not exist\",\n // it is an entry loam no longer reads at all, and the refusal has to say so.\n const patterns = patternSources(sources);\n if (patterns.length > 0) {\n return {\n ok: false,\n code: \"sources-path-missing\",\n message: `${label}: ${patterns.length} source(s) are glob patterns — ${patterns.join(\", \")}. Patterns are no longer supported: name files or directories (a directory already covers everything beneath it). A stamp over a pattern would vouch for a file set nobody can be sure of.`,\n };\n }\n\n const unsafe = unsafeSources(req.repoDir, sources);\n if (unsafe.length > 0) {\n return {\n ok: false,\n code: \"sources-path-missing\",\n message: `${label}: ${unsafe.length} source(s) escape the service repo — ${unsafe.join(\", \")}. Sources must be relative paths contained by this repository, including through symlinks; vouch will not hash files outside it.`,\n };\n }\n\n const missing = missingSources(req.repoDir, sources);\n if (missing.length > 0) {\n return {\n ok: false,\n code: \"sources-path-missing\",\n message: `${label}: ${missing.length} source(s) do not exist — ${missing.join(\", \")}. Vouching now would stamp a claim about code that is not there.`,\n };\n }\n\n const { digest, index, skipped } = await sourcesDigest(req.repoDir, sources);\n if (index.length === 0) {\n // A directory that exists but holds no files — or only ones the walk leaves\n // out: dot-entries, `node_modules`, anything the repository itself ignores.\n // The paths \"resolve\", but a digest over nothing never changes, so the stamp\n // would read as current forever. The sentence comes from provenance/stamp.ts so\n // that `loam validate` can grade the same state in the same words instead of\n // going green on a document this command refuses.\n return { ok: false, code: \"sources-absent\", message: emptySourcesMessage(label, sources) };\n }\n return { ok: true, path, file, raw, sources, digest, index, skipped };\n}\n"]}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { configOrRefuse, fail, NO_SERVICE_MESSAGE } from "../../core/envelope/json.js";
|
|
2
|
+
import { gitIdentity } from "../../core/provenance/git.js";
|
|
3
|
+
import { today } from "../../core/provenance/stamp.js";
|
|
4
|
+
import { serviceTreePathOf } from "../../core/repo/service-target.js";
|
|
5
|
+
import { runPack } from "./pack/print.js";
|
|
6
|
+
import { confirmVouch } from "./prompt/confirm.js";
|
|
7
|
+
import { emitStampJson, printStamp } from "./report.js";
|
|
8
|
+
import { vouch } from "./run.js";
|
|
9
|
+
import { buildSamplePlan } from "./sample/plan.js";
|
|
10
|
+
import { printReadingList } from "./sample/print.js";
|
|
11
|
+
export function registerVouch(program) {
|
|
12
|
+
program
|
|
13
|
+
.command("vouch")
|
|
14
|
+
.description("Vouch for a service's living specs: stamp spec.md, and arch.spec.md when present, verified against the code they describe")
|
|
15
|
+
.option("--service <id>", "service to vouch for (defaults to the configured service)")
|
|
16
|
+
.option("--yes", "skip the confirmation — required when stdin is not a terminal, and still records `vouched_by`")
|
|
17
|
+
.option("--pack", "print the re-vouch reading pack — the doc-body diff since the last vouch, the source files that moved, and the sections already covered — then exit without vouching; read-only, nothing is stamped")
|
|
18
|
+
.option("--sample <n>", "vouch after reading a deterministic sample of <n> sections per spec file — the stamp records `vouch_scope: sampled`, `loam list` shows `vouched (sampled)`, and `loam validate` reports `sources.sampled-vouch` until a full vouch clears it")
|
|
19
|
+
.option("--json", "emit the machine contract instead of the human view")
|
|
20
|
+
.action(async (opts) => {
|
|
21
|
+
const json = opts.json === true;
|
|
22
|
+
const config = await configOrRefuse(json);
|
|
23
|
+
if (config === null)
|
|
24
|
+
return;
|
|
25
|
+
const service = opts.service ?? config.service;
|
|
26
|
+
if (service === undefined) {
|
|
27
|
+
return fail(json, "invalid-option", NO_SERVICE_MESSAGE);
|
|
28
|
+
}
|
|
29
|
+
// Vouching hashes the code the doc was written from, so it can only run
|
|
30
|
+
// where that code is. From anywhere else the paths are someone else's.
|
|
31
|
+
//
|
|
32
|
+
// TWO conditions, two codes, and the split is the whole point. Both used
|
|
33
|
+
// to answer `invalid-option`, whose `loam explain` row says the
|
|
34
|
+
// invocation itself is wrong — contradictory flags, a mistyped one, a
|
|
35
|
+
// value that cannot be right. Here the invocation is perfectly correct
|
|
36
|
+
// and the REPOSITORY is the wrong one, so that code sent a user whose
|
|
37
|
+
// flags were fine off to re-read their flags, and left CI and agents
|
|
38
|
+
// unable to tell "run this in the service repo" from "you typed the flag
|
|
39
|
+
// wrong". `loam verify --record --service` already draws exactly this
|
|
40
|
+
// line for exactly this reason (see commands/verify/verify.ts); vouch
|
|
41
|
+
// and gherkin now answer the same pair, so a caller branching on
|
|
42
|
+
// `error.code` gets one answer from all three. The messages are
|
|
43
|
+
// unchanged — only the code moved.
|
|
44
|
+
if (config.service === undefined) {
|
|
45
|
+
return fail(json, "repository-unavailable", `Cannot vouch for '${service}' from here: this is not a service repo. \`sources\` resolve against the service's own repo — run it there.`);
|
|
46
|
+
}
|
|
47
|
+
if (config.service !== service) {
|
|
48
|
+
return fail(json, "service-mismatch", `Cannot vouch for '${service}' from here: this repo is '${config.service}'. \`sources\` resolve against the service's own repo — run it there.`);
|
|
49
|
+
}
|
|
50
|
+
// The repo root, not the cwd — see the comment on `repoDir` below; the
|
|
51
|
+
// identity has to be asked of the same directory the sources resolve in,
|
|
52
|
+
// or a subdirectory with its own git config would answer for it.
|
|
53
|
+
const repoDir = config.root ?? process.cwd();
|
|
54
|
+
// The flag's own grammar, before anything is read or hashed: `--sample`
|
|
55
|
+
// decides what the run CLAIMS, so a value nobody can read must not reach
|
|
56
|
+
// a stamp. Whole numbers only, and at least one — `0` is a vouch that
|
|
57
|
+
// read nothing, and there is already a way to record that (do not
|
|
58
|
+
// vouch). Checked before `--pack` below so a typo is refused the same
|
|
59
|
+
// way in both modes.
|
|
60
|
+
let sampleSize;
|
|
61
|
+
if (opts.sample !== undefined) {
|
|
62
|
+
if (!/^\d+$/.test(opts.sample.trim()) || Number(opts.sample) < 1) {
|
|
63
|
+
return fail(json, "invalid-option", `--sample expects a positive whole number of sections; got '${opts.sample}'. ` +
|
|
64
|
+
"Nothing was read and nothing was stamped.");
|
|
65
|
+
}
|
|
66
|
+
sampleSize = Number(opts.sample);
|
|
67
|
+
}
|
|
68
|
+
// The reading pack: read-only, so it runs BEFORE — and instead of —
|
|
69
|
+
// every write-path gate below (identity, TTY, `--yes`, lock, journal),
|
|
70
|
+
// which all defend the stamp; pack/pack.ts's banner carries the full
|
|
71
|
+
// reasoning. It runs AFTER the wrong-repo gate above on purpose: the
|
|
72
|
+
// source delta resolves `sources` here. `--yes` does not compose — it
|
|
73
|
+
// is the unattended stamp, and a pack that stamped would defeat the
|
|
74
|
+
// read it just prescribed.
|
|
75
|
+
if (opts.pack === true) {
|
|
76
|
+
if (opts.yes === true) {
|
|
77
|
+
return fail(json, "invalid-option", "--pack is the reading list and --yes is the unattended stamp; a pack that immediately " +
|
|
78
|
+
`stamped would defeat the read it just prescribed. Run --pack, read it, then \`loam vouch --service ${service}\`.`);
|
|
79
|
+
}
|
|
80
|
+
// `--sample` composes with the pack instead of conflicting with it:
|
|
81
|
+
// the pack is the reading list, and a sampled vouch's reading list is
|
|
82
|
+
// the sample. Passing it here makes the pack print the sections the
|
|
83
|
+
// subsequent `loam vouch --sample <n>` will stamp for — the same
|
|
84
|
+
// derivation from the same seed, so the two cannot prescribe
|
|
85
|
+
// different documents.
|
|
86
|
+
return runPack({ docsDir: config.docsDir, service: config.service, repoDir, json, sample: sampleSize });
|
|
87
|
+
}
|
|
88
|
+
// Who. Before any reading, because a run that cannot name a person has
|
|
89
|
+
// nothing to offer at the end of it and should not spend a digest finding
|
|
90
|
+
// that out.
|
|
91
|
+
const vouchedBy = await gitIdentity(repoDir);
|
|
92
|
+
if (vouchedBy === null) {
|
|
93
|
+
return fail(json, "vouch-unattributable", `Cannot vouch for '${service}': git names no \`user.email\` in ${repoDir}, so the stamp would ` +
|
|
94
|
+
"record a claim with nobody behind it — which is the one thing `status: verified` must not mean. " +
|
|
95
|
+
"Set it (`git config user.email you@example.com`) and re-run.");
|
|
96
|
+
}
|
|
97
|
+
// Whether a person is actually here — the gate the banner's "records a
|
|
98
|
+
// person" paragraph tells the history of. `vouch` is the only command in
|
|
99
|
+
// loam whose output is a claim about a HUMAN act — every other check is
|
|
100
|
+
// internal consistency, which fluent prose satisfies — and why an agent
|
|
101
|
+
// must not be able to make that claim for itself is recorded on the
|
|
102
|
+
// allowlist that no longer covers this command
|
|
103
|
+
// (core/agent/tools/dialects.ts). Nothing but a terminal or an explicit
|
|
104
|
+
// `--yes` gets past here.
|
|
105
|
+
const attended = opts.yes === true;
|
|
106
|
+
if (!attended) {
|
|
107
|
+
if (process.stdin.isTTY !== true) {
|
|
108
|
+
return fail(json, "vouch-unattended", `Cannot vouch for '${service}' with nothing on the other end of stdin: this command records that ` +
|
|
109
|
+
"a PERSON read the code and says the document matches it, and nobody was asked. Run it from a " +
|
|
110
|
+
"terminal, or pass --yes to state that you are standing behind it anyway — `vouched_by` records " +
|
|
111
|
+
`${vouchedBy} either way.`);
|
|
112
|
+
}
|
|
113
|
+
// `--json` and a prompt do not compose: the envelope is one JSON
|
|
114
|
+
// document on stdout, and a question printed beside it is not parseable
|
|
115
|
+
// by the consumer that asked for it. A JSON caller is a program, so it
|
|
116
|
+
// gets the same answer a pipe does — say so with --yes.
|
|
117
|
+
if (json) {
|
|
118
|
+
return fail(json, "vouch-unattended", `Cannot vouch for '${service}' in --json mode without --yes: the confirmation is a question for a ` +
|
|
119
|
+
"person, and it cannot be asked on a stream whose whole contract is one JSON document.");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// The reading list is built BEFORE the question and AFTER the attendance
|
|
123
|
+
// gates: a run that cannot ask anybody anything must not spend two
|
|
124
|
+
// source-tree digests finding that out, and a person must not be asked
|
|
125
|
+
// to confirm a sample nobody has shown them. Every refusal a vouch can
|
|
126
|
+
// raise about these documents fires in here, so it lands before the read
|
|
127
|
+
// rather than after it.
|
|
128
|
+
let sample;
|
|
129
|
+
if (sampleSize !== undefined) {
|
|
130
|
+
const built = await buildSamplePlan({ docsDir: config.docsDir, service: config.service, repoDir, n: sampleSize });
|
|
131
|
+
if (!built.ok)
|
|
132
|
+
return fail(json, built.code, built.message);
|
|
133
|
+
sample = built.plan;
|
|
134
|
+
if (!json)
|
|
135
|
+
printReadingList(sample, service);
|
|
136
|
+
}
|
|
137
|
+
const servicePath = await serviceTreePathOf(config.docsDir, service);
|
|
138
|
+
if (!attended && !(await confirmVouch({ service, vouchedBy, docsDir: config.docsDir, servicePath, sample }))) {
|
|
139
|
+
return fail(json, "vouch-declined", `Nothing was stamped for '${service}'.`);
|
|
140
|
+
}
|
|
141
|
+
const outcome = await vouch({
|
|
142
|
+
docsDir: config.docsDir,
|
|
143
|
+
// The guard above proved `service` IS `config.service`, and only the
|
|
144
|
+
// latter carries the parse (`loam.json`'s `service` field is validated
|
|
145
|
+
// at load). Same string, but only one spelling is pathable.
|
|
146
|
+
service: config.service,
|
|
147
|
+
vouchedBy,
|
|
148
|
+
// The repo root, not the cwd. `sources:` are spelled relative to the
|
|
149
|
+
// repository — that is what they mean in the frontmatter and what
|
|
150
|
+
// `loam validate` resolves them against — so vouching from a
|
|
151
|
+
// subdirectory used to report every real source as missing
|
|
152
|
+
// (`sources-path-missing`) and refuse the stamp. `config.root` is the
|
|
153
|
+
// directory loam.json was found in, which is the only definition of
|
|
154
|
+
// "this repo" that does not move with the caller.
|
|
155
|
+
repoDir,
|
|
156
|
+
today: today(new Date()),
|
|
157
|
+
// Absent for an ordinary vouch, which is what makes an ordinary vouch
|
|
158
|
+
// CLEAR a prior sample's scope rather than leave it standing.
|
|
159
|
+
...(sample === undefined ? {} : { sample }),
|
|
160
|
+
});
|
|
161
|
+
if (!outcome.ok)
|
|
162
|
+
return fail(json, outcome.code, outcome.message);
|
|
163
|
+
const report = { service, docsDir: config.docsDir, outcome, ...(sample === undefined ? {} : { sample }) };
|
|
164
|
+
if (json)
|
|
165
|
+
return emitStampJson(report);
|
|
166
|
+
printStamp(report);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=vouch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vouch.js","sourceRoot":"","sources":["../../../src/commands/vouch/vouch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { configOrRefuse, fail, NO_SERVICE_MESSAGE } from \"../../core/envelope/json.js\";\nimport { gitIdentity } from \"../../core/provenance/git.js\";\nimport { today } from \"../../core/provenance/stamp.js\";\nimport { serviceTreePathOf } from \"../../core/repo/service-target.js\";\nimport { runPack } from \"./pack/print.js\";\nimport { confirmVouch } from \"./prompt/confirm.js\";\nimport { emitStampJson, printStamp } from \"./report.js\";\nimport { vouch } from \"./run.js\";\nimport { buildSamplePlan, type SamplePlan } from \"./sample/plan.js\";\nimport { printReadingList } from \"./sample/print.js\";\n\n/**\n * `loam vouch` — the human act SCHEMA.md has always described as \"promote draft\n * -> verified\".\n *\n * Everything else loam checks is internal consistency, and an agent writing\n * fluent prose satisfies all of it. This is the one command that records a\n * person: they read the code, they say the document matches it, and loam stamps\n * a digest of what they read — and a digest of the document they read it\n * against, so neither side can move quietly. From then on `loam validate` can\n * tell the difference between a document nobody has checked, one that still\n * matches the code, one the code has moved out from under, and one whose own\n * prose changed after the stamp.\n *\n * \"Records a person\" was, for two releases, a thing this file said and did not\n * do. There was no `vouched_by`, no identity of any kind and no interactive\n * gate, so an agent could run it twice unattended and stamp `verified` both\n * times — while the skill files loam generates pre-approved `Bash(loam:*)`,\n * which meant the agent that wrote the draft was permitted to promote it. Three\n * things close that, and none of them is a signature: the stamp carries git's\n * `user.email` (`vouched_by`), the run refuses without a terminal or an explicit\n * `--yes`, and the generated allowlist names loam's read-only and authoring\n * verbs one by one instead of all of them (core/agent/tools/dialects.ts). What that buys is\n * attribution and a deliberate act, not proof — git config is a text file. A\n * reviewer can now ask a named person what they read, which is the question\n * `status: verified` was silently answering with nobody.\n *\n * The stamp is only worth what it claims, so vouch refuses everything it cannot\n * actually verify — a frontmatter block that will not parse (whose fields\n * nobody can read, and whose rewrite would lose the author's lines), a spec\n * with no sources, a glob pattern (no longer supported), a source that is\n * gone, a directory holding no files, or a repo that is not this service's —\n * and refuses without writing anything.\n *\n * \"The document\" is every spec-axis file the service has: spec.md always, and\n * arch.spec.md beside it when present — same frontmatter conventions, same\n * stamp, one vouch. The refusal discipline is per file but the vouch is\n * all-or-nothing per service: one unverifiable file refuses the whole run, so\n * a `verified` service never means \"half-stamped\".\n */\n\ninterface VouchOptions {\n service?: string;\n yes?: boolean;\n pack?: boolean;\n /** `--sample <n>` as typed — a string until it is proved to be a whole number. */\n sample?: string;\n json?: boolean;\n}\n\nexport function registerVouch(program: Command): void {\n program\n .command(\"vouch\")\n .description(\n \"Vouch for a service's living specs: stamp spec.md, and arch.spec.md when present, verified against the code they describe\",\n )\n .option(\"--service <id>\", \"service to vouch for (defaults to the configured service)\")\n .option(\n \"--yes\",\n \"skip the confirmation — required when stdin is not a terminal, and still records `vouched_by`\",\n )\n .option(\n \"--pack\",\n \"print the re-vouch reading pack — the doc-body diff since the last vouch, the source files that moved, and the sections already covered — then exit without vouching; read-only, nothing is stamped\",\n )\n .option(\n \"--sample <n>\",\n \"vouch after reading a deterministic sample of <n> sections per spec file — the stamp records `vouch_scope: sampled`, `loam list` shows `vouched (sampled)`, and `loam validate` reports `sources.sampled-vouch` until a full vouch clears it\",\n )\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: VouchOptions) => {\n const json = opts.json === true;\n\n const config = await configOrRefuse(json);\n if (config === null) return;\n\n const service = opts.service ?? config.service;\n if (service === undefined) {\n return fail(json, \"invalid-option\", NO_SERVICE_MESSAGE);\n }\n // Vouching hashes the code the doc was written from, so it can only run\n // where that code is. From anywhere else the paths are someone else's.\n //\n // TWO conditions, two codes, and the split is the whole point. Both used\n // to answer `invalid-option`, whose `loam explain` row says the\n // invocation itself is wrong — contradictory flags, a mistyped one, a\n // value that cannot be right. Here the invocation is perfectly correct\n // and the REPOSITORY is the wrong one, so that code sent a user whose\n // flags were fine off to re-read their flags, and left CI and agents\n // unable to tell \"run this in the service repo\" from \"you typed the flag\n // wrong\". `loam verify --record --service` already draws exactly this\n // line for exactly this reason (see commands/verify/verify.ts); vouch\n // and gherkin now answer the same pair, so a caller branching on\n // `error.code` gets one answer from all three. The messages are\n // unchanged — only the code moved.\n if (config.service === undefined) {\n return fail(\n json,\n \"repository-unavailable\",\n `Cannot vouch for '${service}' from here: this is not a service repo. \\`sources\\` resolve against the service's own repo — run it there.`,\n );\n }\n if (config.service !== service) {\n return fail(\n json,\n \"service-mismatch\",\n `Cannot vouch for '${service}' from here: this repo is '${config.service}'. \\`sources\\` resolve against the service's own repo — run it there.`,\n );\n }\n\n // The repo root, not the cwd — see the comment on `repoDir` below; the\n // identity has to be asked of the same directory the sources resolve in,\n // or a subdirectory with its own git config would answer for it.\n const repoDir = config.root ?? process.cwd();\n\n // The flag's own grammar, before anything is read or hashed: `--sample`\n // decides what the run CLAIMS, so a value nobody can read must not reach\n // a stamp. Whole numbers only, and at least one — `0` is a vouch that\n // read nothing, and there is already a way to record that (do not\n // vouch). Checked before `--pack` below so a typo is refused the same\n // way in both modes.\n let sampleSize: number | undefined;\n if (opts.sample !== undefined) {\n if (!/^\\d+$/.test(opts.sample.trim()) || Number(opts.sample) < 1) {\n return fail(\n json,\n \"invalid-option\",\n `--sample expects a positive whole number of sections; got '${opts.sample}'. ` +\n \"Nothing was read and nothing was stamped.\",\n );\n }\n sampleSize = Number(opts.sample);\n }\n\n // The reading pack: read-only, so it runs BEFORE — and instead of —\n // every write-path gate below (identity, TTY, `--yes`, lock, journal),\n // which all defend the stamp; pack/pack.ts's banner carries the full\n // reasoning. It runs AFTER the wrong-repo gate above on purpose: the\n // source delta resolves `sources` here. `--yes` does not compose — it\n // is the unattended stamp, and a pack that stamped would defeat the\n // read it just prescribed.\n if (opts.pack === true) {\n if (opts.yes === true) {\n return fail(\n json,\n \"invalid-option\",\n \"--pack is the reading list and --yes is the unattended stamp; a pack that immediately \" +\n `stamped would defeat the read it just prescribed. Run --pack, read it, then \\`loam vouch --service ${service}\\`.`,\n );\n }\n // `--sample` composes with the pack instead of conflicting with it:\n // the pack is the reading list, and a sampled vouch's reading list is\n // the sample. Passing it here makes the pack print the sections the\n // subsequent `loam vouch --sample <n>` will stamp for — the same\n // derivation from the same seed, so the two cannot prescribe\n // different documents.\n return runPack({ docsDir: config.docsDir, service: config.service, repoDir, json, sample: sampleSize });\n }\n\n // Who. Before any reading, because a run that cannot name a person has\n // nothing to offer at the end of it and should not spend a digest finding\n // that out.\n const vouchedBy = await gitIdentity(repoDir);\n if (vouchedBy === null) {\n return fail(\n json,\n \"vouch-unattributable\",\n `Cannot vouch for '${service}': git names no \\`user.email\\` in ${repoDir}, so the stamp would ` +\n \"record a claim with nobody behind it — which is the one thing `status: verified` must not mean. \" +\n \"Set it (`git config user.email you@example.com`) and re-run.\",\n );\n }\n\n // Whether a person is actually here — the gate the banner's \"records a\n // person\" paragraph tells the history of. `vouch` is the only command in\n // loam whose output is a claim about a HUMAN act — every other check is\n // internal consistency, which fluent prose satisfies — and why an agent\n // must not be able to make that claim for itself is recorded on the\n // allowlist that no longer covers this command\n // (core/agent/tools/dialects.ts). Nothing but a terminal or an explicit\n // `--yes` gets past here.\n const attended = opts.yes === true;\n if (!attended) {\n if (process.stdin.isTTY !== true) {\n return fail(\n json,\n \"vouch-unattended\",\n `Cannot vouch for '${service}' with nothing on the other end of stdin: this command records that ` +\n \"a PERSON read the code and says the document matches it, and nobody was asked. Run it from a \" +\n \"terminal, or pass --yes to state that you are standing behind it anyway — `vouched_by` records \" +\n `${vouchedBy} either way.`,\n );\n }\n // `--json` and a prompt do not compose: the envelope is one JSON\n // document on stdout, and a question printed beside it is not parseable\n // by the consumer that asked for it. A JSON caller is a program, so it\n // gets the same answer a pipe does — say so with --yes.\n if (json) {\n return fail(\n json,\n \"vouch-unattended\",\n `Cannot vouch for '${service}' in --json mode without --yes: the confirmation is a question for a ` +\n \"person, and it cannot be asked on a stream whose whole contract is one JSON document.\",\n );\n }\n }\n\n // The reading list is built BEFORE the question and AFTER the attendance\n // gates: a run that cannot ask anybody anything must not spend two\n // source-tree digests finding that out, and a person must not be asked\n // to confirm a sample nobody has shown them. Every refusal a vouch can\n // raise about these documents fires in here, so it lands before the read\n // rather than after it.\n let sample: SamplePlan | undefined;\n if (sampleSize !== undefined) {\n const built = await buildSamplePlan({ docsDir: config.docsDir, service: config.service, repoDir, n: sampleSize });\n if (!built.ok) return fail(json, built.code, built.message);\n sample = built.plan;\n if (!json) printReadingList(sample, service);\n }\n const servicePath = await serviceTreePathOf(config.docsDir, service);\n if (!attended && !(await confirmVouch({ service, vouchedBy, docsDir: config.docsDir, servicePath, sample }))) {\n return fail(json, \"vouch-declined\", `Nothing was stamped for '${service}'.`);\n }\n\n const outcome = await vouch({\n docsDir: config.docsDir,\n // The guard above proved `service` IS `config.service`, and only the\n // latter carries the parse (`loam.json`'s `service` field is validated\n // at load). Same string, but only one spelling is pathable.\n service: config.service,\n vouchedBy,\n // The repo root, not the cwd. `sources:` are spelled relative to the\n // repository — that is what they mean in the frontmatter and what\n // `loam validate` resolves them against — so vouching from a\n // subdirectory used to report every real source as missing\n // (`sources-path-missing`) and refuse the stamp. `config.root` is the\n // directory loam.json was found in, which is the only definition of\n // \"this repo\" that does not move with the caller.\n repoDir,\n today: today(new Date()),\n // Absent for an ordinary vouch, which is what makes an ordinary vouch\n // CLEAR a prior sample's scope rather than leave it standing.\n ...(sample === undefined ? {} : { sample }),\n });\n if (!outcome.ok) return fail(json, outcome.code, outcome.message);\n\n const report = { service, docsDir: config.docsDir, outcome, ...(sample === undefined ? {} : { sample }) };\n if (json) return emitStampJson(report);\n printStamp(report);\n });\n}\n"]}
|