@ybotok/loam 0.2.0-alpha.1 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3448 -0
- package/COMPARISON.md +91 -3
- package/CONTRIBUTING.md +37 -0
- package/MIGRATING-from-OpenSpec.md +47 -23
- package/QUICKSTART.md +189 -12
- package/README.md +274 -65
- package/ROADMAP.md +572 -31
- package/SCHEMA.md +1709 -155
- package/WORKFLOW.md +298 -72
- package/dist/cli.js +26 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +5 -10
- package/dist/commands/adopt/adopt.js.map +1 -1
- package/dist/commands/adopt/render.js +50 -9
- package/dist/commands/adopt/render.js.map +1 -1
- package/dist/commands/archive/archive.js +16 -19
- package/dist/commands/archive/archive.js.map +1 -1
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +77 -43
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +21 -19
- package/dist/commands/archive/plan/gate.js.map +1 -1
- package/dist/commands/archive/plan/landscape.js +167 -30
- package/dist/commands/archive/plan/landscape.js.map +1 -1
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +14 -19
- package/dist/commands/archive/plan/refusal.js.map +1 -1
- package/dist/commands/archive/plan/specs.js +137 -56
- package/dist/commands/archive/plan/specs.js.map +1 -1
- package/dist/commands/archive/plan/state.js +3 -0
- package/dist/commands/archive/plan/state.js.map +1 -1
- package/dist/commands/archive/run.js +134 -30
- package/dist/commands/archive/run.js.map +1 -1
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +85 -18
- package/dist/commands/context/context.js.map +1 -1
- package/dist/commands/context/print.js +29 -7
- package/dist/commands/context/print.js.map +1 -1
- package/dist/commands/delta/delta.js +102 -14
- package/dist/commands/delta/delta.js.map +1 -1
- package/dist/commands/delta/print.js +17 -1
- package/dist/commands/delta/print.js.map +1 -1
- package/dist/commands/dependencies.js +3 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +20 -27
- package/dist/commands/diff/diff.js.map +1 -1
- package/dist/commands/doctor.js +60 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +89 -13
- package/dist/commands/explain/explain.js.map +1 -1
- package/dist/commands/explore.js +16 -10
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +45 -8
- package/dist/commands/gate/gate.js.map +1 -1
- package/dist/commands/gate/print.js +15 -3
- package/dist/commands/gate/print.js.map +1 -1
- package/dist/commands/gherkin/commit.js +13 -54
- package/dist/commands/gherkin/commit.js.map +1 -1
- package/dist/commands/gherkin/gherkin.js +36 -20
- package/dist/commands/gherkin/gherkin.js.map +1 -1
- package/dist/commands/gherkin/reconcile.js +10 -13
- package/dist/commands/gherkin/reconcile.js.map +1 -1
- package/dist/commands/init/first-hour.js +44 -0
- package/dist/commands/init/first-hour.js.map +1 -1
- package/dist/commands/init/init.js +18 -22
- package/dist/commands/init/init.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +4 -6
- package/dist/commands/list/campaign/campaign.js.map +1 -1
- package/dist/commands/list/json.js +5 -7
- package/dist/commands/list/json.js.map +1 -1
- package/dist/commands/list/list.js +44 -29
- package/dist/commands/list/list.js.map +1 -1
- package/dist/commands/list/print.js +52 -9
- package/dist/commands/list/print.js.map +1 -1
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +37 -34
- package/dist/commands/list/views.js.map +1 -1
- package/dist/commands/mcp/dispatch.js +91 -36
- package/dist/commands/mcp/dispatch.js.map +1 -1
- package/dist/commands/mcp/mcp.js +56 -15
- package/dist/commands/mcp/mcp.js.map +1 -1
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/active.js +27 -22
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/target.js +2 -2
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/error.js +7 -8
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +8 -22
- package/dist/commands/new/commit.js.map +1 -1
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +59 -14
- package/dist/commands/new/new.js.map +1 -1
- package/dist/commands/new/templates.js +48 -124
- package/dist/commands/new/templates.js.map +1 -1
- package/dist/commands/open.js +3 -7
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/policy/gate.js +27 -0
- package/dist/commands/policy/gate.js.map +1 -1
- package/dist/commands/rebase/plan.js +2 -2
- package/dist/commands/rebase/plan.js.map +1 -1
- package/dist/commands/rebase/rebase.js +60 -35
- package/dist/commands/rebase/rebase.js.map +1 -1
- package/dist/commands/seed/commit.js +55 -26
- package/dist/commands/seed/commit.js.map +1 -1
- package/dist/commands/seed/plan.js +158 -13
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/seed/seed.js +13 -11
- package/dist/commands/seed/seed.js.map +1 -1
- package/dist/commands/show/feature.js +9 -5
- package/dist/commands/show/feature.js.map +1 -1
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +35 -6
- package/dist/commands/show/marks.js.map +1 -1
- package/dist/commands/show/service.js +41 -33
- package/dist/commands/show/service.js.map +1 -1
- package/dist/commands/show/show.js +17 -7
- package/dist/commands/show/show.js.map +1 -1
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +2 -0
- package/dist/commands/status/json.js.map +1 -1
- package/dist/commands/status/print.js +89 -37
- package/dist/commands/status/print.js.map +1 -1
- package/dist/commands/status/status.js +3 -7
- package/dist/commands/status/status.js.map +1 -1
- package/dist/commands/steps/steps.js +103 -23
- package/dist/commands/steps/steps.js.map +1 -1
- package/dist/commands/subsystem/edit.js +7 -7
- package/dist/commands/subsystem/edit.js.map +1 -1
- package/dist/commands/subsystem/move.js +106 -46
- package/dist/commands/subsystem/move.js.map +1 -1
- package/dist/commands/subsystem/query.js +2 -4
- package/dist/commands/subsystem/query.js.map +1 -1
- package/dist/commands/subsystem/subsystem.js +4 -7
- package/dist/commands/subsystem/subsystem.js.map +1 -1
- package/dist/commands/subsystem/sync.js +289 -74
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +147 -45
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +200 -21
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +42 -26
- package/dist/commands/unarchive/manifest.js.map +1 -1
- package/dist/commands/unarchive/restore.js +83 -33
- package/dist/commands/unarchive/restore.js.map +1 -1
- package/dist/commands/unarchive/unarchive.js +22 -30
- package/dist/commands/unarchive/unarchive.js.map +1 -1
- package/dist/commands/validate/arch-coverage.js +78 -27
- package/dist/commands/validate/arch-coverage.js.map +1 -1
- package/dist/commands/validate/checks/fleet-shape.js +34 -126
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
- package/dist/commands/validate/checks/health-deps.js +9 -6
- package/dist/commands/validate/checks/health-deps.js.map +1 -1
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +18 -8
- package/dist/commands/validate/checks/requirements.js.map +1 -1
- package/dist/commands/validate/checks/sources.js +11 -2
- package/dist/commands/validate/checks/sources.js.map +1 -1
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +26 -20
- package/dist/commands/validate/feature.js.map +1 -1
- package/dist/commands/validate/fleet/census.js +37 -13
- package/dist/commands/validate/fleet/census.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +144 -126
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/load.js +66 -0
- package/dist/commands/validate/fleet/load.js.map +1 -1
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +44 -14
- package/dist/commands/validate/fleet/obligations.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/print.js +10 -2
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +50 -15
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +40 -47
- package/dist/commands/validate/fleet/views/stale.js.map +1 -1
- package/dist/commands/validate/links/corpus.js +1 -4
- package/dist/commands/validate/links/corpus.js.map +1 -1
- package/dist/commands/validate/links/glossary.js.map +1 -1
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +36 -160
- package/dist/commands/validate/report.js.map +1 -1
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +21 -107
- package/dist/commands/validate/service/api.js.map +1 -1
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +36 -14
- package/dist/commands/validate/service/events/events.js.map +1 -1
- package/dist/commands/validate/service/events/message-producers.js +1 -1
- package/dist/commands/validate/service/events/message-producers.js.map +1 -1
- package/dist/commands/validate/service/evidence-pins.js +56 -10
- package/dist/commands/validate/service/evidence-pins.js.map +1 -1
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +121 -61
- package/dist/commands/validate/service/service.js.map +1 -1
- package/dist/commands/validate/service/specs.js +88 -28
- package/dist/commands/validate/service/specs.js.map +1 -1
- package/dist/commands/validate/service/spine.js +38 -3
- package/dist/commands/validate/service/spine.js.map +1 -1
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +85 -60
- package/dist/commands/validate/validate.js.map +1 -1
- package/dist/commands/verify/cross/diff.js +2 -6
- package/dist/commands/verify/cross/diff.js.map +1 -1
- package/dist/commands/verify/evidence/contract.js +1 -1
- package/dist/commands/verify/evidence/contract.js.map +1 -1
- package/dist/commands/verify/evidence/read.js +12 -3
- package/dist/commands/verify/evidence/read.js.map +1 -1
- package/dist/commands/verify/frozen.js +45 -23
- package/dist/commands/verify/frozen.js.map +1 -1
- package/dist/commands/verify/record.js +69 -17
- package/dist/commands/verify/record.js.map +1 -1
- package/dist/commands/verify/report.js +27 -44
- package/dist/commands/verify/report.js.map +1 -1
- package/dist/commands/verify/results.js +112 -30
- package/dist/commands/verify/results.js.map +1 -1
- package/dist/commands/verify/verify.js +55 -52
- package/dist/commands/verify/verify.js.map +1 -1
- package/dist/commands/vouch/pack/pack.js +2 -2
- package/dist/commands/vouch/pack/pack.js.map +1 -1
- package/dist/commands/vouch/pack/print.js +1 -6
- package/dist/commands/vouch/pack/print.js.map +1 -1
- package/dist/commands/vouch/pack/sections.js +1 -2
- package/dist/commands/vouch/pack/sections.js.map +1 -1
- package/dist/commands/vouch/run.js +26 -81
- package/dist/commands/vouch/run.js.map +1 -1
- package/dist/commands/vouch/sample/plan.js +20 -34
- package/dist/commands/vouch/sample/plan.js.map +1 -1
- package/dist/commands/vouch/vet/verify.js +39 -7
- package/dist/commands/vouch/vet/verify.js.map +1 -1
- package/dist/commands/vouch/vouch.js +10 -17
- package/dist/commands/vouch/vouch.js.map +1 -1
- package/dist/core/agent/agents-md/command-map.js +81 -106
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/explain.js +21 -9
- package/dist/core/agent/agents-md/map/explain.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
- package/dist/core/agent/agents-md/map/mcp.js +10 -7
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
- package/dist/core/agent/agents-md/map/status.js +24 -8
- package/dist/core/agent/agents-md/map/status.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +80 -8
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md/map/usecases.js +88 -10
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
- package/dist/core/agent/agents-md/refusals.js +49 -22
- package/dist/core/agent/agents-md/refusals.js.map +1 -1
- package/dist/core/agent/agents-md.js +39 -6
- package/dist/core/agent/agents-md.js.map +1 -1
- package/dist/core/agent/agents-stamp.js +10 -0
- package/dist/core/agent/agents-stamp.js.map +1 -1
- package/dist/core/agent/protocol.js +1 -1
- package/dist/core/agent/protocol.js.map +1 -1
- package/dist/core/agent/scaffold.js +10 -15
- package/dist/core/agent/scaffold.js.map +1 -1
- package/dist/core/agent/support/report.js +46 -5
- package/dist/core/agent/support/report.js.map +1 -1
- package/dist/core/agent/tools/dialects.js +1 -0
- package/dist/core/agent/tools/dialects.js.map +1 -1
- package/dist/core/agent/tools/registry.js +41 -76
- package/dist/core/agent/tools/registry.js.map +1 -1
- package/dist/core/agent/workflows/adopt.js +158 -11
- package/dist/core/agent/workflows/adopt.js.map +1 -1
- package/dist/core/agent/workflows/check.js +78 -39
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/agent/workflows/closing.js +88 -27
- package/dist/core/agent/workflows/closing.js.map +1 -1
- package/dist/core/agent/workflows/feature.js +128 -13
- package/dist/core/agent/workflows/feature.js.map +1 -1
- package/dist/core/agent/workflows/implement.js +96 -13
- package/dist/core/agent/workflows/implement.js.map +1 -1
- package/dist/core/agent/workflows/reference/authoring.js +106 -4
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
- package/dist/core/agent/workflows/reference/codes.js +8 -6
- package/dist/core/agent/workflows/reference/codes.js.map +1 -1
- package/dist/core/agent/workflows/reference/done-check.js +37 -15
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +6 -3
- package/dist/core/agent/workflows/reference/reference.js.map +1 -1
- package/dist/core/agent/workflows/reference/spine.js +68 -27
- package/dist/core/agent/workflows/reference/spine.js.map +1 -1
- package/dist/core/asyncapi/baseline/plan.js +14 -81
- package/dist/core/asyncapi/baseline/plan.js.map +1 -1
- package/dist/core/asyncapi/digest.js +30 -25
- package/dist/core/asyncapi/digest.js.map +1 -1
- package/dist/core/asyncapi/merge/components.js +5 -4
- package/dist/core/asyncapi/merge/components.js.map +1 -1
- package/dist/core/asyncapi/merge/error.js +7 -2
- package/dist/core/asyncapi/merge/error.js.map +1 -1
- package/dist/core/asyncapi/merge/markers.js +32 -50
- package/dist/core/asyncapi/merge/markers.js.map +1 -1
- package/dist/core/asyncapi/merge/merge.js +33 -53
- package/dist/core/asyncapi/merge/merge.js.map +1 -1
- package/dist/core/asyncapi/merge/pin.js +12 -36
- package/dist/core/asyncapi/merge/pin.js.map +1 -1
- package/dist/core/asyncapi/model.js.map +1 -1
- package/dist/core/asyncapi/read.js +36 -12
- package/dist/core/asyncapi/read.js.map +1 -1
- package/dist/core/brief/brief.js +96 -36
- package/dist/core/brief/brief.js.map +1 -1
- package/dist/core/brief/checks.js +138 -3
- package/dist/core/brief/checks.js.map +1 -1
- package/dist/core/brief/landscape.js +209 -130
- package/dist/core/brief/landscape.js.map +1 -1
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +109 -31
- package/dist/core/brief/targets.js.map +1 -1
- package/dist/core/brief/unchecked.js +14 -3
- package/dist/core/brief/unchecked.js.map +1 -1
- package/dist/core/c4/arch.js +90 -182
- package/dist/core/c4/arch.js.map +1 -1
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +169 -14
- package/dist/core/c4/likec4.js.map +1 -1
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
- package/dist/core/c4/parsed/values.js +54 -1
- package/dist/core/c4/parsed/values.js.map +1 -1
- package/dist/core/c4/parsed/view-ids.js +39 -1
- package/dist/core/c4/parsed/view-ids.js.map +1 -1
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +123 -7
- package/dist/core/c4/project/architecture.js.map +1 -1
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +43 -12
- package/dist/core/c4/project/documents.js.map +1 -1
- package/dist/core/c4/project/load.js +79 -43
- package/dist/core/c4/project/load.js.map +1 -1
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +78 -17
- package/dist/core/c4/resolve/service.js.map +1 -1
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/template.js +65 -1
- package/dist/core/c4/seed/template.js.map +1 -1
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +297 -10
- package/dist/core/c4/source-mask.js.map +1 -1
- package/dist/core/c4/source-scan.js +222 -141
- package/dist/core/c4/source-scan.js.map +1 -1
- package/dist/core/c4/splice/authored-source.js +79 -13
- package/dist/core/c4/splice/authored-source.js.map +1 -1
- package/dist/core/c4/splice/contract.js +20 -0
- package/dist/core/c4/splice/contract.js.map +1 -1
- package/dist/core/c4/splice/delta-blocks.js +20 -20
- package/dist/core/c4/splice/delta-blocks.js.map +1 -1
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +37 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -1
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +182 -114
- package/dist/core/c4/splice/landscape-merge.js.map +1 -1
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +160 -56
- package/dist/core/c4/splice/placement.js.map +1 -1
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +13 -19
- package/dist/core/c4/workspace.js.map +1 -1
- package/dist/core/capabilities/capabilities.js +6 -6
- package/dist/core/capabilities/capabilities.js.map +1 -1
- package/dist/core/capabilities/delta/doc.js +7 -10
- package/dist/core/capabilities/delta/doc.js.map +1 -1
- package/dist/core/capabilities/delta/uncovered.js +2 -2
- package/dist/core/capabilities/delta/uncovered.js.map +1 -1
- package/dist/core/capabilities/findings.js +18 -22
- package/dist/core/capabilities/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/findings.js +12 -19
- package/dist/core/capabilities/realizes/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/join.js +0 -20
- package/dist/core/capabilities/realizes/join.js.map +1 -1
- package/dist/core/capabilities/rollup.js +6 -0
- package/dist/core/capabilities/rollup.js.map +1 -1
- package/dist/core/capabilities/tree.js +6 -28
- package/dist/core/capabilities/tree.js.map +1 -1
- package/dist/core/capabilities/usecase-join.js +3 -13
- package/dist/core/capabilities/usecase-join.js.map +1 -1
- package/dist/core/coherence/authoring/scaffold.js +11 -3
- package/dist/core/coherence/authoring/scaffold.js.map +1 -1
- package/dist/core/coherence/authoring/sentinels.js +2 -1
- package/dist/core/coherence/authoring/sentinels.js.map +1 -1
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +103 -22
- package/dist/core/coherence/coherence.js.map +1 -1
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +60 -34
- package/dist/core/coherence/declared.js.map +1 -1
- package/dist/core/coherence/events/declared.js +44 -59
- package/dist/core/coherence/events/declared.js.map +1 -1
- package/dist/core/coherence/events/events.js +147 -16
- package/dist/core/coherence/events/events.js.map +1 -1
- package/dist/core/coherence/events/grades.js +31 -8
- package/dist/core/coherence/events/grades.js.map +1 -1
- package/dist/core/coherence/events/lookups.js +28 -87
- package/dist/core/coherence/events/lookups.js.map +1 -1
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/lookups.js +18 -78
- package/dist/core/coherence/lookups.js.map +1 -1
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/delta.js +51 -6
- package/dist/core/delta/delta.js.map +1 -1
- package/dist/core/dependencies/fanin.js +2 -2
- package/dist/core/dependencies/fanin.js.map +1 -1
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +94 -12
- package/dist/core/diff/base-git.js.map +1 -1
- package/dist/core/diff/base-state.js +49 -21
- package/dist/core/diff/base-state.js.map +1 -1
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +22 -6
- package/dist/core/diff/scope/changed-paths.js.map +1 -1
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +100 -31
- package/dist/core/diff/semantic.js.map +1 -1
- package/dist/core/docs.js +31 -22
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +34 -18
- package/dist/core/doctor/agents.js.map +1 -1
- package/dist/core/doctor/config.js +7 -3
- package/dist/core/doctor/config.js.map +1 -1
- package/dist/core/doctor/doctor.js +91 -11
- package/dist/core/doctor/doctor.js.map +1 -1
- package/dist/core/doctor/report.js.map +1 -1
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/document/apply.js +158 -11
- package/dist/core/document/apply.js.map +1 -1
- package/dist/core/document/frontmatter.js +55 -0
- package/dist/core/document/frontmatter.js.map +1 -1
- package/dist/core/document/parse.js +29 -6
- package/dist/core/document/parse.js.map +1 -1
- package/dist/core/document/scenarios.js +17 -0
- package/dist/core/document/scenarios.js.map +1 -1
- package/dist/core/document/spec.js +4 -11
- package/dist/core/document/spec.js.map +1 -1
- package/dist/core/envelope/config.js +10 -0
- package/dist/core/envelope/config.js.map +1 -1
- package/dist/core/envelope/json.js +34 -0
- package/dist/core/envelope/json.js.map +1 -1
- package/dist/core/explain/families.js +26 -21
- package/dist/core/explain/families.js.map +1 -1
- package/dist/core/explain/lookup.js +14 -1
- package/dist/core/explain/lookup.js.map +1 -1
- package/dist/core/explain/refusals.js +5 -5
- package/dist/core/explain/refusals.js.map +1 -1
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +68 -109
- package/dist/core/explain/terms.js.map +1 -1
- package/dist/core/explore/explore.js +40 -10
- package/dist/core/explore/explore.js.map +1 -1
- package/dist/core/fleet-context.js +81 -95
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +11 -4
- package/dist/core/gate/checks.js.map +1 -1
- package/dist/core/gate/partners.js +69 -28
- package/dist/core/gate/partners.js.map +1 -1
- package/dist/core/gate/report.js.map +1 -1
- package/dist/core/gate/verification.js +75 -12
- package/dist/core/gate/verification.js.map +1 -1
- package/dist/core/gherkin/stale.js +13 -37
- package/dist/core/gherkin/stale.js.map +1 -1
- package/dist/core/glossary/delta.js +10 -7
- package/dist/core/glossary/delta.js.map +1 -1
- package/dist/core/glossary/tree.js +6 -19
- package/dist/core/glossary/tree.js.map +1 -1
- package/dist/core/kernel/concurrency.js +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -1
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/path-safety.js +38 -0
- package/dist/core/kernel/path-safety.js.map +1 -1
- package/dist/core/kernel/records.js +11 -0
- package/dist/core/kernel/records.js.map +1 -1
- package/dist/core/links/backlinks.js +1 -3
- package/dist/core/links/backlinks.js.map +1 -1
- package/dist/core/links/corpus.js +51 -37
- package/dist/core/links/corpus.js.map +1 -1
- package/dist/core/links/findings.js.map +1 -1
- package/dist/core/links/parse.js +38 -9
- package/dist/core/links/parse.js.map +1 -1
- package/dist/core/mcp/argv.js +101 -0
- package/dist/core/mcp/argv.js.map +1 -1
- package/dist/core/mcp/author-tools.js +2 -1
- package/dist/core/mcp/author-tools.js.map +1 -1
- package/dist/core/mcp/protocol.js +2 -2
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/mcp/tools.js +43 -33
- package/dist/core/mcp/tools.js.map +1 -1
- package/dist/core/openapi/baseline/gate.js +53 -12
- package/dist/core/openapi/baseline/gate.js.map +1 -1
- package/dist/core/openapi/baseline/plan.js +40 -10
- package/dist/core/openapi/baseline/plan.js.map +1 -1
- package/dist/core/openapi/baseline/record.js +0 -1
- package/dist/core/openapi/baseline/record.js.map +1 -1
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +38 -24
- package/dist/core/openapi/depth.js.map +1 -1
- package/dist/core/openapi/digest.js +52 -2
- package/dist/core/openapi/digest.js.map +1 -1
- package/dist/core/openapi/doc.js +12 -4
- package/dist/core/openapi/doc.js.map +1 -1
- package/dist/core/openapi/merge/components.js +25 -60
- package/dist/core/openapi/merge/components.js.map +1 -1
- package/dist/core/openapi/merge/error.js +3 -13
- package/dist/core/openapi/merge/error.js.map +1 -1
- package/dist/core/openapi/merge/markers.js +26 -30
- package/dist/core/openapi/merge/markers.js.map +1 -1
- package/dist/core/openapi/merge/merge.js +28 -52
- package/dist/core/openapi/merge/merge.js.map +1 -1
- package/dist/core/openapi/merge/pin.js +17 -35
- package/dist/core/openapi/merge/pin.js.map +1 -1
- package/dist/core/openspec/decide/verdict.js.map +1 -1
- package/dist/core/openspec/inventory.js +4 -5
- package/dist/core/openspec/inventory.js.map +1 -1
- package/dist/core/openspec/model/mapping.js +30 -28
- package/dist/core/openspec/model/mapping.js.map +1 -1
- package/dist/core/openspec/model/model.js +12 -7
- package/dist/core/openspec/model/model.js.map +1 -1
- package/dist/core/openspec/scan/changes.js +10 -4
- package/dist/core/openspec/scan/changes.js.map +1 -1
- package/dist/core/openspec/scan/config.js +7 -16
- package/dist/core/openspec/scan/config.js.map +1 -1
- package/dist/core/openspec/scan/shape.js +63 -19
- package/dist/core/openspec/scan/shape.js.map +1 -1
- package/dist/core/openspec/scan/walk.js +21 -38
- package/dist/core/openspec/scan/walk.js.map +1 -1
- package/dist/core/pack/living.js +43 -4
- package/dist/core/pack/living.js.map +1 -1
- package/dist/core/pack/pack.js +50 -6
- package/dist/core/pack/pack.js.map +1 -1
- package/dist/core/projection/arch-slice.js +2 -2
- package/dist/core/projection/arch-slice.js.map +1 -1
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +48 -12
- package/dist/core/provenance/findings.js.map +1 -1
- package/dist/core/provenance/git.js +33 -57
- package/dist/core/provenance/git.js.map +1 -1
- package/dist/core/provenance/gitq/moves.js +71 -114
- package/dist/core/provenance/gitq/moves.js.map +1 -1
- package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
- package/dist/core/provenance/sources.js +23 -6
- package/dist/core/provenance/sources.js.map +1 -1
- package/dist/core/provenance/stamp.js +5 -17
- package/dist/core/provenance/stamp.js.map +1 -1
- package/dist/core/repo/authored/paths.js +18 -0
- package/dist/core/repo/authored/paths.js.map +1 -1
- package/dist/core/repo/entries.js.map +1 -1
- package/dist/core/repo/paths.js +92 -6
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/repo.js +74 -14
- package/dist/core/repo/repo.js.map +1 -1
- package/dist/core/repo/tree/find.js +12 -3
- package/dist/core/repo/tree/find.js.map +1 -1
- package/dist/core/repo/tree/fs.js +27 -1
- package/dist/core/repo/tree/fs.js.map +1 -1
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +53 -32
- package/dist/core/repo/tree/walk.js.map +1 -1
- package/dist/core/results.js +47 -12
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +121 -13
- package/dist/core/scaffold/landscape.js.map +1 -1
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/staging/commit.js +26 -15
- package/dist/core/staging/commit.js.map +1 -1
- package/dist/core/staging/lock.js +74 -12
- package/dist/core/staging/lock.js.map +1 -1
- package/dist/core/staging/recovery/intent.js +2 -5
- package/dist/core/staging/recovery/intent.js.map +1 -1
- package/dist/core/staging/recovery/recover.js +84 -6
- package/dist/core/staging/recovery/recover.js.map +1 -1
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +24 -14
- package/dist/core/staging/txn/forward.js.map +1 -1
- package/dist/core/staging/writes.js.map +1 -1
- package/dist/core/status/actions/execution.js +11 -0
- package/dist/core/status/actions/execution.js.map +1 -1
- package/dist/core/status/contracts.js +39 -15
- package/dist/core/status/contracts.js.map +1 -1
- package/dist/core/status/feature/artifacts.js +33 -8
- package/dist/core/status/feature/artifacts.js.map +1 -1
- package/dist/core/status/feature/feature.js +24 -17
- package/dist/core/status/feature/feature.js.map +1 -1
- package/dist/core/status/feature/next.js +20 -7
- package/dist/core/status/feature/next.js.map +1 -1
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +43 -14
- package/dist/core/status/fleet/fleet.js.map +1 -1
- package/dist/core/status/fleet/next.js +153 -58
- package/dist/core/status/fleet/next.js.map +1 -1
- package/dist/core/status/report.js.map +1 -1
- package/dist/core/status/scan.js.map +1 -1
- package/dist/core/status/verification.js +30 -15
- package/dist/core/status/verification.js.map +1 -1
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +11 -14
- package/dist/core/usecases/capability.js.map +1 -1
- package/dist/core/usecases/delta/claims.js +31 -7
- package/dist/core/usecases/delta/claims.js.map +1 -1
- package/dist/core/usecases/delta/flows.js +5 -7
- package/dist/core/usecases/delta/flows.js.map +1 -1
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +32 -191
- package/dist/core/usecases/delta/overlay.js.map +1 -1
- package/dist/core/usecases/fleet.js +195 -36
- package/dist/core/usecases/fleet.js.map +1 -1
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +26 -14
- package/dist/core/usecases/operations.js.map +1 -1
- package/dist/core/usecases/place.js.map +1 -1
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/verify/answers.js +12 -5
- package/dist/core/verify/answers.js.map +1 -1
- package/dist/core/verify/build.js +102 -82
- package/dist/core/verify/build.js.map +1 -1
- package/dist/core/verify/checklist.js +70 -12
- package/dist/core/verify/checklist.js.map +1 -1
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +3 -2
- package/dist/core/verify/pins/lint.js.map +1 -1
- package/dist/core/verify/pins/pin.js +1 -1
- package/dist/core/verify/pins/pin.js.map +1 -1
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/{file.js → read/shape.js} +16 -104
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +35 -12
- package/dist/core/verify/record.js.map +1 -1
- package/dist/core/verify/store/commit.js +40 -30
- package/dist/core/verify/store/commit.js.map +1 -1
- package/dist/core/verify/store/render.js +8 -4
- package/dist/core/verify/store/render.js.map +1 -1
- package/dist/core/vocabulary/issue.js +4 -0
- package/dist/core/vocabulary/issue.js.map +1 -1
- package/dist/core/vocabulary/maturity.js +75 -4
- package/dist/core/vocabulary/maturity.js.map +1 -1
- package/dist/core/vocabulary/report.js +16 -1
- package/dist/core/vocabulary/report.js.map +1 -1
- package/examples/README.md +54 -11
- package/examples/docs/architecture/landscape.likec4 +62 -6
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +7 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
- package/examples/docs/likec4.config.json +0 -1
- package/examples/docs/services/checkout-web/model.likec4 +39 -56
- package/examples/docs/services/order-service/arch.spec.md +13 -6
- package/examples/docs/services/order-service/asyncapi.yaml +3 -2
- package/examples/docs/services/order-service/model.likec4 +58 -70
- package/examples/docs/services/payment-service/arch.spec.md +7 -4
- package/examples/docs/services/payment-service/model.likec4 +38 -37
- package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
- package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
- package/examples/docs/services/platform/notification-service/health.yaml +8 -3
- package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
- package/package.json +1 -1
- package/dist/commands/validate/checks/vocabulary.js +0 -31
- package/dist/commands/validate/checks/vocabulary.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
- package/dist/core/agent/agents-md/artifacts.js +0 -220
- package/dist/core/agent/agents-md/artifacts.js.map +0 -1
- package/dist/core/agent/agents-md/cycle.js +0 -165
- package/dist/core/agent/agents-md/cycle.js.map +0 -1
- package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
- package/dist/core/agent/agents-md/spine.js +0 -40
- package/dist/core/agent/agents-md/spine.js.map +0 -1
- package/dist/core/coherence/events/merged.js +0 -40
- package/dist/core/coherence/events/merged.js.map +0 -1
- package/dist/core/diff/current-state.js +0 -96
- package/dist/core/diff/current-state.js.map +0 -1
- package/dist/core/diff/victims.js +0 -247
- package/dist/core/diff/victims.js.map +0 -1
- package/dist/core/repo/tree/views.js +0 -172
- package/dist/core/repo/tree/views.js.map +0 -1
- package/dist/core/staging/snapshot.js.map +0 -1
- package/dist/core/verify/file.js.map +0 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one way both contract axes read and write a contract document: parse it,
|
|
3
|
+
* refuse its first parse error, resolve it, and hand it back as text.
|
|
4
|
+
*
|
|
5
|
+
* The helpers are axis-neutral and take the refusal to raise as a `fail`
|
|
6
|
+
* callback, because the event axis's six entry points spelled the same parse,
|
|
7
|
+
* first-error, resolve and serialize sequence the OpenAPI axis's did, against
|
|
8
|
+
* its own error class (../asyncapi/merge/error.ts, beside ./merge/error.ts). A
|
|
9
|
+
* leaf of its own, named for what it holds, at the lowest package both merge
|
|
10
|
+
* packages already import — not inside either axis's refusal module, where the
|
|
11
|
+
* event axis would read its contracts through a file named for an error.
|
|
12
|
+
* Import direction is asyncapi → openapi, as everywhere else on the contract
|
|
13
|
+
* axes. `writeTreeOver` is the write an EDIT takes — a merge into a living
|
|
14
|
+
* contract, a strip of a feature's markers, the pins and baseline record
|
|
15
|
+
* `loam rebase` stamps into one — so that only what changed is re-printed.
|
|
16
|
+
*/
|
|
17
|
+
import { isDeepStrictEqual } from "node:util";
|
|
18
|
+
import { Document, Pair, Scalar, YAMLMap, isMap, isScalar, parseDocument } from "yaml";
|
|
19
|
+
function errorMessage(error) {
|
|
20
|
+
return error instanceof Error ? error.message : String(error);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse a contract, refuse its first parse error, and resolve it. `check` runs
|
|
24
|
+
* between the two, on the AST: the event axis refuses an ambiguous slot key
|
|
25
|
+
* there, BEFORE resolution, so a document that is both ambiguous and carries
|
|
26
|
+
* an unresolvable alias is refused for the ambiguity, exactly as it was when
|
|
27
|
+
* each entry point spelled the sequence out.
|
|
28
|
+
*/
|
|
29
|
+
export function readTree(text, fail, check) {
|
|
30
|
+
const doc = parseDocument(text);
|
|
31
|
+
if (doc.errors.length > 0)
|
|
32
|
+
throw fail(doc.errors[0].message);
|
|
33
|
+
check?.(doc);
|
|
34
|
+
return { doc, plain: resolveTree(doc, fail) };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve aliases once with the document's own anchor context. Calling an
|
|
38
|
+
* individual AST node's toJSON() loses that context and can silently turn an
|
|
39
|
+
* aliased operation, slot or component into the wrong value. An alias that
|
|
40
|
+
* cannot be resolved at all is a document loam cannot read, and says so.
|
|
41
|
+
*/
|
|
42
|
+
export function resolveTree(doc, fail) {
|
|
43
|
+
try {
|
|
44
|
+
return doc.toJS() ?? {};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw fail(errorMessage(error));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Hand the whole document back through the printer. Not exported: it is
|
|
52
|
+
* `writeTreeOver`'s first step and its fallback, and a writer calling it
|
|
53
|
+
* directly would re-print the author's whole contract — the cost
|
|
54
|
+
* `writeTreeOver` exists to avoid.
|
|
55
|
+
*/
|
|
56
|
+
function writeTree(doc, fail) {
|
|
57
|
+
try {
|
|
58
|
+
return doc.toString();
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw fail(errorMessage(error));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Hand an EDITED document back over the text it was parsed from: every map
|
|
66
|
+
* entry the edit did not change keeps its original bytes, and only the entries
|
|
67
|
+
* it added, replaced or removed are written fresh.
|
|
68
|
+
*
|
|
69
|
+
* WHY THE WHOLE-DOCUMENT WRITE WAS NOT ENOUGH. `writeTree` re-serializes every
|
|
70
|
+
* node, and the `yaml` library's printer has opinions the author never asked
|
|
71
|
+
* for: it re-folds every plain or quoted scalar at 80 columns, re-pads every
|
|
72
|
+
* flow sequence (`[a, b]` becomes `[ a, b ]`), and turns CRLF into LF. So an
|
|
73
|
+
* archive that added one channel to a living contract rewrote a long
|
|
74
|
+
* `description` three sections away, and the merge's diff — the thing a
|
|
75
|
+
* reviewer reads to learn what the feature changed — carried lines nobody
|
|
76
|
+
* touched. `lineWidth: 0` is not the fix, and was measured not to be: it stops
|
|
77
|
+
* the folding by JOINING every scalar the author folded by hand onto one line,
|
|
78
|
+
* which on loam's own `examples/docs` rewrote 38 lines of a contract the
|
|
79
|
+
* default printer had left alone. No printer setting reproduces an author's
|
|
80
|
+
* layout; only the author's bytes do.
|
|
81
|
+
*
|
|
82
|
+
* HOW. Both trees are walked in step, block map by block map, keyed on the
|
|
83
|
+
* entry key: an entry whose resolved value is unchanged is left exactly where it
|
|
84
|
+
* is, an entry that changed is either descended into (both sides are block
|
|
85
|
+
* maps) or replaced by the printer's spelling of its new value, a new entry is
|
|
86
|
+
* printed after the entry the edit placed it behind, and a removed one is cut
|
|
87
|
+
* out with the comment lines directly above it — which is where the `yaml`
|
|
88
|
+
* library attaches such a comment, and so what the whole-document write would
|
|
89
|
+
* have removed with it.
|
|
90
|
+
*
|
|
91
|
+
* VERIFIED, OR NOT USED. The spliced text is parsed back and compared, resolved
|
|
92
|
+
* value against resolved value, with the edited tree. Anything the walk does
|
|
93
|
+
* not understand — a key that is not a scalar, a key spelled twice, an entry
|
|
94
|
+
* not on a line of its own, a reorder, an alias it cannot print alone — makes
|
|
95
|
+
* it answer nothing, and so does a splice that would read back as a different
|
|
96
|
+
* document: the fallback is `writeTree`, the old behaviour exactly, so this can
|
|
97
|
+
* only ever narrow a diff and never change what a contract says. The
|
|
98
|
+
* whole-document write also runs first, every time, so a document it cannot
|
|
99
|
+
* print fails the way it always failed.
|
|
100
|
+
*/
|
|
101
|
+
export function writeTreeOver(doc, source, fail) {
|
|
102
|
+
const whole = writeTree(doc, fail);
|
|
103
|
+
const spliced = splicedText(doc, source);
|
|
104
|
+
return spliced !== null && readsAs(spliced, doc) ? spliced : whole;
|
|
105
|
+
}
|
|
106
|
+
function splicedText(doc, source) {
|
|
107
|
+
const original = parseDocument(source);
|
|
108
|
+
if (original.errors.length > 0)
|
|
109
|
+
return null;
|
|
110
|
+
const run = { source, eol: source.includes("\r\n") ? "\r\n" : "\n", edits: [] };
|
|
111
|
+
try {
|
|
112
|
+
// Resolved through each document's own anchors, once — what "unchanged"
|
|
113
|
+
// means is decided on these, never on the nodes.
|
|
114
|
+
const before = { node: original.contents, plain: original.toJS() };
|
|
115
|
+
const after = { node: doc.contents, plain: doc.toJS() };
|
|
116
|
+
if (!spliceMap(run, before, after))
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// A node the printer cannot print alone — an alias whose anchor sits
|
|
121
|
+
// outside the entry being written — is a document this walk does not
|
|
122
|
+
// understand, and the answer for those is the whole-document write.
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// Stable by position, so two insertions at one point keep the order the
|
|
126
|
+
// walk emitted them in — which is the edited tree's order.
|
|
127
|
+
const edits = [...run.edits].sort((a, b) => a.from - b.from);
|
|
128
|
+
let out = "";
|
|
129
|
+
let cursor = 0;
|
|
130
|
+
for (const edit of edits) {
|
|
131
|
+
if (edit.from < cursor)
|
|
132
|
+
return null;
|
|
133
|
+
out += source.slice(cursor, edit.from) + edit.text;
|
|
134
|
+
cursor = edit.to;
|
|
135
|
+
}
|
|
136
|
+
return out + source.slice(cursor);
|
|
137
|
+
}
|
|
138
|
+
/** Does the spliced text read back as exactly the edited document? */
|
|
139
|
+
function readsAs(text, doc) {
|
|
140
|
+
try {
|
|
141
|
+
const back = parseDocument(text);
|
|
142
|
+
return back.errors.length === 0 && isDeepStrictEqual(back.toJS(), doc.toJS());
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function blockMap(node) {
|
|
149
|
+
return isMap(node) && node.flow !== true;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* An entry's key as the resolved tree spells it, or null for a key this walk
|
|
153
|
+
* will not match on. A key the edit SET arrives as the raw value rather than a
|
|
154
|
+
* node — `setIn` builds the pair from what it was handed — and is the same key.
|
|
155
|
+
*/
|
|
156
|
+
function keyOf(pair) {
|
|
157
|
+
const value = isScalar(pair.key) ? pair.key.value : pair.key;
|
|
158
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : null;
|
|
159
|
+
}
|
|
160
|
+
function child(plain, key) {
|
|
161
|
+
return plain !== null && typeof plain === "object" ? plain[key] : undefined;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Splice one block map. Answers false — and the whole splice is abandoned — on
|
|
165
|
+
* any shape it does not understand; see `writeTreeOver`.
|
|
166
|
+
*/
|
|
167
|
+
function spliceMap(run, before, after) {
|
|
168
|
+
if (!blockMap(before.node) || !blockMap(after.node) || before.node.items.length === 0)
|
|
169
|
+
return false;
|
|
170
|
+
const located = locateEntries(run.source, before.node.items);
|
|
171
|
+
if (located === null)
|
|
172
|
+
return false;
|
|
173
|
+
const { entries, column: indent } = located;
|
|
174
|
+
const byKey = new Map();
|
|
175
|
+
for (const [at, entry] of entries.entries()) {
|
|
176
|
+
const key = keyOf(entry.pair);
|
|
177
|
+
if (key === null || byKey.has(key))
|
|
178
|
+
return false;
|
|
179
|
+
byKey.set(key, { at, entry });
|
|
180
|
+
}
|
|
181
|
+
const kept = new Set();
|
|
182
|
+
let insertAt = entries[0].lead;
|
|
183
|
+
let lastAt = -1;
|
|
184
|
+
for (const pair of after.node.items) {
|
|
185
|
+
const key = keyOf(pair);
|
|
186
|
+
if (key === null || kept.has(key))
|
|
187
|
+
return false;
|
|
188
|
+
kept.add(key);
|
|
189
|
+
const was = byKey.get(key);
|
|
190
|
+
if (was === undefined) {
|
|
191
|
+
run.edits.push({ from: insertAt, to: insertAt, text: printed(run, pair, indent, insertAt) });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// A reorder is a change this walk cannot express by keeping bytes where
|
|
195
|
+
// they are, and the whole-document write expresses it exactly.
|
|
196
|
+
if (was.at < lastAt)
|
|
197
|
+
return false;
|
|
198
|
+
lastAt = was.at;
|
|
199
|
+
insertAt = was.entry.end;
|
|
200
|
+
const old = { node: was.entry.pair.value, plain: child(before.plain, key) };
|
|
201
|
+
const now = { node: pair.value, plain: child(after.plain, key) };
|
|
202
|
+
if (isDeepStrictEqual(old.plain, now.plain))
|
|
203
|
+
continue;
|
|
204
|
+
const mark = run.edits.length;
|
|
205
|
+
if (blockMap(old.node) && blockMap(now.node) && spliceMap(run, old, now))
|
|
206
|
+
continue;
|
|
207
|
+
// Not descended into, or the descent failed: drop whatever it collected
|
|
208
|
+
// and write the entry whole, from its key line to its end. The comment
|
|
209
|
+
// lines above it stay — they are outside the range, and the key printed
|
|
210
|
+
// here carries none of its own.
|
|
211
|
+
run.edits.length = mark;
|
|
212
|
+
run.edits.push({ from: was.entry.line, to: was.entry.end, text: printed(run, pair, indent, was.entry.line) });
|
|
213
|
+
}
|
|
214
|
+
for (const [key, { entry }] of byKey) {
|
|
215
|
+
if (!kept.has(key))
|
|
216
|
+
run.edits.push({ from: entry.lead, to: entry.end, text: "" });
|
|
217
|
+
}
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
/** Each entry's line, comment lead and end — or null when one is not on a line of its own at one indentation. */
|
|
221
|
+
function locateEntries(source, items) {
|
|
222
|
+
const entries = [];
|
|
223
|
+
let column = null;
|
|
224
|
+
let bound = 0;
|
|
225
|
+
for (const pair of items) {
|
|
226
|
+
const key = pair.key;
|
|
227
|
+
const value = pair.value;
|
|
228
|
+
if (!key?.range || !value?.range)
|
|
229
|
+
return null;
|
|
230
|
+
const start = key.range[0];
|
|
231
|
+
const line = source.lastIndexOf("\n", start - 1) + 1;
|
|
232
|
+
if (line < bound || !/^ *$/.test(source.slice(line, start)))
|
|
233
|
+
return null;
|
|
234
|
+
if (column !== null && start - line !== column)
|
|
235
|
+
return null;
|
|
236
|
+
column = start - line;
|
|
237
|
+
const lead = commentLead(source, { line, bound, attached: isScalar(key) && key.commentBefore !== undefined });
|
|
238
|
+
// An EMPTY value — `a:`, `a: !tag`, `a: &x` — ends AT its line break rather
|
|
239
|
+
// than past it, measured on both line endings; without the step a cut
|
|
240
|
+
// leaves a stray blank line, and an insert after it joins the next line.
|
|
241
|
+
let end = value.range[2];
|
|
242
|
+
if (end > 0 && source[end - 1] !== "\n") {
|
|
243
|
+
if (source.startsWith("\r\n", end))
|
|
244
|
+
end += 2;
|
|
245
|
+
else if (source[end] === "\n")
|
|
246
|
+
end += 1;
|
|
247
|
+
}
|
|
248
|
+
entries.push({ pair, line, lead, end });
|
|
249
|
+
bound = end;
|
|
250
|
+
}
|
|
251
|
+
return column === null ? null : { entries, column };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Where the comment block above an entry's key line starts — the lines the
|
|
255
|
+
* `yaml` library attaches to the key, which a removed entry takes with it, as
|
|
256
|
+
* the whole-document write would. Contiguous comment lines always; across blank
|
|
257
|
+
* lines too when the key carries an attached comment, because the library
|
|
258
|
+
* attaches one separated by a blank line as well. Never above `bound`, the end
|
|
259
|
+
* of the entry before, and never onto a blank line ABOVE the block: those
|
|
260
|
+
* separate this entry from the previous one and stay.
|
|
261
|
+
*/
|
|
262
|
+
function commentLead(source, at) {
|
|
263
|
+
let lead = at.line;
|
|
264
|
+
for (let cursor = at.line; cursor > at.bound;) {
|
|
265
|
+
const previous = source.lastIndexOf("\n", cursor - 2) + 1;
|
|
266
|
+
if (previous < at.bound)
|
|
267
|
+
break;
|
|
268
|
+
const text = source.slice(previous, cursor).trim();
|
|
269
|
+
if (text.startsWith("#"))
|
|
270
|
+
lead = previous;
|
|
271
|
+
else if (text !== "" || !at.attached)
|
|
272
|
+
break;
|
|
273
|
+
cursor = previous;
|
|
274
|
+
}
|
|
275
|
+
return lead;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* One entry as the printer spells it, indented to its map's column, in the
|
|
279
|
+
* original's line break. The key is printed BARE — a fresh scalar with the
|
|
280
|
+
* original's quoting style and none of its comments — because the comment
|
|
281
|
+
* lines above an entry stay in place outside the range being replaced, and the
|
|
282
|
+
* printer would otherwise write them a second time.
|
|
283
|
+
*/
|
|
284
|
+
function printed(run, pair, indent, at) {
|
|
285
|
+
const key = new Scalar(isScalar(pair.key) ? pair.key.value : pair.key);
|
|
286
|
+
if (isScalar(pair.key) && pair.key.type !== undefined)
|
|
287
|
+
key.type = pair.key.type;
|
|
288
|
+
const map = new YAMLMap();
|
|
289
|
+
map.items.push(new Pair(key, pair.value));
|
|
290
|
+
const single = new Document();
|
|
291
|
+
single.contents = map;
|
|
292
|
+
const text = single
|
|
293
|
+
.toString()
|
|
294
|
+
.split("\n")
|
|
295
|
+
.map((line) => (line === "" ? line : " ".repeat(indent) + line))
|
|
296
|
+
.join(run.eol);
|
|
297
|
+
// Written where the original stopped without a final line break, the entry
|
|
298
|
+
// needs one in front of it, or it would join the line it follows.
|
|
299
|
+
return at === run.source.length && at > 0 && !run.source.endsWith("\n") ? run.eol + text : text;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=contract-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-tree.js","sourceRoot":"","sources":["../../../src/core/openapi/contract-tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The one way both contract axes read and write a contract document: parse it,\n * refuse its first parse error, resolve it, and hand it back as text.\n *\n * The helpers are axis-neutral and take the refusal to raise as a `fail`\n * callback, because the event axis's six entry points spelled the same parse,\n * first-error, resolve and serialize sequence the OpenAPI axis's did, against\n * its own error class (../asyncapi/merge/error.ts, beside ./merge/error.ts). A\n * leaf of its own, named for what it holds, at the lowest package both merge\n * packages already import — not inside either axis's refusal module, where the\n * event axis would read its contracts through a file named for an error.\n * Import direction is asyncapi → openapi, as everywhere else on the contract\n * axes. `writeTreeOver` is the write an EDIT takes — a merge into a living\n * contract, a strip of a feature's markers, the pins and baseline record\n * `loam rebase` stamps into one — so that only what changed is re-printed.\n */\nimport { isDeepStrictEqual } from \"node:util\";\nimport { Document, Pair, Scalar, YAMLMap, isMap, isScalar, parseDocument, type Node } from \"yaml\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** A contract's AST, for the writes, and its resolved plain tree, for every shape question. */\nexport interface ContractTree {\n doc: Document.Parsed;\n plain: unknown;\n}\n\n/**\n * Parse a contract, refuse its first parse error, and resolve it. `check` runs\n * between the two, on the AST: the event axis refuses an ambiguous slot key\n * there, BEFORE resolution, so a document that is both ambiguous and carries\n * an unresolvable alias is refused for the ambiguity, exactly as it was when\n * each entry point spelled the sequence out.\n */\nexport function readTree(text: string, fail: (detail: string) => Error, check?: (doc: Document) => void): ContractTree {\n const doc = parseDocument(text);\n if (doc.errors.length > 0) throw fail(doc.errors[0]!.message);\n check?.(doc);\n return { doc, plain: resolveTree(doc, fail) };\n}\n\n/**\n * Resolve aliases once with the document's own anchor context. Calling an\n * individual AST node's toJSON() loses that context and can silently turn an\n * aliased operation, slot or component into the wrong value. An alias that\n * cannot be resolved at all is a document loam cannot read, and says so.\n */\nexport function resolveTree(doc: Document, fail: (detail: string) => Error): unknown {\n try {\n return doc.toJS() ?? {};\n } catch (error) {\n throw fail(errorMessage(error));\n }\n}\n\n/**\n * Hand the whole document back through the printer. Not exported: it is\n * `writeTreeOver`'s first step and its fallback, and a writer calling it\n * directly would re-print the author's whole contract — the cost\n * `writeTreeOver` exists to avoid.\n */\nfunction writeTree(doc: Document, fail: (detail: string) => Error): string {\n try {\n return doc.toString();\n } catch (error) {\n throw fail(errorMessage(error));\n }\n}\n\n/**\n * Hand an EDITED document back over the text it was parsed from: every map\n * entry the edit did not change keeps its original bytes, and only the entries\n * it added, replaced or removed are written fresh.\n *\n * WHY THE WHOLE-DOCUMENT WRITE WAS NOT ENOUGH. `writeTree` re-serializes every\n * node, and the `yaml` library's printer has opinions the author never asked\n * for: it re-folds every plain or quoted scalar at 80 columns, re-pads every\n * flow sequence (`[a, b]` becomes `[ a, b ]`), and turns CRLF into LF. So an\n * archive that added one channel to a living contract rewrote a long\n * `description` three sections away, and the merge's diff — the thing a\n * reviewer reads to learn what the feature changed — carried lines nobody\n * touched. `lineWidth: 0` is not the fix, and was measured not to be: it stops\n * the folding by JOINING every scalar the author folded by hand onto one line,\n * which on loam's own `examples/docs` rewrote 38 lines of a contract the\n * default printer had left alone. No printer setting reproduces an author's\n * layout; only the author's bytes do.\n *\n * HOW. Both trees are walked in step, block map by block map, keyed on the\n * entry key: an entry whose resolved value is unchanged is left exactly where it\n * is, an entry that changed is either descended into (both sides are block\n * maps) or replaced by the printer's spelling of its new value, a new entry is\n * printed after the entry the edit placed it behind, and a removed one is cut\n * out with the comment lines directly above it — which is where the `yaml`\n * library attaches such a comment, and so what the whole-document write would\n * have removed with it.\n *\n * VERIFIED, OR NOT USED. The spliced text is parsed back and compared, resolved\n * value against resolved value, with the edited tree. Anything the walk does\n * not understand — a key that is not a scalar, a key spelled twice, an entry\n * not on a line of its own, a reorder, an alias it cannot print alone — makes\n * it answer nothing, and so does a splice that would read back as a different\n * document: the fallback is `writeTree`, the old behaviour exactly, so this can\n * only ever narrow a diff and never change what a contract says. The\n * whole-document write also runs first, every time, so a document it cannot\n * print fails the way it always failed.\n */\nexport function writeTreeOver(doc: Document, source: string, fail: (detail: string) => Error): string {\n const whole = writeTree(doc, fail);\n const spliced = splicedText(doc, source);\n return spliced !== null && readsAs(spliced, doc) ? spliced : whole;\n}\n\n/** One replacement of `source[from, to)`. An insertion is `from === to`. */\ninterface Edit {\n from: number;\n to: number;\n text: string;\n}\n\n/** What one walk shares: the original text, its line break, and the edits collected so far. */\ninterface SpliceRun {\n source: string;\n eol: string;\n edits: Edit[];\n}\n\n/** One original entry, located: where its key line starts, where its comments start, where it ends. */\ninterface Located {\n pair: Pair;\n /** Start of the line the key is on. */\n line: number;\n /** Start of the contiguous comment lines directly above that line, or `line` when there are none. */\n lead: number;\n /** End of the entry, past its line break. */\n end: number;\n}\n\n\n/** One side of the walk: a node, and the value it resolves to through its own document. */\ninterface Side {\n node: unknown;\n plain: unknown;\n}\n\nfunction splicedText(doc: Document, source: string): string | null {\n const original = parseDocument(source);\n if (original.errors.length > 0) return null;\n const run: SpliceRun = { source, eol: source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\", edits: [] };\n try {\n // Resolved through each document's own anchors, once — what \"unchanged\"\n // means is decided on these, never on the nodes.\n const before: Side = { node: original.contents, plain: original.toJS() };\n const after: Side = { node: doc.contents, plain: doc.toJS() };\n if (!spliceMap(run, before, after)) return null;\n } catch {\n // A node the printer cannot print alone — an alias whose anchor sits\n // outside the entry being written — is a document this walk does not\n // understand, and the answer for those is the whole-document write.\n return null;\n }\n // Stable by position, so two insertions at one point keep the order the\n // walk emitted them in — which is the edited tree's order.\n const edits = [...run.edits].sort((a, b) => a.from - b.from);\n let out = \"\";\n let cursor = 0;\n for (const edit of edits) {\n if (edit.from < cursor) return null;\n out += source.slice(cursor, edit.from) + edit.text;\n cursor = edit.to;\n }\n return out + source.slice(cursor);\n}\n\n/** Does the spliced text read back as exactly the edited document? */\nfunction readsAs(text: string, doc: Document): boolean {\n try {\n const back = parseDocument(text);\n return back.errors.length === 0 && isDeepStrictEqual(back.toJS(), doc.toJS());\n } catch {\n return false;\n }\n}\n\nfunction blockMap(node: unknown): node is YAMLMap {\n return isMap(node) && node.flow !== true;\n}\n\n/**\n * An entry's key as the resolved tree spells it, or null for a key this walk\n * will not match on. A key the edit SET arrives as the raw value rather than a\n * node — `setIn` builds the pair from what it was handed — and is the same key.\n */\nfunction keyOf(pair: Pair): string | null {\n const value: unknown = isScalar(pair.key) ? pair.key.value : pair.key;\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? String(value) : null;\n}\n\nfunction child(plain: unknown, key: string): unknown {\n return plain !== null && typeof plain === \"object\" ? (plain as Record<string, unknown>)[key] : undefined;\n}\n\n/**\n * Splice one block map. Answers false — and the whole splice is abandoned — on\n * any shape it does not understand; see `writeTreeOver`.\n */\nfunction spliceMap(run: SpliceRun, before: Side, after: Side): boolean {\n if (!blockMap(before.node) || !blockMap(after.node) || before.node.items.length === 0) return false;\n const located = locateEntries(run.source, before.node.items);\n if (located === null) return false;\n const { entries, column: indent } = located;\n const byKey = new Map<string, { at: number; entry: Located }>();\n for (const [at, entry] of entries.entries()) {\n const key = keyOf(entry.pair);\n if (key === null || byKey.has(key)) return false;\n byKey.set(key, { at, entry });\n }\n const kept = new Set<string>();\n let insertAt = entries[0]!.lead;\n let lastAt = -1;\n for (const pair of after.node.items) {\n const key = keyOf(pair);\n if (key === null || kept.has(key)) return false;\n kept.add(key);\n const was = byKey.get(key);\n if (was === undefined) {\n run.edits.push({ from: insertAt, to: insertAt, text: printed(run, pair, indent, insertAt) });\n continue;\n }\n // A reorder is a change this walk cannot express by keeping bytes where\n // they are, and the whole-document write expresses it exactly.\n if (was.at < lastAt) return false;\n lastAt = was.at;\n insertAt = was.entry.end;\n const old: Side = { node: was.entry.pair.value, plain: child(before.plain, key) };\n const now: Side = { node: pair.value, plain: child(after.plain, key) };\n if (isDeepStrictEqual(old.plain, now.plain)) continue;\n const mark = run.edits.length;\n if (blockMap(old.node) && blockMap(now.node) && spliceMap(run, old, now)) continue;\n // Not descended into, or the descent failed: drop whatever it collected\n // and write the entry whole, from its key line to its end. The comment\n // lines above it stay — they are outside the range, and the key printed\n // here carries none of its own.\n run.edits.length = mark;\n run.edits.push({ from: was.entry.line, to: was.entry.end, text: printed(run, pair, indent, was.entry.line) });\n }\n for (const [key, { entry }] of byKey) {\n if (!kept.has(key)) run.edits.push({ from: entry.lead, to: entry.end, text: \"\" });\n }\n return true;\n}\n\n/** A block map's entries, located, and the one column every key in it starts at. */\ninterface LocatedMap {\n entries: Located[];\n column: number;\n}\n\n/** Each entry's line, comment lead and end — or null when one is not on a line of its own at one indentation. */\nfunction locateEntries(source: string, items: readonly Pair[]): LocatedMap | null {\n const entries: Located[] = [];\n let column: number | null = null;\n let bound = 0;\n for (const pair of items) {\n const key = pair.key as Node | null;\n const value = pair.value as Node | null;\n if (!key?.range || !value?.range) return null;\n const start = key.range[0];\n const line = source.lastIndexOf(\"\\n\", start - 1) + 1;\n if (line < bound || !/^ *$/.test(source.slice(line, start))) return null;\n if (column !== null && start - line !== column) return null;\n column = start - line;\n const lead = commentLead(source, { line, bound, attached: isScalar(key) && key.commentBefore !== undefined });\n // An EMPTY value — `a:`, `a: !tag`, `a: &x` — ends AT its line break rather\n // than past it, measured on both line endings; without the step a cut\n // leaves a stray blank line, and an insert after it joins the next line.\n let end = value.range[2];\n if (end > 0 && source[end - 1] !== \"\\n\") {\n if (source.startsWith(\"\\r\\n\", end)) end += 2;\n else if (source[end] === \"\\n\") end += 1;\n }\n entries.push({ pair, line, lead, end });\n bound = end;\n }\n return column === null ? null : { entries, column };\n}\n\n/**\n * Where the comment block above an entry's key line starts — the lines the\n * `yaml` library attaches to the key, which a removed entry takes with it, as\n * the whole-document write would. Contiguous comment lines always; across blank\n * lines too when the key carries an attached comment, because the library\n * attaches one separated by a blank line as well. Never above `bound`, the end\n * of the entry before, and never onto a blank line ABOVE the block: those\n * separate this entry from the previous one and stay.\n */\nfunction commentLead(source: string, at: { line: number; bound: number; attached: boolean }): number {\n let lead = at.line;\n for (let cursor = at.line; cursor > at.bound; ) {\n const previous = source.lastIndexOf(\"\\n\", cursor - 2) + 1;\n if (previous < at.bound) break;\n const text = source.slice(previous, cursor).trim();\n if (text.startsWith(\"#\")) lead = previous;\n else if (text !== \"\" || !at.attached) break;\n cursor = previous;\n }\n return lead;\n}\n\n/**\n * One entry as the printer spells it, indented to its map's column, in the\n * original's line break. The key is printed BARE — a fresh scalar with the\n * original's quoting style and none of its comments — because the comment\n * lines above an entry stay in place outside the range being replaced, and the\n * printer would otherwise write them a second time.\n */\nfunction printed(run: SpliceRun, pair: Pair, indent: number, at: number): string {\n const key = new Scalar(isScalar(pair.key) ? pair.key.value : pair.key);\n if (isScalar(pair.key) && pair.key.type !== undefined) key.type = pair.key.type;\n const map = new YAMLMap();\n map.items.push(new Pair(key, pair.value));\n const single = new Document();\n single.contents = map;\n const text = single\n .toString()\n .split(\"\\n\")\n .map((line) => (line === \"\" ? line : \" \".repeat(indent) + line))\n .join(run.eol);\n // Written where the original stopped without a final line break, the entry\n // needs one in front of it, or it would join the line it follows.\n return at === run.source.length && at > 0 && !run.source.endsWith(\"\\n\") ? run.eol + text : text;\n}\n"]}
|
|
@@ -10,10 +10,14 @@
|
|
|
10
10
|
* says, only whether one was declared at all, so the reader's structure-only
|
|
11
11
|
* stance holds.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
* package already imports this package (`HTTP_METHODS` from
|
|
15
|
-
* reverse import would
|
|
16
|
-
* `resolvePointer` copies exist on the asyncapi axis.
|
|
13
|
+
* This module used to keep a private pointer walk rather than import the
|
|
14
|
+
* merge's: the merge package already imports this package (`HTTP_METHODS` from
|
|
15
|
+
* doc.ts), so the reverse import would have been a package cycle — the same
|
|
16
|
+
* reason read-side `resolvePointer` copies exist on the asyncapi axis. The two
|
|
17
|
+
* plain `$ref` questions now live HERE, at the axis root (`collectRefs` and
|
|
18
|
+
* `resolvePointer`, at the bottom), so the private copy went: the dangling-ref
|
|
19
|
+
* probe below, the merge's component closure and the reader's closure digest
|
|
20
|
+
* (`closureDigester`, ./digest.ts) all ask the same two questions.
|
|
17
21
|
*/
|
|
18
22
|
/** Status codes whose response legitimately carries no body. */
|
|
19
23
|
const NO_CONTENT = new Set(["204", "304"]);
|
|
@@ -78,45 +82,55 @@ export function failureCodesOf(op) {
|
|
|
78
82
|
* scope and never graded, matching the merge's documented stance.
|
|
79
83
|
*/
|
|
80
84
|
export function danglingRefs(root) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
// A Set keeps first-insertion order, so dedup and document order both hold.
|
|
86
|
+
return [...new Set(collectRefs(root).filter((ref) => ref.startsWith("#/") && !resolvePointer(root, ref).found))];
|
|
87
|
+
}
|
|
88
|
+
/*
|
|
89
|
+
* `$ref` as a pair of plain questions — which ones does this tree contain, and
|
|
90
|
+
* what does one point at. Both lived in `./merge/components.ts`, beside the
|
|
91
|
+
* component closure that was their only caller, until the reader needed the same
|
|
92
|
+
* walk; the header says why the root and not there.
|
|
93
|
+
*/
|
|
94
|
+
/** Every `$ref` string in a tree, in document order — duplicates kept, external refs included. */
|
|
95
|
+
export function collectRefs(node) {
|
|
96
|
+
const out = [];
|
|
97
|
+
const walk = (current) => {
|
|
98
|
+
if (Array.isArray(current)) {
|
|
99
|
+
for (const value of current)
|
|
85
100
|
walk(value);
|
|
86
101
|
return;
|
|
87
102
|
}
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
continue;
|
|
103
|
+
if (current !== null && typeof current === "object") {
|
|
104
|
+
for (const [key, value] of Object.entries(current)) {
|
|
105
|
+
if (key === "$ref" && typeof value === "string")
|
|
106
|
+
out.push(value);
|
|
107
|
+
else
|
|
108
|
+
walk(value);
|
|
95
109
|
}
|
|
96
|
-
walk(value);
|
|
97
110
|
}
|
|
98
111
|
};
|
|
99
|
-
walk(
|
|
100
|
-
return
|
|
112
|
+
walk(node);
|
|
113
|
+
return out;
|
|
101
114
|
}
|
|
102
|
-
/**
|
|
103
|
-
function
|
|
115
|
+
/** Resolve a local JSON pointer (`#/a/b~1c`) against a plain JS tree. */
|
|
116
|
+
export function resolvePointer(root, ref) {
|
|
104
117
|
let current = root;
|
|
105
118
|
for (const raw of ref.slice(2).split("/")) {
|
|
106
119
|
const segment = raw.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
107
120
|
if (Array.isArray(current)) {
|
|
108
121
|
const index = Number(segment);
|
|
109
|
-
if (!Number.isInteger(index) || index < 0 || index >= current.length)
|
|
110
|
-
return false;
|
|
122
|
+
if (!Number.isInteger(index) || index < 0 || index >= current.length) {
|
|
123
|
+
return { found: false, value: undefined };
|
|
124
|
+
}
|
|
111
125
|
current = current[index];
|
|
112
126
|
}
|
|
113
127
|
else if (current !== null && typeof current === "object" && segment in current) {
|
|
114
128
|
current = current[segment];
|
|
115
129
|
}
|
|
116
130
|
else {
|
|
117
|
-
return false;
|
|
131
|
+
return { found: false, value: undefined };
|
|
118
132
|
}
|
|
119
133
|
}
|
|
120
|
-
return true;
|
|
134
|
+
return { found: true, value: current };
|
|
121
135
|
}
|
|
122
136
|
//# sourceMappingURL=depth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"depth.js","sourceRoot":"","sources":["../../../src/core/openapi/depth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"depth.js","sourceRoot":"","sources":["../../../src/core/openapi/depth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gEAAgE;AAChE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAW;IAC7C,IAAI,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,SAAS,GAAI,EAA8B,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/G,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,SAAoC,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/E,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,IAAI,MAAM,IAAI,GAAG;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAS;QACxF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAkC,CAAC,EAAE,CAAC;YACtE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAK,KAAiC,EAAE,CAAC;gBAClG,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,EAAW;IACxC,IAAI,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,SAAS,GAAI,EAA8B,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/F,OAAO,MAAM,CAAC,IAAI,CAAC,SAAoC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,4EAA4E;IAC5E,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnH,CAAC;AAED;;;;;GAKG;AAEH,kGAAkG;AAClG,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAQ,EAAE;QACtC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,OAAO;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QACD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnD,IAAI,GAAG,KAAK,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;oBAC5D,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,GAAW;IACvD,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAC5C,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAK,OAAmC,EAAE,CAAC;YAC9G,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC","sourcesContent":["/**\n * The contract-depth probes: does an operation say anything about what it\n * returns, and does every internal `$ref` point at something.\n *\n * Form validated and depth did not, and that was invisible from the output:\n * an operation whose one response is `description: OK`, and a `$ref` to a\n * schema nobody ever wrote, both validate exactly as cleanly as a complete\n * contract even though a reader still needs the code. Everything here is a\n * PRESENCE probe over the document's own keys: nothing reads what a schema\n * says, only whether one was declared at all, so the reader's structure-only\n * stance holds.\n *\n * This module used to keep a private pointer walk rather than import the\n * merge's: the merge package already imports this package (`HTTP_METHODS` from\n * doc.ts), so the reverse import would have been a package cycle — the same\n * reason read-side `resolvePointer` copies exist on the asyncapi axis. The two\n * plain `$ref` questions now live HERE, at the axis root (`collectRefs` and\n * `resolvePointer`, at the bottom), so the private copy went: the dangling-ref\n * probe below, the merge's component closure and the reader's closure digest\n * (`closureDigester`, ./digest.ts) all ask the same two questions.\n */\n\n/** Status codes whose response legitimately carries no body. */\nconst NO_CONTENT = new Set([\"204\", \"304\"]);\n\n/**\n * True when no response declares content with a schema while at least one\n * response should carry a body — an operation with no `responses` at all\n * counts, one whose only responses are 204/304 does not. A response that is\n * itself a `$ref` counts as described: somebody wrote the shape down, and the\n * dangling case is the ref probe's finding, not this one's.\n */\nexport function responseUndescribed(op: unknown): boolean {\n if (op === null || typeof op !== \"object\") return true;\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || responses === undefined || typeof responses !== \"object\" || Array.isArray(responses)) {\n return true;\n }\n const entries = Object.entries(responses as Record<string, unknown>);\n if (entries.length === 0) return true;\n let owesBody = false;\n for (const [code, resp] of entries) {\n if (NO_CONTENT.has(code)) continue;\n owesBody = true;\n if (resp === null || typeof resp !== \"object\" || Array.isArray(resp)) continue;\n const rec = resp as Record<string, unknown>;\n if (\"$ref\" in rec) return false;\n const content = rec[\"content\"];\n if (content === null || typeof content !== \"object\" || Array.isArray(content)) continue;\n for (const media of Object.values(content as Record<string, unknown>)) {\n if (media !== null && typeof media === \"object\" && \"schema\" in (media as Record<string, unknown>)) {\n return false;\n }\n }\n }\n return owesBody;\n}\n\n/**\n * The non-2xx response codes an operation declares, in document order.\n *\n * Exact three-digit codes only. `default` names no case — it is whatever else\n * happens — and the `4XX`/`5XX` wildcards name a class rather than a refusal,\n * so no scenario could be written for either and demanding one would teach an\n * author to write a scenario about nothing. 1xx and 3xx are excluded with 2xx:\n * a redirect or a continue is not the service saying no.\n */\nexport function failureCodesOf(op: unknown): string[] {\n if (op === null || typeof op !== \"object\") return [];\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || typeof responses !== \"object\" || Array.isArray(responses)) return [];\n return Object.keys(responses as Record<string, unknown>).filter((code) => /^[45]\\d\\d$/.test(code));\n}\n\n/**\n * Every internal `#/` reference in the document that resolves to nothing —\n * deduped, document order. External references (URLs, file paths) are out of\n * scope and never graded, matching the merge's documented stance.\n */\nexport function danglingRefs(root: unknown): string[] {\n // A Set keeps first-insertion order, so dedup and document order both hold.\n return [...new Set(collectRefs(root).filter((ref) => ref.startsWith(\"#/\") && !resolvePointer(root, ref).found))];\n}\n\n/*\n * `$ref` as a pair of plain questions — which ones does this tree contain, and\n * what does one point at. Both lived in `./merge/components.ts`, beside the\n * component closure that was their only caller, until the reader needed the same\n * walk; the header says why the root and not there.\n */\n\n/** Every `$ref` string in a tree, in document order — duplicates kept, external refs included. */\nexport function collectRefs(node: unknown): string[] {\n const out: string[] = [];\n const walk = (current: unknown): void => {\n if (Array.isArray(current)) {\n for (const value of current) walk(value);\n return;\n }\n if (current !== null && typeof current === \"object\") {\n for (const [key, value] of Object.entries(current)) {\n if (key === \"$ref\" && typeof value === \"string\") out.push(value);\n else walk(value);\n }\n }\n };\n walk(node);\n return out;\n}\n\n/** Resolve a local JSON pointer (`#/a/b~1c`) against a plain JS tree. */\nexport function resolvePointer(root: unknown, ref: string): { found: boolean; value: unknown } {\n let current: unknown = root;\n for (const raw of ref.slice(2).split(\"/\")) {\n const segment = raw.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n if (Array.isArray(current)) {\n const index = Number(segment);\n if (!Number.isInteger(index) || index < 0 || index >= current.length) {\n return { found: false, value: undefined };\n }\n current = current[index];\n } else if (current !== null && typeof current === \"object\" && segment in (current as Record<string, unknown>)) {\n current = (current as Record<string, unknown>)[segment];\n } else {\n return { found: false, value: undefined };\n }\n }\n return { found: true, value: current };\n}\n"]}
|
|
@@ -10,14 +10,17 @@
|
|
|
10
10
|
* is that it fires only for real ones.
|
|
11
11
|
*/
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
|
+
import { collectRefs, resolvePointer } from "./depth.js";
|
|
13
14
|
/**
|
|
14
15
|
* The baseline marker: which living version of this operation a FEATURE delta
|
|
15
16
|
* was written against. Same idea as a requirement's `Based-On:` (core/document/spec.ts),
|
|
16
17
|
* in the vendor-extension shape this axis already uses for `x-loam-remove`.
|
|
17
18
|
*
|
|
18
19
|
* This axis needs it MORE than the requirement axis does, because a feature's
|
|
19
|
-
* openapi.yaml
|
|
20
|
-
*
|
|
20
|
+
* openapi.yaml may spell operations it does not change: it needs only what it
|
|
21
|
+
* adds, changes or removes (the merge leaves everything else to the living
|
|
22
|
+
* contract), but restating more is legal — for context, or a contract pasted
|
|
23
|
+
* whole, which is what loam's own docs once taught — and the merge upserts every
|
|
21
24
|
* operation the document spells. So a feature that never meant to touch
|
|
22
25
|
* `refundOrder` — it merely quoted it — pushes its authoring-time copy back over
|
|
23
26
|
* whatever landed in between, reverting another team's shipped change without
|
|
@@ -154,6 +157,53 @@ export function valueDigest(node) {
|
|
|
154
157
|
export function operationDigest(node) {
|
|
155
158
|
return valueDigest(withoutOperationBaseline(node));
|
|
156
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* The identity of what a node PROMISES rather than of its own bytes: the
|
|
162
|
+
* `operationDigest` input plus every internal `$ref` it reaches, transitively,
|
|
163
|
+
* each paired with the digest of what it resolves to in `root`. One digester per
|
|
164
|
+
* document; call it once per operation or message.
|
|
165
|
+
*
|
|
166
|
+
* `operationDigest` stops at the node on purpose — a pin says which version of
|
|
167
|
+
* THIS slot a delta was written against, and components carry their own pins.
|
|
168
|
+
* But a reviewer asking "did this operation change?" means the contract a
|
|
169
|
+
* consumer codes against, and in a factored document that is mostly somewhere
|
|
170
|
+
* else: renaming a required field of `#/components/schemas/Payment` leaves every
|
|
171
|
+
* operation returning it byte-identical, and `loam diff` reported exactly that
|
|
172
|
+
* PR as "no fleet-meaningful changes". This digest is what diff compares.
|
|
173
|
+
*
|
|
174
|
+
* The memo is per document and per ref, so a schema twenty operations reference
|
|
175
|
+
* is resolved, walked and hashed once. A ref that resolves to nothing still
|
|
176
|
+
* contributes — as a marker no 16-hex digest can equal — so a dangling ref that
|
|
177
|
+
* starts resolving reads as a change. External refs (anything not `#/`) are not
|
|
178
|
+
* followed, matching every other reader here; the ref string itself is part of
|
|
179
|
+
* the node's own bytes, so re-pointing one still moves the digest.
|
|
180
|
+
*/
|
|
181
|
+
export function closureDigester(root) {
|
|
182
|
+
const targets = new Map();
|
|
183
|
+
const target = (ref) => {
|
|
184
|
+
let hit = targets.get(ref);
|
|
185
|
+
if (hit === undefined) {
|
|
186
|
+
const resolved = resolvePointer(root, ref);
|
|
187
|
+
hit = resolved.found ? { digest: valueDigest(resolved.value), refs: collectRefs(resolved.value) } : { digest: "unresolved", refs: [] };
|
|
188
|
+
targets.set(ref, hit);
|
|
189
|
+
}
|
|
190
|
+
return hit;
|
|
191
|
+
};
|
|
192
|
+
return (node) => {
|
|
193
|
+
const reached = new Map();
|
|
194
|
+
const queue = collectRefs(node);
|
|
195
|
+
while (queue.length > 0) {
|
|
196
|
+
const ref = queue.pop();
|
|
197
|
+
if (!ref.startsWith("#/") || reached.has(ref))
|
|
198
|
+
continue;
|
|
199
|
+
const hit = target(ref);
|
|
200
|
+
reached.set(ref, hit.digest);
|
|
201
|
+
queue.push(...hit.refs);
|
|
202
|
+
}
|
|
203
|
+
// canonicalJson sorts keys, so the walk order above never reaches the digest.
|
|
204
|
+
return valueDigest({ node: withoutOperationBaseline(node), refs: Object.fromEntries(reached) });
|
|
205
|
+
};
|
|
206
|
+
}
|
|
157
207
|
/**
|
|
158
208
|
* What a pin says, from digests alone — the one definition every decider
|
|
159
209
|
* shares: the gate (./baseline/gate.ts) and the merge
|