@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.2
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 +2635 -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 +599 -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 +323 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +180 -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 +252 -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 +204 -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 +270 -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 +251 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +251 -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 +337 -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 +48 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +174 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +90 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +158 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +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 +187 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +220 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/service.js +159 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +144 -0
- package/dist/core/c4/resolve/steps.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 +139 -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 +174 -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 +287 -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/deployment/delta.js +188 -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 +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 +137 -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 +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +277 -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 +196 -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 +197 -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 +72 -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 +58 -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,65 @@
|
|
|
1
|
+
// A fleet use case: the ordered hops that fulfil one business capability.
|
|
2
|
+
//
|
|
3
|
+
// This file is the whole shape of the axis. A `dynamic view` tagged
|
|
4
|
+
// `#cap-<slug>` opts in to grading; an untagged one is somebody's hand-drawn
|
|
5
|
+
// diagram and loam never says a word about it. The slug is the capability id
|
|
6
|
+
// from architecture/capabilities.yaml with every `/` flattened to `-`, because
|
|
7
|
+
// a LikeC4 tag name cannot carry a slash — `identity/tokens` would be
|
|
8
|
+
// `#cap-identity-tokens`.
|
|
9
|
+
//
|
|
10
|
+
// It lives in its own file rather than in architecture/landscape.likec4 for a
|
|
11
|
+
// reason that is about people, not parsing: the map belongs to whoever owns the
|
|
12
|
+
// fleet's topology, and a flow changes when a business need changes. Different
|
|
13
|
+
// reasons to edit are different files. The whole `architecture/` directory is
|
|
14
|
+
// read as ONE LikeC4 project, so the steps below resolve against the landscape's
|
|
15
|
+
// elements even though this file declares none — which also means exactly one
|
|
16
|
+
// file in this directory declares the `specification` block, and it is not this
|
|
17
|
+
// one.
|
|
18
|
+
//
|
|
19
|
+
// THE TAG MUST BE THE FIRST THING IN THE VIEW BODY. Written after `title` it is
|
|
20
|
+
// five parse errors, none of which mentions tags. That is the mistake every
|
|
21
|
+
// author makes once.
|
|
22
|
+
//
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
//
|
|
25
|
+
// Two things about this particular flow are worth reading before you copy it.
|
|
26
|
+
//
|
|
27
|
+
// The first hop is a PERSON, and it is here on purpose: `customer ->
|
|
28
|
+
// checkoutWeb` is backed by a real edge that carries no `metadata { op }`, and
|
|
29
|
+
// checkout-web is a real services/ directory — so every condition of
|
|
30
|
+
// `usecase.step-unlinked` is met except the one that matters, which is that a
|
|
31
|
+
// person is not a caller. Somebody clicking a button owes no operationId. Delete
|
|
32
|
+
// that exemption from the checker and this file is what notices: the example
|
|
33
|
+
// fleet's warning count moves from eight to nine and test/examples.test.ts
|
|
34
|
+
// fails.
|
|
35
|
+
//
|
|
36
|
+
// The hop from checkout-web to order-service is DELIBERATELY NOT DRAWN, and its
|
|
37
|
+
// absence is the more useful half of the lesson. The landscape declares two
|
|
38
|
+
// edges for that pair — `Calls createOrder` and `Calls getOrder` — so a step
|
|
39
|
+
// between those two elements names two operations, and loam refuses to guess
|
|
40
|
+
// which one the flow exercises: `usecase.step-contested` (warn), listing both
|
|
41
|
+
// candidates. That is the check working. The two fixes are the ones the message
|
|
42
|
+
// offers: draw the hop between elements that name exactly one operation, or give
|
|
43
|
+
// the candidates one operation between them.
|
|
44
|
+
|
|
45
|
+
views {
|
|
46
|
+
dynamic view uc_order_notification {
|
|
47
|
+
#cap-order-notifications
|
|
48
|
+
#req-NOTIFY-ONCE
|
|
49
|
+
title 'Order notification'
|
|
50
|
+
description 'A placed order reaches the customer as exactly one confirmation'
|
|
51
|
+
|
|
52
|
+
// A person, not a caller — see above.
|
|
53
|
+
customer -> marketplace.checkoutWeb 'places the order'
|
|
54
|
+
|
|
55
|
+
// Producer to topic: the edge carries `publishes`, so the hop reaches a
|
|
56
|
+
// declared API — an AsyncAPI one — and loam does not also demand an HTTP
|
|
57
|
+
// operationId for it. The event spine grades this edge on its own terms.
|
|
58
|
+
marketplace.orderService -> kafka.orderEvents 'announces OrderPlaced'
|
|
59
|
+
|
|
60
|
+
// Topic to consumer, the same exemption from the other side. Modelling the
|
|
61
|
+
// TOPIC rather than the broker is what keeps this readable: an edge into
|
|
62
|
+
// `kafka` itself would put every service in the fleet on one node.
|
|
63
|
+
kafka.orderEvents -> marketplace.notificationService 'sends the confirmation'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Checkout
|
|
2
|
+
|
|
3
|
+
The customer has chosen what to buy and now wants to be done. Everything from
|
|
4
|
+
the filled cart to the confirmed, paid [order](../../glossary/order.md) is this
|
|
5
|
+
capability: the prices they were shown, the money leaving their card exactly
|
|
6
|
+
once, and the confirmation that tells them it worked. Exactly once means one
|
|
7
|
+
[authorization](../../glossary/payments/authorization.md), which is a word this
|
|
8
|
+
fleet uses in one sense and writes down.
|
|
9
|
+
|
|
10
|
+
This narrative slot is why the tree exists at all. `architecture/capabilities.yaml`
|
|
11
|
+
can declare the word `checkout` and nothing more; the paragraph above is what a
|
|
12
|
+
business analyst actually writes, and before this file there was nowhere in a
|
|
13
|
+
loam docs repo to put it. It is also the loam equivalent of OpenSpec's
|
|
14
|
+
`## Purpose` prose, which the migrator used to drop into `legacy/`.
|
|
15
|
+
|
|
16
|
+
The requirements below are the analyst's, and each one is a promise a customer
|
|
17
|
+
could check from outside — no operationId, no element id, no message name, and
|
|
18
|
+
no service named. That is the rule the tree is held to, and half of it is
|
|
19
|
+
checked: `Operations:`, `Covers:`, `Publishes:` and `Consumes:` are refused here
|
|
20
|
+
(`capability.requirement-service-scoped`), while "names no service" is an
|
|
21
|
+
authoring rule this file keeps and pull-request review holds, because matching
|
|
22
|
+
service names in prose would be a heuristic and loam does not guess.
|
|
23
|
+
|
|
24
|
+
Which services carry which part of this is not written here and must not be:
|
|
25
|
+
that is the fleet map's question, and `loam list capabilities` answers it from
|
|
26
|
+
the `Capability:` lines the service specs already carry.
|
|
27
|
+
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
### Requirement: A confirmed order charges the customer exactly once
|
|
31
|
+
Requirement-ID: CHECKOUT-CHARGE-ONCE
|
|
32
|
+
The fleet SHALL charge a customer at most once for a single confirmed order,
|
|
33
|
+
and SHALL confirm an order only after that charge has been authorized.
|
|
34
|
+
|
|
35
|
+
#### Scenario: The customer submits the same order twice
|
|
36
|
+
- **Given** a customer who has confirmed an order
|
|
37
|
+
- **When** they submit the same order again without changing it
|
|
38
|
+
- **Then** they are shown the order they already placed
|
|
39
|
+
- **And** their card is charged only for the first one
|
|
40
|
+
|
|
41
|
+
#### Scenario: Authorization is declined
|
|
42
|
+
- **Given** a customer whose card is declined
|
|
43
|
+
- **When** they confirm the order
|
|
44
|
+
- **Then** no order is confirmed
|
|
45
|
+
- **And** they are told the payment did not go through
|
|
46
|
+
|
|
47
|
+
### Requirement: The price shown is the price charged
|
|
48
|
+
Requirement-ID: CHECKOUT-PRICE-HONOURED
|
|
49
|
+
The fleet SHALL charge the total the customer was shown at the moment they
|
|
50
|
+
confirmed, even if a price changes while the order is being placed.
|
|
51
|
+
|
|
52
|
+
#### Scenario: A price changes mid-checkout
|
|
53
|
+
- **Given** a customer looking at a total of 40.00
|
|
54
|
+
- **When** the price of an item rises before they confirm
|
|
55
|
+
- **Then** confirming still charges 40.00
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Identity tokens
|
|
2
|
+
|
|
3
|
+
Somebody signs in once and stays signed in for a while; the fleet has to keep
|
|
4
|
+
answering "is this still them?" without asking again, and has to stop answering
|
|
5
|
+
yes the moment it should not.
|
|
6
|
+
|
|
7
|
+
This file also demonstrates NESTING, which is the part of the tree that is easy
|
|
8
|
+
to get wrong when reading the layout. The id is `identity/tokens` — one id, with
|
|
9
|
+
the slash inside it, exactly as `architecture/capabilities.yaml` spells the key
|
|
10
|
+
and exactly as a requirement's `Capability:` line writes it. The tree does not
|
|
11
|
+
collapse it and does not invent a separator: the id's own slashes ARE the
|
|
12
|
+
directories, so the document lives at `capabilities/identity/tokens/spec.md`.
|
|
13
|
+
|
|
14
|
+
`capabilities/identity/` therefore holds no `spec.md` of its own, and that earns
|
|
15
|
+
no finding: a directory with a capability beneath it is a group. It would earn
|
|
16
|
+
`capability.doc-missing` only if it held neither a document nor anything below.
|
|
17
|
+
If the fleet later decides that `identity` is a capability in its own right,
|
|
18
|
+
adding `capabilities/identity/spec.md` makes it one — a directory may be both a
|
|
19
|
+
capability and the parent of others, because that is what the ids already say.
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
### Requirement: A revoked session stops working everywhere
|
|
24
|
+
Requirement-ID: IDENTITY-REVOKE-EVERYWHERE
|
|
25
|
+
When a person's session is revoked, the fleet SHALL stop honouring it — in
|
|
26
|
+
every part of the product, not only the one they revoked it from.
|
|
27
|
+
|
|
28
|
+
#### Scenario: Signing out of a lost phone
|
|
29
|
+
- **Given** a person signed in on two devices
|
|
30
|
+
- **When** they sign out one of them from the other
|
|
31
|
+
- **Then** the signed-out device can no longer act as them
|
|
32
|
+
|
|
33
|
+
### Requirement: A refused sign-in never says which half was wrong
|
|
34
|
+
Requirement-ID: IDENTITY-ONE-REFUSAL
|
|
35
|
+
When a sign-in is refused, the fleet SHALL give the same answer whether the
|
|
36
|
+
account does not exist or the secret was wrong — a refusal that tells them apart
|
|
37
|
+
lets anyone test which accounts exist.
|
|
38
|
+
|
|
39
|
+
#### Scenario: An account that does not exist
|
|
40
|
+
- **Given** a sign-in attempt for an account nobody has registered
|
|
41
|
+
- **When** it is refused
|
|
42
|
+
- **Then** the refusal is word for word the one a wrong password gets
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Order notifications
|
|
2
|
+
|
|
3
|
+
The customer has bought something and now wants to know it worked. Every event
|
|
4
|
+
in an [order](../../glossary/order.md)'s life that they would want to hear about
|
|
5
|
+
reaches them, once.
|
|
6
|
+
|
|
7
|
+
This capability carries the example's demonstration of the axis's second
|
|
8
|
+
realizer, and it is the reason the tree exists at all. The promise below is
|
|
9
|
+
**cross-service by construction**: an order is placed in one service, the event
|
|
10
|
+
crosses a broker, and a third service sends the message. No single service's
|
|
11
|
+
`spec.md` can promise "exactly one confirmation", because each of them promises
|
|
12
|
+
only its own part — `order-service` promises to announce the order,
|
|
13
|
+
`notification-service` promises to send what it receives, and neither can
|
|
14
|
+
promise what happens between them.
|
|
15
|
+
|
|
16
|
+
A USE CASE can, because it IS the hop sequence. So
|
|
17
|
+
`architecture/usecases/order-notification.likec4` carries `#req-NOTIFY-ONCE`
|
|
18
|
+
beside its `#cap-order-notifications` tag, and that tag is the architect's
|
|
19
|
+
answer to this promise: these hops, in this order, are what keeps it. loam
|
|
20
|
+
grades the claim down to the operation, and `capability.requirement-unrealized`
|
|
21
|
+
stays silent for this requirement because a flow keeps it.
|
|
22
|
+
|
|
23
|
+
Written with no `Operations:`, `Covers:`, `Publishes:` or `Consumes:` line —
|
|
24
|
+
those resolve against one service's own contract, and a capability requirement
|
|
25
|
+
must be observable from outside the fleet.
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
### Requirement: A placed order produces exactly one confirmation
|
|
30
|
+
Requirement-ID: NOTIFY-ONCE
|
|
31
|
+
The fleet SHALL send a customer exactly one confirmation for an order they
|
|
32
|
+
placed — not none if a service restarts mid-flight, and not two if a message is
|
|
33
|
+
delivered twice.
|
|
34
|
+
|
|
35
|
+
#### Scenario: The order is placed and the customer is told
|
|
36
|
+
- **Given** a customer who has just placed an order
|
|
37
|
+
- **When** the order is accepted
|
|
38
|
+
- **Then** they receive one confirmation naming that order
|
|
39
|
+
|
|
40
|
+
#### Scenario: The same event arrives twice
|
|
41
|
+
- **Given** a confirmation already sent for an order
|
|
42
|
+
- **When** the same event is delivered again
|
|
43
|
+
- **Then** the customer receives nothing further
|
package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-FEAT-101-0001
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-07-20
|
|
5
|
+
feature: FEAT-101
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 1. Introduce a dedicated payment-split-service
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
Splitting logic is non-trivial and will be reused beyond checkout.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
Create a new bounded-context service `payment-split-service` rather than embedding the logic in `payment-service`.
|
|
15
|
+
|
|
16
|
+
## Consequences
|
|
17
|
+
- +1 service to operate, with clean ownership.
|
|
18
|
+
- `payment-service` gains a synchronous dependency — modeled as `criticality: degradable` in its `health.yaml`.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// C4 DELTA for FEAT-101 — new/changed elements + relationships tagged #FEAT-101.
|
|
2
|
+
// Self-contained so it validates on its own; loam projects the #FEAT-101 subset per service.
|
|
3
|
+
//
|
|
4
|
+
// The tag is loam's ONLY way of seeing the delta: a file that declares elements or
|
|
5
|
+
// relationships with none carrying `#FEAT-101` is `delta.nothing-tagged` (error), because
|
|
6
|
+
// everything in it would be invisible to the checks and the archive would merge nothing.
|
|
7
|
+
specification {
|
|
8
|
+
element group
|
|
9
|
+
element softwareSystem
|
|
10
|
+
element container
|
|
11
|
+
element topic {
|
|
12
|
+
#external
|
|
13
|
+
#platform
|
|
14
|
+
}
|
|
15
|
+
tag external
|
|
16
|
+
tag platform
|
|
17
|
+
tag FEAT-101
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
model {
|
|
21
|
+
// Existing elements, referenced for context and left untagged — archive merges only what
|
|
22
|
+
// carries the feature tag, so quoting the neighbourhood costs nothing.
|
|
23
|
+
//
|
|
24
|
+
// The new service is declared INSIDE the group the landscape already draws, which is where
|
|
25
|
+
// archive splices it: a nested element lands inside its parent's block, never as a flat
|
|
26
|
+
// dotted id, which LikeC4 rejects at top level.
|
|
27
|
+
marketplace = group 'Marketplace' {
|
|
28
|
+
checkoutWeb = softwareSystem 'checkout-web'
|
|
29
|
+
paymentService = softwareSystem 'payment-service'
|
|
30
|
+
|
|
31
|
+
paymentSplitService = softwareSystem 'payment-split-service' {
|
|
32
|
+
#FEAT-101
|
|
33
|
+
description 'Splits a payment across payees'
|
|
34
|
+
// The binding, not the title, is what ties this element to the
|
|
35
|
+
// `services/payment-split-service/` directory archive will create. A
|
|
36
|
+
// title works too and is what most existing repositories rely on — and
|
|
37
|
+
// it is also the trap: rename the box in a diagram and every check that
|
|
38
|
+
// joined it to its directory silently stops matching.
|
|
39
|
+
metadata {
|
|
40
|
+
service 'payment-split-service'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
api = container 'api' {
|
|
44
|
+
technology 'Spring Boot'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The broker AND the topic the new edge points at, both already in the
|
|
50
|
+
// landscape: a delta references the channel, never the server, so the merged
|
|
51
|
+
// map does not grow one more spoke on a hub.
|
|
52
|
+
kafka = softwareSystem 'kafka' {
|
|
53
|
+
#external
|
|
54
|
+
#platform
|
|
55
|
+
paymentEvents = topic 'payment.events'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
marketplace.paymentService -> marketplace.paymentSplitService 'Calls createSplit' {
|
|
59
|
+
#FEAT-101
|
|
60
|
+
metadata { op 'createSplit' }
|
|
61
|
+
}
|
|
62
|
+
// Read back at capture time: settlement needs the shares the split recorded.
|
|
63
|
+
marketplace.paymentService -> marketplace.paymentSplitService 'Calls getSplit' {
|
|
64
|
+
#FEAT-101
|
|
65
|
+
metadata { op 'getSplit' }
|
|
66
|
+
}
|
|
67
|
+
// The one tagged addition this feature leaves uncovered, on purpose: no
|
|
68
|
+
// `Covers:` line in any of its arch.spec.md deltas names it, so
|
|
69
|
+
// `c4.uncovered` (warn) says the architectural obligations behind this call
|
|
70
|
+
// ship untested. A `Covers: checkout-web -> payment-split-service` line
|
|
71
|
+
// would close it — and would also close the edge above, since an edge entry
|
|
72
|
+
// resolves by ENDPOINT, so two edges between one pair are one target.
|
|
73
|
+
marketplace.checkoutWeb -> marketplace.paymentSplitService 'Calls createSplit' {
|
|
74
|
+
#FEAT-101
|
|
75
|
+
metadata { op 'createSplit' }
|
|
76
|
+
}
|
|
77
|
+
// Drawn with the message in its title and no `metadata { publishes }`, deliberately: the
|
|
78
|
+
// metadata is a JOIN, and the join demands a contract — an edge publishing a message its
|
|
79
|
+
// bound service's contract (feature ∪ living) declares no send for is refused as
|
|
80
|
+
// `c4-event.message-undefined`. The async axis has the full feature lifecycle
|
|
81
|
+
// (`specs/payment-service/asyncapi.yaml` beside this delta is its demonstration — the
|
|
82
|
+
// living contract restated under `loam rebase` pins, plus a new producer side), but
|
|
83
|
+
// payment-split-service's own contract is deferred until the consumer of `PaymentSplit`
|
|
84
|
+
// exists, so the edge stays title-only rather than pointing at a contract nobody wrote.
|
|
85
|
+
marketplace.paymentSplitService -> kafka.paymentEvents 'Publishes PaymentSplit' {
|
|
86
|
+
#FEAT-101
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
views {
|
|
91
|
+
view feat_101 {
|
|
92
|
+
include *
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
feature: FEAT-101
|
|
3
|
+
title: Payment splitting
|
|
4
|
+
status: in_progress # proposed -> in_progress -> built -> done
|
|
5
|
+
owner: payments-team
|
|
6
|
+
services: [payment-service, payment-split-service, checkout-web]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# FEAT-101 — Payment splitting
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
Marketplaces need to split one customer payment across multiple payees (sellers). Today a
|
|
13
|
+
seller is paid by a separate transfer run reconciled by hand at the end of the day, which is
|
|
14
|
+
where every payout dispute this quarter came from: the customer's payment and the sellers'
|
|
15
|
+
shares are two records nothing joins.
|
|
16
|
+
|
|
17
|
+
This file is where the "why" lives, and the archive gate holds it to that: the delta says what
|
|
18
|
+
changed, and nothing else says what for. A feature whose `intent.md` is missing, or says nothing
|
|
19
|
+
outside the scaffold's own comments, is refused by `intent.empty` — a warning that gates, so a
|
|
20
|
+
change cannot fold into the living docs with its reason unwritten.
|
|
21
|
+
|
|
22
|
+
## Business acceptance
|
|
23
|
+
- A customer can split a payment across 2+ payees before confirming.
|
|
24
|
+
- Each payee receives their share; the shares sum to the total.
|
|
25
|
+
- A split that does not sum to the total is refused, and the customer is told which shares are
|
|
26
|
+
in play — a silent rounding fix is a payout dispute six weeks later.
|
|
27
|
+
|
|
28
|
+
## Architectural summary
|
|
29
|
+
New `payment-split-service`; `payment-service` and `checkout-web` call it; it publishes
|
|
30
|
+
`PaymentSplit`. UI adds a split-payment page in `checkout-web`. See `delta.likec4`, and
|
|
31
|
+
`adrs/0001-dedicated-split-service.md` for why the logic is not folded into `payment-service`.
|
|
32
|
+
|
|
33
|
+
## Not in this feature
|
|
34
|
+
Payouts themselves. A split records who is owed what; moving the money is separate work, and
|
|
35
|
+
deliberately not smuggled in here — a feature whose intent and whose delta describe different
|
|
36
|
+
scopes is one nobody can review as a diff.
|
|
37
|
+
|
|
38
|
+
The `PaymentSplit` event is drawn in `delta.likec4` with the message in its title and no
|
|
39
|
+
contract join yet — deliberately, not for lack of machinery. The async axis has the full
|
|
40
|
+
feature lifecycle, and this feature's `specs/payment-service/asyncapi.yaml` is its
|
|
41
|
+
demonstration: the living contract restated under `loam rebase`'s pins, plus the new
|
|
42
|
+
`payment.PaymentSplitAuthorized` producer side the archive will merge. The split service's own
|
|
43
|
+
contract is deferred until a consumer of `PaymentSplit` exists, and the edge stays unjoined
|
|
44
|
+
rather than pointing at a contract nobody wrote.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# checkout-web — requirement delta for FEAT-101
|
|
2
|
+
|
|
3
|
+
## ADDED Requirements
|
|
4
|
+
|
|
5
|
+
### Requirement: Split payment on checkout
|
|
6
|
+
|
|
7
|
+
Requirement-ID: WEB-SPLIT
|
|
8
|
+
The UI SHALL let a customer split a payment across two or more payees before confirming, and
|
|
9
|
+
SHALL show the recorded split back to them before the payment is taken.
|
|
10
|
+
|
|
11
|
+
#### Scenario: Customer splits a payment across two payees
|
|
12
|
+
- **Given** a payment of 100.00 USD
|
|
13
|
+
- **When** the customer assigns 60.00 to "seller-x" and 40.00 to "seller-y"
|
|
14
|
+
- **And** confirms
|
|
15
|
+
- **Then** `createSplit` is called on `payment-split-service`
|
|
16
|
+
- **And** the split is shown as confirmed
|
|
17
|
+
|
|
18
|
+
#### Scenario: A split that does not sum to the total cannot be confirmed
|
|
19
|
+
- **Given** a payment of 100.00 USD
|
|
20
|
+
- **When** the customer assigns 60.00 to "seller-x" and 30.00 to "seller-y"
|
|
21
|
+
- **Then** the confirm control stays disabled and the remaining 10.00 is shown as unassigned
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# The event-contract delta: what FEAT-101 changes about the messages
|
|
2
|
+
# payment-service puts on the bus.
|
|
3
|
+
#
|
|
4
|
+
# Like the openapi delta, this is a COMPLETE AsyncAPI 3.0 document, not a
|
|
5
|
+
# patch: the living contract is restated around the one change. Identity is
|
|
6
|
+
# the slot — `channels.<key>`, `operations.<key>`, `components.messages.<key>`
|
|
7
|
+
# — and `x-loam-based-on` (written by `loam rebase`, never by hand) is what
|
|
8
|
+
# lets the merge tell a restated slot from an edited one: a pinned QUOTE is
|
|
9
|
+
# never a merge input, so a change that lands on the living contract after
|
|
10
|
+
# this delta was written survives the archive. The new slots below carry no
|
|
11
|
+
# pin — there is no living version for them to be based on.
|
|
12
|
+
asyncapi: 3.0.0
|
|
13
|
+
info:
|
|
14
|
+
title: payment-service events
|
|
15
|
+
version: "1.0"
|
|
16
|
+
|
|
17
|
+
channels:
|
|
18
|
+
paymentEvents:
|
|
19
|
+
address: payment.events.v1
|
|
20
|
+
description: Payment lifecycle events, published by the outbox relay
|
|
21
|
+
messages:
|
|
22
|
+
PaymentAuthorized:
|
|
23
|
+
$ref: '#/components/messages/PaymentAuthorized'
|
|
24
|
+
PaymentCaptured:
|
|
25
|
+
$ref: '#/components/messages/PaymentCaptured'
|
|
26
|
+
x-loam-based-on: 036cbb7e0245e1a9
|
|
27
|
+
# NEW: split authorizations are announced on their own topic, so a consumer
|
|
28
|
+
# that only reconciles splits does not filter the whole lifecycle stream.
|
|
29
|
+
paymentSplitEvents:
|
|
30
|
+
address: payment.splits.v1
|
|
31
|
+
description: Split-authorization events, published by the outbox relay
|
|
32
|
+
messages:
|
|
33
|
+
PaymentSplitAuthorized:
|
|
34
|
+
$ref: '#/components/messages/PaymentSplitAuthorized'
|
|
35
|
+
|
|
36
|
+
operations:
|
|
37
|
+
sendPaymentAuthorized:
|
|
38
|
+
action: send
|
|
39
|
+
channel:
|
|
40
|
+
$ref: '#/channels/paymentEvents'
|
|
41
|
+
messages:
|
|
42
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentAuthorized'
|
|
43
|
+
x-loam-based-on: 72934fd7ed7f6df9
|
|
44
|
+
sendPaymentCaptured:
|
|
45
|
+
action: send
|
|
46
|
+
channel:
|
|
47
|
+
$ref: '#/channels/paymentEvents'
|
|
48
|
+
messages:
|
|
49
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentCaptured'
|
|
50
|
+
x-loam-based-on: 01ac447e38a868cc
|
|
51
|
+
sendPaymentSplitAuthorized:
|
|
52
|
+
action: send
|
|
53
|
+
channel:
|
|
54
|
+
$ref: '#/channels/paymentSplitEvents'
|
|
55
|
+
|
|
56
|
+
components:
|
|
57
|
+
messages:
|
|
58
|
+
PaymentAuthorized:
|
|
59
|
+
# Namespaced by the domain that owns it. One message has exactly one
|
|
60
|
+
# producer: two services declaring they send this name is
|
|
61
|
+
# `asyncapi.message-contested`, and then which contract a consumer reads
|
|
62
|
+
# is a coin flip.
|
|
63
|
+
name: payment.PaymentAuthorized
|
|
64
|
+
title: Payment authorized
|
|
65
|
+
# JSON Schema today, because this fleet runs no schema registry. An Avro
|
|
66
|
+
# record here later needs a `schemaFormat:` line and no other change:
|
|
67
|
+
# everything below is opaque to loam.
|
|
68
|
+
payload:
|
|
69
|
+
type: object
|
|
70
|
+
required: [ paymentId, orderId, amount, currency, authorizedAt ]
|
|
71
|
+
properties:
|
|
72
|
+
paymentId:
|
|
73
|
+
type: string
|
|
74
|
+
format: uuid
|
|
75
|
+
orderId:
|
|
76
|
+
type: string
|
|
77
|
+
amount:
|
|
78
|
+
type: integer
|
|
79
|
+
description: minor units
|
|
80
|
+
currency:
|
|
81
|
+
type: string
|
|
82
|
+
pattern: '^[A-Z]{3}$'
|
|
83
|
+
authorizedAt:
|
|
84
|
+
type: string
|
|
85
|
+
format: date-time
|
|
86
|
+
x-loam-based-on: 0e5a230802d1573b
|
|
87
|
+
PaymentCaptured:
|
|
88
|
+
name: payment.PaymentCaptured
|
|
89
|
+
title: Payment captured
|
|
90
|
+
payload:
|
|
91
|
+
type: object
|
|
92
|
+
required: [ paymentId, orderId, capturedAmount, currency, capturedAt ]
|
|
93
|
+
properties:
|
|
94
|
+
paymentId:
|
|
95
|
+
type: string
|
|
96
|
+
format: uuid
|
|
97
|
+
orderId:
|
|
98
|
+
type: string
|
|
99
|
+
capturedAmount:
|
|
100
|
+
type: integer
|
|
101
|
+
description: minor units
|
|
102
|
+
currency:
|
|
103
|
+
type: string
|
|
104
|
+
pattern: '^[A-Z]{3}$'
|
|
105
|
+
capturedAt:
|
|
106
|
+
type: string
|
|
107
|
+
format: date-time
|
|
108
|
+
x-loam-based-on: 449d5409ccf1b59f
|
|
109
|
+
# NEW: the split-aware half of an authorization. The split itself is
|
|
110
|
+
# payment-split-service's business; this event says the reservation on the
|
|
111
|
+
# payer's card is covered by a recorded split.
|
|
112
|
+
PaymentSplitAuthorized:
|
|
113
|
+
name: payment.PaymentSplitAuthorized
|
|
114
|
+
title: Split authorization completed
|
|
115
|
+
payload:
|
|
116
|
+
type: object
|
|
117
|
+
required: [ paymentId, orderId, splitId, authorizedAt ]
|
|
118
|
+
properties:
|
|
119
|
+
paymentId:
|
|
120
|
+
type: string
|
|
121
|
+
format: uuid
|
|
122
|
+
orderId:
|
|
123
|
+
type: string
|
|
124
|
+
splitId:
|
|
125
|
+
type: string
|
|
126
|
+
format: uuid
|
|
127
|
+
authorizedAt:
|
|
128
|
+
type: string
|
|
129
|
+
format: date-time
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# payment-service — requirement delta for FEAT-101
|
|
2
|
+
|
|
3
|
+
## MODIFIED Requirements
|
|
4
|
+
|
|
5
|
+
### Requirement: Authorize a payment, splitting it when the order is flagged
|
|
6
|
+
|
|
7
|
+
Requirement-ID: PAY-AUTHORIZE
|
|
8
|
+
Based-On: 820301445e65f9f4
|
|
9
|
+
The service SHALL reserve funds for an order before capture, SHALL treat an authorization
|
|
10
|
+
request as idempotent by order id, and SHALL delegate splitting to `payment-split-service` when
|
|
11
|
+
the order is flagged for splitting.
|
|
12
|
+
|
|
13
|
+
Operations: authorizePayment
|
|
14
|
+
Publishes: payment.PaymentAuthorized
|
|
15
|
+
Realizes: checkout#CHECKOUT-CHARGE-ONCE
|
|
16
|
+
|
|
17
|
+
#### Scenario: Successful authorization
|
|
18
|
+
- **Given** an order with a valid payment method
|
|
19
|
+
- **When** authorization is requested
|
|
20
|
+
- **Then** funds are reserved and a `PaymentAuthorized` event is emitted
|
|
21
|
+
|
|
22
|
+
#### Scenario: A retry of the same authorization returns the first result
|
|
23
|
+
- **Given** an authorization already reserved for order "A-1"
|
|
24
|
+
- **When** the same request arrives again after a caller timeout
|
|
25
|
+
- **Then** the original authorization is returned and no second reservation is made
|
|
26
|
+
|
|
27
|
+
#### Scenario: A second authorization for the same order with a different amount is refused
|
|
28
|
+
- **Given** an authorization already reserved for order "A-1" of 100.00 USD
|
|
29
|
+
- **When** an authorization of 120.00 USD is requested for the same order
|
|
30
|
+
- **Then** the request is refused with 409 and the first reservation stands
|
|
31
|
+
|
|
32
|
+
#### Scenario: Split order delegates to the split service
|
|
33
|
+
- **Given** an order flagged for splitting
|
|
34
|
+
- **When** authorization is requested
|
|
35
|
+
- **Then** payment-service calls `createSplit` on `payment-split-service`
|
|
36
|
+
- **And** the authorization succeeds only once the split is recorded
|
package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# payment-split-service — architecture delta for FEAT-101
|
|
2
|
+
|
|
3
|
+
Architectural obligations of the new service — what no business scenario was ever
|
|
4
|
+
going to say. Each requirement's `Covers:` line names the delta's tagged elements
|
|
5
|
+
and edges it accounts for; a tagged addition nothing covers is `c4.uncovered`.
|
|
6
|
+
(The `checkout-web -> payment-split-service` edge is left uncovered on purpose —
|
|
7
|
+
it is the example's demonstration of that warning.)
|
|
8
|
+
|
|
9
|
+
Every entry below names a SERVICE rather than an element id. Both forms resolve — an entry
|
|
10
|
+
matches an element by its id or by the service it stands for, and an edge by resolving each
|
|
11
|
+
endpoint the same way — and the service form is the one that survives the landscape moving a box
|
|
12
|
+
into a grouping element, which is exactly what happened to this fleet.
|
|
13
|
+
|
|
14
|
+
## ADDED Requirements
|
|
15
|
+
|
|
16
|
+
### Requirement: PaymentSplit leaves through the transactional outbox
|
|
17
|
+
|
|
18
|
+
Requirement-ID: ARCH-SPL-OUTBOX
|
|
19
|
+
The service SHALL record a split and its `PaymentSplit` event in one database
|
|
20
|
+
transaction, published to kafka by an outbox relay — never a dual write.
|
|
21
|
+
|
|
22
|
+
Covers: payment-split-service, payment-split-service -> kafka.paymentEvents
|
|
23
|
+
|
|
24
|
+
#### Scenario: Broker down when a split is recorded
|
|
25
|
+
- **Given** a recorded split whose `PaymentSplit` event is still in the outbox
|
|
26
|
+
- **When** kafka is unavailable
|
|
27
|
+
- **Then** the split stays committed and the event is published once kafka returns
|
|
28
|
+
|
|
29
|
+
### Requirement: createSplit is idempotent under retries
|
|
30
|
+
|
|
31
|
+
Requirement-ID: ARCH-SPL-IDEMPOTENT
|
|
32
|
+
The service SHALL treat createSplit as idempotent by order id, so a caller's
|
|
33
|
+
timeout-and-retry never records a second split.
|
|
34
|
+
|
|
35
|
+
Covers: payment-service -> payment-split-service
|
|
36
|
+
|
|
37
|
+
#### Scenario: payment-service retries createSplit
|
|
38
|
+
- **Given** a split already recorded for order "A-1"
|
|
39
|
+
- **When** the same createSplit request arrives again after a caller timeout
|
|
40
|
+
- **Then** the original split is returned and no second split is recorded
|