@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,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a successful vouch prints: the machine envelope, and the screen the
|
|
3
|
+
* person who just vouched is looking at.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `vouch.ts` when `--sample` arrived and that file reached its
|
|
6
|
+
* line limit, on the phase seam the command already had: everything above it
|
|
7
|
+
* decides whether to write, everything here describes what was written. The
|
|
8
|
+
* two renderings stay in one module because they report the SAME stamp, and
|
|
9
|
+
* the one failure this file exists to prevent is a text screen and a payload
|
|
10
|
+
* that disagree about what a document now says.
|
|
11
|
+
*/
|
|
12
|
+
import { emitJson, repoPath } from "../../core/envelope/json.js";
|
|
13
|
+
import { plural, sayRecovered } from "../policy/format.js";
|
|
14
|
+
import { scopeJson } from "./sample/print.js";
|
|
15
|
+
/**
|
|
16
|
+
* The plan entry for one stamped file, joined by FILENAME — never by position.
|
|
17
|
+
* The two axes are stamped by two separate calls, and pairing them by index
|
|
18
|
+
* would hang one file's headings off the other file's scope.
|
|
19
|
+
*/
|
|
20
|
+
function plannedAxis(report, spec) {
|
|
21
|
+
return report.sample?.axes.find((axis) => axis.file === spec.file);
|
|
22
|
+
}
|
|
23
|
+
export function emitStampJson(report) {
|
|
24
|
+
const { spec, archSpec: arch } = report.outcome.stamped;
|
|
25
|
+
emitJson({
|
|
26
|
+
command: "vouch",
|
|
27
|
+
service: report.service,
|
|
28
|
+
path: repoPath(report.docsDir, spec.path),
|
|
29
|
+
...(report.outcome.recovered === null ? {} : { recovered: report.outcome.recovered }),
|
|
30
|
+
status: report.outcome.status,
|
|
31
|
+
last_verified: report.outcome.lastVerified,
|
|
32
|
+
vouched_by: report.outcome.vouchedBy,
|
|
33
|
+
sources: spec.sources,
|
|
34
|
+
sources_digest: spec.digest,
|
|
35
|
+
content_digest: spec.contentDigest,
|
|
36
|
+
files: spec.files,
|
|
37
|
+
skipped: spec.skipped,
|
|
38
|
+
// Additive, and beside `status` rather than inside it: `verified` is a
|
|
39
|
+
// frozen string and a sampled read is a qualification of it, not a fourth
|
|
40
|
+
// status. Null — never omitted — for a file read in full, so a consumer
|
|
41
|
+
// can tell "this loam says it was full" from "this loam has never heard
|
|
42
|
+
// of scopes".
|
|
43
|
+
vouchScope: scopeJson(spec.vouchScope, plannedAxis(report, spec)),
|
|
44
|
+
// The architecture axis, same keys: null when the service has no
|
|
45
|
+
// arch.spec.md, so a consumer can tell "none present" from an older
|
|
46
|
+
// loam that never reported the axis. status/last_verified are not
|
|
47
|
+
// repeated — the vouch is one act, and they hold for every file in it.
|
|
48
|
+
archSpec: arch === null
|
|
49
|
+
? null
|
|
50
|
+
: {
|
|
51
|
+
path: repoPath(report.docsDir, arch.path),
|
|
52
|
+
sources: arch.sources,
|
|
53
|
+
sources_digest: arch.digest,
|
|
54
|
+
content_digest: arch.contentDigest,
|
|
55
|
+
files: arch.files,
|
|
56
|
+
skipped: arch.skipped,
|
|
57
|
+
// Per file, because the sample is per file: one `--sample 3` run
|
|
58
|
+
// can stamp a sampled spec.md beside a fully-read arch.spec.md,
|
|
59
|
+
// and one scope for the pair would be false about one of them.
|
|
60
|
+
vouchScope: scopeJson(arch.vouchScope, plannedAxis(report, arch)),
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function printStamp(report) {
|
|
65
|
+
const { outcome, service } = report;
|
|
66
|
+
const { spec, archSpec: arch } = outcome.stamped;
|
|
67
|
+
// spec.md first, arch.spec.md behind it when present — the order the
|
|
68
|
+
// person who vouched reads them in, and the order the axes are declared.
|
|
69
|
+
if (outcome.recovered !== null)
|
|
70
|
+
console.log(`${sayRecovered(outcome.recovered)}\n`);
|
|
71
|
+
for (const [i, s] of [spec, ...(arch === null ? [] : [arch])].entries()) {
|
|
72
|
+
console.log(`${i > 0 ? "\n" : ""}${service} vouched — ${repoPath(report.docsDir, s.path)}\n`);
|
|
73
|
+
console.log(` status ${outcome.status}`);
|
|
74
|
+
console.log(` last_verified ${outcome.lastVerified}`);
|
|
75
|
+
console.log(` vouched_by ${outcome.vouchedBy}`);
|
|
76
|
+
console.log(` sources_digest ${s.digest} (${plural(s.files, "file")} from ${plural(s.sources.length, "source")})`);
|
|
77
|
+
console.log(` content_digest ${s.contentDigest}`);
|
|
78
|
+
// On the same screen as the digests, in the same column, because this is
|
|
79
|
+
// the field that says the promise beside it is partial. A reader who scans
|
|
80
|
+
// the stamp and stops must not be able to miss it.
|
|
81
|
+
if (s.vouchScope !== null) {
|
|
82
|
+
console.log(` vouch_scope sampled ${s.vouchScope.sections}/${s.vouchScope.of} seed=${s.vouchScope.seed} ` +
|
|
83
|
+
`(${plural(s.vouchScope.of - s.vouchScope.sections, "section")} unread)`);
|
|
84
|
+
}
|
|
85
|
+
// Said at the moment of stamping, not only later by `loam validate`:
|
|
86
|
+
// this is the one screen the person who vouched is actually looking at,
|
|
87
|
+
// and what it lists is the part of the tree their promise does not cover.
|
|
88
|
+
if (s.skipped.length > 0) {
|
|
89
|
+
console.log(`\n ⚠ ${plural(s.skipped.length, "path")} under those sources went unhashed:`);
|
|
90
|
+
for (const skip of s.skipped)
|
|
91
|
+
console.log(` ${skip.path} — ${skip.reason}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const sampled = [spec, arch].some((s) => s !== null && s.vouchScope !== null);
|
|
95
|
+
console.log(`\n\`loam validate\` will now say when that code moves out from under the spec — or when the spec moves under its own stamp.`);
|
|
96
|
+
if (sampled) {
|
|
97
|
+
console.log(`It will also report \`sources.sampled-vouch\` for '${service}' until a person vouches for the whole document ` +
|
|
98
|
+
`(\`loam vouch --service ${service}\`, no --sample), which clears the scope.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/vouch/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a successful vouch prints: the machine envelope, and the screen the\n * person who just vouched is looking at.\n *\n * Split out of `vouch.ts` when `--sample` arrived and that file reached its\n * line limit, on the phase seam the command already had: everything above it\n * decides whether to write, everything here describes what was written. The\n * two renderings stay in one module because they report the SAME stamp, and\n * the one failure this file exists to prevent is a text screen and a payload\n * that disagree about what a document now says.\n */\nimport { emitJson, repoPath } from \"../../core/envelope/json.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { plural, sayRecovered } from \"../policy/format.js\";\nimport type { StampedSpec, VouchOutcome } from \"./contract.js\";\nimport type { PlannedAxis, SamplePlan } from \"./sample/plan.js\";\nimport { scopeJson } from \"./sample/print.js\";\n\nexport interface StampReport {\n service: string;\n docsDir: DocsDir;\n /** The successful arm — the only one that has a stamp to describe. */\n outcome: Extract<VouchOutcome, { ok: true }>;\n /** The reading list this run was answered against, when it was a sampled one. */\n sample?: SamplePlan;\n}\n\n/**\n * The plan entry for one stamped file, joined by FILENAME — never by position.\n * The two axes are stamped by two separate calls, and pairing them by index\n * would hang one file's headings off the other file's scope.\n */\nfunction plannedAxis(report: StampReport, spec: StampedSpec): PlannedAxis | undefined {\n return report.sample?.axes.find((axis) => axis.file === spec.file);\n}\n\nexport function emitStampJson(report: StampReport): void {\n const { spec, archSpec: arch } = report.outcome.stamped;\n emitJson({\n command: \"vouch\",\n service: report.service,\n path: repoPath(report.docsDir, spec.path),\n ...(report.outcome.recovered === null ? {} : { recovered: report.outcome.recovered }),\n status: report.outcome.status,\n last_verified: report.outcome.lastVerified,\n vouched_by: report.outcome.vouchedBy,\n sources: spec.sources,\n sources_digest: spec.digest,\n content_digest: spec.contentDigest,\n files: spec.files,\n skipped: spec.skipped,\n // Additive, and beside `status` rather than inside it: `verified` is a\n // frozen string and a sampled read is a qualification of it, not a fourth\n // status. Null — never omitted — for a file read in full, so a consumer\n // can tell \"this loam says it was full\" from \"this loam has never heard\n // of scopes\".\n vouchScope: scopeJson(spec.vouchScope, plannedAxis(report, spec)),\n // The architecture axis, same keys: null when the service has no\n // arch.spec.md, so a consumer can tell \"none present\" from an older\n // loam that never reported the axis. status/last_verified are not\n // repeated — the vouch is one act, and they hold for every file in it.\n archSpec:\n arch === null\n ? null\n : {\n path: repoPath(report.docsDir, arch.path),\n sources: arch.sources,\n sources_digest: arch.digest,\n content_digest: arch.contentDigest,\n files: arch.files,\n skipped: arch.skipped,\n // Per file, because the sample is per file: one `--sample 3` run\n // can stamp a sampled spec.md beside a fully-read arch.spec.md,\n // and one scope for the pair would be false about one of them.\n vouchScope: scopeJson(arch.vouchScope, plannedAxis(report, arch)),\n },\n });\n}\n\nexport function printStamp(report: StampReport): void {\n const { outcome, service } = report;\n const { spec, archSpec: arch } = outcome.stamped;\n // spec.md first, arch.spec.md behind it when present — the order the\n // person who vouched reads them in, and the order the axes are declared.\n if (outcome.recovered !== null) console.log(`${sayRecovered(outcome.recovered)}\\n`);\n for (const [i, s] of [spec, ...(arch === null ? [] : [arch])].entries()) {\n console.log(`${i > 0 ? \"\\n\" : \"\"}${service} vouched — ${repoPath(report.docsDir, s.path)}\\n`);\n console.log(` status ${outcome.status}`);\n console.log(` last_verified ${outcome.lastVerified}`);\n console.log(` vouched_by ${outcome.vouchedBy}`);\n console.log(\n ` sources_digest ${s.digest} (${plural(s.files, \"file\")} from ${plural(s.sources.length, \"source\")})`,\n );\n console.log(` content_digest ${s.contentDigest}`);\n // On the same screen as the digests, in the same column, because this is\n // the field that says the promise beside it is partial. A reader who scans\n // the stamp and stops must not be able to miss it.\n if (s.vouchScope !== null) {\n console.log(\n ` vouch_scope sampled ${s.vouchScope.sections}/${s.vouchScope.of} seed=${s.vouchScope.seed} ` +\n `(${plural(s.vouchScope.of - s.vouchScope.sections, \"section\")} unread)`,\n );\n }\n // Said at the moment of stamping, not only later by `loam validate`:\n // this is the one screen the person who vouched is actually looking at,\n // and what it lists is the part of the tree their promise does not cover.\n if (s.skipped.length > 0) {\n console.log(`\\n ⚠ ${plural(s.skipped.length, \"path\")} under those sources went unhashed:`);\n for (const skip of s.skipped) console.log(` ${skip.path} — ${skip.reason}`);\n }\n }\n const sampled = [spec, arch].some((s) => s !== null && s.vouchScope !== null);\n console.log(\n `\\n\\`loam validate\\` will now say when that code moves out from under the spec — or when the spec moves under its own stamp.`,\n );\n if (sampled) {\n console.log(\n `It will also report \\`sources.sampled-vouch\\` for '${service}' until a person vouches for the whole document ` +\n `(\\`loam vouch --service ${service}\\`, no --sample), which clears the scope.`,\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stamp itself: verify every spec, then write them all or none.
|
|
3
|
+
*
|
|
4
|
+
* Separate from the command because this half has nothing to say to a terminal.
|
|
5
|
+
* It refuses on any spec it cannot verify and stamps none of them — a vouch is
|
|
6
|
+
* a person's claim that the documents match the code, and a partial one would
|
|
7
|
+
* put that claim on files nobody checked.
|
|
8
|
+
*
|
|
9
|
+
* What lands in each file: `status`, `last_verified`, `vouched_by`,
|
|
10
|
+
* `sources_digest`, the `sources_files` index, `content_digest` — and
|
|
11
|
+
* `vouch_scope` when the person read a sample rather than the document — with
|
|
12
|
+
* every byte below the frontmatter left identical. Nothing is written unless
|
|
13
|
+
* all of it can be stamped truthfully for EVERY file: a half-stamp (verified
|
|
14
|
+
* with no digest behind it, or one file stamped and its sibling not) is
|
|
15
|
+
* exactly the claim this command exists to stop being possible, so every
|
|
16
|
+
* present file is verified before any is written, and the writing itself is
|
|
17
|
+
* staged and swapped in like archive's merge, so a failure between the pair's
|
|
18
|
+
* two writes rolls the first back instead of leaving it. The two digests are
|
|
19
|
+
* the two halves of one promise — `sources_digest` pins the code that was
|
|
20
|
+
* read, `content_digest` pins the words it was read against — so
|
|
21
|
+
* `loam validate` can see either side move. (This paragraph came from a
|
|
22
|
+
* docblock stranded at the foot of `vouch.ts` when the stamp moved down here.)
|
|
23
|
+
*/
|
|
24
|
+
import { contentDigest, withFrontmatterFields } from "../../core/document/frontmatter.js";
|
|
25
|
+
import { encodeVouchScope } from "../../core/provenance/sample/scope.js";
|
|
26
|
+
import { encodeSourceIndex } from "../../core/provenance/stamp.js";
|
|
27
|
+
import { rollbackStaged, stageWrites } from "../../core/staging/commit.js";
|
|
28
|
+
import {} from "../../core/staging/interrupted.js";
|
|
29
|
+
import { LOCK_WAIT_MS } from "../../core/staging/lock.js";
|
|
30
|
+
import { openCommitWindow, recoverIfJournaled } from "../../core/staging/recovery/recover.js";
|
|
31
|
+
import { commitStaged } from "../../core/staging/txn/transaction.js";
|
|
32
|
+
import {} from "../../core/staging/writes.js";
|
|
33
|
+
import {} from "./contract.js";
|
|
34
|
+
import { axisScope, sampleDrift } from "./sample/plan.js";
|
|
35
|
+
import { verifyAxes } from "./vet/verify.js";
|
|
36
|
+
export async function vouch(req) {
|
|
37
|
+
// A predecessor's journal is rolled forward BEFORE verification reads a
|
|
38
|
+
// byte. Recovery under the commit lock alone was tried first and kept as
|
|
39
|
+
// the backstop, but it changes files verification has already read, so the
|
|
40
|
+
// run's own raced check then refused a sound stamp and the fix doctor
|
|
41
|
+
// prints took two runs instead of one. Cheap when there is nothing to do:
|
|
42
|
+
// one existsSync.
|
|
43
|
+
const early = await recoverIfJournaled(req.docsDir);
|
|
44
|
+
if (!early.ok)
|
|
45
|
+
return early;
|
|
46
|
+
// Verify first, stamp after: spec.md is required (a missing one is
|
|
47
|
+
// `unknown-target`), arch.spec.md rides when it exists, and one file that
|
|
48
|
+
// cannot be verified refuses the run before anything is written. The walk is
|
|
49
|
+
// `verifyAxes` (vet/verify.ts), shared with the reading list, and it hands
|
|
50
|
+
// the two files back by name — vet/verify.ts says why not a loop.
|
|
51
|
+
const axes = await verifyAxes(req);
|
|
52
|
+
if (!axes.ok)
|
|
53
|
+
return axes;
|
|
54
|
+
const { spec: specVerified, arch: archVerified } = axes;
|
|
55
|
+
const verified = [specVerified, ...(archVerified === null ? [] : [archVerified])];
|
|
56
|
+
// The READING window's race, which the commit window's byte compare cannot
|
|
57
|
+
// see. Under `--sample` a person spends minutes on the list before they
|
|
58
|
+
// answer, and the sample they were shown was chosen from digests taken
|
|
59
|
+
// before that. If either digest moved — or a second axis file appeared —
|
|
60
|
+
// the sections they read are not the sections this stamp would claim, and
|
|
61
|
+
// `vouch_scope` would record a read that did not happen. Nothing is written.
|
|
62
|
+
const raced = req.sample === undefined ? null : sampleDrift(req.sample, verified, req.service);
|
|
63
|
+
if (raced !== null)
|
|
64
|
+
return { ok: false, code: "vouch-raced", message: raced };
|
|
65
|
+
const specPlan = planStamp(specVerified, req);
|
|
66
|
+
const archPlan = archVerified === null ? null : planStamp(archVerified, req);
|
|
67
|
+
const writes = [specPlan.write, ...(archPlan === null ? [] : [archPlan.write])];
|
|
68
|
+
// The slow half — reading specs, hashing sources, composing stamps — ran
|
|
69
|
+
// UNLOCKED above, so vouches for independent services do not serialise
|
|
70
|
+
// behind one repo-wide mutex. Only the commit window takes the docs lock:
|
|
71
|
+
// the same one archive, rebase and verify --record hold, in the waiting
|
|
72
|
+
// form, because two vouches for different services are both supposed to
|
|
73
|
+
// land. This is the lock the roadmap called missing: without it a vouch
|
|
74
|
+
// could stage against bytes an archive was mid-swap over, and the byte
|
|
75
|
+
// compare below would refuse a perfectly sound stamp — or worse, an
|
|
76
|
+
// interrupted commit's journal would be silently written over.
|
|
77
|
+
//
|
|
78
|
+
// A journal under the lock means the last writer never finished; the window
|
|
79
|
+
// recovers or refuses before reading the pre-images this commit will compare.
|
|
80
|
+
const opened = await openCommitWindow(req.docsDir, LOCK_WAIT_MS);
|
|
81
|
+
if (!opened.ok)
|
|
82
|
+
return opened;
|
|
83
|
+
try {
|
|
84
|
+
return await commitStamp(req, { writes, specPlan, archPlan, verified }, opened.recovered ?? early.recovered);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
await opened.release();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The commit window: stage, compare against what verification read, journal,
|
|
92
|
+
* swap. Split from `vouch` so the lock's extent is visible in the code shape —
|
|
93
|
+
* everything in here holds it, nothing above does.
|
|
94
|
+
*/
|
|
95
|
+
async function commitStamp(req, plan, recovered) {
|
|
96
|
+
const { writes, specPlan, archPlan, verified } = plan;
|
|
97
|
+
const staged = await stageWrites(writes);
|
|
98
|
+
// One shared docs repo, ten service repos, and nothing stopping two of them
|
|
99
|
+
// from vouching at once. Between reading a spec and swapping the stamp in
|
|
100
|
+
// there is a window in which somebody else's vouch (or an editor, or a merge)
|
|
101
|
+
// can land in the same file — and because the new bytes were computed from
|
|
102
|
+
// the OLD ones, swapping them in would take that stamp back out without a
|
|
103
|
+
// word. `stageWrites` has already read what is on disk right now, so the
|
|
104
|
+
// check is a comparison, not another read: if the file is not what was
|
|
105
|
+
// verified, this run is describing a document that no longer exists.
|
|
106
|
+
// Bytes, not text: `stageWrites` reads the file as a Buffer (a string
|
|
107
|
+
// comparison against it is never equal, which made every vouch report
|
|
108
|
+
// `vouch-raced` and stamp nothing). A file that is GONE is still a race —
|
|
109
|
+
// `null` is not "empty", it is "the document this run described is not
|
|
110
|
+
// there any more".
|
|
111
|
+
// Joined by path, not by index: pairing the two lists positionally assumed
|
|
112
|
+
// `stageWrites` returns one entry per planned write in order — true today,
|
|
113
|
+
// promised nowhere, and a compare-and-set that silently compares the wrong
|
|
114
|
+
// pair would stamp over somebody else's vouch. A staged write no verified
|
|
115
|
+
// file claims has nothing to be compared against, so it counts as raced;
|
|
116
|
+
// fail-closed is the only safe direction here.
|
|
117
|
+
const verifiedByPath = new Map(verified.map((v) => [v.path, v]));
|
|
118
|
+
const raced = staged.filter((s) => {
|
|
119
|
+
const v = verifiedByPath.get(s.write.path);
|
|
120
|
+
return v === undefined || s.before === null || !s.before.equals(Buffer.from(v.raw, "utf8"));
|
|
121
|
+
});
|
|
122
|
+
if (raced.length > 0) {
|
|
123
|
+
// Nothing has swapped yet, so the rollback is only the temp files going
|
|
124
|
+
// away — the other writer's stamp is left exactly as it landed.
|
|
125
|
+
await rollbackStaged(staged);
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
code: "vouch-raced",
|
|
129
|
+
message: `${req.service}: ${raced.map((s) => s.write.path).join(", ")} changed while this vouch was running — ` +
|
|
130
|
+
`another vouch or an edit landed first. Nothing was stamped: re-read the document and re-run.`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// The journaled commit: intent fsynced before the first rename, so a kill
|
|
134
|
+
// between the pair's two swaps is recoverable instead of invisible — the
|
|
135
|
+
// exact half-stamped state the all-or-nothing verification exists to rule
|
|
136
|
+
// out used to be reachable through that one window. The codes are archive's,
|
|
137
|
+
// reused rather than minted: rolled back → nothing changed, re-running can
|
|
138
|
+
// work; incomplete → the files listed need a human.
|
|
139
|
+
const committed = await commitStaged({
|
|
140
|
+
root: req.docsDir,
|
|
141
|
+
command: "vouch",
|
|
142
|
+
// Runnable where vouch runs — the SERVICE repo, with --yes because the
|
|
143
|
+
// journal's reader may be unattended. Any other journaled docs-repo
|
|
144
|
+
// writer recovers this journal on its next run too.
|
|
145
|
+
rerun: `loam vouch --service ${req.service} --yes`,
|
|
146
|
+
target: req.service,
|
|
147
|
+
}, staged, "stamped");
|
|
148
|
+
if (!committed.ok) {
|
|
149
|
+
return committed.raced
|
|
150
|
+
? {
|
|
151
|
+
ok: false,
|
|
152
|
+
code: "vouch-raced",
|
|
153
|
+
message: `${req.service}: a document changed while this vouch was committing — ` +
|
|
154
|
+
`another writer landed first. Nothing was stamped: re-read and re-run.`,
|
|
155
|
+
}
|
|
156
|
+
: { ok: false, code: committed.code, message: committed.message };
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
ok: true,
|
|
160
|
+
status: "verified",
|
|
161
|
+
lastVerified: req.today,
|
|
162
|
+
vouchedBy: req.vouchedBy,
|
|
163
|
+
recovered,
|
|
164
|
+
stamped: { spec: specPlan.stamped, archSpec: archPlan === null ? null : archPlan.stamped },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* One verified file's share of the commit: the bytes to write, and the record
|
|
169
|
+
* of what was stamped into them. Kept beside each other because they are the
|
|
170
|
+
* same computation — the report must describe the file that was actually
|
|
171
|
+
* written, not a second guess at it.
|
|
172
|
+
*/
|
|
173
|
+
export function planStamp(v, req) {
|
|
174
|
+
// Two passes on purpose: `content_digest` hashes the body BELOW the
|
|
175
|
+
// frontmatter, and withFrontmatterFields promises that body byte-identical —
|
|
176
|
+
// so hashing after the first stamp and writing the hash in a second one
|
|
177
|
+
// yields a digest that is true of the file exactly as written. A re-vouch
|
|
178
|
+
// takes the same road and refreshes every field, this one included.
|
|
179
|
+
//
|
|
180
|
+
// The scope this file's stamp will carry — null both when the run is an
|
|
181
|
+
// ordinary vouch and when a sampled run's `--sample <n>` covered the whole
|
|
182
|
+
// file. Joined to the plan by FILENAME rather than taken positionally: the
|
|
183
|
+
// two axes are stamped by two separate calls, and a scope written onto the
|
|
184
|
+
// wrong file would claim a person read four sections of a document they
|
|
185
|
+
// never opened.
|
|
186
|
+
const planned = req.sample?.axes.find((axis) => axis.file === v.file);
|
|
187
|
+
// A verified file with no planned axis is unreachable — `sampleDrift`
|
|
188
|
+
// refuses that run before this line — and null is the safe direction if it
|
|
189
|
+
// ever were: a full stamp that CLEARS any prior scope, never one claiming a
|
|
190
|
+
// sample nobody was shown.
|
|
191
|
+
const scope = planned === undefined ? null : axisScope(planned);
|
|
192
|
+
const restamped = withFrontmatterFields(v.raw, {
|
|
193
|
+
status: "verified",
|
|
194
|
+
last_verified: req.today,
|
|
195
|
+
// WHO, beside when. Without it `status: verified` recorded that the word
|
|
196
|
+
// had been written and nothing about who wrote it, so a vouch and an
|
|
197
|
+
// agent's own draft left the same trace in the document — the one
|
|
198
|
+
// distinction this command exists to make.
|
|
199
|
+
vouched_by: req.vouchedBy,
|
|
200
|
+
sources_digest: v.digest,
|
|
201
|
+
// Beside the digest, what it was taken over. `sources_digest` alone can
|
|
202
|
+
// only ever say THAT the code moved; the next `loam validate` reads this
|
|
203
|
+
// back to say which files did.
|
|
204
|
+
sources_files: encodeSourceIndex(v.index),
|
|
205
|
+
// Beside `vouched_by`, never inside `status`: the rung string `vouched`
|
|
206
|
+
// and the status `verified` are a published contract, and a sampled read
|
|
207
|
+
// is not a fourth status — it is a qualification of this one.
|
|
208
|
+
...(scope === null ? {} : { vouch_scope: encodeVouchScope(scope) }),
|
|
209
|
+
},
|
|
210
|
+
// A full vouch CLEARS any scope a previous sampled one left, rather than
|
|
211
|
+
// stranding a claim that would keep a fully-read document reading as
|
|
212
|
+
// partial forever. Removing a key that was never there is a no-op, so
|
|
213
|
+
// this rides on every run that is not itself sampling.
|
|
214
|
+
scope === null ? ["vouch_scope"] : []);
|
|
215
|
+
const bodyDigest = contentDigest(restamped);
|
|
216
|
+
return {
|
|
217
|
+
write: { path: v.path, content: withFrontmatterFields(restamped, { content_digest: bodyDigest }) },
|
|
218
|
+
stamped: {
|
|
219
|
+
path: v.path,
|
|
220
|
+
file: v.file,
|
|
221
|
+
digest: v.digest,
|
|
222
|
+
contentDigest: bodyDigest,
|
|
223
|
+
sources: v.sources,
|
|
224
|
+
files: v.index.length,
|
|
225
|
+
skipped: v.skipped,
|
|
226
|
+
vouchScope: scope,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/vouch/run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The stamp itself: verify every spec, then write them all or none.\n *\n * Separate from the command because this half has nothing to say to a terminal.\n * It refuses on any spec it cannot verify and stamps none of them — a vouch is\n * a person's claim that the documents match the code, and a partial one would\n * put that claim on files nobody checked.\n *\n * What lands in each file: `status`, `last_verified`, `vouched_by`,\n * `sources_digest`, the `sources_files` index, `content_digest` — and\n * `vouch_scope` when the person read a sample rather than the document — with\n * every byte below the frontmatter left identical. Nothing is written unless\n * all of it can be stamped truthfully for EVERY file: a half-stamp (verified\n * with no digest behind it, or one file stamped and its sibling not) is\n * exactly the claim this command exists to stop being possible, so every\n * present file is verified before any is written, and the writing itself is\n * staged and swapped in like archive's merge, so a failure between the pair's\n * two writes rolls the first back instead of leaving it. The two digests are\n * the two halves of one promise — `sources_digest` pins the code that was\n * read, `content_digest` pins the words it was read against — so\n * `loam validate` can see either side move. (This paragraph came from a\n * docblock stranded at the foot of `vouch.ts` when the stamp moved down here.)\n */\nimport { contentDigest, withFrontmatterFields } from \"../../core/document/frontmatter.js\";\nimport { encodeVouchScope } from \"../../core/provenance/sample/scope.js\";\nimport { encodeSourceIndex } from \"../../core/provenance/stamp.js\";\nimport { rollbackStaged, stageWrites } from \"../../core/staging/commit.js\";\nimport { type CommitRecovery } from \"../../core/staging/interrupted.js\";\nimport { LOCK_WAIT_MS } from \"../../core/staging/lock.js\";\nimport { openCommitWindow, recoverIfJournaled } from \"../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { type PlannedWrite } from \"../../core/staging/writes.js\";\nimport { type StampedSpec, type VouchOutcome, type VouchRequest } from \"./contract.js\";\nimport { axisScope, sampleDrift } from \"./sample/plan.js\";\nimport { verifyAxes, type VerifiedSpec } from \"./vet/verify.js\";\n\nexport async function vouch(req: VouchRequest): Promise<VouchOutcome> {\n // A predecessor's journal is rolled forward BEFORE verification reads a\n // byte. Recovery under the commit lock alone was tried first and kept as\n // the backstop, but it changes files verification has already read, so the\n // run's own raced check then refused a sound stamp and the fix doctor\n // prints took two runs instead of one. Cheap when there is nothing to do:\n // one existsSync.\n const early = await recoverIfJournaled(req.docsDir);\n if (!early.ok) return early;\n // Verify first, stamp after: spec.md is required (a missing one is\n // `unknown-target`), arch.spec.md rides when it exists, and one file that\n // cannot be verified refuses the run before anything is written. The walk is\n // `verifyAxes` (vet/verify.ts), shared with the reading list, and it hands\n // the two files back by name — vet/verify.ts says why not a loop.\n const axes = await verifyAxes(req);\n if (!axes.ok) return axes;\n const { spec: specVerified, arch: archVerified } = axes;\n const verified: VerifiedSpec[] = [specVerified, ...(archVerified === null ? [] : [archVerified])];\n\n // The READING window's race, which the commit window's byte compare cannot\n // see. Under `--sample` a person spends minutes on the list before they\n // answer, and the sample they were shown was chosen from digests taken\n // before that. If either digest moved — or a second axis file appeared —\n // the sections they read are not the sections this stamp would claim, and\n // `vouch_scope` would record a read that did not happen. Nothing is written.\n const raced = req.sample === undefined ? null : sampleDrift(req.sample, verified, req.service);\n if (raced !== null) return { ok: false, code: \"vouch-raced\", message: raced };\n\n const specPlan = planStamp(specVerified, req);\n const archPlan = archVerified === null ? null : planStamp(archVerified, req);\n const writes: PlannedWrite[] = [specPlan.write, ...(archPlan === null ? [] : [archPlan.write])];\n\n // The slow half — reading specs, hashing sources, composing stamps — ran\n // UNLOCKED above, so vouches for independent services do not serialise\n // behind one repo-wide mutex. Only the commit window takes the docs lock:\n // the same one archive, rebase and verify --record hold, in the waiting\n // form, because two vouches for different services are both supposed to\n // land. This is the lock the roadmap called missing: without it a vouch\n // could stage against bytes an archive was mid-swap over, and the byte\n // compare below would refuse a perfectly sound stamp — or worse, an\n // interrupted commit's journal would be silently written over.\n //\n // A journal under the lock means the last writer never finished; the window\n // recovers or refuses before reading the pre-images this commit will compare.\n const opened = await openCommitWindow(req.docsDir, LOCK_WAIT_MS);\n if (!opened.ok) return opened;\n try {\n return await commitStamp(req, { writes, specPlan, archPlan, verified }, opened.recovered ?? early.recovered);\n } finally {\n await opened.release();\n }\n}\n\n/**\n * The commit window: stage, compare against what verification read, journal,\n * swap. Split from `vouch` so the lock's extent is visible in the code shape —\n * everything in here holds it, nothing above does.\n */\nasync function commitStamp(\n req: VouchRequest,\n plan: {\n writes: PlannedWrite[];\n specPlan: { write: PlannedWrite; stamped: StampedSpec };\n archPlan: { write: PlannedWrite; stamped: StampedSpec } | null;\n verified: VerifiedSpec[];\n },\n recovered: CommitRecovery | null,\n): Promise<VouchOutcome> {\n const { writes, specPlan, archPlan, verified } = plan;\n const staged = await stageWrites(writes);\n\n // One shared docs repo, ten service repos, and nothing stopping two of them\n // from vouching at once. Between reading a spec and swapping the stamp in\n // there is a window in which somebody else's vouch (or an editor, or a merge)\n // can land in the same file — and because the new bytes were computed from\n // the OLD ones, swapping them in would take that stamp back out without a\n // word. `stageWrites` has already read what is on disk right now, so the\n // check is a comparison, not another read: if the file is not what was\n // verified, this run is describing a document that no longer exists.\n // Bytes, not text: `stageWrites` reads the file as a Buffer (a string\n // comparison against it is never equal, which made every vouch report\n // `vouch-raced` and stamp nothing). A file that is GONE is still a race —\n // `null` is not \"empty\", it is \"the document this run described is not\n // there any more\".\n // Joined by path, not by index: pairing the two lists positionally assumed\n // `stageWrites` returns one entry per planned write in order — true today,\n // promised nowhere, and a compare-and-set that silently compares the wrong\n // pair would stamp over somebody else's vouch. A staged write no verified\n // file claims has nothing to be compared against, so it counts as raced;\n // fail-closed is the only safe direction here.\n const verifiedByPath = new Map(verified.map((v) => [v.path, v] as const));\n const raced = staged.filter((s) => {\n const v = verifiedByPath.get(s.write.path);\n return v === undefined || s.before === null || !s.before.equals(Buffer.from(v.raw, \"utf8\"));\n });\n if (raced.length > 0) {\n // Nothing has swapped yet, so the rollback is only the temp files going\n // away — the other writer's stamp is left exactly as it landed.\n await rollbackStaged(staged);\n return {\n ok: false,\n code: \"vouch-raced\",\n message:\n `${req.service}: ${raced.map((s) => s.write.path).join(\", \")} changed while this vouch was running — ` +\n `another vouch or an edit landed first. Nothing was stamped: re-read the document and re-run.`,\n };\n }\n\n // The journaled commit: intent fsynced before the first rename, so a kill\n // between the pair's two swaps is recoverable instead of invisible — the\n // exact half-stamped state the all-or-nothing verification exists to rule\n // out used to be reachable through that one window. The codes are archive's,\n // reused rather than minted: rolled back → nothing changed, re-running can\n // work; incomplete → the files listed need a human.\n const committed = await commitStaged(\n {\n root: req.docsDir,\n command: \"vouch\",\n // Runnable where vouch runs — the SERVICE repo, with --yes because the\n // journal's reader may be unattended. Any other journaled docs-repo\n // writer recovers this journal on its next run too.\n rerun: `loam vouch --service ${req.service} --yes`,\n target: req.service,\n },\n staged,\n \"stamped\",\n );\n if (!committed.ok) {\n return committed.raced\n ? {\n ok: false,\n code: \"vouch-raced\",\n message:\n `${req.service}: a document changed while this vouch was committing — ` +\n `another writer landed first. Nothing was stamped: re-read and re-run.`,\n }\n : { ok: false, code: committed.code, message: committed.message };\n }\n return {\n ok: true,\n status: \"verified\",\n lastVerified: req.today,\n vouchedBy: req.vouchedBy,\n recovered,\n stamped: { spec: specPlan.stamped, archSpec: archPlan === null ? null : archPlan.stamped },\n };\n}\n\n/**\n * One verified file's share of the commit: the bytes to write, and the record\n * of what was stamped into them. Kept beside each other because they are the\n * same computation — the report must describe the file that was actually\n * written, not a second guess at it.\n */\nexport function planStamp(v: VerifiedSpec, req: VouchRequest): { write: PlannedWrite; stamped: StampedSpec } {\n // Two passes on purpose: `content_digest` hashes the body BELOW the\n // frontmatter, and withFrontmatterFields promises that body byte-identical —\n // so hashing after the first stamp and writing the hash in a second one\n // yields a digest that is true of the file exactly as written. A re-vouch\n // takes the same road and refreshes every field, this one included.\n //\n // The scope this file's stamp will carry — null both when the run is an\n // ordinary vouch and when a sampled run's `--sample <n>` covered the whole\n // file. Joined to the plan by FILENAME rather than taken positionally: the\n // two axes are stamped by two separate calls, and a scope written onto the\n // wrong file would claim a person read four sections of a document they\n // never opened.\n const planned = req.sample?.axes.find((axis) => axis.file === v.file);\n // A verified file with no planned axis is unreachable — `sampleDrift`\n // refuses that run before this line — and null is the safe direction if it\n // ever were: a full stamp that CLEARS any prior scope, never one claiming a\n // sample nobody was shown.\n const scope = planned === undefined ? null : axisScope(planned);\n const restamped = withFrontmatterFields(\n v.raw,\n {\n status: \"verified\",\n last_verified: req.today,\n // WHO, beside when. Without it `status: verified` recorded that the word\n // had been written and nothing about who wrote it, so a vouch and an\n // agent's own draft left the same trace in the document — the one\n // distinction this command exists to make.\n vouched_by: req.vouchedBy,\n sources_digest: v.digest,\n // Beside the digest, what it was taken over. `sources_digest` alone can\n // only ever say THAT the code moved; the next `loam validate` reads this\n // back to say which files did.\n sources_files: encodeSourceIndex(v.index),\n // Beside `vouched_by`, never inside `status`: the rung string `vouched`\n // and the status `verified` are a published contract, and a sampled read\n // is not a fourth status — it is a qualification of this one.\n ...(scope === null ? {} : { vouch_scope: encodeVouchScope(scope) }),\n },\n // A full vouch CLEARS any scope a previous sampled one left, rather than\n // stranding a claim that would keep a fully-read document reading as\n // partial forever. Removing a key that was never there is a no-op, so\n // this rides on every run that is not itself sampling.\n scope === null ? [\"vouch_scope\"] : [],\n );\n const bodyDigest = contentDigest(restamped);\n return {\n write: { path: v.path, content: withFrontmatterFields(restamped, { content_digest: bodyDigest }) },\n stamped: {\n path: v.path,\n file: v.file,\n digest: v.digest,\n contentDigest: bodyDigest,\n sources: v.sources,\n files: v.index.length,\n skipped: v.skipped,\n vouchScope: scope,\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pre-pass behind `loam vouch --sample <n>`: decide, before anyone is
|
|
3
|
+
* asked anything, which sections of which files this vouch will actually
|
|
4
|
+
* cover.
|
|
5
|
+
*
|
|
6
|
+
* It has to happen before the confirmation because a sampled vouch's question
|
|
7
|
+
* is different in kind — "have you read THESE four sections", not "have you
|
|
8
|
+
* read the code" — and a question that names nothing is the reflex this
|
|
9
|
+
* command exists to interrupt. So the reading list is computed first, printed,
|
|
10
|
+
* and only then is the person asked.
|
|
11
|
+
*
|
|
12
|
+
* It runs the vouch's own vetting (`../vet/verify.ts`: the same axis walk
|
|
13
|
+
* `run.ts` makes, over the call the reading pack makes), which means every
|
|
14
|
+
* refusal a vouch can raise about a document — an unreadable header, no
|
|
15
|
+
* `sources`, a glob pattern, a source that is gone, an expansion covering no
|
|
16
|
+
* files — fires HERE, before the prompt, with the same code and the same
|
|
17
|
+
* words. A person should not read four sections and then be told the run was
|
|
18
|
+
* never going to stamp.
|
|
19
|
+
*
|
|
20
|
+
* The cost is that the sources are walked and hashed twice: once to seed the
|
|
21
|
+
* sample, once at the stamp. That is the honesty price of the seed being
|
|
22
|
+
* content-derived, and `run.ts` spends the second walk anyway — what the
|
|
23
|
+
* second walk buys is the drift check, which refuses a stamp whose sample was
|
|
24
|
+
* chosen from a document that has since moved.
|
|
25
|
+
*/
|
|
26
|
+
import { contentDigest, rawBody } from "../../../core/document/frontmatter.js";
|
|
27
|
+
import { planSample } from "../../../core/provenance/sample/scope.js";
|
|
28
|
+
import { verifyAxes } from "../vet/verify.js";
|
|
29
|
+
/** The scope a planned axis will stamp, or null for one that was read in full. */
|
|
30
|
+
export function axisScope(axis) {
|
|
31
|
+
return axis.mode === "full" ? null : { sections: axis.picked.length, of: axis.of, seed: axis.seed };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What moved between the reading list and the stamp, as a phrase for the
|
|
35
|
+
* refusal — or null when the plan and the fresh verification describe the same
|
|
36
|
+
* documents.
|
|
37
|
+
*
|
|
38
|
+
* Joined by FILENAME both ways, and both directions matter: a plan entry with
|
|
39
|
+
* no verified file means an axis vanished mid-read, a verified file with no
|
|
40
|
+
* plan entry means one appeared and nobody was shown it. Comparing counts, or
|
|
41
|
+
* zipping the two lists, would call the second case fine.
|
|
42
|
+
*
|
|
43
|
+
* The digests, not the bytes: `content_digest` and `sources_digest` are the
|
|
44
|
+
* seed's own inputs, so a change in either is exactly a change in which
|
|
45
|
+
* sections a sample would pick. It lives here rather than in `run.ts` because
|
|
46
|
+
* it is a question about the PLAN — whether the reading list still describes
|
|
47
|
+
* these files — and the answer has to be computed the same way the plan was.
|
|
48
|
+
*/
|
|
49
|
+
export function sampleDrift(plan, verified, service) {
|
|
50
|
+
const now = new Map(verified.map((v) => [v.file, v]));
|
|
51
|
+
const moved = plan.axes
|
|
52
|
+
.filter((axis) => {
|
|
53
|
+
const v = now.get(axis.file);
|
|
54
|
+
return v === undefined || contentDigest(v.raw) !== axis.contentDigest || v.digest !== axis.sourcesDigest;
|
|
55
|
+
})
|
|
56
|
+
.map((axis) => axis.file);
|
|
57
|
+
const planned = new Set(plan.axes.map((axis) => axis.file));
|
|
58
|
+
const appeared = verified.filter((v) => !planned.has(v.file)).map((v) => v.file);
|
|
59
|
+
const files = [...moved, ...appeared];
|
|
60
|
+
if (files.length === 0)
|
|
61
|
+
return null;
|
|
62
|
+
// The whole sentence, not the file list: `run.ts` returns it verbatim under
|
|
63
|
+
// `vouch-raced`, and the diagnosis — which is about a READING window nothing
|
|
64
|
+
// locks — belongs beside the check that can explain it.
|
|
65
|
+
return (`${service}: ${files.join(", ")} changed while you were reading the sample — the sections you were shown are ` +
|
|
66
|
+
`not the sections a stamp would now cover. Nothing was stamped: re-run for a fresh reading list.`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build the reading list. The axis walk is `run.ts`'s own — `verifyAxes`, which
|
|
70
|
+
* refuses a missing spec.md in vet/verify.ts's one sentence (the same absence
|
|
71
|
+
* and the same fix; three spellings would read as three different problems) —
|
|
72
|
+
* and so is the all-or-nothing discipline: one file that cannot be verified
|
|
73
|
+
* refuses the run before a person is asked to read anything.
|
|
74
|
+
*/
|
|
75
|
+
export async function buildSamplePlan(req) {
|
|
76
|
+
const verified = await verifyAxes(req);
|
|
77
|
+
if (!verified.ok)
|
|
78
|
+
return verified;
|
|
79
|
+
const axes = [];
|
|
80
|
+
for (const vetted of verified.arch === null ? [verified.spec] : [verified.spec, verified.arch]) {
|
|
81
|
+
const digest = contentDigest(vetted.raw);
|
|
82
|
+
// The BODY, so no frontmatter line can be picked as a section — and the
|
|
83
|
+
// same slice `content_digest` is taken over, which is what makes the
|
|
84
|
+
// seed's inputs and the sampled text describe one document.
|
|
85
|
+
const body = rawBody(vetted.raw);
|
|
86
|
+
const sample = planSample({
|
|
87
|
+
service: req.service,
|
|
88
|
+
contentDigest: digest,
|
|
89
|
+
sourcesDigest: vetted.digest,
|
|
90
|
+
body,
|
|
91
|
+
n: req.n,
|
|
92
|
+
});
|
|
93
|
+
const base = {
|
|
94
|
+
file: vetted.file,
|
|
95
|
+
path: vetted.path,
|
|
96
|
+
contentDigest: digest,
|
|
97
|
+
sourcesDigest: vetted.digest,
|
|
98
|
+
of: sample.of,
|
|
99
|
+
// The header's line count, by subtraction rather than a second parse:
|
|
100
|
+
// `rawBody` is the one definition of where the body starts, and asking
|
|
101
|
+
// it twice is how the two answers drift.
|
|
102
|
+
lineOffset: vetted.raw.slice(0, vetted.raw.length - body.length).split("\n").length - 1,
|
|
103
|
+
sources: { entries: vetted.sources, files: vetted.index.length },
|
|
104
|
+
};
|
|
105
|
+
axes.push(sample.picked.length >= sample.of
|
|
106
|
+
? { ...base, mode: "full" }
|
|
107
|
+
: { ...base, mode: "sampled", seed: sample.seed, picked: sample.picked });
|
|
108
|
+
}
|
|
109
|
+
return { ok: true, plan: { n: req.n, axes } };
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../../src/commands/vouch/sample/plan.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The pre-pass behind `loam vouch --sample <n>`: decide, before anyone is\n * asked anything, which sections of which files this vouch will actually\n * cover.\n *\n * It has to happen before the confirmation because a sampled vouch's question\n * is different in kind — \"have you read THESE four sections\", not \"have you\n * read the code\" — and a question that names nothing is the reflex this\n * command exists to interrupt. So the reading list is computed first, printed,\n * and only then is the person asked.\n *\n * It runs the vouch's own vetting (`../vet/verify.ts`: the same axis walk\n * `run.ts` makes, over the call the reading pack makes), which means every\n * refusal a vouch can raise about a document — an unreadable header, no\n * `sources`, a glob pattern, a source that is gone, an expansion covering no\n * files — fires HERE, before the prompt, with the same code and the same\n * words. A person should not read four sections and then be told the run was\n * never going to stamp.\n *\n * The cost is that the sources are walked and hashed twice: once to seed the\n * sample, once at the stamp. That is the honesty price of the seed being\n * content-derived, and `run.ts` spends the second walk anyway — what the\n * second walk buys is the drift check, which refuses a stamp whose sample was\n * chosen from a document that has since moved.\n */\nimport { contentDigest, rawBody } from \"../../../core/document/frontmatter.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport type { PathableService } from \"../../../core/kernel/ids/service.js\";\nimport type { DocSection } from \"../../../core/provenance/sample/sections.js\";\nimport { planSample, type VouchScope } from \"../../../core/provenance/sample/scope.js\";\nimport { verifyAxes, type AxesRefusal, type VerifiedSpec } from \"../vet/verify.js\";\n\n/**\n * One spec-axis file's share of a `--sample <n>` run, as the pre-pass decided\n * it and the stamp must honour it.\n *\n * A variant rather than an optional `picked?:`, because \"read in full\" and\n * \"sampled\" are two different claims and the difference decides whether the\n * file gets a `vouch_scope` at all. The two digests ride on both arms: they\n * are what the seed was derived from, and the stamp re-checks them against a\n * fresh verification, because a person reads for minutes and nothing locks\n * the document while they do.\n */\ninterface PlannedAxisBase {\n /** The axis's filename — \"spec.md\" or \"arch.spec.md\". The key the stamp joins on. */\n file: string;\n /** Absolute path, for the reading list's own line. */\n path: string;\n /** `contentDigest(raw)` when the reading list was built. */\n contentDigest: string;\n /** The sources digest when the reading list was built. */\n sourcesDigest: string;\n /** Every section the body had. */\n of: number;\n /**\n * How many lines of frontmatter sit above the body. `DocSection.line` is\n * counted within the BODY — that is what the splitter can promise, since it\n * is handed a body — and a reading list that printed those numbers as file\n * lines would send a person to the wrong place in every stamped document.\n * Added once, at the display edge.\n */\n lineOffset: number;\n /** The `sources` entries as the frontmatter spells them, and how many files they expanded to. */\n sources: { entries: string[]; files: number };\n}\n\nexport type PlannedAxis =\n /** `of <= n`: the sample covers the whole file, so this axis is an ordinary full vouch. */\n | (PlannedAxisBase & { mode: \"full\" })\n | (PlannedAxisBase & { mode: \"sampled\"; seed: string; picked: readonly DocSection[] });\n\nexport interface SamplePlan {\n /** `--sample <n>` as the person typed it — carried so the output can say what was asked for. */\n n: number;\n /**\n * Every spec-axis file the pre-pass verified, sampled or not. Complete on\n * purpose: the stamp compares this roster against what it re-verifies, so an\n * arch.spec.md that appeared while the person was reading refuses the run\n * instead of riding along unread.\n */\n axes: PlannedAxis[];\n}\n\n/** The scope a planned axis will stamp, or null for one that was read in full. */\nexport function axisScope(axis: PlannedAxis): VouchScope | null {\n return axis.mode === \"full\" ? null : { sections: axis.picked.length, of: axis.of, seed: axis.seed };\n}\n\n/**\n * What moved between the reading list and the stamp, as a phrase for the\n * refusal — or null when the plan and the fresh verification describe the same\n * documents.\n *\n * Joined by FILENAME both ways, and both directions matter: a plan entry with\n * no verified file means an axis vanished mid-read, a verified file with no\n * plan entry means one appeared and nobody was shown it. Comparing counts, or\n * zipping the two lists, would call the second case fine.\n *\n * The digests, not the bytes: `content_digest` and `sources_digest` are the\n * seed's own inputs, so a change in either is exactly a change in which\n * sections a sample would pick. It lives here rather than in `run.ts` because\n * it is a question about the PLAN — whether the reading list still describes\n * these files — and the answer has to be computed the same way the plan was.\n */\nexport function sampleDrift(\n plan: SamplePlan,\n verified: readonly VerifiedSpec[],\n service: string,\n): string | null {\n const now = new Map(verified.map((v) => [v.file, v] as const));\n const moved = plan.axes\n .filter((axis) => {\n const v = now.get(axis.file);\n return v === undefined || contentDigest(v.raw) !== axis.contentDigest || v.digest !== axis.sourcesDigest;\n })\n .map((axis) => axis.file);\n const planned = new Set(plan.axes.map((axis) => axis.file));\n const appeared = verified.filter((v) => !planned.has(v.file)).map((v) => v.file);\n const files = [...moved, ...appeared];\n if (files.length === 0) return null;\n // The whole sentence, not the file list: `run.ts` returns it verbatim under\n // `vouch-raced`, and the diagnosis — which is about a READING window nothing\n // locks — belongs beside the check that can explain it.\n return (\n `${service}: ${files.join(\", \")} changed while you were reading the sample — the sections you were shown are ` +\n `not the sections a stamp would now cover. Nothing was stamped: re-run for a fresh reading list.`\n );\n}\n\nexport interface SampleRequest {\n docsDir: DocsDir;\n service: PathableService;\n /** The service's own repo — what `sources` resolve against. */\n repoDir: string;\n /** How many sections to read per spec-axis file. A whole number of at least 1; the caller validates. */\n n: number;\n}\n\nexport type SampleOutcome = { ok: true; plan: SamplePlan } | AxesRefusal;\n\n/**\n * Build the reading list. The axis walk is `run.ts`'s own — `verifyAxes`, which\n * refuses a missing spec.md in vet/verify.ts's one sentence (the same absence\n * and the same fix; three spellings would read as three different problems) —\n * and so is the all-or-nothing discipline: one file that cannot be verified\n * refuses the run before a person is asked to read anything.\n */\nexport async function buildSamplePlan(req: SampleRequest): Promise<SampleOutcome> {\n const verified = await verifyAxes(req);\n if (!verified.ok) return verified;\n const axes: PlannedAxis[] = [];\n for (const vetted of verified.arch === null ? [verified.spec] : [verified.spec, verified.arch]) {\n const digest = contentDigest(vetted.raw);\n // The BODY, so no frontmatter line can be picked as a section — and the\n // same slice `content_digest` is taken over, which is what makes the\n // seed's inputs and the sampled text describe one document.\n const body = rawBody(vetted.raw);\n const sample = planSample({\n service: req.service,\n contentDigest: digest,\n sourcesDigest: vetted.digest,\n body,\n n: req.n,\n });\n const base = {\n file: vetted.file,\n path: vetted.path,\n contentDigest: digest,\n sourcesDigest: vetted.digest,\n of: sample.of,\n // The header's line count, by subtraction rather than a second parse:\n // `rawBody` is the one definition of where the body starts, and asking\n // it twice is how the two answers drift.\n lineOffset: vetted.raw.slice(0, vetted.raw.length - body.length).split(\"\\n\").length - 1,\n sources: { entries: vetted.sources, files: vetted.index.length },\n };\n axes.push(\n sample.picked.length >= sample.of\n ? { ...base, mode: \"full\" }\n : { ...base, mode: \"sampled\", seed: sample.seed, picked: sample.picked },\n );\n }\n return { ok: true, plan: { n: req.n, axes } };\n}\n"]}
|