@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2548 -86
- package/COMPARISON.md +80 -63
- package/CONTRIBUTING.md +84 -0
- package/MIGRATING-from-OpenSpec.md +213 -54
- package/QUICKSTART.md +125 -0
- package/README.md +450 -150
- package/ROADMAP.md +494 -0
- package/SCHEMA.md +2355 -256
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +701 -0
- package/dist/cli.js +113 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +209 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +268 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +77 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +159 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +317 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +161 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +111 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +237 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +27 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +251 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/context/context.js +99 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +283 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +279 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +205 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +9 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +93 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +5 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +151 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +29 -24
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +115 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +54 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +146 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +246 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +149 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +28 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +146 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +65 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +157 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +343 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +301 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/views.js +105 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +183 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +34 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +170 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +19 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/commit.js +76 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/new.js +283 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +355 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +203 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +275 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +192 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +133 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +172 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +178 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/marks.js +24 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/{show.js → show/service.js} +63 -152
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +77 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/json.js +45 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +157 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +119 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +189 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +265 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +115 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +101 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +103 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +94 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +70 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +160 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +67 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +194 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +296 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +55 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +254 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +76 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/checks/vocabulary.js +31 -0
- package/dist/commands/validate/checks/vocabulary.js.map +1 -0
- package/dist/commands/validate/feature.js +216 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +69 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +353 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +52 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +236 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +63 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/steps.js +197 -0
- package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +40 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +59 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +92 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/report.js +269 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/service/api.js +338 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +219 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +131 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/service.js +250 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +219 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +113 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/validate.js +338 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +182 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +72 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +241 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +226 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +223 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +246 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +217 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +271 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +142 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +285 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +125 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +123 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +176 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/artifacts.js +220 -0
- package/dist/core/agent/agents-md/artifacts.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +324 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/cycle.js +165 -0
- package/dist/core/agent/agents-md/cycle.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +34 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +41 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +62 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +32 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +60 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +246 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
- package/dist/core/agent/agents-md/spine.js +40 -0
- package/dist/core/agent/agents-md/spine.js.map +1 -0
- package/dist/core/agent/agents-md.js +170 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +259 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +103 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +150 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +228 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +133 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +334 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +262 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +105 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +105 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +209 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +65 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +188 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +16 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +297 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +110 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +141 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +91 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +33 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +308 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +215 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +107 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +225 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +250 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +194 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/targets.js +226 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +47 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +282 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +88 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +57 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +75 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/project/architecture.js +45 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/documents.js +58 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +183 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/resolve/service.js +113 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +109 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/source-mask.js +82 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +227 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +101 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +10 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +36 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +269 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +194 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/workspace.js +172 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +50 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +342 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +181 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +143 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +199 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +126 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +277 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +177 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +74 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/coherence.js +251 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/declared.js +269 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +206 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +204 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +166 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +122 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/merged.js +40 -0
- package/dist/core/coherence/events/merged.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +155 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +296 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/diff/base-git.js +148 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +209 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/current-state.js +96 -0
- package/dist/core/diff/current-state.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +188 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/semantic.js +243 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/diff/victims.js +247 -0
- package/dist/core/diff/victims.js.map +1 -0
- package/dist/core/docs.js +7 -64
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +222 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +135 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +275 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +77 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +263 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +221 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +241 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +79 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +175 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +175 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +181 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms.js +144 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/{explore.js → explore/explore.js} +50 -101
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +120 -78
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +201 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +205 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +113 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +234 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +106 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +86 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +68 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +104 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +236 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +111 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +72 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +314 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +166 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +112 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +175 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/depth.js +122 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +189 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +44 -106
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +234 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +26 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +208 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +256 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +128 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +221 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +76 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +65 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +235 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +200 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +260 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +133 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +118 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +76 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/provenance/findings.js +208 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +225 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +182 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +263 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +232 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +192 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +236 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +248 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +52 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +64 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/views.js +172 -0
- package/dist/core/repo/tree/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +234 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +99 -2
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +131 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +241 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +206 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +98 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +126 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot.js +202 -0
- package/dist/core/staging/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +171 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +49 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +102 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +171 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +207 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +150 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +187 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +207 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +201 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/usecases/capability.js +169 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +116 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +103 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +235 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +137 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/operations.js +111 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +173 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +150 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +201 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/file.js +257 -0
- package/dist/core/verify/file.js.map +1 -0
- package/dist/core/verify/pins/lint.js +157 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/record.js +142 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +89 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +57 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +55 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +145 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/{report.js → vocabulary/report.js} +30 -2
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +189 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +280 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/subsystems.likec4 +11 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +9 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +109 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +127 -0
- package/examples/docs/services/order-service/asyncapi.yaml +108 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +138 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +73 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +67 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
- package/examples/docs/services/platform/notification-service/health.yaml +35 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -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.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- 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.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.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.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
- /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
- /package/dist/core/{records.js → kernel/records.js} +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The re-vouch reading pack: everything `loam vouch --pack` computes and
|
|
3
|
+
* nothing it prints. Three derivations per spec-axis file, all read-only and
|
|
4
|
+
* all from stamps `loam vouch` already writes — (a) the body's diff from the
|
|
5
|
+
* last commit whose version of the file hashes to the stamped
|
|
6
|
+
* `content_digest`, (b) the source files that moved against the stamped
|
|
7
|
+
* per-file index, (c) the sections whose text is identical to the vouched
|
|
8
|
+
* ancestor's, which the person need not re-read. Nothing here writes, locks
|
|
9
|
+
* or stamps; a "pack" in vouch's vocabulary is always the READING pack — the
|
|
10
|
+
* context pack (`core/pack/`) is a different artifact for a different reader.
|
|
11
|
+
*
|
|
12
|
+
* Why this mode may relax vouch's unattended refusal: the vouch gates
|
|
13
|
+
* (identity, TTY, `--yes`, the docs lock) all defend the WRITE — a
|
|
14
|
+
* `status: verified` no person stood behind. The pack writes nothing and can
|
|
15
|
+
* stamp nothing, so refusing it unattended would only stop agents from doing
|
|
16
|
+
* the one thing they are supposed to do here: prepare the exact reading list
|
|
17
|
+
* a HUMAN then works through before running the vouch itself, which keeps
|
|
18
|
+
* every one of its gates. That is also why `--pack --yes` is refused at the
|
|
19
|
+
* flag boundary (vouch.ts): the two flags point at opposite halves of the
|
|
20
|
+
* act, and a pack that stamped would defeat the read it just prescribed.
|
|
21
|
+
* Journal recovery is different in kind: it is not a gate but a read-side
|
|
22
|
+
* NEED (run.ts rolls it forward "before verification reads a byte" precisely
|
|
23
|
+
* because it changes files a reader has already read), and the pack cannot
|
|
24
|
+
* perform it because recovery is itself a write — so `buildPack` detects the
|
|
25
|
+
* pending journal and reports it instead. What survives unchanged is the
|
|
26
|
+
* wrong-repo gate — the source delta resolves `sources` against the
|
|
27
|
+
* service's own repo, so from anywhere else the paths are someone else's.
|
|
28
|
+
*
|
|
29
|
+
* The fail-closed doctrine, stated once for all three parts: when git cannot
|
|
30
|
+
* answer — no repository, no history, the walk's cap passed, a decline
|
|
31
|
+
* mid-walk — the body degrades to "full read", never to a guessed diff; and
|
|
32
|
+
* an unanswerable question never shrinks the list, because "nobody could
|
|
33
|
+
* look" is not "nothing changed". Only the axis's UNCHANGED list may licence
|
|
34
|
+
* skipping a section, and it is only ever computed from a found ancestor or
|
|
35
|
+
* a digest-equal body.
|
|
36
|
+
*/
|
|
37
|
+
import { existsSync } from "node:fs";
|
|
38
|
+
import { join } from "node:path";
|
|
39
|
+
import { loadFile } from "../../../core/c4/likec4.js";
|
|
40
|
+
import { serviceResolver } from "../../../core/c4/resolve/service.js";
|
|
41
|
+
import { repoPath } from "../../../core/envelope/json.js";
|
|
42
|
+
import { parseFrontmatter, rawBody, stringField } from "../../../core/document/frontmatter.js";
|
|
43
|
+
import { sectionHeadings } from "../../../core/document/parse.js";
|
|
44
|
+
import { bodyDiffText, findVouchedAncestor } from "../../../core/provenance/gitq/vouched-ancestor.js";
|
|
45
|
+
import { contentDigest, decodeSourceIndex, sourceDelta } from "../../../core/provenance/stamp.js";
|
|
46
|
+
import { landscapePath, servicePathsAt, SPEC_AXES, unfiledServicePaths } from "../../../core/repo/paths.js";
|
|
47
|
+
import { enumeratedServices } from "../../../core/repo/service-target.js";
|
|
48
|
+
import { COMMIT_INTENT } from "../../../core/staging/interrupted.js";
|
|
49
|
+
import { NotUtf8Error, readUtf8 } from "../../../core/staging/writes.js";
|
|
50
|
+
import { landscapeEvidence } from "../../../core/vocabulary/maturity.js";
|
|
51
|
+
import { noLivingSpecMessage, verifySpec } from "../vet/verify.js";
|
|
52
|
+
import { forwardSample, priorScope, sectionDelta } from "./sections.js";
|
|
53
|
+
async function readAxis(path) {
|
|
54
|
+
try {
|
|
55
|
+
const raw = await readUtf8(path);
|
|
56
|
+
return { kind: "read", raw, fm: parseFrontmatter(raw) };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (!(err instanceof NotUtf8Error))
|
|
60
|
+
throw err;
|
|
61
|
+
return { kind: "unreadable", reason: err.message };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function buildPack(req) {
|
|
65
|
+
// One enumeration answers both questions this function has: where the
|
|
66
|
+
// service's files live (a filed service is not at the root join), and which
|
|
67
|
+
// ids the landscape's resolver may bind to (the same `known` set every
|
|
68
|
+
// other landscape reader passes). The two-line resolution below is
|
|
69
|
+
// `locateServicePaths` (core/repo/service-target.ts) inlined — that helper
|
|
70
|
+
// enumerates internally, and calling it here would walk the tree twice.
|
|
71
|
+
const entries = await enumeratedServices(req.docsDir);
|
|
72
|
+
const entry = entries.find((s) => s.id === req.service);
|
|
73
|
+
const paths = entry === undefined ? unfiledServicePaths(req.docsDir, req.service) : servicePathsAt(entry.dir);
|
|
74
|
+
if (!existsSync(paths.spec)) {
|
|
75
|
+
// One sentence, from `vet/verify.ts`: these commands must not describe the
|
|
76
|
+
// same absence differently, and the fix — adopt first — is the same fix.
|
|
77
|
+
return { ok: false, code: "unknown-target", message: noLivingSpecMessage(paths.spec, req.service) };
|
|
78
|
+
}
|
|
79
|
+
const [specAxis, archAxis] = SPEC_AXES;
|
|
80
|
+
const specRead = await readAxis(paths[specAxis.key]);
|
|
81
|
+
// First vouch is a property of the REQUIRED axis: with neither digest
|
|
82
|
+
// stamped on spec.md there is no prior read to diff against, so the pack is
|
|
83
|
+
// the whole document, landscape claims first. A malformed or unreadable
|
|
84
|
+
// header deliberately does NOT count as first-vouch — it cannot prove the
|
|
85
|
+
// stamps absent, and claiming "first vouch" over a document that may carry
|
|
86
|
+
// one would order the read around a guess.
|
|
87
|
+
const firstVouch = specRead.kind === "read" &&
|
|
88
|
+
!specRead.fm.malformed &&
|
|
89
|
+
stringField(specRead.fm, "content_digest") === undefined &&
|
|
90
|
+
stringField(specRead.fm, "sources_digest") === undefined;
|
|
91
|
+
const spec = await packAxis(req, { path: paths[specAxis.key], file: specAxis.file, read: specRead });
|
|
92
|
+
let archSpec = null;
|
|
93
|
+
if (existsSync(paths[archAxis.key])) {
|
|
94
|
+
const archRead = await readAxis(paths[archAxis.key]);
|
|
95
|
+
archSpec = await packAxis(req, { path: paths[archAxis.key], file: archAxis.file, read: archRead });
|
|
96
|
+
}
|
|
97
|
+
const knownIds = new Set(entries.map((s) => s.id));
|
|
98
|
+
return {
|
|
99
|
+
ok: true,
|
|
100
|
+
report: {
|
|
101
|
+
service: req.service,
|
|
102
|
+
packMode: firstVouch ? "first-vouch" : "re-vouch",
|
|
103
|
+
// One existsSync, the same one run.ts pays before verification reads a
|
|
104
|
+
// byte: a predecessor's journal means the stamps just read may predate
|
|
105
|
+
// the write it was killed inside. The pack cannot recover (a write) —
|
|
106
|
+
// it warns, and the next journaled writer rolls the journal forward.
|
|
107
|
+
pendingCommit: existsSync(join(req.docsDir, COMMIT_INTENT)),
|
|
108
|
+
spec,
|
|
109
|
+
archSpec,
|
|
110
|
+
landscape: firstVouch ? await landscapeSlice(req.docsDir, req.service, knownIds) : null,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** One spec-axis file's full share of the pack: body verdict, source verdict, stamp fields. */
|
|
115
|
+
async function packAxis(req, axis) {
|
|
116
|
+
const rel = repoPath(req.docsDir, axis.path);
|
|
117
|
+
// The source half rides on verifySpec — the vouch's own vetting, message
|
|
118
|
+
// for message. The pack never refuses over sources: "your re-vouch will
|
|
119
|
+
// refuse, fix this first" IS the worklist, so the refusal sentence travels
|
|
120
|
+
// as the `unavailable` reason instead of an exit code.
|
|
121
|
+
const vetted = await verifySpec({ service: req.service, repoDir: req.repoDir }, axis.path, axis.file);
|
|
122
|
+
// What the digest recompute would NOT hash. Empty on a refusal because
|
|
123
|
+
// nobody walked — never because there is nothing to say.
|
|
124
|
+
const skipped = vetted.ok ? vetted.skipped : [];
|
|
125
|
+
if (axis.read.kind === "unreadable") {
|
|
126
|
+
// Per-axis containment: an undecodable file suspends THIS axis with the
|
|
127
|
+
// decode error as both reasons — the sibling axis still gets its pack.
|
|
128
|
+
return {
|
|
129
|
+
path: rel,
|
|
130
|
+
file: axis.file,
|
|
131
|
+
body: { kind: "full-read", reason: axis.read.reason },
|
|
132
|
+
sources: { kind: "unavailable", reason: vetted.ok ? axis.read.reason : vetted.message },
|
|
133
|
+
skipped,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const { raw, fm } = axis.read;
|
|
137
|
+
const vouchedBy = stringField(fm, "vouched_by");
|
|
138
|
+
const lastVerified = stringField(fm, "last_verified");
|
|
139
|
+
const body = await bodyArm(req, { rel, raw, fm });
|
|
140
|
+
const sources = sourcesArm(vetted, fm);
|
|
141
|
+
const stampedScope = priorScope(fm, body.kind === "unchanged" ? rawBody(raw) : null);
|
|
142
|
+
return {
|
|
143
|
+
path: rel,
|
|
144
|
+
file: axis.file,
|
|
145
|
+
...(vouchedBy === undefined ? {} : { vouchedBy }),
|
|
146
|
+
...(lastVerified === undefined ? {} : { lastVerified }),
|
|
147
|
+
body,
|
|
148
|
+
sources,
|
|
149
|
+
skipped,
|
|
150
|
+
// A full read is exactly where the heading listing IS the reading plan —
|
|
151
|
+
// per axis, not per mode, so an arch.spec.md created after the last vouch
|
|
152
|
+
// gets its plan inside a re-vouch pack. `rawBody` first so no frontmatter
|
|
153
|
+
// line can ever masquerade as a section.
|
|
154
|
+
...(body.kind === "full-read" ? { headings: sectionHeadings(rawBody(raw)).map((h) => h.text) } : {}),
|
|
155
|
+
// Only an UNCHANGED body can license naming what the last sampled vouch
|
|
156
|
+
// read: the recompute needs the bytes that vouch was taken over, and a
|
|
157
|
+
// digest-equal body is exactly those bytes. When the body has moved the
|
|
158
|
+
// scope is still reported — it still means the document was not read in
|
|
159
|
+
// full — with no covered list behind it. Reaching back to the vouched
|
|
160
|
+
// ancestor for the older body would be more information; it would also
|
|
161
|
+
// put a git walk behind a claim about what a person read, and the answer
|
|
162
|
+
// when git cannot speak would have to be this same one.
|
|
163
|
+
...(stampedScope === null ? {} : { vouchScope: stampedScope }),
|
|
164
|
+
...(req.sample === undefined || !vetted.ok
|
|
165
|
+
? {}
|
|
166
|
+
: { sample: forwardSample({ service: req.service, raw, sourcesDigest: vetted.digest, n: req.sample }) }),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/** The body verdict: unchanged, a diff from the vouched ancestor, or an honest full read. */
|
|
170
|
+
async function bodyArm(req, doc) {
|
|
171
|
+
// Deliberately NOT branched on the report-level first-vouch mode: the mode
|
|
172
|
+
// orders the read (landscape first), but each axis answers from its OWN
|
|
173
|
+
// stamps. In the one corpus where they disagree — spec.md hand-reverted to
|
|
174
|
+
// draft while arch.spec.md still carries a stamp — the stamped axis gets
|
|
175
|
+
// its real diff rather than a false "nobody has read this yet".
|
|
176
|
+
if (doc.fm.malformed) {
|
|
177
|
+
return {
|
|
178
|
+
kind: "full-read",
|
|
179
|
+
reason: "the frontmatter cannot be read as YAML, so whatever content_digest it carries is unreachable — fix the header, then read the whole file",
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const stamped = stringField(doc.fm, "content_digest");
|
|
183
|
+
if (stamped === undefined) {
|
|
184
|
+
return {
|
|
185
|
+
kind: "full-read",
|
|
186
|
+
reason: stringField(doc.fm, "sources_digest") === undefined
|
|
187
|
+
? "this file has never been vouched, so the whole of it is the read"
|
|
188
|
+
: "the last vouch predates content_digest, so no vouched body exists to diff from — read the whole file",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// The cheap answer first, and without git: the digest recipe is byte-exact
|
|
192
|
+
// over the working-tree file, so equality here IS "no byte of the body
|
|
193
|
+
// moved since the stamp".
|
|
194
|
+
if (contentDigest(doc.raw) === stamped)
|
|
195
|
+
return { kind: "unchanged" };
|
|
196
|
+
const ancestor = await findVouchedAncestor(req.docsDir, doc.rel, stamped);
|
|
197
|
+
if (ancestor.kind !== "found") {
|
|
198
|
+
return { kind: "full-read", reason: ancestor.kind === "none" ? ancestor.reason : ancestor.detail };
|
|
199
|
+
}
|
|
200
|
+
const diff = await bodyDiffText(req.docsDir, ancestor.commit, doc.rel);
|
|
201
|
+
// An ancestor without a printable diff could still licence a section delta,
|
|
202
|
+
// but a pack that says "these sections changed, no diff shown" invites
|
|
203
|
+
// skipping the rest on this run's partial word — degrade the whole arm to
|
|
204
|
+
// the full read instead; read more, never less.
|
|
205
|
+
if (diff.kind === "failed")
|
|
206
|
+
return { kind: "full-read", reason: diff.reason };
|
|
207
|
+
return {
|
|
208
|
+
kind: "diff",
|
|
209
|
+
ancestorCommit: ancestor.commit,
|
|
210
|
+
diff: diff.diff,
|
|
211
|
+
sections: sectionDelta(rawBody(ancestor.text), rawBody(doc.raw)),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/** The source verdict, from the vouch's own vetting plus the stamped digests. */
|
|
215
|
+
function sourcesArm(vetted, fm) {
|
|
216
|
+
if (!vetted.ok)
|
|
217
|
+
return { kind: "unavailable", reason: vetted.message };
|
|
218
|
+
const stamped = stringField(fm, "sources_digest");
|
|
219
|
+
if (stamped === undefined)
|
|
220
|
+
return { kind: "unvouched" };
|
|
221
|
+
if (vetted.digest === stamped)
|
|
222
|
+
return { kind: "unchanged" };
|
|
223
|
+
const index = decodeSourceIndex(stringField(fm, "sources_files"));
|
|
224
|
+
const delta = sourceDelta(index, vetted.index);
|
|
225
|
+
if (delta === null)
|
|
226
|
+
return { kind: "uncounted", countThen: index.count ?? null, countNow: vetted.index.length };
|
|
227
|
+
return { kind: "delta", ...delta };
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* The fleet map's claims about the service — a first vouch reads these before
|
|
231
|
+
* the spec, because the landscape is the one document making claims ABOUT the
|
|
232
|
+
* service that the person is not the author of. Absence and unparseability
|
|
233
|
+
* both come back as `silent`: per landscapeEvidence's own rule they prove
|
|
234
|
+
* nothing about who calls the service, and the pack says so rather than
|
|
235
|
+
* printing an empty edge list that reads as "nobody does".
|
|
236
|
+
*/
|
|
237
|
+
async function landscapeSlice(docsDir, service, known) {
|
|
238
|
+
const silent = {
|
|
239
|
+
kind: "silent",
|
|
240
|
+
reason: `the fleet map says nothing about ${service} (absent or unparseable)`,
|
|
241
|
+
};
|
|
242
|
+
const path = landscapePath(docsDir);
|
|
243
|
+
if (!existsSync(path))
|
|
244
|
+
return silent;
|
|
245
|
+
let land;
|
|
246
|
+
try {
|
|
247
|
+
land = await loadFile(path);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// Unreadable is not "no claims" — but for a reading list both collapse to
|
|
251
|
+
// the same honest sentence: the map cannot brief this read.
|
|
252
|
+
return silent;
|
|
253
|
+
}
|
|
254
|
+
if (land.errors.length > 0)
|
|
255
|
+
return silent;
|
|
256
|
+
const svcOf = serviceResolver(land.elements, known);
|
|
257
|
+
const evidence = landscapeEvidence({
|
|
258
|
+
id: service,
|
|
259
|
+
parses: true,
|
|
260
|
+
relationships: land.relationships,
|
|
261
|
+
elementIds: land.elements.map((e) => e.id),
|
|
262
|
+
svcOf,
|
|
263
|
+
});
|
|
264
|
+
return { kind: "edges", inbound: evidence.inbound, outbound: evidence.outbound };
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=pack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack.js","sourceRoot":"","sources":["../../../../src/commands/vouch/pack/pack.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The re-vouch reading pack: everything `loam vouch --pack` computes and\n * nothing it prints. Three derivations per spec-axis file, all read-only and\n * all from stamps `loam vouch` already writes — (a) the body's diff from the\n * last commit whose version of the file hashes to the stamped\n * `content_digest`, (b) the source files that moved against the stamped\n * per-file index, (c) the sections whose text is identical to the vouched\n * ancestor's, which the person need not re-read. Nothing here writes, locks\n * or stamps; a \"pack\" in vouch's vocabulary is always the READING pack — the\n * context pack (`core/pack/`) is a different artifact for a different reader.\n *\n * Why this mode may relax vouch's unattended refusal: the vouch gates\n * (identity, TTY, `--yes`, the docs lock) all defend the WRITE — a\n * `status: verified` no person stood behind. The pack writes nothing and can\n * stamp nothing, so refusing it unattended would only stop agents from doing\n * the one thing they are supposed to do here: prepare the exact reading list\n * a HUMAN then works through before running the vouch itself, which keeps\n * every one of its gates. That is also why `--pack --yes` is refused at the\n * flag boundary (vouch.ts): the two flags point at opposite halves of the\n * act, and a pack that stamped would defeat the read it just prescribed.\n * Journal recovery is different in kind: it is not a gate but a read-side\n * NEED (run.ts rolls it forward \"before verification reads a byte\" precisely\n * because it changes files a reader has already read), and the pack cannot\n * perform it because recovery is itself a write — so `buildPack` detects the\n * pending journal and reports it instead. What survives unchanged is the\n * wrong-repo gate — the source delta resolves `sources` against the\n * service's own repo, so from anywhere else the paths are someone else's.\n *\n * The fail-closed doctrine, stated once for all three parts: when git cannot\n * answer — no repository, no history, the walk's cap passed, a decline\n * mid-walk — the body degrades to \"full read\", never to a guessed diff; and\n * an unanswerable question never shrinks the list, because \"nobody could\n * look\" is not \"nothing changed\". Only the axis's UNCHANGED list may licence\n * skipping a section, and it is only ever computed from a found ancestor or\n * a digest-equal body.\n */\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { loadFile } from \"../../../core/c4/likec4.js\";\nimport { serviceResolver } from \"../../../core/c4/resolve/service.js\";\nimport { repoPath } from \"../../../core/envelope/json.js\";\nimport { parseFrontmatter, rawBody, stringField, type Frontmatter } from \"../../../core/document/frontmatter.js\";\nimport { sectionHeadings } from \"../../../core/document/parse.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { bodyDiffText, findVouchedAncestor } from \"../../../core/provenance/gitq/vouched-ancestor.js\";\nimport { contentDigest, decodeSourceIndex, sourceDelta } from \"../../../core/provenance/stamp.js\";\nimport { landscapePath, servicePathsAt, SPEC_AXES, unfiledServicePaths } from \"../../../core/repo/paths.js\";\nimport { enumeratedServices } from \"../../../core/repo/service-target.js\";\nimport { COMMIT_INTENT } from \"../../../core/staging/interrupted.js\";\nimport { NotUtf8Error, readUtf8 } from \"../../../core/staging/writes.js\";\nimport { landscapeEvidence } from \"../../../core/vocabulary/maturity.js\";\nimport { noLivingSpecMessage, verifySpec } from \"../vet/verify.js\";\nimport type { PackAxis, PackBody, PackLandscape, PackOutcome, PackRequest, PackSources } from \"./contract.js\";\nimport { forwardSample, priorScope, sectionDelta } from \"./sections.js\";\n\n/** One axis file off disk: its text and header, or the reason nobody could read it. */\ntype AxisRead =\n | { kind: \"read\"; raw: string; fm: Frontmatter }\n | { kind: \"unreadable\"; reason: string };\n\nasync function readAxis(path: string): Promise<AxisRead> {\n try {\n const raw = await readUtf8(path);\n return { kind: \"read\", raw, fm: parseFrontmatter(raw) };\n } catch (err) {\n if (!(err instanceof NotUtf8Error)) throw err;\n return { kind: \"unreadable\", reason: err.message };\n }\n}\n\nexport async function buildPack(req: PackRequest): Promise<PackOutcome> {\n // One enumeration answers both questions this function has: where the\n // service's files live (a filed service is not at the root join), and which\n // ids the landscape's resolver may bind to (the same `known` set every\n // other landscape reader passes). The two-line resolution below is\n // `locateServicePaths` (core/repo/service-target.ts) inlined — that helper\n // enumerates internally, and calling it here would walk the tree twice.\n const entries = await enumeratedServices(req.docsDir);\n const entry = entries.find((s) => s.id === req.service);\n const paths = entry === undefined ? unfiledServicePaths(req.docsDir, req.service) : servicePathsAt(entry.dir);\n if (!existsSync(paths.spec)) {\n // One sentence, from `vet/verify.ts`: these commands must not describe the\n // same absence differently, and the fix — adopt first — is the same fix.\n return { ok: false, code: \"unknown-target\", message: noLivingSpecMessage(paths.spec, req.service) };\n }\n const [specAxis, archAxis] = SPEC_AXES;\n const specRead = await readAxis(paths[specAxis.key]);\n\n // First vouch is a property of the REQUIRED axis: with neither digest\n // stamped on spec.md there is no prior read to diff against, so the pack is\n // the whole document, landscape claims first. A malformed or unreadable\n // header deliberately does NOT count as first-vouch — it cannot prove the\n // stamps absent, and claiming \"first vouch\" over a document that may carry\n // one would order the read around a guess.\n const firstVouch =\n specRead.kind === \"read\" &&\n !specRead.fm.malformed &&\n stringField(specRead.fm, \"content_digest\") === undefined &&\n stringField(specRead.fm, \"sources_digest\") === undefined;\n\n const spec = await packAxis(req, { path: paths[specAxis.key], file: specAxis.file, read: specRead });\n let archSpec: PackAxis | null = null;\n if (existsSync(paths[archAxis.key])) {\n const archRead = await readAxis(paths[archAxis.key]);\n archSpec = await packAxis(req, { path: paths[archAxis.key], file: archAxis.file, read: archRead });\n }\n const knownIds = new Set<string>(entries.map((s) => s.id));\n return {\n ok: true,\n report: {\n service: req.service,\n packMode: firstVouch ? \"first-vouch\" : \"re-vouch\",\n // One existsSync, the same one run.ts pays before verification reads a\n // byte: a predecessor's journal means the stamps just read may predate\n // the write it was killed inside. The pack cannot recover (a write) —\n // it warns, and the next journaled writer rolls the journal forward.\n pendingCommit: existsSync(join(req.docsDir, COMMIT_INTENT)),\n spec,\n archSpec,\n landscape: firstVouch ? await landscapeSlice(req.docsDir, req.service, knownIds) : null,\n },\n };\n}\n\n/** One spec-axis file's full share of the pack: body verdict, source verdict, stamp fields. */\nasync function packAxis(\n req: PackRequest,\n axis: { path: string; file: string; read: AxisRead },\n): Promise<PackAxis> {\n const rel = repoPath(req.docsDir, axis.path);\n // The source half rides on verifySpec — the vouch's own vetting, message\n // for message. The pack never refuses over sources: \"your re-vouch will\n // refuse, fix this first\" IS the worklist, so the refusal sentence travels\n // as the `unavailable` reason instead of an exit code.\n const vetted = await verifySpec({ service: req.service, repoDir: req.repoDir }, axis.path, axis.file);\n // What the digest recompute would NOT hash. Empty on a refusal because\n // nobody walked — never because there is nothing to say.\n const skipped = vetted.ok ? vetted.skipped : [];\n\n if (axis.read.kind === \"unreadable\") {\n // Per-axis containment: an undecodable file suspends THIS axis with the\n // decode error as both reasons — the sibling axis still gets its pack.\n return {\n path: rel,\n file: axis.file,\n body: { kind: \"full-read\", reason: axis.read.reason },\n sources: { kind: \"unavailable\", reason: vetted.ok ? axis.read.reason : vetted.message },\n skipped,\n };\n }\n const { raw, fm } = axis.read;\n const vouchedBy = stringField(fm, \"vouched_by\");\n const lastVerified = stringField(fm, \"last_verified\");\n const body = await bodyArm(req, { rel, raw, fm });\n const sources = sourcesArm(vetted, fm);\n const stampedScope = priorScope(fm, body.kind === \"unchanged\" ? rawBody(raw) : null);\n return {\n path: rel,\n file: axis.file,\n ...(vouchedBy === undefined ? {} : { vouchedBy }),\n ...(lastVerified === undefined ? {} : { lastVerified }),\n body,\n sources,\n skipped,\n // A full read is exactly where the heading listing IS the reading plan —\n // per axis, not per mode, so an arch.spec.md created after the last vouch\n // gets its plan inside a re-vouch pack. `rawBody` first so no frontmatter\n // line can ever masquerade as a section.\n ...(body.kind === \"full-read\" ? { headings: sectionHeadings(rawBody(raw)).map((h) => h.text) } : {}),\n // Only an UNCHANGED body can license naming what the last sampled vouch\n // read: the recompute needs the bytes that vouch was taken over, and a\n // digest-equal body is exactly those bytes. When the body has moved the\n // scope is still reported — it still means the document was not read in\n // full — with no covered list behind it. Reaching back to the vouched\n // ancestor for the older body would be more information; it would also\n // put a git walk behind a claim about what a person read, and the answer\n // when git cannot speak would have to be this same one.\n ...(stampedScope === null ? {} : { vouchScope: stampedScope }),\n ...(req.sample === undefined || !vetted.ok\n ? {}\n : { sample: forwardSample({ service: req.service, raw, sourcesDigest: vetted.digest, n: req.sample }) }),\n };\n}\n\n/** The body verdict: unchanged, a diff from the vouched ancestor, or an honest full read. */\nasync function bodyArm(\n req: PackRequest,\n doc: { rel: string; raw: string; fm: Frontmatter },\n): Promise<PackBody> {\n // Deliberately NOT branched on the report-level first-vouch mode: the mode\n // orders the read (landscape first), but each axis answers from its OWN\n // stamps. In the one corpus where they disagree — spec.md hand-reverted to\n // draft while arch.spec.md still carries a stamp — the stamped axis gets\n // its real diff rather than a false \"nobody has read this yet\".\n if (doc.fm.malformed) {\n return {\n kind: \"full-read\",\n reason: \"the frontmatter cannot be read as YAML, so whatever content_digest it carries is unreachable — fix the header, then read the whole file\",\n };\n }\n const stamped = stringField(doc.fm, \"content_digest\");\n if (stamped === undefined) {\n return {\n kind: \"full-read\",\n reason:\n stringField(doc.fm, \"sources_digest\") === undefined\n ? \"this file has never been vouched, so the whole of it is the read\"\n : \"the last vouch predates content_digest, so no vouched body exists to diff from — read the whole file\",\n };\n }\n // The cheap answer first, and without git: the digest recipe is byte-exact\n // over the working-tree file, so equality here IS \"no byte of the body\n // moved since the stamp\".\n if (contentDigest(doc.raw) === stamped) return { kind: \"unchanged\" };\n\n const ancestor = await findVouchedAncestor(req.docsDir, doc.rel, stamped);\n if (ancestor.kind !== \"found\") {\n return { kind: \"full-read\", reason: ancestor.kind === \"none\" ? ancestor.reason : ancestor.detail };\n }\n const diff = await bodyDiffText(req.docsDir, ancestor.commit, doc.rel);\n // An ancestor without a printable diff could still licence a section delta,\n // but a pack that says \"these sections changed, no diff shown\" invites\n // skipping the rest on this run's partial word — degrade the whole arm to\n // the full read instead; read more, never less.\n if (diff.kind === \"failed\") return { kind: \"full-read\", reason: diff.reason };\n return {\n kind: \"diff\",\n ancestorCommit: ancestor.commit,\n diff: diff.diff,\n sections: sectionDelta(rawBody(ancestor.text), rawBody(doc.raw)),\n };\n}\n\n/** The source verdict, from the vouch's own vetting plus the stamped digests. */\nfunction sourcesArm(vetted: Awaited<ReturnType<typeof verifySpec>>, fm: Frontmatter): PackSources {\n if (!vetted.ok) return { kind: \"unavailable\", reason: vetted.message };\n const stamped = stringField(fm, \"sources_digest\");\n if (stamped === undefined) return { kind: \"unvouched\" };\n if (vetted.digest === stamped) return { kind: \"unchanged\" };\n const index = decodeSourceIndex(stringField(fm, \"sources_files\"));\n const delta = sourceDelta(index, vetted.index);\n if (delta === null) return { kind: \"uncounted\", countThen: index.count ?? null, countNow: vetted.index.length };\n return { kind: \"delta\", ...delta };\n}\n\n/**\n * The fleet map's claims about the service — a first vouch reads these before\n * the spec, because the landscape is the one document making claims ABOUT the\n * service that the person is not the author of. Absence and unparseability\n * both come back as `silent`: per landscapeEvidence's own rule they prove\n * nothing about who calls the service, and the pack says so rather than\n * printing an empty edge list that reads as \"nobody does\".\n */\nasync function landscapeSlice(docsDir: DocsDir, service: string, known: Set<string>): Promise<PackLandscape> {\n const silent: PackLandscape = {\n kind: \"silent\",\n reason: `the fleet map says nothing about ${service} (absent or unparseable)`,\n };\n const path = landscapePath(docsDir);\n if (!existsSync(path)) return silent;\n let land: Awaited<ReturnType<typeof loadFile>>;\n try {\n land = await loadFile(path);\n } catch {\n // Unreadable is not \"no claims\" — but for a reading list both collapse to\n // the same honest sentence: the map cannot brief this read.\n return silent;\n }\n if (land.errors.length > 0) return silent;\n const svcOf = serviceResolver(land.elements, known);\n const evidence = landscapeEvidence({\n id: service,\n parses: true,\n relationships: land.relationships,\n elementIds: land.elements.map((e) => e.id),\n svcOf,\n });\n return { kind: \"edges\", inbound: evidence.inbound, outbound: evidence.outbound };\n}\n"]}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reading pack's two renderings — the human view in the proposal's order
|
|
3
|
+
* (per axis: the body diff, then the source worklist, then the sections
|
|
4
|
+
* already covered; first vouch: the fleet map's claims, then everything), and
|
|
5
|
+
* the `--json` envelope. `runPack` is the whole command surface of
|
|
6
|
+
* `--pack`: vouch.ts hands over here as soon as the flag combination is
|
|
7
|
+
* legal, so the write path's machinery — identity, prompt, lock, journal —
|
|
8
|
+
* never loads for a run that cannot write. Exit 0 covers every computed pack
|
|
9
|
+
* INCLUDING full-read fallbacks ("read everything" is an answer, not a
|
|
10
|
+
* failure); only refusals exit 1.
|
|
11
|
+
*/
|
|
12
|
+
import { emitJson, fail } from "../../../core/envelope/json.js";
|
|
13
|
+
import { plural } from "../../policy/format.js";
|
|
14
|
+
import { buildPack } from "./pack.js";
|
|
15
|
+
export async function runPack(req) {
|
|
16
|
+
const outcome = await buildPack({
|
|
17
|
+
docsDir: req.docsDir,
|
|
18
|
+
service: req.service,
|
|
19
|
+
repoDir: req.repoDir,
|
|
20
|
+
...(req.sample === undefined ? {} : { sample: req.sample }),
|
|
21
|
+
});
|
|
22
|
+
if (!outcome.ok)
|
|
23
|
+
return fail(req.json, outcome.code, outcome.message);
|
|
24
|
+
if (req.json) {
|
|
25
|
+
emitJson(packPayload(outcome.report));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
printPack(outcome.report);
|
|
29
|
+
}
|
|
30
|
+
/** The additive `--json` shape: `mode: "pack"` beside the write path's stamp payload. */
|
|
31
|
+
function packPayload(report) {
|
|
32
|
+
return {
|
|
33
|
+
command: "vouch",
|
|
34
|
+
mode: "pack",
|
|
35
|
+
service: report.service,
|
|
36
|
+
packMode: report.packMode,
|
|
37
|
+
pendingCommit: report.pendingCommit,
|
|
38
|
+
spec: axisPayload(report.spec),
|
|
39
|
+
archSpec: report.archSpec === null ? null : axisPayload(report.archSpec),
|
|
40
|
+
...(report.landscape === null ? {} : { landscape: report.landscape }),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** One axis, stamp fields under their frontmatter spellings. */
|
|
44
|
+
function axisPayload(axis) {
|
|
45
|
+
return {
|
|
46
|
+
path: axis.path,
|
|
47
|
+
file: axis.file,
|
|
48
|
+
...(axis.vouchedBy === undefined ? {} : { vouched_by: axis.vouchedBy }),
|
|
49
|
+
...(axis.lastVerified === undefined ? {} : { last_verified: axis.lastVerified }),
|
|
50
|
+
body: axis.body,
|
|
51
|
+
sources: axis.sources,
|
|
52
|
+
skipped: axis.skipped,
|
|
53
|
+
...(axis.headings === undefined ? {} : { headings: axis.headings }),
|
|
54
|
+
...(axis.vouchScope === undefined ? {} : { vouchScope: axis.vouchScope }),
|
|
55
|
+
...(axis.sample === undefined ? {} : { sample: axis.sample }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function printPack(report) {
|
|
59
|
+
// Before anything else: a pack computed over a half-committed docs repo may
|
|
60
|
+
// be describing bytes the next journaled writer will replace, and a person
|
|
61
|
+
// must know that before they spend a read on it.
|
|
62
|
+
if (report.pendingCommit) {
|
|
63
|
+
console.log("⚠ an interrupted docs-repo commit is pending — what is on disk (this pack included) may " +
|
|
64
|
+
"predate it. Any journaled docs-repo writer (`loam vouch`, `loam archive`) rolls it " +
|
|
65
|
+
"forward on its next run; re-run --pack after.\n");
|
|
66
|
+
}
|
|
67
|
+
if (report.packMode === "first-vouch") {
|
|
68
|
+
console.log(`${report.service} first-vouch reading pack — the whole document is the read\n`);
|
|
69
|
+
printLandscape(report);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(`${report.service} re-vouch reading pack\n`);
|
|
73
|
+
}
|
|
74
|
+
for (const axis of [report.spec, ...(report.archSpec === null ? [] : [report.archSpec])]) {
|
|
75
|
+
printAxis(axis);
|
|
76
|
+
}
|
|
77
|
+
console.log(`\nWhen the read is done, a person runs \`loam vouch --service ${report.service}\` in the service's own repo — the pack stamps nothing.`);
|
|
78
|
+
}
|
|
79
|
+
/** The fleet map's claims — first, because the spec's author did not write them. */
|
|
80
|
+
function printLandscape(report) {
|
|
81
|
+
if (report.landscape === null)
|
|
82
|
+
return;
|
|
83
|
+
if (report.landscape.kind === "silent") {
|
|
84
|
+
console.log(` ${report.landscape.reason}\n`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const { inbound, outbound } = report.landscape;
|
|
88
|
+
if (inbound.length === 0 && outbound.length === 0) {
|
|
89
|
+
console.log(` the fleet map draws no edge touching ${report.service}\n`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log(" what the fleet map says:");
|
|
93
|
+
for (const edge of inbound)
|
|
94
|
+
console.log(` ${edgeLine(edge.service, report.service, edge)}`);
|
|
95
|
+
for (const edge of outbound)
|
|
96
|
+
console.log(` ${edgeLine(report.service, edge.service, edge)}`);
|
|
97
|
+
console.log("");
|
|
98
|
+
}
|
|
99
|
+
function edgeLine(from, to, edge) {
|
|
100
|
+
const label = edge.op !== null ? ` (${edge.op})` : edge.title !== null ? ` — ${edge.title}` : "";
|
|
101
|
+
return `${from} -> ${to}${label}`;
|
|
102
|
+
}
|
|
103
|
+
/** One axis in the proposal's order: (a) body, (b) source worklist, (c) already covered. */
|
|
104
|
+
function printAxis(axis) {
|
|
105
|
+
console.log(`${axis.path}\n`);
|
|
106
|
+
printBody(axis);
|
|
107
|
+
printSources(axis);
|
|
108
|
+
printSkipped(axis);
|
|
109
|
+
printSampledStamp(axis);
|
|
110
|
+
printCovered(axis);
|
|
111
|
+
// Under `--sample` the sampled list REPLACES the full heading listing —
|
|
112
|
+
// printing both would make the list a person must not skip look like the
|
|
113
|
+
// one they may. The diff above is never filtered: a sample narrows what the
|
|
114
|
+
// stamp CLAIMS, never what a reader is shown.
|
|
115
|
+
if (axis.sample !== undefined) {
|
|
116
|
+
printSample(axis.sample);
|
|
117
|
+
}
|
|
118
|
+
else if (axis.headings !== undefined) {
|
|
119
|
+
console.log(` sections to read (${axis.headings.length}):`);
|
|
120
|
+
for (const heading of axis.headings)
|
|
121
|
+
console.log(` ${heading}`);
|
|
122
|
+
console.log("");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The forward sample: exactly what the `--sample <n>` vouch after this pack
|
|
127
|
+
* will stand behind. The consequences are named in one line rather than
|
|
128
|
+
* restated at length — `sample/print.ts` says them in full at the prompt,
|
|
129
|
+
* which is the screen where somebody is about to commit to them.
|
|
130
|
+
*/
|
|
131
|
+
function printSample(sample) {
|
|
132
|
+
if (sample.covers) {
|
|
133
|
+
console.log(` sampled read: the sample reaches all ${sample.of} section(s) — the vouch after it is an ordinary full one.\n`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
console.log(` sampled read — ${sample.headings.length} of ${sample.of} section(s), seed=${sample.seed}:`);
|
|
137
|
+
console.log(" the preamble above the first heading — always read, never part of the count");
|
|
138
|
+
for (const heading of sample.headings)
|
|
139
|
+
console.log(` ${heading}`);
|
|
140
|
+
console.log(`\n Reading only these is what --sample means, and the stamp will say so: \`vouch_scope: sampled ` +
|
|
141
|
+
`${sample.headings.length}/${sample.of}\`, then \`sources.sampled-vouch\` until somebody reads the whole document.\n`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The last vouch's own scope, printed BEFORE the covered list it disqualifies
|
|
145
|
+
* — which sections that person actually read (`sections.ts`'s `priorScope`
|
|
146
|
+
* recomputes them from the stamped seed), and which have now survived a vouch
|
|
147
|
+
* without anybody looking. Where the read set cannot be recomputed, no
|
|
148
|
+
* covered set is named at all: an unreproducible sample licenses nothing.
|
|
149
|
+
*/
|
|
150
|
+
function printSampledStamp(axis) {
|
|
151
|
+
const scope = axis.vouchScope;
|
|
152
|
+
if (scope === undefined)
|
|
153
|
+
return;
|
|
154
|
+
const whose = `${axis.vouchedBy === undefined ? "" : ` by ${axis.vouchedBy}`}${axis.lastVerified === undefined ? "" : ` on ${axis.lastVerified}`}`;
|
|
155
|
+
console.log(scope.scope === null
|
|
156
|
+
? ` ⚠ the last vouch${whose} carries a vouch_scope this loam cannot read (\`${scope.stamped}\`) — graded as ` +
|
|
157
|
+
"SAMPLED, because an unreadable scope must never be taken for a full read."
|
|
158
|
+
: ` ⚠ the last vouch${whose} was SAMPLED: ${scope.scope.sections} of ${scope.scope.of} section(s), ` +
|
|
159
|
+
`seed=${scope.scope.seed}. "Unchanged since then" does not mean anybody read it.`);
|
|
160
|
+
if (scope.read === null) {
|
|
161
|
+
console.log(" which sections it read cannot be recomputed (the body moved, or the scope does not decode), so nothing here is covered.\n");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
console.log(` read at that vouch (${scope.read.length}): ${scope.read.join(" · ")}`);
|
|
165
|
+
if (scope.unread !== null && scope.unread.length > 0) {
|
|
166
|
+
console.log(` NEVER read by anyone (${scope.unread.length}) — this is the read:`);
|
|
167
|
+
for (const heading of scope.unread)
|
|
168
|
+
console.log(` ${heading}`);
|
|
169
|
+
}
|
|
170
|
+
console.log("");
|
|
171
|
+
}
|
|
172
|
+
function printBody(axis) {
|
|
173
|
+
const since = axis.lastVerified === undefined ? "the stamp" : axis.lastVerified;
|
|
174
|
+
switch (axis.body.kind) {
|
|
175
|
+
case "unchanged":
|
|
176
|
+
// The qualification is the whole point after a sampled vouch: the text
|
|
177
|
+
// did not move, and most of it was still never read. Saying "nothing to
|
|
178
|
+
// re-read" over that would be this feature's worst failure — a partial
|
|
179
|
+
// read reported as a finished one — so the sentence stops at what it
|
|
180
|
+
// can actually claim and hands off to the scope block below.
|
|
181
|
+
console.log(axis.vouchScope === undefined
|
|
182
|
+
? ` body unchanged since ${since} — nothing of the document itself to re-read\n`
|
|
183
|
+
: ` body unchanged since ${since} — but that vouch was sampled, so "unchanged" is not "read"\n`);
|
|
184
|
+
return;
|
|
185
|
+
case "full-read":
|
|
186
|
+
console.log(` full read: ${axis.body.reason}\n`);
|
|
187
|
+
return;
|
|
188
|
+
case "diff": {
|
|
189
|
+
// "The file's diff", not "the body's": a hand edit to the header after
|
|
190
|
+
// the vouch rides along in git's hunks, and promising body-only would
|
|
191
|
+
// make truthful noise read as a bug.
|
|
192
|
+
console.log(` body changed since ${since} — the file's diff from its last vouched state (${axis.body.ancestorCommit.slice(0, 12)}):\n`);
|
|
193
|
+
console.log(axis.body.diff.trimEnd());
|
|
194
|
+
const { changed, added, removed } = axis.body.sections;
|
|
195
|
+
const summary = [
|
|
196
|
+
...(changed.length > 0 ? [`changed: ${changed.join(", ")}`] : []),
|
|
197
|
+
...(added.length > 0 ? [`added: ${added.join(", ")}`] : []),
|
|
198
|
+
...(removed.length > 0 ? [`removed: ${removed.join(", ")}`] : []),
|
|
199
|
+
];
|
|
200
|
+
if (summary.length > 0)
|
|
201
|
+
console.log(`\n sections ${summary.join("; ")}`);
|
|
202
|
+
console.log("");
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function printSources(axis) {
|
|
208
|
+
switch (axis.sources.kind) {
|
|
209
|
+
case "unchanged":
|
|
210
|
+
console.log(" sources unchanged since the stamp\n");
|
|
211
|
+
return;
|
|
212
|
+
case "unvouched":
|
|
213
|
+
console.log(" sources carry no sources_digest yet — the vouch will stamp one\n");
|
|
214
|
+
return;
|
|
215
|
+
case "unavailable":
|
|
216
|
+
console.log(` sources — the re-vouch will refuse until this is fixed:\n ${axis.sources.reason}\n`);
|
|
217
|
+
return;
|
|
218
|
+
case "uncounted":
|
|
219
|
+
console.log(` sources changed — ${axis.sources.countThen === null ? "an unknown number of" : axis.sources.countThen} file(s) at the stamp, ` +
|
|
220
|
+
`${axis.sources.countNow} now, and the stamp cannot name which moved: re-read the sources\n`);
|
|
221
|
+
return;
|
|
222
|
+
case "delta": {
|
|
223
|
+
const { added, changed, removed } = axis.sources;
|
|
224
|
+
const moved = added.length + changed.length + removed.length;
|
|
225
|
+
// movedSources' one-column annotated layout, so a reader who knows the
|
|
226
|
+
// stale finding's shape reads this without learning a second one.
|
|
227
|
+
console.log(` sources — ${moved} path(s) moved since the stamp:`);
|
|
228
|
+
for (const path of added)
|
|
229
|
+
console.log(` added ${path}`);
|
|
230
|
+
for (const path of changed)
|
|
231
|
+
console.log(` changed ${path}`);
|
|
232
|
+
for (const path of removed)
|
|
233
|
+
console.log(` removed ${path}`);
|
|
234
|
+
console.log("");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* The hole in the promise, said BEFORE the stamp rather than only on
|
|
241
|
+
* vouch.ts's post-stamp screen: paths under the listed sources the digest
|
|
242
|
+
* will not hash. Same sentence as that screen, so the pre-vouch and
|
|
243
|
+
* post-vouch descriptions of one hole cannot drift apart.
|
|
244
|
+
*/
|
|
245
|
+
function printSkipped(axis) {
|
|
246
|
+
if (axis.skipped.length === 0)
|
|
247
|
+
return;
|
|
248
|
+
console.log(` ⚠ ${plural(axis.skipped.length, "path")} under those sources went unhashed — the vouch's digest says nothing about what is behind them:`);
|
|
249
|
+
for (const skip of axis.skipped)
|
|
250
|
+
console.log(` ${skip.path} — ${skip.reason}`);
|
|
251
|
+
console.log("");
|
|
252
|
+
}
|
|
253
|
+
/** (c): what the previous vouch already covers, so the read can stop where it should. */
|
|
254
|
+
function printCovered(axis) {
|
|
255
|
+
if (axis.body.kind !== "diff" || axis.body.sections.unchanged.length === 0)
|
|
256
|
+
return;
|
|
257
|
+
const by = axis.vouchedBy === undefined ? "" : ` by ${axis.vouchedBy}`;
|
|
258
|
+
const on = axis.lastVerified === undefined ? "" : ` on ${axis.lastVerified}`;
|
|
259
|
+
// The licence to skip rests entirely on somebody having read the section
|
|
260
|
+
// before. A sampled vouch did not read most of them, so after one this list
|
|
261
|
+
// is only "text that did not move" — it is still worth printing (a reader
|
|
262
|
+
// wants to know what is stable), but it must not be printed under a heading
|
|
263
|
+
// that says a person covered it.
|
|
264
|
+
console.log(axis.vouchScope === undefined
|
|
265
|
+
? ` unchanged — previously vouched${by}${on}:`
|
|
266
|
+
: ` unchanged since the sampled vouch${by}${on} — text that did not move, NOT a covered list:`);
|
|
267
|
+
for (const heading of axis.body.sections.unchanged)
|
|
268
|
+
console.log(` ${heading}`);
|
|
269
|
+
console.log("");
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=print.js.map
|