@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 @@
|
|
|
1
|
+
{"version":3,"file":"delta.js","sourceRoot":"","sources":["../../../src/commands/delta/delta.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { loadConfig } from \"../../core/envelope/config.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport { emitJson, emitJsonError, fail, repoPath, reportNoConfig, sayExplain } from \"../../core/envelope/json.js\";\nimport { loadFile } from \"../../core/c4/likec4.js\";\nimport { compareIds, nearestIds } from \"../../core/repo/entries.js\";\nimport { featurePaths, featureSpecPaths } from \"../../core/repo/paths.js\";\nimport { missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { parseRequirements } from \"../../core/document/parse.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { stripFrontmatter } from \"../../core/document/frontmatter.js\";\nimport { apiChanges } from \"../../core/projection/api.js\";\nimport { eventChanges } from \"../../core/projection/events.js\";\nimport { archSlice, introducedServices, livingServices } from \"../../core/projection/arch-slice.js\";\nimport { useCaseBlastRadius } from \"../../core/usecases/touch.js\";\nimport { featureCapabilityDeltas } from \"../../core/capabilities/delta/tree.js\";\nimport { capabilityDeltaSummaries } from \"../../core/capabilities/delta/summary.js\";\nimport { printApi, printArchSlice, printCapabilities, printEvents, printRequirements, printUseCases } from \"./print.js\";\nimport { indent } from \"./print.js\";\n\ninterface DeltaOptions {\n service?: string;\n json?: boolean;\n}\n\nexport function registerDelta(program: Command): void {\n program\n .command(\"delta\")\n .argument(\"<featureId>\", \"feature id, e.g. FEAT-101\")\n .description(\"Project a feature onto a service: why + requirement delta + C4 changes\")\n .option(\"--service <id>\", \"service to project onto (defaults to the configured service)\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (featureId: string, opts: DeltaOptions) => {\n const json = opts.json === true;\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n\n // The id grammar first, and on the RAW argument: `--service ../../etc`\n // reaches `featureSpecPaths` and reads from outside the feature directory.\n // One grammar for the whole tool (core/kernel/ids/service.ts).\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service, \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n }\n\n // The feature is resolved BEFORE the service is chosen, because every\n // sentence about the service (\"which ones does this feature touch?\") is\n // only answerable once the feature is known.\n const feature = await resolveFeature(config.docsDir, featureId, \"exclude\");\n if (!feature) {\n fail(json, \"unknown-target\", await missingFeatureMessage(config.docsDir, featureId));\n return;\n }\n // Canonical id from here on — the delta's tags carry `#FEAT-5`, so a raw\n // `FEAT-5-slug` argument used to empty the architecture slice silently.\n const { id } = feature;\n const paths = featurePaths(feature.dir);\n\n const deltaDoc = existsSync(paths.delta) ? await loadFile(paths.delta) : null;\n // Services the feature speaks about at all: one with a requirement delta,\n // or one its C4 delta introduces. This is the list a refusal quotes.\n const featureServices = [\n ...new Set([...feature.services, ...introducedServices(deltaDoc, id)]),\n ].sort(compareIds);\n\n const service = opts.service ?? config.service;\n if (!service) {\n // The refusal NAMES the choices. \"No service. Pass --service <id>\" told\n // the reader the shape of the flag and nothing about the answer, so the\n // next step was always to go list the feature's specs/ by hand — and an\n // agent had no way to recover at all. The list rides the JSON envelope\n // for the same reason.\n const message =\n `No service to project ${id} onto. Pass --service <id> or set 'service' in loam.json.` +\n (featureServices.length === 0\n ? ` ${id} carries no per-service delta yet.`\n : ` ${id} touches: ${featureServices.join(\", \")}.`);\n if (json) emitJsonError(\"invalid-option\", message, { feature: id, services: featureServices });\n else {\n console.error(message);\n // This arm refuses by hand because the envelope carries `services` as\n // data, which `fail()` has no room for — so the code and its lookup\n // are asked for explicitly, with the same code the branch above\n // emits. Without it this was one of the two refusals that most needed\n // `loam explain` and had no way to name it.\n sayExplain(\"invalid-option\");\n process.exitCode = 1;\n }\n return;\n }\n\n // A service nobody has heard of produces a perfectly plausible EMPTY\n // report — no requirements, no edges, \"no architecture change\" — which an\n // agent consuming this as a task brief reads as \"nothing to do here\".\n // A typo must never be indistinguishable from a finished service.\n const living = await livingServices(config.docsDir);\n if (!featureServices.includes(service) && !living.includes(service)) {\n const near = nearestIds(service, [...new Set([...featureServices, ...living])]);\n fail(\n json,\n \"unknown-target\",\n `No service '${service}': it is neither a services/${service}/ in the docs repo nor a service ${id} touches` +\n (featureServices.length === 0 ? \"\" : ` (${featureServices.join(\", \")})`) +\n (near.length === 0 ? \".\" : ` — did you mean ${near.map((n) => `'${n}'`).join(\" or \")}?`),\n );\n return;\n }\n\n // Why — business intent\n const intent = existsSync(paths.intent)\n ? stripFrontmatter(await readFile(paths.intent, \"utf8\")).trim()\n : null;\n\n // Requirement delta for this service (OpenSpec style), business and arch:\n // the same projection covers both axes, in the same shape, so the payload\n // stays one task — the arch requirements are the integration/ops half the\n // business ones never mention.\n const specPaths = featureSpecPaths(feature.dir, service);\n const reqs = existsSync(specPaths.spec)\n ? parseRequirements(await readFile(specPaths.spec, \"utf8\"))\n : [];\n const archReqs = existsSync(specPaths.archSpec)\n ? parseRequirements(await readFile(specPaths.archSpec, \"utf8\"))\n : [];\n\n // The contract axis. Until now no command surfaced it at all: the feature's\n // openapi.yaml was read by validate and by archive, and the one command\n // whose output IS the implementation task never mentioned it — so \"add the\n // endpoint\" was the half of the work the brief left out.\n const api = await apiChanges(specPaths.openapi);\n\n // The event axis, same reasoning: a feature's asyncapi.yaml is merged by\n // archive and graded by validate, so the brief must name what it changes\n // — a message the implementer was never told to publish is the same\n // dropped work as an endpoint the brief left out.\n const events = await eventChanges(specPaths.asyncapi);\n\n // C4 architecture slice. The fleet union mirrors coherence's: services/\n // plus the feature's own specs/ names, so the slice and the validator\n // resolve a container-targeted edge to the same owner.\n const fleet = new Set([...living, ...featureServices]);\n const arch = archSlice(deltaDoc, service, id, fleet);\n\n // The use-case axis, and the one section here that is a fact about the\n // FLEET rather than about the feature's own files: which declared business\n // flows already run through this service, and at which hop. An implementer\n // handed \"add the endpoint\" and not told that step 4 of Checkout is the\n // caller has to go find that out, and on a fleet of a hundred nobody does.\n //\n // The fleet set is `living ∪ featureServices`, the same union `archSlice`\n // resolves with, so a service this feature INTRODUCES resolves to itself\n // rather than to a container's title. And `useCaseBlastRadius` gates its\n // own load: a docs repo whose architecture/ never mentions the reserved\n // tag prefix costs a readdir and a few file reads here, not a LikeC4\n // workspace — which is what keeps this command usable inside\n // /loam-implement's inner loop.\n const useCases = await useCaseBlastRadius({\n docsDir: config.docsDir,\n known: fleet,\n services: new Set([service]),\n });\n\n // The business axis. Like the use-case section above it is a fact about\n // the FEATURE rather than about this service's own files, and it is here\n // for the sharper version of that section's reason: a capability delta\n // NAMES NO SERVICE, so projecting the feature onto a service would drop\n // it entirely — and the implementer handed \"add the endpoint\" would never\n // learn which business promise the requirement they are about to write is\n // supposed to keep. `Realizes: <capability>#<id>` is the line that says\n // so, it is written on the SERVICE requirement, and the id in it is the\n // one thing here that cannot be guessed.\n //\n // Not narrowed by `--service`, deliberately: the promise is what the\n // whole feature is for, and narrowing it would report a capability-only\n // feature as having nothing to say about every service in turn. One\n // `existsSync` for a fleet that has not adopted the axis.\n const capabilities = await capabilityDeltaSummaries(\n (await featureCapabilityDeltas(feature.dir)).docs,\n async (path) => parseRequirements(await readFile(path, \"utf8\")),\n );\n\n // An unparseable delta.likec4 empties the C4 slice, and a consumer\n // reading this projection as a task brief — the JSON payload and the\n // printed view alike — would take that as \"no architecture change\": the\n // vacuously-green pattern. The output stays as informative as ever (and\n // `ok` stays true under --json: the command ran); the exit code is what\n // stops a pipeline from building on it, so it is set BEFORE the format\n // fork — the guard is about the delta, not about how it is rendered.\n //\n // The two contract axes fail the same way and earn the same guard: an\n // openapi.yaml or asyncapi.yaml that does not parse projects as an empty\n // change list. `validate --feature` does catch both these days\n // (`openapi.invalid` / `asyncapi.invalid` on the feature's own files),\n // but the guard stays this command's own: the brief is consumed by\n // agents that never ran validate, so the exit code must carry the\n // failure itself.\n if (arch.errors.length > 0 || api.unreadable || events.unreadable) process.exitCode = 1;\n\n if (json) {\n const reqJson = (r: Requirement): Record<string, unknown> => ({\n kind: r.kind,\n id: r.id,\n name: r.name,\n text: r.text.join(\"\\n\").trim(),\n operations: r.operations,\n covers: r.covers,\n // Scenarios go out verbatim: they are the acceptance criteria and the\n // source for the tests whoever picks this up is expected to write.\n scenarios: r.scenarios.map((s) => ({ name: s.name, lines: s.lines })),\n });\n emitJson({\n command: \"delta\",\n feature: id,\n service,\n services: featureServices,\n path: repoPath(config.docsDir, feature.dir),\n intent,\n requirements: reqs.map(reqJson),\n // Same shape, separate section: an arch requirement's scenarios are\n // integration/ops tests, and a consumer must not have to parse prose\n // to tell the two apart.\n archRequirements: archReqs.map(reqJson),\n api: api.changes,\n // `api` stays exactly the operations array it has always been — a\n // consumer indexing it must not have to learn a new shape — so the\n // readability of the document rides alongside as its own key,\n // spelled the way `loam show` already spells it for a living\n // contract. Additive, which the envelope permits (core/envelope/json.ts).\n openapi: {\n unreadable: api.unreadable,\n ...(api.error === undefined ? {} : { error: api.error }),\n },\n // The event axis arrives after the api/openapi pair settled its\n // split shape, so it is one additive key carrying both halves:\n // the declarations and the document's readability.\n events: {\n changes: events.changes,\n unreadable: events.unreadable,\n ...(events.error === undefined ? {} : { error: events.error }),\n },\n architecture: arch,\n // Additive, which the envelope permits (core/envelope/json.ts), and\n // deliberately NOT wired into the exit-code guard above. The three\n // conditions there are about the FEATURE's own documents; an\n // `architecture/` that does not parse is a pre-existing fleet defect\n // `validate` already reports as `landscape.invalid`, and making every\n // `loam delta` in such a repo exit 1 would be a new gate wearing the\n // clothes of a new field. `unreadable` is how this payload says it\n // could not look.\n useCases: {\n unreadable: useCases.unreadable,\n ...(useCases.error === undefined ? {} : { error: useCases.error }),\n flows: useCases.flows,\n },\n // Additive, and an empty array rather than an absent key for the same\n // reason `loam show`'s is: a consumer must not have to tell \"this\n // feature changes no capability\" from \"this loam does not report\n // them\". The shape is `show`'s, verbatim — the two commands are read\n // side by side, and a second shape for one idea is a second thing to\n // learn.\n capabilities: capabilities.map((c) => ({\n id: c.id,\n path: repoPath(config.docsDir, c.spec),\n added: c.added,\n modified: c.modified,\n removed: c.removed,\n promises: c.promises,\n })),\n });\n return;\n }\n\n console.log(`${id} · ${service}\\n`);\n if (intent) {\n console.log(indent(intent, \" \"));\n console.log();\n }\n if (existsSync(specPaths.spec)) printRequirements(reqs, \"Requirements\");\n else console.log(\"Requirements: (none for this service)\\n\");\n if (existsSync(specPaths.archSpec)) printRequirements(archReqs, \"Arch requirements\");\n if (existsSync(specPaths.openapi)) printApi(api);\n if (existsSync(specPaths.asyncapi)) printEvents(events);\n if (existsSync(paths.delta)) printArchSlice(arch, service);\n printCapabilities(capabilities);\n printUseCases(useCases, service);\n });\n}\n"]}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The delta as a person reads it: requirements, contract changes, the
|
|
3
|
+
* architecture slice for one service, and the business promises the feature
|
|
4
|
+
* changes.
|
|
5
|
+
*
|
|
6
|
+
* Rendering only. Everything printed here comes from `../../core/projection/`
|
|
7
|
+
* or `../../core/capabilities/`, which is also what `--json` emits.
|
|
8
|
+
*/
|
|
9
|
+
import {} from "../../core/document/spec.js";
|
|
10
|
+
import {} from "../../core/projection/api.js";
|
|
11
|
+
import {} from "../../core/projection/arch-slice.js";
|
|
12
|
+
import {} from "../../core/projection/events.js";
|
|
13
|
+
import {} from "../../core/usecases/touch.js";
|
|
14
|
+
import {} from "../../core/capabilities/delta/summary.js";
|
|
15
|
+
/**
|
|
16
|
+
* The requirement delta, in full.
|
|
17
|
+
*
|
|
18
|
+
* The text view used to print headings and scenario NAMES only, which made it a
|
|
19
|
+
* table of contents for a file the reader then had to open — while `--json`
|
|
20
|
+
* carried the requirement body and the Given/When/Then lines verbatim. The two
|
|
21
|
+
* are the same briefing, so they carry the same content: a person reading this
|
|
22
|
+
* in a terminal is being asked to implement it, exactly like the agent reading
|
|
23
|
+
* the payload.
|
|
24
|
+
*/
|
|
25
|
+
export function printRequirements(reqs, label) {
|
|
26
|
+
if (reqs.length === 0) {
|
|
27
|
+
console.log(`${label}: (none)\n`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log(`${label}:`);
|
|
31
|
+
for (const r of reqs) {
|
|
32
|
+
const tag = r.kind === "BASE" ? "" : `[${r.kind}] `;
|
|
33
|
+
const n = r.scenarios.length;
|
|
34
|
+
console.log(` ${tag}${r.name} (${n} scenario${n === 1 ? "" : "s"})`);
|
|
35
|
+
// The body VERBATIM, and that is the whole of the requirement's text —
|
|
36
|
+
// `Operations:`, `Covers:`, `Publishes:`, `Consumes:`, `Requires:`,
|
|
37
|
+
// `Realizes:`, `Requirement-ID:` and `Based-On:` are body lines, kept in
|
|
38
|
+
// `text` on purpose so a requirement round-trips through
|
|
39
|
+
// `serializeRequirements` and rides inside its own digest
|
|
40
|
+
// (core/document/parse.ts states that rule).
|
|
41
|
+
//
|
|
42
|
+
// This used to print `Operations:` and `Covers:` AGAIN from the parsed
|
|
43
|
+
// fields underneath, so every requirement carrying either line showed it
|
|
44
|
+
// twice — and the other five directives, which have no such re-print, showed
|
|
45
|
+
// it once. Nothing caught it: the human view is not asserted anywhere, and
|
|
46
|
+
// the duplication is only visible on a requirement that has one. Found by
|
|
47
|
+
// running `loam delta` over loam's own self-model, which is the kind of
|
|
48
|
+
// pressure ROADMAP.md's self-hosting section says the axis buys.
|
|
49
|
+
const body = r.text.join("\n").trim();
|
|
50
|
+
if (body.length > 0)
|
|
51
|
+
console.log(indent(body, " "));
|
|
52
|
+
for (const s of r.scenarios) {
|
|
53
|
+
console.log(`\n Scenario: ${s.name}`);
|
|
54
|
+
// Verbatim, bullets and markdown emphasis included: these lines are the
|
|
55
|
+
// acceptance criteria, and paraphrasing them here would put a second
|
|
56
|
+
// wording of the contract in front of whoever implements it.
|
|
57
|
+
for (const line of s.lines)
|
|
58
|
+
console.log(` ${line}`);
|
|
59
|
+
}
|
|
60
|
+
console.log();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function printApi(api) {
|
|
64
|
+
if (api.unreadable) {
|
|
65
|
+
// Worded like `loam show`'s answer for the same failure on a living
|
|
66
|
+
// contract, and deliberately WITHOUT a "run `loam validate`" hint: the
|
|
67
|
+
// parser's own message is already quoted below and the exit code carries
|
|
68
|
+
// the failure, so another command adds a hop, not information.
|
|
69
|
+
// (`validate --feature` does grade `openapi.invalid` on this same file
|
|
70
|
+
// these days; the fix is still in the YAML, not in its output.)
|
|
71
|
+
console.log("API: openapi.yaml does not parse");
|
|
72
|
+
if (api.error !== undefined)
|
|
73
|
+
console.log(` ${api.error}`);
|
|
74
|
+
console.log();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (api.changes.length === 0) {
|
|
78
|
+
console.log("API: (the openapi delta defines no operations)\n");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
console.log("API (this feature's openapi.yaml for the service):");
|
|
82
|
+
for (const op of api.changes) {
|
|
83
|
+
const marker = op.remove ? "REMOVE " : "";
|
|
84
|
+
console.log(` ${marker}${op.method} ${op.path} ${op.operationId}${op.summary === null ? "" : ` — ${op.summary}`}`);
|
|
85
|
+
}
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
export function printEvents(events) {
|
|
89
|
+
if (events.unreadable) {
|
|
90
|
+
// Same wording stance as printApi above, `asyncapi.invalid` being the
|
|
91
|
+
// validate finding on this file.
|
|
92
|
+
console.log("Events: asyncapi.yaml does not parse");
|
|
93
|
+
if (events.error !== undefined)
|
|
94
|
+
console.log(` ${events.error}`);
|
|
95
|
+
console.log();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (events.changes.length === 0) {
|
|
99
|
+
console.log("Events: (the asyncapi delta declares no messages)\n");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
console.log("Events (this feature's asyncapi.yaml for the service):");
|
|
103
|
+
for (const m of events.changes) {
|
|
104
|
+
const marker = m.remove ? "REMOVE " : "";
|
|
105
|
+
const direction = m.direction === null ? "" : `${m.direction.toUpperCase()} `;
|
|
106
|
+
console.log(` ${marker}${direction}${m.message} (${m.slot})`);
|
|
107
|
+
}
|
|
108
|
+
console.log();
|
|
109
|
+
}
|
|
110
|
+
export function printArchSlice(arch, service) {
|
|
111
|
+
if (arch.errors.length > 0) {
|
|
112
|
+
console.log("Architecture: delta.likec4 has errors — run `loam validate`.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
console.log("Architecture:");
|
|
116
|
+
if (arch.isNew)
|
|
117
|
+
console.log(` NEW service — create ${service}`);
|
|
118
|
+
if (arch.outbound.length > 0) {
|
|
119
|
+
console.log(" Outbound (new calls from this service):");
|
|
120
|
+
for (const e of arch.outbound)
|
|
121
|
+
console.log(` → ${e.service} "${e.title ?? ""}"`);
|
|
122
|
+
}
|
|
123
|
+
if (arch.inbound.length > 0) {
|
|
124
|
+
console.log(" Inbound (this service is newly called):");
|
|
125
|
+
for (const e of arch.inbound)
|
|
126
|
+
console.log(` ← ${e.service} "${e.title ?? ""}"`);
|
|
127
|
+
}
|
|
128
|
+
if (!arch.isNew && arch.outbound.length === 0 && arch.inbound.length === 0) {
|
|
129
|
+
console.log(" (no architecture change for this service)");
|
|
130
|
+
}
|
|
131
|
+
console.log();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The business flows this service already appears in.
|
|
135
|
+
*
|
|
136
|
+
* Printed even when it is empty, unlike the sections above, which are skipped
|
|
137
|
+
* when the feature has no such file. Those absences are facts about the FEATURE
|
|
138
|
+
* — no asyncapi.yaml means this change declares no events — while this one is a
|
|
139
|
+
* fact about the fleet, and "no use case draws this service" is the answer an
|
|
140
|
+
* implementer most needs to see stated rather than inferred from a missing
|
|
141
|
+
* heading.
|
|
142
|
+
*
|
|
143
|
+
* The unreadable arm exists so that emptiness is never ambiguous: an
|
|
144
|
+
* `architecture/` that does not parse produces the same empty list as a fleet
|
|
145
|
+
* that draws nothing, and only this line tells the two apart.
|
|
146
|
+
*/
|
|
147
|
+
export function printUseCases(useCases, service) {
|
|
148
|
+
if (useCases.unreadable) {
|
|
149
|
+
console.log("Use cases: architecture/ does not parse, so the flows through this service could not be read");
|
|
150
|
+
if (useCases.error !== undefined)
|
|
151
|
+
console.log(` ${useCases.error}`);
|
|
152
|
+
console.log();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (useCases.flows.length === 0) {
|
|
156
|
+
console.log(`Use cases: (no declared flow draws ${service})\n`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
console.log("Use cases (business flows this service is already a hop of):");
|
|
160
|
+
for (const flow of useCases.flows) {
|
|
161
|
+
console.log(` ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);
|
|
162
|
+
for (const step of flow.steps) {
|
|
163
|
+
const label = step.title === undefined ? "" : ` '${step.title}'`;
|
|
164
|
+
console.log(` step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
console.log();
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The business promises this feature changes, and the exact `Realizes:` entry
|
|
171
|
+
* each one is addressed by.
|
|
172
|
+
*
|
|
173
|
+
* SILENT WHEN THERE ARE NONE, unlike the use-case section above, and the
|
|
174
|
+
* asymmetry is deliberate. "No declared flow draws this service" is an answer
|
|
175
|
+
* about the FLEET — the flows exist and none of them names you — so saying so
|
|
176
|
+
* is informative. A feature with no capability delta is the normal state of
|
|
177
|
+
* every feature in a fleet that has not adopted the business axis, and a line
|
|
178
|
+
* announcing that on every projection would be the noise that teaches people to
|
|
179
|
+
* skim the brief.
|
|
180
|
+
*
|
|
181
|
+
* The entry is printed WHOLE (`Realizes: refunds#REF-1`) rather than as a
|
|
182
|
+
* capability and an id a reader has to assemble: it is text somebody is about
|
|
183
|
+
* to paste into a requirement, and the one spelling mistake it can carry —
|
|
184
|
+
* the `#` — is the one nothing downstream can suggest a fix for.
|
|
185
|
+
*/
|
|
186
|
+
export function printCapabilities(capabilities) {
|
|
187
|
+
if (capabilities.length === 0)
|
|
188
|
+
return;
|
|
189
|
+
console.log("Capabilities (business promises this feature changes):");
|
|
190
|
+
for (const c of capabilities) {
|
|
191
|
+
console.log(` ${c.id} +${c.added} ~${c.modified} -${c.removed}`);
|
|
192
|
+
for (const p of c.promises) {
|
|
193
|
+
const entry = p.id === null ? "(no Requirement-ID: yet)" : `Realizes: ${c.id}#${p.id}`;
|
|
194
|
+
console.log(` ${p.kind} '${p.name}' — ${entry}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
console.log();
|
|
198
|
+
}
|
|
199
|
+
export function indent(text, pad) {
|
|
200
|
+
return text
|
|
201
|
+
.split("\n")
|
|
202
|
+
.map((l) => (l.length > 0 ? pad + l : l))
|
|
203
|
+
.join("\n");
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=print.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/delta/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The delta as a person reads it: requirements, contract changes, the\n * architecture slice for one service, and the business promises the feature\n * changes.\n *\n * Rendering only. Everything printed here comes from `../../core/projection/`\n * or `../../core/capabilities/`, which is also what `--json` emits.\n */\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { type ApiSlice } from \"../../core/projection/api.js\";\nimport { type ArchSlice } from \"../../core/projection/arch-slice.js\";\nimport { type EventSlice } from \"../../core/projection/events.js\";\nimport { type UseCaseBlastRadius } from \"../../core/usecases/touch.js\";\nimport { type CapabilityDeltaSummary } from \"../../core/capabilities/delta/summary.js\";\n\n/**\n * The requirement delta, in full.\n *\n * The text view used to print headings and scenario NAMES only, which made it a\n * table of contents for a file the reader then had to open — while `--json`\n * carried the requirement body and the Given/When/Then lines verbatim. The two\n * are the same briefing, so they carry the same content: a person reading this\n * in a terminal is being asked to implement it, exactly like the agent reading\n * the payload.\n */\nexport function printRequirements(reqs: Requirement[], label: string): void {\n if (reqs.length === 0) {\n console.log(`${label}: (none)\\n`);\n return;\n }\n console.log(`${label}:`);\n for (const r of reqs) {\n const tag = r.kind === \"BASE\" ? \"\" : `[${r.kind}] `;\n const n = r.scenarios.length;\n console.log(` ${tag}${r.name} (${n} scenario${n === 1 ? \"\" : \"s\"})`);\n // The body VERBATIM, and that is the whole of the requirement's text —\n // `Operations:`, `Covers:`, `Publishes:`, `Consumes:`, `Requires:`,\n // `Realizes:`, `Requirement-ID:` and `Based-On:` are body lines, kept in\n // `text` on purpose so a requirement round-trips through\n // `serializeRequirements` and rides inside its own digest\n // (core/document/parse.ts states that rule).\n //\n // This used to print `Operations:` and `Covers:` AGAIN from the parsed\n // fields underneath, so every requirement carrying either line showed it\n // twice — and the other five directives, which have no such re-print, showed\n // it once. Nothing caught it: the human view is not asserted anywhere, and\n // the duplication is only visible on a requirement that has one. Found by\n // running `loam delta` over loam's own self-model, which is the kind of\n // pressure ROADMAP.md's self-hosting section says the axis buys.\n const body = r.text.join(\"\\n\").trim();\n if (body.length > 0) console.log(indent(body, \" \"));\n for (const s of r.scenarios) {\n console.log(`\\n Scenario: ${s.name}`);\n // Verbatim, bullets and markdown emphasis included: these lines are the\n // acceptance criteria, and paraphrasing them here would put a second\n // wording of the contract in front of whoever implements it.\n for (const line of s.lines) console.log(` ${line}`);\n }\n console.log();\n }\n}\n\nexport function printApi(api: ApiSlice): void {\n if (api.unreadable) {\n // Worded like `loam show`'s answer for the same failure on a living\n // contract, and deliberately WITHOUT a \"run `loam validate`\" hint: the\n // parser's own message is already quoted below and the exit code carries\n // the failure, so another command adds a hop, not information.\n // (`validate --feature` does grade `openapi.invalid` on this same file\n // these days; the fix is still in the YAML, not in its output.)\n console.log(\"API: openapi.yaml does not parse\");\n if (api.error !== undefined) console.log(` ${api.error}`);\n console.log();\n return;\n }\n if (api.changes.length === 0) {\n console.log(\"API: (the openapi delta defines no operations)\\n\");\n return;\n }\n console.log(\"API (this feature's openapi.yaml for the service):\");\n for (const op of api.changes) {\n const marker = op.remove ? \"REMOVE \" : \"\";\n console.log(\n ` ${marker}${op.method} ${op.path} ${op.operationId}${op.summary === null ? \"\" : ` — ${op.summary}`}`,\n );\n }\n console.log();\n}\n\nexport function printEvents(events: EventSlice): void {\n if (events.unreadable) {\n // Same wording stance as printApi above, `asyncapi.invalid` being the\n // validate finding on this file.\n console.log(\"Events: asyncapi.yaml does not parse\");\n if (events.error !== undefined) console.log(` ${events.error}`);\n console.log();\n return;\n }\n if (events.changes.length === 0) {\n console.log(\"Events: (the asyncapi delta declares no messages)\\n\");\n return;\n }\n console.log(\"Events (this feature's asyncapi.yaml for the service):\");\n for (const m of events.changes) {\n const marker = m.remove ? \"REMOVE \" : \"\";\n const direction = m.direction === null ? \"\" : `${m.direction.toUpperCase()} `;\n console.log(` ${marker}${direction}${m.message} (${m.slot})`);\n }\n console.log();\n}\n\nexport function printArchSlice(arch: ArchSlice, service: string): void {\n if (arch.errors.length > 0) {\n console.log(\"Architecture: delta.likec4 has errors — run `loam validate`.\");\n return;\n }\n console.log(\"Architecture:\");\n if (arch.isNew) console.log(` NEW service — create ${service}`);\n if (arch.outbound.length > 0) {\n console.log(\" Outbound (new calls from this service):\");\n for (const e of arch.outbound) console.log(` → ${e.service} \"${e.title ?? \"\"}\"`);\n }\n if (arch.inbound.length > 0) {\n console.log(\" Inbound (this service is newly called):\");\n for (const e of arch.inbound) console.log(` ← ${e.service} \"${e.title ?? \"\"}\"`);\n }\n if (!arch.isNew && arch.outbound.length === 0 && arch.inbound.length === 0) {\n console.log(\" (no architecture change for this service)\");\n }\n console.log();\n}\n\n/**\n * The business flows this service already appears in.\n *\n * Printed even when it is empty, unlike the sections above, which are skipped\n * when the feature has no such file. Those absences are facts about the FEATURE\n * — no asyncapi.yaml means this change declares no events — while this one is a\n * fact about the fleet, and \"no use case draws this service\" is the answer an\n * implementer most needs to see stated rather than inferred from a missing\n * heading.\n *\n * The unreadable arm exists so that emptiness is never ambiguous: an\n * `architecture/` that does not parse produces the same empty list as a fleet\n * that draws nothing, and only this line tells the two apart.\n */\nexport function printUseCases(useCases: UseCaseBlastRadius, service: string): void {\n if (useCases.unreadable) {\n console.log(\"Use cases: architecture/ does not parse, so the flows through this service could not be read\");\n if (useCases.error !== undefined) console.log(` ${useCases.error}`);\n console.log();\n return;\n }\n if (useCases.flows.length === 0) {\n console.log(`Use cases: (no declared flow draws ${service})\\n`);\n return;\n }\n console.log(\"Use cases (business flows this service is already a hop of):\");\n for (const flow of useCases.flows) {\n console.log(` ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n for (const step of flow.steps) {\n const label = step.title === undefined ? \"\" : ` '${step.title}'`;\n console.log(` step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);\n }\n }\n console.log();\n}\n\n/**\n * The business promises this feature changes, and the exact `Realizes:` entry\n * each one is addressed by.\n *\n * SILENT WHEN THERE ARE NONE, unlike the use-case section above, and the\n * asymmetry is deliberate. \"No declared flow draws this service\" is an answer\n * about the FLEET — the flows exist and none of them names you — so saying so\n * is informative. A feature with no capability delta is the normal state of\n * every feature in a fleet that has not adopted the business axis, and a line\n * announcing that on every projection would be the noise that teaches people to\n * skim the brief.\n *\n * The entry is printed WHOLE (`Realizes: refunds#REF-1`) rather than as a\n * capability and an id a reader has to assemble: it is text somebody is about\n * to paste into a requirement, and the one spelling mistake it can carry —\n * the `#` — is the one nothing downstream can suggest a fix for.\n */\nexport function printCapabilities(capabilities: readonly CapabilityDeltaSummary[]): void {\n if (capabilities.length === 0) return;\n console.log(\"Capabilities (business promises this feature changes):\");\n for (const c of capabilities) {\n console.log(` ${c.id} +${c.added} ~${c.modified} -${c.removed}`);\n for (const p of c.promises) {\n const entry = p.id === null ? \"(no Requirement-ID: yet)\" : `Realizes: ${c.id}#${p.id}`;\n console.log(` ${p.kind} '${p.name}' — ${entry}`);\n }\n }\n console.log();\n}\n\nexport function indent(text: string, pad: string): string {\n return text\n .split(\"\\n\")\n .map((l) => (l.length > 0 ? pad + l : l))\n .join(\"\\n\");\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { loadConfig } from "../core/config.js";
|
|
2
|
-
import { analyzeDependencies
|
|
1
|
+
import { loadConfig } from "../core/envelope/config.js";
|
|
2
|
+
import { analyzeDependencies } from "../core/dependencies/dependencies.js";
|
|
3
|
+
import {} from "../core/dependencies/facts.js";
|
|
3
4
|
import { FleetContext } from "../core/fleet-context.js";
|
|
4
|
-
import { emitJson, fail, reportNoConfig } from "../core/json.js";
|
|
5
|
-
import { missingFeatureMessage, resolveFeature } from "../core/repo.js";
|
|
5
|
+
import { emitJson, fail, reportNoConfig } from "../core/envelope/json.js";
|
|
6
|
+
import { missingFeatureMessage, resolveFeature } from "../core/repo/repo.js";
|
|
6
7
|
export function registerDependencies(program) {
|
|
7
8
|
program
|
|
8
9
|
.command("dependencies")
|
|
@@ -11,11 +12,12 @@ export function registerDependencies(program) {
|
|
|
11
12
|
.option("--json", "emit the machine contract instead of the human view")
|
|
12
13
|
.action(async (featureArg, opts) => {
|
|
13
14
|
const json = opts.json === true;
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
16
|
-
reportNoConfig(json);
|
|
15
|
+
const loaded = await loadConfig();
|
|
16
|
+
if (loaded.kind !== "loaded") {
|
|
17
|
+
reportNoConfig(json, loaded);
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
20
|
+
const config = loaded.config;
|
|
19
21
|
const context = new FleetContext();
|
|
20
22
|
const feature = featureArg === undefined
|
|
21
23
|
? null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/commands/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/commands/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAA+C,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM7E,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,CAAC,aAAa,EAAE,uDAAuD,CAAC;SAChF,WAAW,CAAC,uEAAuE,CAAC;SACpF,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,IAAyB,EAAE,EAAE;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE7B,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,UAAU,KAAK,SAAS;YACtC,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QACzE,IAAI,UAAU,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACjD,yEAAyE;YACzE,0EAA0E;YAC1E,yEAAyE;YACzE,wEAAwE;YACxE,oDAAoD;YACpD,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/F,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9E,IAAI,IAAI,EAAE,CAAC;YACT,QAAQ,CAAC;gBACP,OAAO,EAAE,cAAc;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,IAAI;gBAC5B,GAAG,KAAK;aACT,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,UAAU,CAAC,MAAwB;IAC1C,OAAO,MAAM,CAAC,IAAI,KAAK,WAAW;QAChC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,cAAc,MAAM,CAAC,WAAW,EAAE;QACrD,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED,SAAS,UAAU,CAAC,KAAsB,EAAE,SAAkB;IAC5D,MAAM,KAAK,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS,oBAAoB,CAAC;IAC7F,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAEzF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrF,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjF,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACzC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,KAAK,aAAa;gBAC3C,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;gBACxC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YACrB,uEAAuE;YACvE,wEAAwE;YACxE,yEAAyE;YACzE,0EAA0E;YAC1E,4DAA4D;YAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,QAAQ,CAAC,QAAQ,MAAM,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC","sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"../core/envelope/config.js\";\nimport { analyzeDependencies } from \"../core/dependencies/dependencies.js\";\nimport { type DependencyGraph, type DependencyReason } from \"../core/dependencies/facts.js\";\nimport { FleetContext } from \"../core/fleet-context.js\";\nimport { emitJson, fail, reportNoConfig } from \"../core/envelope/json.js\";\nimport { missingFeatureMessage, resolveFeature } from \"../core/repo/repo.js\";\n\ninterface DependenciesOptions {\n json?: boolean;\n}\n\nexport function registerDependencies(program: Command): void {\n program\n .command(\"dependencies\")\n .argument(\"[featureId]\", \"active feature id; omit for the whole in-flight graph\")\n .description(\"Show dependencies and conflicts derived from active feature artifacts\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (featureArg: string | undefined, opts: DependenciesOptions) => {\n const json = opts.json === true;\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n\n const context = new FleetContext();\n const feature = featureArg === undefined\n ? null\n : await resolveFeature(config.docsDir, featureArg, \"exclude\", context);\n if (featureArg !== undefined && feature === null) {\n // The shared miss message rather than a local one: this command resolves\n // in `exclude` mode, so the commonest miss is an id that HAS shipped, and\n // \"no active feature\" leaves the reader to discover that themselves. The\n // helper reuses the context already built above, so saying so costs one\n // enumeration this invocation has already paid for.\n fail(json, \"unknown-target\", await missingFeatureMessage(config.docsDir, featureArg, context));\n return;\n }\n\n const graph = await analyzeDependencies(config.docsDir, feature?.id, context);\n if (json) {\n emitJson({\n command: \"dependencies\",\n docsDir: config.docsDir,\n feature: feature?.id ?? null,\n ...graph,\n });\n return;\n }\n printGraph(graph, feature?.id);\n });\n}\n\nfunction reasonText(reason: DependencyReason): string {\n return reason.kind === \"operation\"\n ? `${reason.service} operation ${reason.operationId}`\n : `${reason.service}/${reason.axis} ${reason.identity}`;\n}\n\nfunction printGraph(graph: DependencyGraph, featureId?: string): void {\n const scope = featureId === undefined ? \"active features\" : `${featureId} and prerequisites`;\n console.log(`dependencies — ${scope} (${graph.nodes.length})`);\n console.log(` order: ${graph.order.length === 0 ? \"(none)\" : graph.order.join(\" → \")}`);\n\n for (const node of graph.nodes) {\n console.log(`\\n ${node.id}${node.dependsOn.length === 0 ? \" (independent)\" : \"\"}`);\n for (const edge of graph.edges.filter((candidate) => candidate.from === node.id)) {\n console.log(` depends on ${edge.to}`);\n for (const reason of edge.reasons) console.log(` - ${reasonText(reason)}`);\n }\n }\n\n if (graph.conflicts.length > 0) {\n console.log(\"\\n conflicts\");\n for (const conflict of graph.conflicts) {\n const where = conflict.kind === \"requirement\"\n ? `${conflict.service}/${conflict.axis}`\n : conflict.service;\n // \"added by\" vs \"changed by\": the two collisions want different fixes.\n // Two features ADDING the same identity is usually duplicated work that\n // should become one feature; two features CHANGING it is usually genuine\n // parallel work whose second archive would silently overwrite the first's\n // full text, so the losers need to be re-based, not merged.\n const how = conflict.change === \"added\" ? \"added by\" : \"changed by\";\n console.log(` ! ${where} ${conflict.identity} — ${how} ${conflict.features.join(\", \")}`);\n }\n }\n\n if (graph.cycles.length > 0) {\n console.log(\"\\n cycles\");\n for (const cycle of graph.cycles) console.log(` ! ${cycle.join(\" ↔ \")}`);\n }\n}\n"]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { loadConfig } from "../../core/envelope/config.js";
|
|
2
|
+
import { emitJson, fail, reportNoConfig } from "../../core/envelope/json.js";
|
|
3
|
+
import { findingJson } from "../../core/vocabulary/report.js";
|
|
4
|
+
import { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from "../policy/gate.js";
|
|
5
|
+
import { DocsRepoUnavailableError } from "../../core/repo/state.js";
|
|
6
|
+
import { FleetContext } from "../../core/fleet-context.js";
|
|
7
|
+
import { resolveBase } from "../../core/diff/base-git.js";
|
|
8
|
+
import { readBaseFleet } from "../../core/diff/base-state.js";
|
|
9
|
+
import { readCurrentFleet } from "../../core/diff/current-state.js";
|
|
10
|
+
import { victimIndex } from "../../core/diff/victims.js";
|
|
11
|
+
import { computeDiff } from "../../core/diff/semantic.js";
|
|
12
|
+
import { printDiff } from "./print.js";
|
|
13
|
+
export function registerDiff(program) {
|
|
14
|
+
program
|
|
15
|
+
.command("diff")
|
|
16
|
+
.description("Semantic diff of the living docs against a base git ref of the docs repo — fleet-meaningful changes, with the joined victims of every removal named")
|
|
17
|
+
.requiredOption("--base <ref>", "base git ref of the docs repo (e.g. main, origin/main, a commit sha)")
|
|
18
|
+
.option("--json", "emit the machine contract instead of the human view")
|
|
19
|
+
.action(async (opts) => {
|
|
20
|
+
const json = opts.json === true;
|
|
21
|
+
const loaded = await loadConfig();
|
|
22
|
+
if (loaded.kind !== "loaded") {
|
|
23
|
+
reportNoConfig(json, loaded);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const { docsDir } = loaded.config;
|
|
27
|
+
// "services" on purpose: both sides of the diff are enumerations of the
|
|
28
|
+
// fleet, and a docsDir with no services/ has no fleet to diff.
|
|
29
|
+
if (!docsRepoReady(json, docsDir, "services"))
|
|
30
|
+
return;
|
|
31
|
+
const base = await resolveBase(docsDir, opts.base);
|
|
32
|
+
// Unlike provenance's "git will not say", diff REFUSES when git cannot
|
|
33
|
+
// answer: without the base there is no honest diff, and a silently
|
|
34
|
+
// empty base would report the whole fleet as added.
|
|
35
|
+
if (base.kind === "no-git") {
|
|
36
|
+
fail(json, "repository-unavailable", `The docs repo at ${docsDir} is not somewhere git can answer from (${base.detail}) — ` +
|
|
37
|
+
`loam diff reads the base state with read-only git questions (rev-parse/ls-tree/show), so it needs the docs repo ` +
|
|
38
|
+
`to be a git checkout with the base ref present. Clone the docs repo with its history, then re-run.`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (base.kind === "no-ref") {
|
|
42
|
+
fail(json, "unknown-target", `--base ${opts.base} does not resolve to a commit in the docs repo at ${docsDir}` +
|
|
43
|
+
`${base.detail === "" ? "" : ` (${base.detail})`}. ` +
|
|
44
|
+
`Pass a ref that exists there — main, origin/main, a tag or a commit sha — fetching first if it lives on the remote.`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const context = new FleetContext();
|
|
48
|
+
let diff;
|
|
49
|
+
try {
|
|
50
|
+
const baseFleet = await readBaseFleet({ docsDir, commit: base.commit, prefix: base.prefix });
|
|
51
|
+
if (baseFleet.kind === "failed") {
|
|
52
|
+
fail(json, "repository-unavailable", `git could not list services/ at ${opts.base} in the docs repo at ${docsDir} (${baseFleet.detail}) — ` +
|
|
53
|
+
`without the base tree there is no honest diff. Re-run once git can answer.`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const current = await readCurrentFleet(docsDir, context);
|
|
57
|
+
const victims = victimIndex({ docsDir, context, current: current.services, ambiguous: current.ambiguous });
|
|
58
|
+
diff = await computeDiff({ base: baseFleet.fleet, current, victims });
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof DocsRepoUnavailableError) {
|
|
62
|
+
reportDocsRepoError(json, err);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
reportRepositoryUnavailable(json, err, "the fleet could not be diffed", docsDir);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Error findings gate (the validate convention); suspended axes gate too,
|
|
69
|
+
// because an exit 0 over a diff nobody could fully read would be the
|
|
70
|
+
// "green over zero services" failure one step later.
|
|
71
|
+
if (diff.breaking || diff.summary.unreadable > 0)
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
if (json) {
|
|
74
|
+
emitJson({
|
|
75
|
+
command: "diff",
|
|
76
|
+
docsDir,
|
|
77
|
+
base: { ref: opts.base, commit: base.commit },
|
|
78
|
+
services: diff.services.map((s) => ({
|
|
79
|
+
id: s.id,
|
|
80
|
+
change: s.change,
|
|
81
|
+
findings: s.findings.map((finding) => findingJson(finding, { path: `services/${s.id}`, role: "scope" })),
|
|
82
|
+
unreadable: s.unreadable,
|
|
83
|
+
...(s.ambiguous === undefined ? {} : { ambiguous: s.ambiguous }),
|
|
84
|
+
})),
|
|
85
|
+
breaking: diff.breaking,
|
|
86
|
+
summary: diff.summary,
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
printDiff(diff, { ref: opts.base, commit: base.commit });
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/commands/diff/diff.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam diff --base <ref>` — the review lens over a docs-repo branch: what\n * changed in fleet-meaningful terms since a base git ref of the DOCS repo,\n * with the current consumers of every removal named. Read-only by\n * construction: the base state comes out of git's object store\n * (`core/diff/base-git.ts`), the current state off the working tree, and\n * nothing is written anywhere.\n *\n * Exit semantics: 0 when the diff was computed and nothing is breaking AND\n * every artifact on both sides could be read; 1 for a refusal, for any\n * error-severity finding (a removal the fleet still consumes — which is what\n * makes this a free gate on a docs-repo PR), and for a diff with suspended\n * axes — \"nobody could look\" must not exit as \"nothing changed\"\n * (`loam context` set that precedent for silent holes).\n */\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"../../core/envelope/config.js\";\nimport { emitJson, fail, reportNoConfig } from \"../../core/envelope/json.js\";\nimport { findingJson } from \"../../core/vocabulary/report.js\";\nimport { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from \"../policy/gate.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { resolveBase } from \"../../core/diff/base-git.js\";\nimport { readBaseFleet } from \"../../core/diff/base-state.js\";\nimport { readCurrentFleet } from \"../../core/diff/current-state.js\";\nimport { victimIndex } from \"../../core/diff/victims.js\";\nimport { computeDiff, type FleetDiff } from \"../../core/diff/semantic.js\";\nimport { printDiff } from \"./print.js\";\n\ninterface DiffOptions {\n base: string;\n json?: boolean;\n}\n\nexport function registerDiff(program: Command): void {\n program\n .command(\"diff\")\n .description(\"Semantic diff of the living docs against a base git ref of the docs repo — fleet-meaningful changes, with the joined victims of every removal named\")\n .requiredOption(\"--base <ref>\", \"base git ref of the docs repo (e.g. main, origin/main, a commit sha)\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: DiffOptions) => {\n const json = opts.json === true;\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const { docsDir } = loaded.config;\n // \"services\" on purpose: both sides of the diff are enumerations of the\n // fleet, and a docsDir with no services/ has no fleet to diff.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n\n const base = await resolveBase(docsDir, opts.base);\n // Unlike provenance's \"git will not say\", diff REFUSES when git cannot\n // answer: without the base there is no honest diff, and a silently\n // empty base would report the whole fleet as added.\n if (base.kind === \"no-git\") {\n fail(\n json,\n \"repository-unavailable\",\n `The docs repo at ${docsDir} is not somewhere git can answer from (${base.detail}) — ` +\n `loam diff reads the base state with read-only git questions (rev-parse/ls-tree/show), so it needs the docs repo ` +\n `to be a git checkout with the base ref present. Clone the docs repo with its history, then re-run.`,\n );\n return;\n }\n if (base.kind === \"no-ref\") {\n fail(\n json,\n \"unknown-target\",\n `--base ${opts.base} does not resolve to a commit in the docs repo at ${docsDir}` +\n `${base.detail === \"\" ? \"\" : ` (${base.detail})`}. ` +\n `Pass a ref that exists there — main, origin/main, a tag or a commit sha — fetching first if it lives on the remote.`,\n );\n return;\n }\n\n const context = new FleetContext();\n let diff: FleetDiff;\n try {\n const baseFleet = await readBaseFleet({ docsDir, commit: base.commit, prefix: base.prefix });\n if (baseFleet.kind === \"failed\") {\n fail(\n json,\n \"repository-unavailable\",\n `git could not list services/ at ${opts.base} in the docs repo at ${docsDir} (${baseFleet.detail}) — ` +\n `without the base tree there is no honest diff. Re-run once git can answer.`,\n );\n return;\n }\n const current = await readCurrentFleet(docsDir, context);\n const victims = victimIndex({ docsDir, context, current: current.services, ambiguous: current.ambiguous });\n diff = await computeDiff({ base: baseFleet.fleet, current, victims });\n } catch (err) {\n if (err instanceof DocsRepoUnavailableError) {\n reportDocsRepoError(json, err);\n return;\n }\n reportRepositoryUnavailable(json, err, \"the fleet could not be diffed\", docsDir);\n return;\n }\n\n // Error findings gate (the validate convention); suspended axes gate too,\n // because an exit 0 over a diff nobody could fully read would be the\n // \"green over zero services\" failure one step later.\n if (diff.breaking || diff.summary.unreadable > 0) process.exitCode = 1;\n if (json) {\n emitJson({\n command: \"diff\",\n docsDir,\n base: { ref: opts.base, commit: base.commit },\n services: diff.services.map((s) => ({\n id: s.id,\n change: s.change,\n findings: s.findings.map((finding) =>\n findingJson(finding, { path: `services/${s.id}`, role: \"scope\" }),\n ),\n unreadable: s.unreadable,\n ...(s.ambiguous === undefined ? {} : { ambiguous: s.ambiguous }),\n })),\n breaking: diff.breaking,\n summary: diff.summary,\n });\n return;\n }\n printDiff(diff, { ref: opts.base, commit: base.commit });\n });\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human rendering for `loam diff` — per-service blocks with the shared
|
|
3
|
+
* severity glyphs, victims as detail lines, one summary line. The JSON side
|
|
4
|
+
* lives in `diff.ts` beside the envelope; this module owns only the text.
|
|
5
|
+
*/
|
|
6
|
+
import { SEVERITY_MARK } from "../../core/vocabulary/report.js";
|
|
7
|
+
function printService(s) {
|
|
8
|
+
console.log(`\n${s.id} — ${s.change}`);
|
|
9
|
+
if (s.ambiguous !== undefined) {
|
|
10
|
+
console.log(` ⚠ service identity ambiguous — claimed by ${s.ambiguous.join(" and ")}; ` +
|
|
11
|
+
`findings for this service are suspended, not empty`);
|
|
12
|
+
}
|
|
13
|
+
for (const u of s.unreadable) {
|
|
14
|
+
// Suspension is not silence: the reader must see that this axis was not
|
|
15
|
+
// graded, or an unreadable file reads as "nothing changed here".
|
|
16
|
+
console.log(` ⚠ ${u.side}: ${u.path} could not be read — ${u.error}; findings on this axis are suspended, not empty`);
|
|
17
|
+
}
|
|
18
|
+
for (const f of s.findings) {
|
|
19
|
+
console.log(` ${SEVERITY_MARK[f.severity]} ${f.code}: ${f.message}`);
|
|
20
|
+
for (const d of f.details ?? [])
|
|
21
|
+
console.log(` - ${d}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function printDiff(diff, base) {
|
|
25
|
+
console.log(`diff vs ${base.ref} (${base.commit.slice(0, 12)})`);
|
|
26
|
+
const changed = diff.services.filter((s) => s.change !== "unchanged");
|
|
27
|
+
if (changed.length === 0) {
|
|
28
|
+
console.log(" no fleet-meaningful changes");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const s of changed)
|
|
32
|
+
printService(s);
|
|
33
|
+
const sum = diff.summary;
|
|
34
|
+
console.log(`\n${sum.added} added · ${sum.removed} removed · ${sum.modified} modified · ${sum.deprecated} deprecated` +
|
|
35
|
+
(sum.unreadable > 0 ? ` · ${sum.unreadable} unreadable` : "") +
|
|
36
|
+
(diff.breaking ? " · BREAKING" : ""));
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=print.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/diff/print.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGhE,SAAS,YAAY,CAAC,CAAc;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CACT,+CAA+C,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;YAC1E,oDAAoD,CACvD,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QAC7B,wEAAwE;QACxE,iEAAiE;QACjE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,wBAAwB,CAAC,CAAC,KAAK,kDAAkD,CAAC,CAAC;IACzH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACtE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAe,EAAE,IAAqC;IAC9E,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,GAAG,CACT,KAAK,GAAG,CAAC,KAAK,YAAY,GAAG,CAAC,OAAO,cAAc,GAAG,CAAC,QAAQ,eAAe,GAAG,CAAC,UAAU,aAAa;QACvG,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CACvC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Human rendering for `loam diff` — per-service blocks with the shared\n * severity glyphs, victims as detail lines, one summary line. The JSON side\n * lives in `diff.ts` beside the envelope; this module owns only the text.\n */\nimport { SEVERITY_MARK } from \"../../core/vocabulary/report.js\";\nimport type { FleetDiff, ServiceDiff } from \"../../core/diff/semantic.js\";\n\nfunction printService(s: ServiceDiff): void {\n console.log(`\\n${s.id} — ${s.change}`);\n if (s.ambiguous !== undefined) {\n console.log(\n ` ⚠ service identity ambiguous — claimed by ${s.ambiguous.join(\" and \")}; ` +\n `findings for this service are suspended, not empty`,\n );\n }\n for (const u of s.unreadable) {\n // Suspension is not silence: the reader must see that this axis was not\n // graded, or an unreadable file reads as \"nothing changed here\".\n console.log(` ⚠ ${u.side}: ${u.path} could not be read — ${u.error}; findings on this axis are suspended, not empty`);\n }\n for (const f of s.findings) {\n console.log(` ${SEVERITY_MARK[f.severity]} ${f.code}: ${f.message}`);\n for (const d of f.details ?? []) console.log(` - ${d}`);\n }\n}\n\nexport function printDiff(diff: FleetDiff, base: { ref: string; commit: string }): void {\n console.log(`diff vs ${base.ref} (${base.commit.slice(0, 12)})`);\n const changed = diff.services.filter((s) => s.change !== \"unchanged\");\n if (changed.length === 0) {\n console.log(\" no fleet-meaningful changes\");\n return;\n }\n for (const s of changed) printService(s);\n const sum = diff.summary;\n console.log(\n `\\n${sum.added} added · ${sum.removed} removed · ${sum.modified} modified · ${sum.deprecated} deprecated` +\n (sum.unreadable > 0 ? ` · ${sum.unreadable} unreadable` : \"\") +\n (diff.breaking ? \" · BREAKING\" : \"\"),\n );\n}\n"]}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { diagnose } from "../core/doctor.js";
|
|
2
|
-
import {
|
|
1
|
+
import { diagnose } from "../core/doctor/doctor.js";
|
|
2
|
+
import {} from "../core/doctor/report.js";
|
|
3
|
+
import { emitJson } from "../core/envelope/json.js";
|
|
3
4
|
export function registerDoctor(program) {
|
|
4
5
|
program
|
|
5
6
|
.command("doctor")
|
|
@@ -44,7 +45,7 @@ function writePathLabel(residue) {
|
|
|
44
45
|
? ["interrupted commit (unreadable)"]
|
|
45
46
|
: residue.intent === null
|
|
46
47
|
? []
|
|
47
|
-
: [`interrupted ${residue.intent.command} of ${residue.intent.feature}`]),
|
|
48
|
+
: [`interrupted ${residue.intent.command} of ${"feature" in residue.intent ? residue.intent.feature : residue.intent.target}`]),
|
|
48
49
|
...(residue.temps.length === 0 ? [] : [`${residue.temps.length} orphaned temp file(s)`]),
|
|
49
50
|
];
|
|
50
51
|
return parts.length === 0 ? "clean" : parts.join(" · ");
|
|
@@ -64,7 +65,7 @@ function printDoctor(report) {
|
|
|
64
65
|
// line above it, this is state, not a complaint. Only the findings block is
|
|
65
66
|
// silent when there is nothing to say.
|
|
66
67
|
const agents = report.agents;
|
|
67
|
-
console.log(` agents ${agents.tools.length === 0 ? "(none)" : agents.tools.join(", ")}`
|
|
68
|
+
console.log(` agents ${agents.tools.length === 0 ? "(none)" : agents.tools.join(", ")} · ${agents.profile}`
|
|
68
69
|
+ ` (${agents.toolsSource}) · ${agents.plannedFiles} files · ${agents.missingFiles.length} missing`
|
|
69
70
|
+ ` · ${agents.staleFiles.length} stale · AGENTS.md ${stampLabel(agents.stamp)}`);
|
|
70
71
|
// The write path is state too, and its clean answer is the one worth printing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAqB,MAAM,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { diagnose } from \"../core/doctor/doctor.js\";\nimport { type DoctorReport } from \"../core/doctor/report.js\";\nimport { emitJson } from \"../core/envelope/json.js\";\n\ninterface DoctorOptions {\n json?: boolean;\n}\n\nexport function registerDoctor(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Diagnose local loam configuration and docs-repo accessibility without writing\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: DoctorOptions) => {\n const report = await diagnose();\n if (opts.json === true) emitJson({ command: \"doctor\", ...report });\n else printDoctor(report);\n if (!report.healthy) process.exitCode = 1;\n });\n}\n\nfunction yesNo(value: boolean): string {\n return value ? \"yes\" : \"no\";\n}\n\n/**\n * The stamp as one readable token. \"absent\" and \"unstamped\" are kept apart\n * because they are different repos: the first has no AGENTS.md at all, the\n * second has one nobody has claimed a version for.\n */\nfunction stampLabel(stamp: DoctorReport[\"agents\"][\"stamp\"]): string {\n if (!stamp.present) return \"absent\";\n if (stamp.version === null) return \"unstamped\";\n return `v${stamp.version}${stamp.stale ? \" (stale)\" : \"\"}`;\n}\n\n/**\n * What a killed writer left in the docs repo, as one line. \"clean\" is the\n * answer on every healthy repo, and \"(unresolved)\" keeps it apart from clean:\n * a docsDir that never resolved was never looked at.\n */\nfunction writePathLabel(residue: DoctorReport[\"writePath\"]): string {\n if (residue === null) return \"(unresolved)\";\n const parts = [\n ...(residue.lock === null ? [] : [`lock held${residue.lock.stale ? \" (stale)\" : \"\"}`]),\n ...(residue.intentUnreadable\n ? [\"interrupted commit (unreadable)\"]\n : residue.intent === null\n ? []\n : [`interrupted ${residue.intent.command} of ${\"feature\" in residue.intent ? residue.intent.feature : residue.intent.target}`]),\n ...(residue.temps.length === 0 ? [] : [`${residue.temps.length} orphaned temp file(s)`]),\n ];\n return parts.length === 0 ? \"clean\" : parts.join(\" · \");\n}\n\nfunction printDoctor(report: DoctorReport): void {\n console.log(`loam doctor — ${report.healthy ? \"healthy\" : \"blocked\"}`);\n console.log(` runtime ${report.runtime.package}@${report.runtime.version}`);\n console.log(` node ${report.runtime.node} ${report.runtime.platform}/${report.runtime.arch}`);\n console.log(` config ${report.config.status} ${report.config.path}`);\n if (report.config.error !== null) console.log(` ${report.config.error}`);\n console.log(` docsDir ${report.docs.path ?? \"(unresolved)\"}`);\n console.log(\n ` access exists ${yesNo(report.docs.exists)} · read ${yesNo(report.docs.readable)} · write ${yesNo(report.docs.writable)}`,\n );\n console.log(\n ` fleet services/ ${yesNo(report.docs.servicesDir)} · landscape ${yesNo(report.docs.landscape)} · ${report.counts.services} services · ${report.counts.activeFeatures} active features`,\n );\n console.log(\n ` binding ${report.currentService.configured ?? \"(none)\"} · ${report.currentService.status}`,\n );\n // The agent surface is reported whether or not it has drifted — like every\n // line above it, this is state, not a complaint. Only the findings block is\n // silent when there is nothing to say.\n const agents = report.agents;\n console.log(\n ` agents ${agents.tools.length === 0 ? \"(none)\" : agents.tools.join(\", \")} · ${agents.profile}`\n + ` (${agents.toolsSource}) · ${agents.plannedFiles} files · ${agents.missingFiles.length} missing`\n + ` · ${agents.staleFiles.length} stale · AGENTS.md ${stampLabel(agents.stamp)}`,\n );\n // The write path is state too, and its clean answer is the one worth printing\n // most often: a reader who has just been told the docs are half-written needs\n // to see it go away.\n console.log(` write path ${writePathLabel(report.writePath)}`);\n if (report.findings.length > 0) {\n console.log(\"\\n findings\");\n for (const finding of report.findings) {\n console.log(` ${finding.severity === \"blocker\" ? \"✗\" : \"⚠\"} ${finding.code}: ${finding.message}`);\n // The fix is printed on its own indented line rather than appended to the\n // message: what is wrong and what to type are two different sentences,\n // and someone scanning a blocked repo reads down the `fix:` column.\n console.log(` fix: ${finding.fix}`);\n }\n }\n}\n"]}
|