@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2548 -86
- package/COMPARISON.md +80 -63
- package/CONTRIBUTING.md +84 -0
- package/MIGRATING-from-OpenSpec.md +213 -54
- package/QUICKSTART.md +125 -0
- package/README.md +450 -150
- package/ROADMAP.md +494 -0
- package/SCHEMA.md +2355 -256
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +701 -0
- package/dist/cli.js +113 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +209 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +268 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +77 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +159 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +317 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +161 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +111 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +237 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +27 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +251 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/context/context.js +99 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +283 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +279 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +205 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +9 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +93 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +5 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +151 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +29 -24
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +115 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +54 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +146 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +246 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +149 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +28 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +146 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +65 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +157 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +343 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +301 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/views.js +105 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +183 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +34 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +170 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +19 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/commit.js +76 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/new.js +283 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +355 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +203 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +275 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +192 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +133 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +172 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +178 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/marks.js +24 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/{show.js → show/service.js} +63 -152
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +77 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/json.js +45 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +157 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +119 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +189 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +265 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +115 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +101 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +103 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +94 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +70 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +160 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +67 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +194 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +296 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +55 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +254 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +76 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/checks/vocabulary.js +31 -0
- package/dist/commands/validate/checks/vocabulary.js.map +1 -0
- package/dist/commands/validate/feature.js +216 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +69 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +353 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +52 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +236 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +63 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/steps.js +197 -0
- package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +40 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +59 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +92 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/report.js +269 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/service/api.js +338 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +219 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +131 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/service.js +250 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +219 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +113 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/validate.js +338 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +182 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +72 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +241 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +226 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +223 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +246 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +217 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +271 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +142 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +285 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +125 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +123 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +176 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/artifacts.js +220 -0
- package/dist/core/agent/agents-md/artifacts.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +324 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/cycle.js +165 -0
- package/dist/core/agent/agents-md/cycle.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +34 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +41 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +62 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +32 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +60 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +246 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
- package/dist/core/agent/agents-md/spine.js +40 -0
- package/dist/core/agent/agents-md/spine.js.map +1 -0
- package/dist/core/agent/agents-md.js +170 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +259 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +103 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +150 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +228 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +133 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +334 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +262 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +105 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +105 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +209 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +65 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +188 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +16 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +297 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +110 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +141 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +91 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +33 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +308 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +215 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +107 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +225 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +250 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +194 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/targets.js +226 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +47 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +282 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +88 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +57 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +75 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/project/architecture.js +45 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/documents.js +58 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +183 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/resolve/service.js +113 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +109 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/source-mask.js +82 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +227 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +101 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +10 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +36 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +269 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +194 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/workspace.js +172 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +50 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +342 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +181 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +143 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +199 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +126 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +277 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +177 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +74 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/coherence.js +251 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/declared.js +269 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +206 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +204 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +166 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +122 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/merged.js +40 -0
- package/dist/core/coherence/events/merged.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +155 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +296 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/diff/base-git.js +148 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +209 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/current-state.js +96 -0
- package/dist/core/diff/current-state.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +188 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/semantic.js +243 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/diff/victims.js +247 -0
- package/dist/core/diff/victims.js.map +1 -0
- package/dist/core/docs.js +7 -64
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +222 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +135 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +275 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +77 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +263 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +221 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +241 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +79 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +175 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +175 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +181 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms.js +144 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/{explore.js → explore/explore.js} +50 -101
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +120 -78
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +201 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +205 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +113 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +234 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +106 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +86 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +68 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +104 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +236 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +111 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +72 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +314 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +166 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +112 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +175 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/depth.js +122 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +189 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +44 -106
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +234 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +26 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +208 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +256 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +128 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +221 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +76 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +65 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +235 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +200 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +260 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +133 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +118 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +76 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/provenance/findings.js +208 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +225 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +182 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +263 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +232 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +192 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +236 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +248 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +52 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +64 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/views.js +172 -0
- package/dist/core/repo/tree/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +234 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +99 -2
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +131 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +241 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +206 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +98 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +126 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot.js +202 -0
- package/dist/core/staging/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +171 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +49 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +102 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +171 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +207 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +150 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +187 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +207 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +201 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/usecases/capability.js +169 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +116 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +103 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +235 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +137 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/operations.js +111 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +173 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +150 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +201 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/file.js +257 -0
- package/dist/core/verify/file.js.map +1 -0
- package/dist/core/verify/pins/lint.js +157 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/record.js +142 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +89 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +57 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +55 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +145 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/{report.js → vocabulary/report.js} +30 -2
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +189 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +280 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/subsystems.likec4 +11 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +9 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +109 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +127 -0
- package/examples/docs/services/order-service/asyncapi.yaml +108 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +138 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +73 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +67 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
- package/examples/docs/services/platform/notification-service/health.yaml +35 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
- /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
- /package/dist/core/{records.js → kernel/records.js} +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# The async contract — the messages this service puts on the bus.
|
|
2
|
+
#
|
|
3
|
+
# AsyncAPI 3.0 only. Its operations are named top-level objects carrying
|
|
4
|
+
# `action: send|receive`, which is what makes a message's direction legible;
|
|
5
|
+
# 2.x spells the same thing as publish/subscribe under a channel, where the
|
|
6
|
+
# two words are ambiguous about whose perspective they take.
|
|
7
|
+
#
|
|
8
|
+
# loam reads message NAMES and the `action` of the operation carrying them.
|
|
9
|
+
# It never joins on anything inside `payload` — the one look inside is a
|
|
10
|
+
# presence probe (a payload declaring no shape at all warns, a non-JSON
|
|
11
|
+
# `schemaFormat` is skipped) — which is what keeps swapping JSON Schema for
|
|
12
|
+
# Avro a `schemaFormat` line here rather than a change in loam.
|
|
13
|
+
#
|
|
14
|
+
# The name is the spine: the landscape edge's `metadata { publishes }`, the
|
|
15
|
+
# requirement's `Publishes:` line and `name` below are one name spelled three
|
|
16
|
+
# times, and they must be identical.
|
|
17
|
+
asyncapi: 3.0.0
|
|
18
|
+
info:
|
|
19
|
+
title: payment-service events
|
|
20
|
+
version: "1.0"
|
|
21
|
+
|
|
22
|
+
channels:
|
|
23
|
+
paymentEvents:
|
|
24
|
+
address: payment.events.v1
|
|
25
|
+
description: Payment lifecycle events, published by the outbox relay
|
|
26
|
+
messages:
|
|
27
|
+
PaymentAuthorized:
|
|
28
|
+
$ref: '#/components/messages/PaymentAuthorized'
|
|
29
|
+
PaymentCaptured:
|
|
30
|
+
$ref: '#/components/messages/PaymentCaptured'
|
|
31
|
+
# NEW: the refund rides the existing lifecycle topic rather than one of
|
|
32
|
+
# its own — a consumer already filtering payment.events for a capture is
|
|
33
|
+
# the same consumer that wants the refund.
|
|
34
|
+
PaymentRefunded:
|
|
35
|
+
$ref: '#/components/messages/PaymentRefunded'
|
|
36
|
+
x-loam-based-on: 036cbb7e0245e1a9
|
|
37
|
+
|
|
38
|
+
operations:
|
|
39
|
+
sendPaymentAuthorized:
|
|
40
|
+
action: send
|
|
41
|
+
channel:
|
|
42
|
+
$ref: '#/channels/paymentEvents'
|
|
43
|
+
messages:
|
|
44
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentAuthorized'
|
|
45
|
+
x-loam-based-on: 72934fd7ed7f6df9
|
|
46
|
+
sendPaymentCaptured:
|
|
47
|
+
action: send
|
|
48
|
+
channel:
|
|
49
|
+
$ref: '#/channels/paymentEvents'
|
|
50
|
+
messages:
|
|
51
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentCaptured'
|
|
52
|
+
x-loam-based-on: 01ac447e38a868cc
|
|
53
|
+
# NEW: announced once, and only after the acquirer has reconciled.
|
|
54
|
+
sendPaymentRefunded:
|
|
55
|
+
action: send
|
|
56
|
+
channel:
|
|
57
|
+
$ref: '#/channels/paymentEvents'
|
|
58
|
+
messages:
|
|
59
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentRefunded'
|
|
60
|
+
|
|
61
|
+
components:
|
|
62
|
+
messages:
|
|
63
|
+
# NEW: the money is back and the acquirer agrees. `refundedAmount` is what
|
|
64
|
+
# the refund actually returned, which is not always the captured amount —
|
|
65
|
+
# a partial refund is the same event with a smaller number.
|
|
66
|
+
PaymentRefunded:
|
|
67
|
+
name: payment.PaymentRefunded
|
|
68
|
+
title: Payment refunded
|
|
69
|
+
payload:
|
|
70
|
+
type: object
|
|
71
|
+
required: [ paymentId, orderId, refundedAmount, currency, refundedAt ]
|
|
72
|
+
properties:
|
|
73
|
+
paymentId:
|
|
74
|
+
type: string
|
|
75
|
+
format: uuid
|
|
76
|
+
orderId:
|
|
77
|
+
type: string
|
|
78
|
+
refundedAmount:
|
|
79
|
+
type: integer
|
|
80
|
+
description: minor units
|
|
81
|
+
currency:
|
|
82
|
+
type: string
|
|
83
|
+
pattern: '^[A-Z]{3}$'
|
|
84
|
+
refundedAt:
|
|
85
|
+
type: string
|
|
86
|
+
format: date-time
|
|
87
|
+
PaymentAuthorized:
|
|
88
|
+
# Namespaced by the domain that owns it. One message has exactly one
|
|
89
|
+
# producer: two services declaring they send this name is
|
|
90
|
+
# `asyncapi.message-contested`, and then which contract a consumer reads
|
|
91
|
+
# is a coin flip.
|
|
92
|
+
name: payment.PaymentAuthorized
|
|
93
|
+
title: Payment authorized
|
|
94
|
+
# JSON Schema today, because this fleet runs no schema registry. An Avro
|
|
95
|
+
# record here later needs a `schemaFormat:` line and no other change:
|
|
96
|
+
# everything below is opaque to loam.
|
|
97
|
+
payload:
|
|
98
|
+
type: object
|
|
99
|
+
required: [ paymentId, orderId, amount, currency, authorizedAt ]
|
|
100
|
+
properties:
|
|
101
|
+
paymentId:
|
|
102
|
+
type: string
|
|
103
|
+
format: uuid
|
|
104
|
+
orderId:
|
|
105
|
+
type: string
|
|
106
|
+
amount:
|
|
107
|
+
type: integer
|
|
108
|
+
description: minor units
|
|
109
|
+
currency:
|
|
110
|
+
type: string
|
|
111
|
+
pattern: '^[A-Z]{3}$'
|
|
112
|
+
authorizedAt:
|
|
113
|
+
type: string
|
|
114
|
+
format: date-time
|
|
115
|
+
x-loam-based-on: 0e5a230802d1573b
|
|
116
|
+
PaymentCaptured:
|
|
117
|
+
name: payment.PaymentCaptured
|
|
118
|
+
title: Payment captured
|
|
119
|
+
payload:
|
|
120
|
+
type: object
|
|
121
|
+
required: [ paymentId, orderId, capturedAmount, currency, capturedAt ]
|
|
122
|
+
properties:
|
|
123
|
+
paymentId:
|
|
124
|
+
type: string
|
|
125
|
+
format: uuid
|
|
126
|
+
orderId:
|
|
127
|
+
type: string
|
|
128
|
+
capturedAmount:
|
|
129
|
+
type: integer
|
|
130
|
+
description: minor units
|
|
131
|
+
currency:
|
|
132
|
+
type: string
|
|
133
|
+
pattern: '^[A-Z]{3}$'
|
|
134
|
+
capturedAt:
|
|
135
|
+
type: string
|
|
136
|
+
format: date-time
|
|
137
|
+
x-loam-based-on: 449d5409ccf1b59f
|
package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# payment-service — requirement delta for FEAT-120
|
|
2
|
+
|
|
3
|
+
## MODIFIED Requirements
|
|
4
|
+
|
|
5
|
+
### Requirement: Refund a captured payment
|
|
6
|
+
|
|
7
|
+
Requirement-ID: PAY-REFUND
|
|
8
|
+
Based-On: 0d5b4ce25f5b07ae
|
|
9
|
+
The service SHALL return captured funds to the customer's payment method, SHALL reconcile the
|
|
10
|
+
refund against the acquirer before reporting it complete, and SHALL refuse a second refund of a
|
|
11
|
+
payment it has already refunded.
|
|
12
|
+
|
|
13
|
+
Operations: refundPayment
|
|
14
|
+
Publishes: payment.PaymentRefunded
|
|
15
|
+
Requires: user/payments:refund
|
|
16
|
+
|
|
17
|
+
#### Scenario: Refund a captured payment in full
|
|
18
|
+
- **Given** a captured payment of 100.00 USD
|
|
19
|
+
- **When** a refund is requested for it
|
|
20
|
+
- **Then** 100.00 USD is returned to the customer's payment method
|
|
21
|
+
- **And** the payment is recorded as refunded
|
|
22
|
+
|
|
23
|
+
#### Scenario: A second refund of the same payment is refused
|
|
24
|
+
- **Given** a payment already refunded in full
|
|
25
|
+
- **When** a refund is requested for it again
|
|
26
|
+
- **Then** the request is refused with 409 and no second refund is issued
|
|
27
|
+
|
|
28
|
+
#### Scenario: The refund is announced only after the acquirer reconciles
|
|
29
|
+
- **Given** a refund accepted by the acquirer but not yet reconciled
|
|
30
|
+
- **When** the reconciliation completes
|
|
31
|
+
- **Then** `payment.PaymentRefunded` is published exactly once for that payment
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Verification record for FEAT-120 — written by `loam verify FEAT-120` (--results / --contract-results / --record).
|
|
2
|
+
#
|
|
3
|
+
# Every claim below was derived mechanically from this feature's own artifacts:
|
|
4
|
+
# delta.likec4, specs/<svc>/spec.md, specs/<svc>/arch.spec.md and specs/<svc>/
|
|
5
|
+
# openapi.yaml. Each verdict names who answered it: `answered_by: runner` means a
|
|
6
|
+
# test report's digest-tagged scenarios answered it mechanically — cucumber JSON,
|
|
7
|
+
# or loam's own {"loamScenarioReport": 1, ...} shape that any runner adapts into;
|
|
8
|
+
# `answered_by: external-runner` means a contract-test report's operationId-matched
|
|
9
|
+
# entries did, and `contractReport:` records which file a --contract-results run
|
|
10
|
+
# read; `answered_by: agent` means somebody's word about the code, which loam did
|
|
11
|
+
# not check. Nothing gates on any of them.
|
|
12
|
+
#
|
|
13
|
+
# A `scenario.tested` claim confirmed by an agent is ATTESTED, not run: loam
|
|
14
|
+
# reports it as `verify.scenario-attested` and the feature does not count as
|
|
15
|
+
# verified until a report answers it. `report:` records the file a --results run
|
|
16
|
+
# read — its sha256 and mtime say WHICH file, not that it came from that commit;
|
|
17
|
+
# no digest can say that.
|
|
18
|
+
#
|
|
19
|
+
# `checklist` is a digest of the claim ids. If `loam verify` stops reporting the same
|
|
20
|
+
# one, the feature changed after this was recorded and these answers are stale.
|
|
21
|
+
feature: FEAT-120
|
|
22
|
+
recorded: 2026-08-29
|
|
23
|
+
checklist: 060a0cc49fcb1d64
|
|
24
|
+
summary:
|
|
25
|
+
claims: 7
|
|
26
|
+
confirmed: 7
|
|
27
|
+
unconfirmed: 0
|
|
28
|
+
claims:
|
|
29
|
+
- id: event.declares-5ba57275
|
|
30
|
+
kind: event.declares
|
|
31
|
+
claim: notification-service declares it receives message 'payment.PaymentRefunded'
|
|
32
|
+
verdict: confirmed
|
|
33
|
+
answered_by: agent
|
|
34
|
+
evidence:
|
|
35
|
+
- internal/consumer/refund.go:18
|
|
36
|
+
note: the consumer subscribes to payment.events.v1 and dispatches PaymentRefunded to the refund notice renderer
|
|
37
|
+
- id: event.declares-02a85dfd
|
|
38
|
+
kind: event.declares
|
|
39
|
+
claim: payment-service declares it sends message 'payment.PaymentRefunded'
|
|
40
|
+
verdict: confirmed
|
|
41
|
+
answered_by: agent
|
|
42
|
+
evidence:
|
|
43
|
+
- src/main/java/com/marketplace/payments/outbox/RefundOutboxRelay.java:44
|
|
44
|
+
note: the outbox relay publishes payment.PaymentRefunded on the acquirer reconciliation callback
|
|
45
|
+
- id: scenario.tested-6a899c70
|
|
46
|
+
kind: scenario.tested
|
|
47
|
+
claim: scenario 'A completed refund is announced once' of requirement 'Notify a customer when a refund completes' (notification-service) is covered by a test
|
|
48
|
+
verdict: confirmed
|
|
49
|
+
answered_by: runner
|
|
50
|
+
evidence:
|
|
51
|
+
- "docs/features/FEAT-120-refund-notification/scenario-report.json: TestRefundNotice_SendsOnce"
|
|
52
|
+
- id: scenario.tested-173ff6e0
|
|
53
|
+
kind: scenario.tested
|
|
54
|
+
claim: scenario 'The broker redelivers a refund already announced' of requirement 'Notify a customer when a refund completes' (notification-service) is covered by a test
|
|
55
|
+
verdict: confirmed
|
|
56
|
+
answered_by: runner
|
|
57
|
+
evidence:
|
|
58
|
+
- "docs/features/FEAT-120-refund-notification/scenario-report.json: TestRefundNotice_IgnoresRedelivery"
|
|
59
|
+
- id: scenario.tested-b8dc0f33
|
|
60
|
+
kind: scenario.tested
|
|
61
|
+
claim: scenario 'Refund a captured payment in full' of requirement 'Refund a captured payment' (payment-service) is covered by a test
|
|
62
|
+
verdict: confirmed
|
|
63
|
+
answered_by: runner
|
|
64
|
+
evidence:
|
|
65
|
+
- "docs/features/FEAT-120-refund-notification/scenario-report.json: RefundPaymentTest#refundsInFull"
|
|
66
|
+
- id: scenario.tested-75b9e98d
|
|
67
|
+
kind: scenario.tested
|
|
68
|
+
claim: scenario 'A second refund of the same payment is refused' of requirement 'Refund a captured payment' (payment-service) is covered by a test
|
|
69
|
+
verdict: confirmed
|
|
70
|
+
answered_by: runner
|
|
71
|
+
evidence:
|
|
72
|
+
- "docs/features/FEAT-120-refund-notification/scenario-report.json: RefundPaymentTest#refusesSecondRefund"
|
|
73
|
+
- id: scenario.tested-8aa6f501
|
|
74
|
+
kind: scenario.tested
|
|
75
|
+
claim: scenario 'The refund is announced only after the acquirer reconciles' of requirement 'Refund a captured payment' (payment-service) is covered by a test
|
|
76
|
+
verdict: confirmed
|
|
77
|
+
answered_by: runner
|
|
78
|
+
evidence:
|
|
79
|
+
- "docs/features/FEAT-120-refund-notification/scenario-report.json: RefundOutboxTest#publishesOnceAfterReconciliation"
|
|
80
|
+
report:
|
|
81
|
+
path: docs/features/FEAT-120-refund-notification/scenario-report.json
|
|
82
|
+
digest: 602bd905c7a4878195fccb98f2134b6d883c0ef42c33b5d8772aaee067dfa3f5
|
|
83
|
+
mtime: 2026-08-28T18:49:56.422Z
|
|
84
|
+
scenarios: 5
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Order
|
|
2
|
+
|
|
3
|
+
What a customer has committed to buy: a set of items, a total they were shown,
|
|
4
|
+
and the intent to pay it. An order exists from the moment the customer confirms
|
|
5
|
+
— before any money moves, and whether or not the
|
|
6
|
+
[authorization](payments/authorization.md) succeeds.
|
|
7
|
+
|
|
8
|
+
An order is not a cart. A cart is what the customer is still editing; an order
|
|
9
|
+
is what they have decided. Nothing in the fleet edits an order in place.
|
|
10
|
+
|
|
11
|
+
The word is used in `capabilities/checkout/spec.md` and
|
|
12
|
+
`capabilities/order-notifications/spec.md`, and the services that carry parts of
|
|
13
|
+
those promises use it in the same sense. That agreement is what a glossary is
|
|
14
|
+
for, and the links to this file are what make it checkable: `glossary.unlinked`
|
|
15
|
+
would name this term the day nothing cited it any more.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Authorization
|
|
2
|
+
|
|
3
|
+
The card issuer's promise that the money for an [order](../order.md) is there
|
|
4
|
+
and reserved. It is not a payment: no funds have moved, and an authorization
|
|
5
|
+
expires if nothing captures it.
|
|
6
|
+
|
|
7
|
+
The distinction matters to the business and not only to the payments team. A
|
|
8
|
+
customer whose card was authorized has not been charged, so "we took your money"
|
|
9
|
+
is the wrong thing to tell them — and a confirmed order that was never
|
|
10
|
+
authorized is the failure `checkout#CHECKOUT-CHARGE-ONCE` exists to rule out.
|
|
11
|
+
|
|
12
|
+
Filed under `glossary/payments/` because the tree spells nesting the way the
|
|
13
|
+
capability tree does: this term's id is `payments/authorization`, and a flat
|
|
14
|
+
directory is not the only shape a growing vocabulary is allowed.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Per-service C4 for a UI service. A UI is a first-class C4 system: it has
|
|
2
|
+
// containers, it has runtime dependencies, and its pages (ui/pages/*.page.yaml)
|
|
3
|
+
// hang off the operations the edges below name.
|
|
4
|
+
//
|
|
5
|
+
// Every .likec4 file is parsed ON ITS OWN — loam never concatenates them — so
|
|
6
|
+
// this document declares the kinds it uses even though architecture/landscape.likec4
|
|
7
|
+
// declares the same ones. Leaving them out here does not inherit, it fails to parse
|
|
8
|
+
// (`c4.invalid`, an error), and the spec/API joins that read the model go quiet with it.
|
|
9
|
+
specification {
|
|
10
|
+
element softwareSystem
|
|
11
|
+
element container
|
|
12
|
+
element person
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
model {
|
|
16
|
+
// The actor belongs in a UI's own model in a way it does not in a backend's:
|
|
17
|
+
// the pages exist for this person, and the flows in ui/pages/ start at them.
|
|
18
|
+
// The landscape draws the same customer -> checkout-web edge at fleet scale;
|
|
19
|
+
// a person is exempt from the service/directory cross-check either way.
|
|
20
|
+
customer = person 'Customer'
|
|
21
|
+
|
|
22
|
+
checkoutWeb = softwareSystem 'checkout-web' {
|
|
23
|
+
description 'Customer-facing checkout UI'
|
|
24
|
+
|
|
25
|
+
spa = container 'spa' {
|
|
26
|
+
description 'Checkout SPA — cart, payment and order status pages'
|
|
27
|
+
technology 'React'
|
|
28
|
+
}
|
|
29
|
+
// A backend-for-frontend, drawn because it is where the fleet call actually
|
|
30
|
+
// originates: the browser holds a session cookie, the fleet speaks bearer
|
|
31
|
+
// tokens, and something has to be the place that translation happens. Drawn
|
|
32
|
+
// as a container of checkout-web and not as a service of its own, because it
|
|
33
|
+
// is deployed and released with the SPA and has no consumer but the SPA —
|
|
34
|
+
// a services/checkout-bff/ would owe a spec, a contract and an owner nobody has.
|
|
35
|
+
bff = container 'bff' {
|
|
36
|
+
description 'Backend-for-frontend: session to bearer, response shaping'
|
|
37
|
+
technology 'Node.js'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
customer -> spa 'Buys'
|
|
41
|
+
spa -> bff 'Calls the checkout BFF'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The services this one actually calls. A service model carries everything the
|
|
45
|
+
// service touches, cross-boundary included, drawn with the edge the service
|
|
46
|
+
// really has — the landscape carries only the boundary crossing (checkout-web ->
|
|
47
|
+
// order-service), while the edge below says WHICH container makes the call.
|
|
48
|
+
// Without these three edges this file would be two boxes and a hop, and
|
|
49
|
+
// `c4.no-relationships` would be right to say a model that reaches nothing is
|
|
50
|
+
// almost never true.
|
|
51
|
+
orderService = softwareSystem 'order-service' {
|
|
52
|
+
description 'Owns the order lifecycle'
|
|
53
|
+
// Bind rather than rely on the title. A renamed box silently stops matching
|
|
54
|
+
// its directory everywhere the two are joined — in the landscape that costs
|
|
55
|
+
// `landscape.binding-unknown` (error) when the id is wrong, and here it is
|
|
56
|
+
// what `health.dependency-unmodelled` resolves a declared dependency
|
|
57
|
+
// through in the services that have a health.yaml. checkout-web has none:
|
|
58
|
+
// a UI is nobody's runtime dependency, so it declares no SLIs, no alerts
|
|
59
|
+
// and no dependency graph, and owes no arch.spec.md to cover them.
|
|
60
|
+
metadata {
|
|
61
|
+
service 'order-service'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
paymentService = softwareSystem 'payment-service' {
|
|
65
|
+
description 'Owns payment authorization/capture'
|
|
66
|
+
metadata {
|
|
67
|
+
service 'payment-service'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// `metadata { op }` is the C4 half of the operation join: the exact
|
|
72
|
+
// operationId order-service's openapi.yaml declares. What `loam validate`
|
|
73
|
+
// grades is the LANDSCAPE's twin of each edge below — `spine.op-undefined`
|
|
74
|
+
// (error) is what it says there when the id names no operation the callee
|
|
75
|
+
// defines. Carrying the op here anyway is what keeps the two documents from
|
|
76
|
+
// drifting into different answers about which operation this container calls;
|
|
77
|
+
// nothing would catch it if they did. Two calls to one service are two edges,
|
|
78
|
+
// not one edge with a list — a view has to be able to show that the status
|
|
79
|
+
// page and the checkout page stand on different operations.
|
|
80
|
+
checkoutWeb.bff -> orderService 'Calls createOrder' {
|
|
81
|
+
metadata {
|
|
82
|
+
op 'createOrder'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
checkoutWeb.bff -> orderService 'Calls getOrder' {
|
|
86
|
+
metadata {
|
|
87
|
+
op 'getOrder'
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Card details go from the browser straight to payment-service and never
|
|
91
|
+
// through the BFF or order-service, which is why this edge starts at the SPA.
|
|
92
|
+
// It carries no `metadata { op }` deliberately: its twin in the landscape is
|
|
93
|
+
// the example's demonstration of `spine.op-link-missing` (warn) — the finding
|
|
94
|
+
// for an edge that SAYS it calls something and names no operation, so nothing
|
|
95
|
+
// can check the call still exists. Free here and one warning there, which is
|
|
96
|
+
// the asymmetry worth knowing: the fleet map is what the spine reads.
|
|
97
|
+
checkoutWeb.spa -> paymentService 'Calls the payment API'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Views are the LikeC4 renderer's, never loam's — no check reads this block.
|
|
101
|
+
// Scoped to the system so the page answers "what does the checkout UI stand on"
|
|
102
|
+
// rather than redrawing the fleet, which architecture/landscape.likec4 already does.
|
|
103
|
+
views {
|
|
104
|
+
view checkout_web of checkoutWeb {
|
|
105
|
+
title 'checkout-web — containers and the services they call'
|
|
106
|
+
include *
|
|
107
|
+
include orderService, paymentService
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: checkout-web
|
|
3
|
+
status: draft
|
|
4
|
+
owner: checkout-team
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# checkout-web
|
|
8
|
+
|
|
9
|
+
The customer-facing checkout SPA. It owns no store and exposes no operations of its own —
|
|
10
|
+
every requirement below is satisfied by calling `order-service` and `payment-service` — which
|
|
11
|
+
is why no requirement here carries an `Operations:` line and why this directory holds no
|
|
12
|
+
`openapi.yaml`. That absence is graded on evidence, not on the file list: `service.no-openapi`
|
|
13
|
+
stays silent because the landscape parses and no op-linked edge points AT checkout-web, so
|
|
14
|
+
nobody is expecting a contract here. A UI in a fleet map that could not be read would get the
|
|
15
|
+
warning instead, because "I could not look" and "nobody calls me" are different facts.
|
|
16
|
+
|
|
17
|
+
**This spec names no `sources:`, on purpose.** `loam validate` reports `sources.absent`
|
|
18
|
+
against it, and that warning is the point: the UI baseline is not yet tied to code, so nothing
|
|
19
|
+
can tell you when the pages drift from what the SPA actually renders, and `loam vouch` would
|
|
20
|
+
refuse to stamp it. Every other service in this example names the paths in its own repository
|
|
21
|
+
its spec was written from; this one shows what the absence costs — a document that is internally
|
|
22
|
+
consistent, passes every join below, and is answerable to nothing outside itself.
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
### Requirement: Checkout flow
|
|
27
|
+
|
|
28
|
+
Requirement-ID: WEB-CHECKOUT
|
|
29
|
+
The UI SHALL carry a customer from a filled cart to a confirmed order in one pass, and SHALL
|
|
30
|
+
show a confirmation only for an order `order-service` has acknowledged — never for one the
|
|
31
|
+
client assumed went through.
|
|
32
|
+
|
|
33
|
+
Capability: checkout
|
|
34
|
+
Realizes: checkout#CHECKOUT-CHARGE-ONCE
|
|
35
|
+
|
|
36
|
+
#### Scenario: Complete a checkout
|
|
37
|
+
- **Given** a cart holding at least one line and a payment method the customer has entered
|
|
38
|
+
- **When** the customer confirms the purchase
|
|
39
|
+
- **Then** `createOrder` records the order and `authorizePayment` reserves the funds against it
|
|
40
|
+
- **And** the confirmation shows the order id the API returned, not one the UI minted
|
|
41
|
+
|
|
42
|
+
#### Scenario: Authorization is refused
|
|
43
|
+
- **Given** a filled cart and a card the issuer declines
|
|
44
|
+
- **When** the customer confirms the purchase
|
|
45
|
+
- **Then** the payment step stays open with the cart, address and delivery choice intact
|
|
46
|
+
- **And** the customer is asked for another payment method rather than being returned to the cart
|
|
47
|
+
|
|
48
|
+
#### Scenario: The customer submits twice
|
|
49
|
+
- **Given** a checkout that has already sent `createOrder` under an idempotency key
|
|
50
|
+
- **When** the customer presses the confirm button again before the first response arrives
|
|
51
|
+
- **Then** the second request carries the same key and `order-service` answers 409
|
|
52
|
+
- **And** the UI opens the order that already exists instead of starting a second checkout
|
|
53
|
+
|
|
54
|
+
### Requirement: Show order status
|
|
55
|
+
|
|
56
|
+
Requirement-ID: WEB-ORDER-STATUS
|
|
57
|
+
The UI SHALL show the current state of an order from `order-service`, and SHALL answer
|
|
58
|
+
identically for an order that does not exist and for one that belongs to somebody else, so a
|
|
59
|
+
guessed id cannot confirm that an order is real.
|
|
60
|
+
|
|
61
|
+
Capability: checkout
|
|
62
|
+
|
|
63
|
+
#### Scenario: Show the current state of an order
|
|
64
|
+
- **Given** a placed order the signed-in customer owns
|
|
65
|
+
- **When** the customer opens its status page
|
|
66
|
+
- **Then** the page renders the state `getOrder` returns
|
|
67
|
+
- **And** it does not fall back to the state the checkout flow last saw, stale since capture
|
|
68
|
+
|
|
69
|
+
#### Scenario: The order id is not the customer's
|
|
70
|
+
- **Given** an order id belonging to another customer
|
|
71
|
+
- **When** the signed-in customer opens its status page
|
|
72
|
+
- **Then** `order-service` answers 404 and the page says the order was not found
|
|
73
|
+
- **And** an id that was never issued produces the same page, so the difference leaks nothing
|
|
74
|
+
|
|
75
|
+
## UI
|
|
76
|
+
|
|
77
|
+
Pages live under `ui/pages/`, one file per page. Each page-spec joins the two axes a UI sits
|
|
78
|
+
between: `consumes:` names the fleet operations the page depends on, by the same `operationId`
|
|
79
|
+
the provider's `openapi.yaml` declares, and `behavior:` names the scenarios above that govern
|
|
80
|
+
what the page does with them. Where the matching landscape edge carries `metadata { op }`, the
|
|
81
|
+
fleet map and the page-spec name that operation twice and can be read against each other; where
|
|
82
|
+
it does not — the `checkout-web` → `payment-service` edge — the page-spec is the only place the
|
|
83
|
+
operation is written down at all. Planned: `loam render` generates an HTML prototype from the
|
|
84
|
+
page-spec, so the prototype and the requirement can never disagree about which endpoint a
|
|
85
|
+
button calls.
|
|
86
|
+
|
|
87
|
+
`split-payment.page.yaml` is the exception in this directory: it carries `feature: FEAT-101`
|
|
88
|
+
because the requirement governing it lives under `features/FEAT-101-payment-splitting/` and not
|
|
89
|
+
in this file yet. Its `behavior:` references are spelled with the feature id in front for exactly
|
|
90
|
+
that reason, and drop it once `loam archive` has folded the delta into the requirements above —
|
|
91
|
+
by hand, since no command reads page-specs yet and none will rewrite this one for you.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Page-spec (source of truth). planned: `loam render` generates an HTML prototype from this (model A).
|
|
2
|
+
# Links the architecture (consumes endpoints) and behavior (governing scenarios).
|
|
3
|
+
# No command reads page-specs yet — the format is illustrative, not contract.
|
|
4
|
+
page: checkout
|
|
5
|
+
title: Checkout
|
|
6
|
+
service: checkout-web
|
|
7
|
+
status: draft
|
|
8
|
+
layout:
|
|
9
|
+
- { type: heading, text: "Checkout" }
|
|
10
|
+
- { type: list, id: cart-lines, itemFields: [sku, quantity, amount] }
|
|
11
|
+
- { type: text, id: total, label: "Total" }
|
|
12
|
+
- { type: field, id: payment-method, label: "Card", required: true }
|
|
13
|
+
- { type: button, id: confirm, text: "Pay and place order" }
|
|
14
|
+
# Every branch a governing scenario describes needs somewhere on the page to
|
|
15
|
+
# happen. This one is where "Authorization is refused" lands: without it the
|
|
16
|
+
# scenario is satisfied by an alert box nobody designed.
|
|
17
|
+
- { type: banner, id: declined, text: "That card was declined — try another payment method" }
|
|
18
|
+
consumes:
|
|
19
|
+
# `consumes:` names the FLEET operation the page depends on — the exact
|
|
20
|
+
# operationId the provider's openapi.yaml declares — not the hop the call
|
|
21
|
+
# takes to get there. The two hops differ: `createOrder` goes through the
|
|
22
|
+
# `bff` container in model.likec4, `authorizePayment` leaves the browser
|
|
23
|
+
# directly so card details never touch our servers. Naming the hop here would
|
|
24
|
+
# make one dependency look unlike the other when the thing that can actually
|
|
25
|
+
# break under them is the same: the provider's contract.
|
|
26
|
+
- { service: order-service, op: createOrder } # POST /orders
|
|
27
|
+
# The one dependency here whose edge carries no `metadata { op }` — see
|
|
28
|
+
# model.likec4, and `spine.op-link-missing` on its landscape twin. Nothing
|
|
29
|
+
# joins this line to anything, so it is a claim rather than a check: that is
|
|
30
|
+
# what the missing link costs, written at the only place that still knows.
|
|
31
|
+
- { service: payment-service, op: authorizePayment } # POST /payments
|
|
32
|
+
behavior:
|
|
33
|
+
# "<service> / <requirement> / <scenario>" for a LIVING scenario: the three
|
|
34
|
+
# names that locate it in services/<service>/spec.md. A scenario that still
|
|
35
|
+
# lives in a feature carries the feature id in front instead (see
|
|
36
|
+
# split-payment.page.yaml) — until FEAT-101 archives, there is no living
|
|
37
|
+
# requirement to point at.
|
|
38
|
+
- "checkout-web / Checkout flow / Complete a checkout"
|
|
39
|
+
- "checkout-web / Checkout flow / Authorization is refused"
|
|
40
|
+
- "checkout-web / Checkout flow / The customer submits twice"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Page-spec (source of truth). planned: `loam render` generates an HTML prototype from this (model A).
|
|
2
|
+
# Links the architecture (consumes endpoints) and behavior (governing scenarios).
|
|
3
|
+
# No command reads page-specs yet — the format is illustrative, not contract.
|
|
4
|
+
page: order-status
|
|
5
|
+
title: Order status
|
|
6
|
+
service: checkout-web
|
|
7
|
+
status: draft
|
|
8
|
+
layout:
|
|
9
|
+
- { type: heading, text: "Order {orderId}" }
|
|
10
|
+
- { type: text, id: state, label: "Status" }
|
|
11
|
+
- { type: list, id: order-lines, itemFields: [sku, quantity, amount] }
|
|
12
|
+
# One empty state for both "no such order" and "not yours" — the page cannot
|
|
13
|
+
# tell them apart, and the governing scenario says it must not try: two
|
|
14
|
+
# different messages would turn the id into an oracle for whether an order exists.
|
|
15
|
+
- { type: banner, id: not-found, text: "We could not find that order" }
|
|
16
|
+
consumes:
|
|
17
|
+
# One operation, one page. The status page reads and never writes, which is
|
|
18
|
+
# why `cancelOrder` is absent: it is order-service's own requirement, gated on
|
|
19
|
+
# `user/orders:cancel`, and a page that consumed it would owe that permission
|
|
20
|
+
# a place in the layout and a scenario naming the refusal.
|
|
21
|
+
- { service: order-service, op: getOrder } # GET /orders/{id}
|
|
22
|
+
behavior:
|
|
23
|
+
- "checkout-web / Show order status / Show the current state of an order"
|
|
24
|
+
- "checkout-web / Show order status / The order id is not the customer's"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Page-spec (source of truth). planned: `loam render` generates an HTML prototype from this (model A).
|
|
2
|
+
# Links the architecture (consumes endpoints) and behavior (governing scenarios).
|
|
3
|
+
# No command reads page-specs yet — the format is illustrative, not contract.
|
|
4
|
+
page: split-payment
|
|
5
|
+
title: Split payment
|
|
6
|
+
service: checkout-web
|
|
7
|
+
feature: FEAT-101
|
|
8
|
+
status: draft
|
|
9
|
+
layout:
|
|
10
|
+
- { type: heading, text: "Split this payment" }
|
|
11
|
+
- { type: list, id: payees, itemFields: [name, amount] }
|
|
12
|
+
- { type: button, id: add-payee, text: "Add payee" }
|
|
13
|
+
# Where "A split that does not sum to the total cannot be confirmed" lands. A
|
|
14
|
+
# disabled confirm button with no remainder on screen is a dead end rather
|
|
15
|
+
# than an explanation, and the scenario says the 10.00 is shown.
|
|
16
|
+
- { type: text, id: unassigned, label: "Unassigned" }
|
|
17
|
+
- { type: button, id: confirm, text: "Confirm split" }
|
|
18
|
+
consumes:
|
|
19
|
+
# createSplit only: the 201 carries back the split this page shows, so nothing
|
|
20
|
+
# here re-reads it through `getSplit`.
|
|
21
|
+
- { service: payment-split-service, op: createSplit } # POST /splits
|
|
22
|
+
behavior:
|
|
23
|
+
# BOTH scenarios of FEAT-101's ADDED `Split payment on checkout` — a page that
|
|
24
|
+
# names only the happy one leaves its own refusal path governed by nothing.
|
|
25
|
+
- "FEAT-101 / checkout-web / Split payment on checkout / Customer splits a payment across two payees"
|
|
26
|
+
- "FEAT-101 / checkout-web / Split payment on checkout / A split that does not sum to the total cannot be confirmed"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-order-service-0001
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-04-22
|
|
5
|
+
service: order-service
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 1. Orchestrate the payment from order-service rather than choreograph it
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
Placing an order needs an authorization, and the two obvious shapes were both on the table.
|
|
12
|
+
|
|
13
|
+
**Choreography**: order-service publishes `OrderPlaced`, payment-service consumes it,
|
|
14
|
+
authorizes, and publishes `PaymentAuthorized`; every service reacts to events and nobody is in
|
|
15
|
+
charge. **Orchestration**: order-service calls `authorizePayment` synchronously as part of
|
|
16
|
+
`createOrder` and drives the lifecycle itself, consuming `PaymentAuthorized` only to learn how
|
|
17
|
+
the decision landed.
|
|
18
|
+
|
|
19
|
+
The deciding question was not coupling — both shapes couple, one through a topic and one
|
|
20
|
+
through a contract — but where a placement that half-happened becomes somebody's problem. In
|
|
21
|
+
the choreographed shape there is no moment at which any single service can answer "is this
|
|
22
|
+
order going to be paid for", so the answer lives in the gaps between four consumers, and the
|
|
23
|
+
customer-facing failure (an order acknowledged that no card will ever be charged for) is
|
|
24
|
+
detectable only by reconciliation after the fact. checkout-web also needs a synchronous answer:
|
|
25
|
+
a checkout page that acknowledges and then silently drops the order is the failure this fleet
|
|
26
|
+
gets support tickets about.
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
order-service orchestrates. `createOrder` calls `authorizePayment` before it acknowledges,
|
|
30
|
+
holds the order in `awaiting_payment`, and advances it to `confirmed` when
|
|
31
|
+
`payment.PaymentAuthorized` arrives. The event is a completion signal for a call this service
|
|
32
|
+
already made — not the trigger that starts the work.
|
|
33
|
+
|
|
34
|
+
Concretely: the synchronous edge `order-service -> payment-service` carries
|
|
35
|
+
`metadata { op 'authorizePayment' }`, and the asynchronous one carries
|
|
36
|
+
`metadata { consumes 'payment.PaymentAuthorized' }`. Both are drawn, because both are real.
|
|
37
|
+
|
|
38
|
+
## Consequences
|
|
39
|
+
- order-service is a hard runtime dependency on payment-service for placement, and
|
|
40
|
+
`health.yaml` says so (`criticality: critical`). A payment-service outage stops placements;
|
|
41
|
+
it is meant to be visible as `order_placement_failures`, not absorbed.
|
|
42
|
+
- The lifecycle is readable in one file — the state machine in `domain` — instead of inferred
|
|
43
|
+
from four services' consumers. This is what makes ORD-CANCEL expressible at all: something
|
|
44
|
+
has to own the transition that refuses a cancellation.
|
|
45
|
+
- Every call in the placement path must be idempotent, because orchestration means retrying.
|
|
46
|
+
ARCH-ORD-IDEMPOTENCY carries that obligation, and it is the reason `createOrder` takes an
|
|
47
|
+
`Idempotency-Key` header at all.
|
|
48
|
+
- Redelivery is still ours to handle: the authorization arrives at-least-once, so
|
|
49
|
+
ARCH-ORD-DEDUPE keeps an applied-payment ledger. Orchestration removed the coordination
|
|
50
|
+
problem, not the delivery guarantee.
|
|
51
|
+
- The v1 endpoint predates this decision and does not participate in it — it places orders
|
|
52
|
+
without an idempotency key, which is exactly why FEAT-112 retires it rather than fixing it.
|