@ybotok/loam 0.2.0-alpha.1 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3448 -0
- package/COMPARISON.md +91 -3
- package/CONTRIBUTING.md +37 -0
- package/MIGRATING-from-OpenSpec.md +47 -23
- package/QUICKSTART.md +189 -12
- package/README.md +274 -65
- package/ROADMAP.md +572 -31
- package/SCHEMA.md +1709 -155
- package/WORKFLOW.md +298 -72
- package/dist/cli.js +26 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +5 -10
- package/dist/commands/adopt/adopt.js.map +1 -1
- package/dist/commands/adopt/render.js +50 -9
- package/dist/commands/adopt/render.js.map +1 -1
- package/dist/commands/archive/archive.js +16 -19
- package/dist/commands/archive/archive.js.map +1 -1
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +77 -43
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +21 -19
- package/dist/commands/archive/plan/gate.js.map +1 -1
- package/dist/commands/archive/plan/landscape.js +167 -30
- package/dist/commands/archive/plan/landscape.js.map +1 -1
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +14 -19
- package/dist/commands/archive/plan/refusal.js.map +1 -1
- package/dist/commands/archive/plan/specs.js +137 -56
- package/dist/commands/archive/plan/specs.js.map +1 -1
- package/dist/commands/archive/plan/state.js +3 -0
- package/dist/commands/archive/plan/state.js.map +1 -1
- package/dist/commands/archive/run.js +134 -30
- package/dist/commands/archive/run.js.map +1 -1
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +85 -18
- package/dist/commands/context/context.js.map +1 -1
- package/dist/commands/context/print.js +29 -7
- package/dist/commands/context/print.js.map +1 -1
- package/dist/commands/delta/delta.js +102 -14
- package/dist/commands/delta/delta.js.map +1 -1
- package/dist/commands/delta/print.js +17 -1
- package/dist/commands/delta/print.js.map +1 -1
- package/dist/commands/dependencies.js +3 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +20 -27
- package/dist/commands/diff/diff.js.map +1 -1
- package/dist/commands/doctor.js +60 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +89 -13
- package/dist/commands/explain/explain.js.map +1 -1
- package/dist/commands/explore.js +16 -10
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +45 -8
- package/dist/commands/gate/gate.js.map +1 -1
- package/dist/commands/gate/print.js +15 -3
- package/dist/commands/gate/print.js.map +1 -1
- package/dist/commands/gherkin/commit.js +13 -54
- package/dist/commands/gherkin/commit.js.map +1 -1
- package/dist/commands/gherkin/gherkin.js +36 -20
- package/dist/commands/gherkin/gherkin.js.map +1 -1
- package/dist/commands/gherkin/reconcile.js +10 -13
- package/dist/commands/gherkin/reconcile.js.map +1 -1
- package/dist/commands/init/first-hour.js +44 -0
- package/dist/commands/init/first-hour.js.map +1 -1
- package/dist/commands/init/init.js +18 -22
- package/dist/commands/init/init.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +4 -6
- package/dist/commands/list/campaign/campaign.js.map +1 -1
- package/dist/commands/list/json.js +5 -7
- package/dist/commands/list/json.js.map +1 -1
- package/dist/commands/list/list.js +44 -29
- package/dist/commands/list/list.js.map +1 -1
- package/dist/commands/list/print.js +52 -9
- package/dist/commands/list/print.js.map +1 -1
- package/dist/commands/list/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +37 -34
- package/dist/commands/list/views.js.map +1 -1
- package/dist/commands/mcp/dispatch.js +91 -36
- package/dist/commands/mcp/dispatch.js.map +1 -1
- package/dist/commands/mcp/mcp.js +56 -15
- package/dist/commands/mcp/mcp.js.map +1 -1
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/active.js +27 -22
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
- package/dist/commands/migrate-openspec/materialize/target.js +2 -2
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/error.js +7 -8
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
- package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
- package/dist/commands/new/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +8 -22
- package/dist/commands/new/commit.js.map +1 -1
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +59 -14
- package/dist/commands/new/new.js.map +1 -1
- package/dist/commands/new/templates.js +48 -124
- package/dist/commands/new/templates.js.map +1 -1
- package/dist/commands/open.js +3 -7
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/policy/gate.js +27 -0
- package/dist/commands/policy/gate.js.map +1 -1
- package/dist/commands/rebase/plan.js +2 -2
- package/dist/commands/rebase/plan.js.map +1 -1
- package/dist/commands/rebase/rebase.js +60 -35
- package/dist/commands/rebase/rebase.js.map +1 -1
- package/dist/commands/seed/commit.js +55 -26
- package/dist/commands/seed/commit.js.map +1 -1
- package/dist/commands/seed/plan.js +158 -13
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/seed/seed.js +13 -11
- package/dist/commands/seed/seed.js.map +1 -1
- package/dist/commands/show/feature.js +9 -5
- package/dist/commands/show/feature.js.map +1 -1
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +35 -6
- package/dist/commands/show/marks.js.map +1 -1
- package/dist/commands/show/service.js +41 -33
- package/dist/commands/show/service.js.map +1 -1
- package/dist/commands/show/show.js +17 -7
- package/dist/commands/show/show.js.map +1 -1
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +2 -0
- package/dist/commands/status/json.js.map +1 -1
- package/dist/commands/status/print.js +89 -37
- package/dist/commands/status/print.js.map +1 -1
- package/dist/commands/status/status.js +3 -7
- package/dist/commands/status/status.js.map +1 -1
- package/dist/commands/steps/steps.js +103 -23
- package/dist/commands/steps/steps.js.map +1 -1
- package/dist/commands/subsystem/edit.js +7 -7
- package/dist/commands/subsystem/edit.js.map +1 -1
- package/dist/commands/subsystem/move.js +106 -46
- package/dist/commands/subsystem/move.js.map +1 -1
- package/dist/commands/subsystem/query.js +2 -4
- package/dist/commands/subsystem/query.js.map +1 -1
- package/dist/commands/subsystem/subsystem.js +4 -7
- package/dist/commands/subsystem/subsystem.js.map +1 -1
- package/dist/commands/subsystem/sync.js +289 -74
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +147 -45
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +200 -21
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +42 -26
- package/dist/commands/unarchive/manifest.js.map +1 -1
- package/dist/commands/unarchive/restore.js +83 -33
- package/dist/commands/unarchive/restore.js.map +1 -1
- package/dist/commands/unarchive/unarchive.js +22 -30
- package/dist/commands/unarchive/unarchive.js.map +1 -1
- package/dist/commands/validate/arch-coverage.js +78 -27
- package/dist/commands/validate/arch-coverage.js.map +1 -1
- package/dist/commands/validate/checks/fleet-shape.js +34 -126
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
- package/dist/commands/validate/checks/health-deps.js +9 -6
- package/dist/commands/validate/checks/health-deps.js.map +1 -1
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +18 -8
- package/dist/commands/validate/checks/requirements.js.map +1 -1
- package/dist/commands/validate/checks/sources.js +11 -2
- package/dist/commands/validate/checks/sources.js.map +1 -1
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +26 -20
- package/dist/commands/validate/feature.js.map +1 -1
- package/dist/commands/validate/fleet/census.js +37 -13
- package/dist/commands/validate/fleet/census.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +144 -126
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/load.js +66 -0
- package/dist/commands/validate/fleet/load.js.map +1 -1
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +44 -14
- package/dist/commands/validate/fleet/obligations.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/print.js +10 -2
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +50 -15
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +40 -47
- package/dist/commands/validate/fleet/views/stale.js.map +1 -1
- package/dist/commands/validate/links/corpus.js +1 -4
- package/dist/commands/validate/links/corpus.js.map +1 -1
- package/dist/commands/validate/links/glossary.js.map +1 -1
- package/dist/commands/validate/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +36 -160
- package/dist/commands/validate/report.js.map +1 -1
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +21 -107
- package/dist/commands/validate/service/api.js.map +1 -1
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +36 -14
- package/dist/commands/validate/service/events/events.js.map +1 -1
- package/dist/commands/validate/service/events/message-producers.js +1 -1
- package/dist/commands/validate/service/events/message-producers.js.map +1 -1
- package/dist/commands/validate/service/evidence-pins.js +56 -10
- package/dist/commands/validate/service/evidence-pins.js.map +1 -1
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +121 -61
- package/dist/commands/validate/service/service.js.map +1 -1
- package/dist/commands/validate/service/specs.js +88 -28
- package/dist/commands/validate/service/specs.js.map +1 -1
- package/dist/commands/validate/service/spine.js +38 -3
- package/dist/commands/validate/service/spine.js.map +1 -1
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +85 -60
- package/dist/commands/validate/validate.js.map +1 -1
- package/dist/commands/verify/cross/diff.js +2 -6
- package/dist/commands/verify/cross/diff.js.map +1 -1
- package/dist/commands/verify/evidence/contract.js +1 -1
- package/dist/commands/verify/evidence/contract.js.map +1 -1
- package/dist/commands/verify/evidence/read.js +12 -3
- package/dist/commands/verify/evidence/read.js.map +1 -1
- package/dist/commands/verify/frozen.js +45 -23
- package/dist/commands/verify/frozen.js.map +1 -1
- package/dist/commands/verify/record.js +69 -17
- package/dist/commands/verify/record.js.map +1 -1
- package/dist/commands/verify/report.js +27 -44
- package/dist/commands/verify/report.js.map +1 -1
- package/dist/commands/verify/results.js +112 -30
- package/dist/commands/verify/results.js.map +1 -1
- package/dist/commands/verify/verify.js +55 -52
- package/dist/commands/verify/verify.js.map +1 -1
- package/dist/commands/vouch/pack/pack.js +2 -2
- package/dist/commands/vouch/pack/pack.js.map +1 -1
- package/dist/commands/vouch/pack/print.js +1 -6
- package/dist/commands/vouch/pack/print.js.map +1 -1
- package/dist/commands/vouch/pack/sections.js +1 -2
- package/dist/commands/vouch/pack/sections.js.map +1 -1
- package/dist/commands/vouch/run.js +26 -81
- package/dist/commands/vouch/run.js.map +1 -1
- package/dist/commands/vouch/sample/plan.js +20 -34
- package/dist/commands/vouch/sample/plan.js.map +1 -1
- package/dist/commands/vouch/vet/verify.js +39 -7
- package/dist/commands/vouch/vet/verify.js.map +1 -1
- package/dist/commands/vouch/vouch.js +10 -17
- package/dist/commands/vouch/vouch.js.map +1 -1
- package/dist/core/agent/agents-md/command-map.js +81 -106
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/explain.js +21 -9
- package/dist/core/agent/agents-md/map/explain.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
- package/dist/core/agent/agents-md/map/mcp.js +10 -7
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
- package/dist/core/agent/agents-md/map/status.js +24 -8
- package/dist/core/agent/agents-md/map/status.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +80 -8
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md/map/usecases.js +88 -10
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
- package/dist/core/agent/agents-md/refusals.js +49 -22
- package/dist/core/agent/agents-md/refusals.js.map +1 -1
- package/dist/core/agent/agents-md.js +39 -6
- package/dist/core/agent/agents-md.js.map +1 -1
- package/dist/core/agent/agents-stamp.js +10 -0
- package/dist/core/agent/agents-stamp.js.map +1 -1
- package/dist/core/agent/protocol.js +1 -1
- package/dist/core/agent/protocol.js.map +1 -1
- package/dist/core/agent/scaffold.js +10 -15
- package/dist/core/agent/scaffold.js.map +1 -1
- package/dist/core/agent/support/report.js +46 -5
- package/dist/core/agent/support/report.js.map +1 -1
- package/dist/core/agent/tools/dialects.js +1 -0
- package/dist/core/agent/tools/dialects.js.map +1 -1
- package/dist/core/agent/tools/registry.js +41 -76
- package/dist/core/agent/tools/registry.js.map +1 -1
- package/dist/core/agent/workflows/adopt.js +158 -11
- package/dist/core/agent/workflows/adopt.js.map +1 -1
- package/dist/core/agent/workflows/check.js +78 -39
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/agent/workflows/closing.js +88 -27
- package/dist/core/agent/workflows/closing.js.map +1 -1
- package/dist/core/agent/workflows/feature.js +128 -13
- package/dist/core/agent/workflows/feature.js.map +1 -1
- package/dist/core/agent/workflows/implement.js +96 -13
- package/dist/core/agent/workflows/implement.js.map +1 -1
- package/dist/core/agent/workflows/reference/authoring.js +106 -4
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
- package/dist/core/agent/workflows/reference/codes.js +8 -6
- package/dist/core/agent/workflows/reference/codes.js.map +1 -1
- package/dist/core/agent/workflows/reference/done-check.js +37 -15
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +6 -3
- package/dist/core/agent/workflows/reference/reference.js.map +1 -1
- package/dist/core/agent/workflows/reference/spine.js +68 -27
- package/dist/core/agent/workflows/reference/spine.js.map +1 -1
- package/dist/core/asyncapi/baseline/plan.js +14 -81
- package/dist/core/asyncapi/baseline/plan.js.map +1 -1
- package/dist/core/asyncapi/digest.js +30 -25
- package/dist/core/asyncapi/digest.js.map +1 -1
- package/dist/core/asyncapi/merge/components.js +5 -4
- package/dist/core/asyncapi/merge/components.js.map +1 -1
- package/dist/core/asyncapi/merge/error.js +7 -2
- package/dist/core/asyncapi/merge/error.js.map +1 -1
- package/dist/core/asyncapi/merge/markers.js +32 -50
- package/dist/core/asyncapi/merge/markers.js.map +1 -1
- package/dist/core/asyncapi/merge/merge.js +33 -53
- package/dist/core/asyncapi/merge/merge.js.map +1 -1
- package/dist/core/asyncapi/merge/pin.js +12 -36
- package/dist/core/asyncapi/merge/pin.js.map +1 -1
- package/dist/core/asyncapi/model.js.map +1 -1
- package/dist/core/asyncapi/read.js +36 -12
- package/dist/core/asyncapi/read.js.map +1 -1
- package/dist/core/brief/brief.js +96 -36
- package/dist/core/brief/brief.js.map +1 -1
- package/dist/core/brief/checks.js +138 -3
- package/dist/core/brief/checks.js.map +1 -1
- package/dist/core/brief/landscape.js +209 -130
- package/dist/core/brief/landscape.js.map +1 -1
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +109 -31
- package/dist/core/brief/targets.js.map +1 -1
- package/dist/core/brief/unchecked.js +14 -3
- package/dist/core/brief/unchecked.js.map +1 -1
- package/dist/core/c4/arch.js +90 -182
- package/dist/core/c4/arch.js.map +1 -1
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +169 -14
- package/dist/core/c4/likec4.js.map +1 -1
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
- package/dist/core/c4/parsed/values.js +54 -1
- package/dist/core/c4/parsed/values.js.map +1 -1
- package/dist/core/c4/parsed/view-ids.js +39 -1
- package/dist/core/c4/parsed/view-ids.js.map +1 -1
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +123 -7
- package/dist/core/c4/project/architecture.js.map +1 -1
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +43 -12
- package/dist/core/c4/project/documents.js.map +1 -1
- package/dist/core/c4/project/load.js +79 -43
- package/dist/core/c4/project/load.js.map +1 -1
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +78 -17
- package/dist/core/c4/resolve/service.js.map +1 -1
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/template.js +65 -1
- package/dist/core/c4/seed/template.js.map +1 -1
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +297 -10
- package/dist/core/c4/source-mask.js.map +1 -1
- package/dist/core/c4/source-scan.js +222 -141
- package/dist/core/c4/source-scan.js.map +1 -1
- package/dist/core/c4/splice/authored-source.js +79 -13
- package/dist/core/c4/splice/authored-source.js.map +1 -1
- package/dist/core/c4/splice/contract.js +20 -0
- package/dist/core/c4/splice/contract.js.map +1 -1
- package/dist/core/c4/splice/delta-blocks.js +20 -20
- package/dist/core/c4/splice/delta-blocks.js.map +1 -1
- package/dist/core/c4/splice/identity/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +37 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -1
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +182 -114
- package/dist/core/c4/splice/landscape-merge.js.map +1 -1
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +160 -56
- package/dist/core/c4/splice/placement.js.map +1 -1
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +13 -19
- package/dist/core/c4/workspace.js.map +1 -1
- package/dist/core/capabilities/capabilities.js +6 -6
- package/dist/core/capabilities/capabilities.js.map +1 -1
- package/dist/core/capabilities/delta/doc.js +7 -10
- package/dist/core/capabilities/delta/doc.js.map +1 -1
- package/dist/core/capabilities/delta/uncovered.js +2 -2
- package/dist/core/capabilities/delta/uncovered.js.map +1 -1
- package/dist/core/capabilities/findings.js +18 -22
- package/dist/core/capabilities/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/findings.js +12 -19
- package/dist/core/capabilities/realizes/findings.js.map +1 -1
- package/dist/core/capabilities/realizes/join.js +0 -20
- package/dist/core/capabilities/realizes/join.js.map +1 -1
- package/dist/core/capabilities/rollup.js +6 -0
- package/dist/core/capabilities/rollup.js.map +1 -1
- package/dist/core/capabilities/tree.js +6 -28
- package/dist/core/capabilities/tree.js.map +1 -1
- package/dist/core/capabilities/usecase-join.js +3 -13
- package/dist/core/capabilities/usecase-join.js.map +1 -1
- package/dist/core/coherence/authoring/scaffold.js +11 -3
- package/dist/core/coherence/authoring/scaffold.js.map +1 -1
- package/dist/core/coherence/authoring/sentinels.js +2 -1
- package/dist/core/coherence/authoring/sentinels.js.map +1 -1
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +103 -22
- package/dist/core/coherence/coherence.js.map +1 -1
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +60 -34
- package/dist/core/coherence/declared.js.map +1 -1
- package/dist/core/coherence/events/declared.js +44 -59
- package/dist/core/coherence/events/declared.js.map +1 -1
- package/dist/core/coherence/events/events.js +147 -16
- package/dist/core/coherence/events/events.js.map +1 -1
- package/dist/core/coherence/events/grades.js +31 -8
- package/dist/core/coherence/events/grades.js.map +1 -1
- package/dist/core/coherence/events/lookups.js +28 -87
- package/dist/core/coherence/events/lookups.js.map +1 -1
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.js.map +1 -0
- package/dist/core/coherence/lookups.js +18 -78
- package/dist/core/coherence/lookups.js.map +1 -1
- package/dist/core/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/delta.js +51 -6
- package/dist/core/delta/delta.js.map +1 -1
- package/dist/core/dependencies/fanin.js +2 -2
- package/dist/core/dependencies/fanin.js.map +1 -1
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +94 -12
- package/dist/core/diff/base-git.js.map +1 -1
- package/dist/core/diff/base-state.js +49 -21
- package/dist/core/diff/base-state.js.map +1 -1
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +22 -6
- package/dist/core/diff/scope/changed-paths.js.map +1 -1
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +100 -31
- package/dist/core/diff/semantic.js.map +1 -1
- package/dist/core/docs.js +31 -22
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +34 -18
- package/dist/core/doctor/agents.js.map +1 -1
- package/dist/core/doctor/config.js +7 -3
- package/dist/core/doctor/config.js.map +1 -1
- package/dist/core/doctor/doctor.js +91 -11
- package/dist/core/doctor/doctor.js.map +1 -1
- package/dist/core/doctor/report.js.map +1 -1
- package/dist/core/doctor/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.js.map +1 -0
- package/dist/core/document/apply.js +158 -11
- package/dist/core/document/apply.js.map +1 -1
- package/dist/core/document/frontmatter.js +55 -0
- package/dist/core/document/frontmatter.js.map +1 -1
- package/dist/core/document/parse.js +29 -6
- package/dist/core/document/parse.js.map +1 -1
- package/dist/core/document/scenarios.js +17 -0
- package/dist/core/document/scenarios.js.map +1 -1
- package/dist/core/document/spec.js +4 -11
- package/dist/core/document/spec.js.map +1 -1
- package/dist/core/envelope/config.js +10 -0
- package/dist/core/envelope/config.js.map +1 -1
- package/dist/core/envelope/json.js +34 -0
- package/dist/core/envelope/json.js.map +1 -1
- package/dist/core/explain/families.js +26 -21
- package/dist/core/explain/families.js.map +1 -1
- package/dist/core/explain/lookup.js +14 -1
- package/dist/core/explain/lookup.js.map +1 -1
- package/dist/core/explain/refusals.js +5 -5
- package/dist/core/explain/refusals.js.map +1 -1
- package/dist/core/explain/terms/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +68 -109
- package/dist/core/explain/terms.js.map +1 -1
- package/dist/core/explore/explore.js +40 -10
- package/dist/core/explore/explore.js.map +1 -1
- package/dist/core/fleet-context.js +81 -95
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +11 -4
- package/dist/core/gate/checks.js.map +1 -1
- package/dist/core/gate/partners.js +69 -28
- package/dist/core/gate/partners.js.map +1 -1
- package/dist/core/gate/report.js.map +1 -1
- package/dist/core/gate/verification.js +75 -12
- package/dist/core/gate/verification.js.map +1 -1
- package/dist/core/gherkin/stale.js +13 -37
- package/dist/core/gherkin/stale.js.map +1 -1
- package/dist/core/glossary/delta.js +10 -7
- package/dist/core/glossary/delta.js.map +1 -1
- package/dist/core/glossary/tree.js +6 -19
- package/dist/core/glossary/tree.js.map +1 -1
- package/dist/core/kernel/concurrency.js +19 -0
- package/dist/core/kernel/concurrency.js.map +1 -1
- package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
- package/dist/core/kernel/path-safety.js +38 -0
- package/dist/core/kernel/path-safety.js.map +1 -1
- package/dist/core/kernel/records.js +11 -0
- package/dist/core/kernel/records.js.map +1 -1
- package/dist/core/links/backlinks.js +1 -3
- package/dist/core/links/backlinks.js.map +1 -1
- package/dist/core/links/corpus.js +51 -37
- package/dist/core/links/corpus.js.map +1 -1
- package/dist/core/links/findings.js.map +1 -1
- package/dist/core/links/parse.js +38 -9
- package/dist/core/links/parse.js.map +1 -1
- package/dist/core/mcp/argv.js +101 -0
- package/dist/core/mcp/argv.js.map +1 -1
- package/dist/core/mcp/author-tools.js +2 -1
- package/dist/core/mcp/author-tools.js.map +1 -1
- package/dist/core/mcp/protocol.js +2 -2
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/mcp/tools.js +43 -33
- package/dist/core/mcp/tools.js.map +1 -1
- package/dist/core/openapi/baseline/gate.js +53 -12
- package/dist/core/openapi/baseline/gate.js.map +1 -1
- package/dist/core/openapi/baseline/plan.js +40 -10
- package/dist/core/openapi/baseline/plan.js.map +1 -1
- package/dist/core/openapi/baseline/record.js +0 -1
- package/dist/core/openapi/baseline/record.js.map +1 -1
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +38 -24
- package/dist/core/openapi/depth.js.map +1 -1
- package/dist/core/openapi/digest.js +52 -2
- package/dist/core/openapi/digest.js.map +1 -1
- package/dist/core/openapi/doc.js +12 -4
- package/dist/core/openapi/doc.js.map +1 -1
- package/dist/core/openapi/merge/components.js +25 -60
- package/dist/core/openapi/merge/components.js.map +1 -1
- package/dist/core/openapi/merge/error.js +3 -13
- package/dist/core/openapi/merge/error.js.map +1 -1
- package/dist/core/openapi/merge/markers.js +26 -30
- package/dist/core/openapi/merge/markers.js.map +1 -1
- package/dist/core/openapi/merge/merge.js +28 -52
- package/dist/core/openapi/merge/merge.js.map +1 -1
- package/dist/core/openapi/merge/pin.js +17 -35
- package/dist/core/openapi/merge/pin.js.map +1 -1
- package/dist/core/openspec/decide/verdict.js.map +1 -1
- package/dist/core/openspec/inventory.js +4 -5
- package/dist/core/openspec/inventory.js.map +1 -1
- package/dist/core/openspec/model/mapping.js +30 -28
- package/dist/core/openspec/model/mapping.js.map +1 -1
- package/dist/core/openspec/model/model.js +12 -7
- package/dist/core/openspec/model/model.js.map +1 -1
- package/dist/core/openspec/scan/changes.js +10 -4
- package/dist/core/openspec/scan/changes.js.map +1 -1
- package/dist/core/openspec/scan/config.js +7 -16
- package/dist/core/openspec/scan/config.js.map +1 -1
- package/dist/core/openspec/scan/shape.js +63 -19
- package/dist/core/openspec/scan/shape.js.map +1 -1
- package/dist/core/openspec/scan/walk.js +21 -38
- package/dist/core/openspec/scan/walk.js.map +1 -1
- package/dist/core/pack/living.js +43 -4
- package/dist/core/pack/living.js.map +1 -1
- package/dist/core/pack/pack.js +50 -6
- package/dist/core/pack/pack.js.map +1 -1
- package/dist/core/projection/arch-slice.js +2 -2
- package/dist/core/projection/arch-slice.js.map +1 -1
- package/dist/core/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +48 -12
- package/dist/core/provenance/findings.js.map +1 -1
- package/dist/core/provenance/git.js +33 -57
- package/dist/core/provenance/git.js.map +1 -1
- package/dist/core/provenance/gitq/moves.js +71 -114
- package/dist/core/provenance/gitq/moves.js.map +1 -1
- package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
- package/dist/core/provenance/sources.js +23 -6
- package/dist/core/provenance/sources.js.map +1 -1
- package/dist/core/provenance/stamp.js +5 -17
- package/dist/core/provenance/stamp.js.map +1 -1
- package/dist/core/repo/authored/paths.js +18 -0
- package/dist/core/repo/authored/paths.js.map +1 -1
- package/dist/core/repo/entries.js.map +1 -1
- package/dist/core/repo/paths.js +92 -6
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/repo.js +74 -14
- package/dist/core/repo/repo.js.map +1 -1
- package/dist/core/repo/tree/find.js +12 -3
- package/dist/core/repo/tree/find.js.map +1 -1
- package/dist/core/repo/tree/fs.js +27 -1
- package/dist/core/repo/tree/fs.js.map +1 -1
- package/dist/core/repo/tree/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +53 -32
- package/dist/core/repo/tree/walk.js.map +1 -1
- package/dist/core/results.js +47 -12
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +121 -13
- package/dist/core/scaffold/landscape.js.map +1 -1
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.js.map +1 -0
- package/dist/core/staging/commit.js +26 -15
- package/dist/core/staging/commit.js.map +1 -1
- package/dist/core/staging/lock.js +74 -12
- package/dist/core/staging/lock.js.map +1 -1
- package/dist/core/staging/recovery/intent.js +2 -5
- package/dist/core/staging/recovery/intent.js.map +1 -1
- package/dist/core/staging/recovery/recover.js +84 -6
- package/dist/core/staging/recovery/recover.js.map +1 -1
- package/dist/core/staging/snapshot/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +24 -14
- package/dist/core/staging/txn/forward.js.map +1 -1
- package/dist/core/staging/writes.js.map +1 -1
- package/dist/core/status/actions/execution.js +11 -0
- package/dist/core/status/actions/execution.js.map +1 -1
- package/dist/core/status/contracts.js +39 -15
- package/dist/core/status/contracts.js.map +1 -1
- package/dist/core/status/feature/artifacts.js +33 -8
- package/dist/core/status/feature/artifacts.js.map +1 -1
- package/dist/core/status/feature/feature.js +24 -17
- package/dist/core/status/feature/feature.js.map +1 -1
- package/dist/core/status/feature/next.js +20 -7
- package/dist/core/status/feature/next.js.map +1 -1
- package/dist/core/status/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +43 -14
- package/dist/core/status/fleet/fleet.js.map +1 -1
- package/dist/core/status/fleet/next.js +153 -58
- package/dist/core/status/fleet/next.js.map +1 -1
- package/dist/core/status/report.js.map +1 -1
- package/dist/core/status/scan.js.map +1 -1
- package/dist/core/status/verification.js +30 -15
- package/dist/core/status/verification.js.map +1 -1
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +11 -14
- package/dist/core/usecases/capability.js.map +1 -1
- package/dist/core/usecases/delta/claims.js +31 -7
- package/dist/core/usecases/delta/claims.js.map +1 -1
- package/dist/core/usecases/delta/flows.js +5 -7
- package/dist/core/usecases/delta/flows.js.map +1 -1
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +32 -191
- package/dist/core/usecases/delta/overlay.js.map +1 -1
- package/dist/core/usecases/fleet.js +195 -36
- package/dist/core/usecases/fleet.js.map +1 -1
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +26 -14
- package/dist/core/usecases/operations.js.map +1 -1
- package/dist/core/usecases/place.js.map +1 -1
- package/dist/core/usecases/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/verify/answers.js +12 -5
- package/dist/core/verify/answers.js.map +1 -1
- package/dist/core/verify/build.js +102 -82
- package/dist/core/verify/build.js.map +1 -1
- package/dist/core/verify/checklist.js +70 -12
- package/dist/core/verify/checklist.js.map +1 -1
- package/dist/core/verify/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +3 -2
- package/dist/core/verify/pins/lint.js.map +1 -1
- package/dist/core/verify/pins/pin.js +1 -1
- package/dist/core/verify/pins/pin.js.map +1 -1
- package/dist/core/verify/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/{file.js → read/shape.js} +16 -104
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +35 -12
- package/dist/core/verify/record.js.map +1 -1
- package/dist/core/verify/store/commit.js +40 -30
- package/dist/core/verify/store/commit.js.map +1 -1
- package/dist/core/verify/store/render.js +8 -4
- package/dist/core/verify/store/render.js.map +1 -1
- package/dist/core/vocabulary/issue.js +4 -0
- package/dist/core/vocabulary/issue.js.map +1 -1
- package/dist/core/vocabulary/maturity.js +75 -4
- package/dist/core/vocabulary/maturity.js.map +1 -1
- package/dist/core/vocabulary/report.js +16 -1
- package/dist/core/vocabulary/report.js.map +1 -1
- package/examples/README.md +54 -11
- package/examples/docs/architecture/landscape.likec4 +62 -6
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +7 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
- package/examples/docs/likec4.config.json +0 -1
- package/examples/docs/services/checkout-web/model.likec4 +39 -56
- package/examples/docs/services/order-service/arch.spec.md +13 -6
- package/examples/docs/services/order-service/asyncapi.yaml +3 -2
- package/examples/docs/services/order-service/model.likec4 +58 -70
- package/examples/docs/services/payment-service/arch.spec.md +7 -4
- package/examples/docs/services/payment-service/model.likec4 +38 -37
- package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
- package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
- package/examples/docs/services/platform/notification-service/health.yaml +8 -3
- package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
- package/package.json +1 -1
- package/dist/commands/validate/checks/vocabulary.js +0 -31
- package/dist/commands/validate/checks/vocabulary.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
- package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
- package/dist/core/agent/agents-md/artifacts.js +0 -220
- package/dist/core/agent/agents-md/artifacts.js.map +0 -1
- package/dist/core/agent/agents-md/cycle.js +0 -165
- package/dist/core/agent/agents-md/cycle.js.map +0 -1
- package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
- package/dist/core/agent/agents-md/spine.js +0 -40
- package/dist/core/agent/agents-md/spine.js.map +0 -1
- package/dist/core/coherence/events/merged.js +0 -40
- package/dist/core/coherence/events/merged.js.map +0 -1
- package/dist/core/diff/current-state.js +0 -96
- package/dist/core/diff/current-state.js.map +0 -1
- package/dist/core/diff/victims.js +0 -247
- package/dist/core/diff/victims.js.map +0 -1
- package/dist/core/repo/tree/views.js +0 -172
- package/dist/core/repo/tree/views.js.map +0 -1
- package/dist/core/staging/snapshot.js.map +0 -1
- package/dist/core/verify/file.js.map +0 -1
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Building one service's slice: the delta brief, then a unit at a time —
|
|
3
|
+
* generated gherkin, steps, code, verify.
|
|
4
|
+
*
|
|
5
|
+
* Steps 3-5 are a LOOP, not a sequence, and that is why `loam tasks` sits at
|
|
6
|
+
* the head of them. They used to be three things done in order — generate the
|
|
7
|
+
* suite, write the definitions, implement — which is only the right order for a
|
|
8
|
+
* slice whose every requirement already owns a scenario. Where one does not,
|
|
9
|
+
* the next thing owed is a sentence in the docs repo, and the body had no step
|
|
10
|
+
* that could say so; where the suite is half written, nothing here answered
|
|
11
|
+
* which half. `at` answers both: the projection names which of four states the
|
|
12
|
+
* next unit is in, and each state names exactly one action, so the numbering
|
|
13
|
+
* below is a table of destinations rather than an itinerary. An editor adding a
|
|
14
|
+
* step must therefore say which `at` value routes to it, or it is unreachable.
|
|
15
|
+
*/
|
|
2
16
|
export const LOAM_IMPLEMENT = {
|
|
3
17
|
name: "loam-implement",
|
|
4
18
|
description: "Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code",
|
|
@@ -10,6 +24,7 @@ export const LOAM_IMPLEMENT = {
|
|
|
10
24
|
"`loam status` — where this feature actually is, and what is owed before you start",
|
|
11
25
|
"`loam context` — the briefing: the service's living slice, and every delta in flight over it",
|
|
12
26
|
"`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out",
|
|
27
|
+
"`loam tasks` — the open units, ordered; `--next` is the single next unit, with the scenario verbatim and the fact that closes it",
|
|
13
28
|
"`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them",
|
|
14
29
|
"write step definitions for the generated scenarios first, outside the generated directory",
|
|
15
30
|
"implement until the suite passes, running it with a JSON report",
|
|
@@ -18,7 +33,8 @@ export const LOAM_IMPLEMENT = {
|
|
|
18
33
|
],
|
|
19
34
|
body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own
|
|
20
35
|
repository, which needs its own committed ./loam.json — if there is none,
|
|
21
|
-
\`loam init --docs <path-to-docs-repo> --service $2
|
|
36
|
+
\`loam init --docs <path-to-docs-repo> --service $2 --agent-profile service\` then
|
|
37
|
+
\`loam doctor\` first.
|
|
22
38
|
|
|
23
39
|
0. \`loam status $1 --json\` — where this feature actually is. Run it before
|
|
24
40
|
anything else if you joined halfway or lost the session: it says which
|
|
@@ -59,12 +75,65 @@ repository, which needs its own committed ./loam.json — if there is none,
|
|
|
59
75
|
document before building anything — for the delta, \`loam validate $1 --json\` names
|
|
60
76
|
the error; the contract delta is not graded by validate, so read the parser message
|
|
61
77
|
the payload carries.
|
|
62
|
-
3.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
3. \`loam tasks $1 --service $2 --next --json\` — ONE unit of work, and the loop
|
|
79
|
+
every step below runs inside. Step 2 is the whole brief; this is the next thing
|
|
80
|
+
to do in it. It writes nothing: the projection is derived from the verify
|
|
81
|
+
checklist, the delta scans, the feature's verification record and — in this,
|
|
82
|
+
the bound service repo — the digest stamps in the generated \`.feature\` files.
|
|
83
|
+
Drop \`--next\` to see every open unit instead of only the head.
|
|
84
|
+
Each entry of \`units[]\` carries its \`id\` (the same id the verify checklist uses
|
|
85
|
+
for that claim), \`kind\` (\`service.exists\`, \`api.exposes\`, \`event.declares\`,
|
|
86
|
+
\`c4.calls\`, \`scenario.tested\` or \`requirement.described\`), \`subject\`, \`claim\`,
|
|
87
|
+
\`digest\`, \`dependsOn\`, \`source\` — the path, line, requirement and scenario it was
|
|
88
|
+
derived from, with the scenario's own \`lines\` verbatim — and \`done.check\`.
|
|
89
|
+
|
|
90
|
+
\`at\` is the instruction. It says what the unit NEEDS, and each of its four
|
|
91
|
+
values names exactly one action:
|
|
92
|
+
- \`describe\` — the requirement owns no scenarios yet. Write the Given/When/Then
|
|
93
|
+
in the DOCS repo, on the requirement \`source\` names, and nothing else. loam
|
|
94
|
+
does not author, and no amount of code closes a unit sitting here.
|
|
95
|
+
- \`generate\` — no stamped \`.feature\` carries this scenario's digest. The only
|
|
96
|
+
action is \`loam gherkin $1\` in this repo (step 4). Do not write code.
|
|
97
|
+
- \`implement\` — the stamped scenario exists and no recorded run has confirmed
|
|
98
|
+
it. Write step definitions outside \`loam/\`, implement until the suite passes,
|
|
99
|
+
then \`loam verify $1 --service $2 --results report.json\` (step 5).
|
|
100
|
+
- \`attested\` — the claim was closed on somebody's word rather than on a run.
|
|
101
|
+
Run the suite and re-record it so it stops resting on an assertion. An
|
|
102
|
+
agent-attested scenario stays visible at \`attested\` forever, deliberately: it
|
|
103
|
+
is the one state that cannot be made to go away by ignoring it.
|
|
104
|
+
|
|
105
|
+
\`done.check\` is the FACT that closes the unit, and the RUNNER decides whether
|
|
106
|
+
that fact holds — never your own reading of the code you just wrote. Done means
|
|
107
|
+
the unit no longer appears, and it stops appearing only once its claim is
|
|
108
|
+
recorded confirmed in a verification record that is not stale. So re-run
|
|
109
|
+
\`loam tasks $1 --service $2 --json\` after every recording instead of working
|
|
110
|
+
down a list you copied out: \`frontier\` (the first ten open unit ids, in order)
|
|
111
|
+
and \`counts\` (\`open\`, \`done\`, \`attested\`) are recomputed from the documents on
|
|
112
|
+
every run, which is what makes taking the head of it always safe.
|
|
113
|
+
\`checklist\` is the digest of the question set the whole projection derives from.
|
|
114
|
+
If it differs from the one you started against, the question set moved under
|
|
115
|
+
you — re-read the feature before continuing, because what you closed earlier may
|
|
116
|
+
not be what is being asked now.
|
|
117
|
+
\`record\` says whether the answers were found at all (\`absent\`, \`recorded\`,
|
|
118
|
+
\`stale\`, \`unreadable\`) and \`stamps\` whether this repo's generated suite could be
|
|
119
|
+
read (\`read\`, \`unknown\`); an \`unknown\` makes every \`generate\` verdict a guess,
|
|
120
|
+
so fix the binding before acting on one. \`contracts\` restates step 6 as data
|
|
121
|
+
(\`expose[]\` and \`call[]\`), \`size\` the shape of the packet, \`review[]\` what a
|
|
122
|
+
reviewer of it will read, and \`waitingOn\` — whenever the packet is narrowed to one
|
|
123
|
+
service: by \`--service\`, or without it to this repo's own service when the feature
|
|
124
|
+
touches it — what another service still owes before your frontier can move.
|
|
125
|
+
Exit 1 with \`ok: true\` is step 2's rule again: delta.likec4 or one of the
|
|
126
|
+
contract axes did not parse, so the projection is SHORT by everything that
|
|
127
|
+
document would have contributed. Fix the document; do not work the units that
|
|
128
|
+
happened to survive it.
|
|
129
|
+
4. \`at: "generate"\` — in the service's repo, \`loam gherkin $1 --json\`. One
|
|
130
|
+
\`.feature\` file per changed requirement lands under \`<gherkinDir>/loam/\`
|
|
131
|
+
(default \`features/loam/\`), scenarios digest-stamped, arch requirements tagged
|
|
132
|
+
\`@architecture\`. Those files ARE the acceptance criteria. Never edit them:
|
|
133
|
+
regeneration rewrites the directory, and \`loam validate\` reports the suite stale
|
|
134
|
+
by digest, not by your intentions. Generating is the WHOLE action for a unit at
|
|
135
|
+
\`generate\`: go back to step 3, where the same unit now reads \`implement\`.
|
|
136
|
+
5. \`at: "implement"\` — step definitions FIRST, outside \`loam/\`, then the code.
|
|
68
137
|
Do not paraphrase a scenario into something easier to pass; it is the acceptance
|
|
69
138
|
criterion someone else reviews against.
|
|
70
139
|
Run \`loam steps --service $2 --json\` before you write any: it collapses every
|
|
@@ -75,14 +144,26 @@ repository, which needs its own committed ./loam.json — if there is none,
|
|
|
75
144
|
and regenerate, rather than writing the second definition.
|
|
76
145
|
A step's argument arrives as an argument: a \`"""\` docstring is the payload, an
|
|
77
146
|
indented table is a DataTable. Assert against them; do not re-parse the step text.
|
|
78
|
-
|
|
79
|
-
(\`cucumber-js --format json:report.json
|
|
147
|
+
Then implement until the suite passes — run it with a JSON report
|
|
148
|
+
(\`cucumber-js --format json:report.json\`; cucumber-jvm, behave, Reqnroll,
|
|
149
|
+
pytest-bdd \`--cucumberjson\` and godog write the same cucumber JSON):
|
|
80
150
|
\`loam verify $1 --service $2 --results report.json\` consumes that report as the
|
|
81
|
-
done-check's answer sheet.
|
|
151
|
+
done-check's answer sheet. A runner with no cucumber formatter answers through
|
|
152
|
+
loam's runner-neutral shape instead, keyed by each scenario's \`@loam-digest\`
|
|
153
|
+
tag — adapting the runner's report into it is a build step you own:
|
|
154
|
+
\`{"loamScenarioReport": 1, "results": [{"digest": "<16 hex>", "status": "passed"}]}\`.
|
|
155
|
+
A cucumber run must have run every step of the stamped scenario: a report
|
|
156
|
+
entry whose step count differs is not that scenario's run and stays
|
|
157
|
+
unconfirmed. Record from THIS repo, with \`--service\` — the
|
|
82
158
|
\`--service\`-less \`--record\` form writes the whole record from one place and is
|
|
83
|
-
refused (\`record-federated\`) once another service has attested.
|
|
159
|
+
refused (\`record-federated\`) once another service has attested. Recording is what
|
|
160
|
+
closes the unit, so step 3 is the command AFTER it, not the end of the run.
|
|
84
161
|
6. Honour the contract: every operation in \`architecture.inbound\` must exist under
|
|
85
162
|
exactly that operationId, and every one in \`architecture.outbound\` must be called.
|
|
163
|
+
The code you just wrote is evidence about the delta's edges. If an edge the
|
|
164
|
+
feature draws as \`connects\` is in fact a publish, a delivery, a read or a write,
|
|
165
|
+
redraw it in delta.likec4 with that kind (\`loam instructions loam-drawing\`) —
|
|
166
|
+
and step 7 applies, because that is a change to the feature's documents.
|
|
86
167
|
7. If building made you change the feature's documents at all — a requirement's
|
|
87
168
|
wording, an operation in its openapi.yaml — **\`loam rebase $1\`** before you
|
|
88
169
|
validate. Every edit you make in the docs repo while other features are in
|
|
@@ -99,7 +180,9 @@ repository, which needs its own committed ./loam.json — if there is none,
|
|
|
99
180
|
8. \`loam validate --feature $1 --json\` before handing back.
|
|
100
181
|
|
|
101
182
|
If the requirement is ambiguous, say so and stop — do not invent behaviour and
|
|
102
|
-
leave the spec disagreeing with the code.
|
|
183
|
+
leave the spec disagreeing with the code. Write the question under
|
|
184
|
+
\`## Open questions\` in the feature's \`intent.md\`, where loam-feature's analyze
|
|
185
|
+
step put the ones it found, so a person answers it once for every service.
|
|
103
186
|
`,
|
|
104
187
|
};
|
|
105
188
|
//# sourceMappingURL=implement.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/implement.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,sGAAsG;IACxG,YAAY,EAAE,qBAAqB;IACnC,OAAO,EACL,oMAAoM;IACtM,UAAU,EAAE,wCAAwC;IACpD,YAAY,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACpC,KAAK,EAAE;QACL,mFAAmF;QACnF,8FAA8F;QAC9F,0GAA0G;QAC1G,6FAA6F;QAC7F,2FAA2F;QAC3F,iEAAiE;QACjE,iGAAiG;QACjG,qGAAqG;KACtG;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/** Building one service's slice: the delta brief, generated gherkin, steps, code, verify. */\nexport const LOAM_IMPLEMENT: CommandContent = {\n name: \"loam-implement\",\n description:\n \"Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code\",\n argumentHint: \"<FEAT-id> [service]\",\n purpose:\n \"Build one service's part of a feature, in that service's own repository. The generated Gherkin is the acceptance criterion — it comes before the step definitions, and those come before the code.\",\n invocation: \"loam instructions loam-implement $1 $2\",\n placeholders: [\"feature\", \"service\"],\n spine: [\n \"`loam status` — where this feature actually is, and what is owed before you start\",\n \"`loam context` — the briefing: the service's living slice, and every delta in flight over it\",\n \"`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out\",\n \"`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them\",\n \"write step definitions for the generated scenarios first, outside the generated directory\",\n \"implement until the suite passes, running it with a JSON report\",\n \"honour the contract in both directions: expose every inbound operation, call every outbound one\",\n \"`loam rebase` if building made you change the feature's documents at all, then validate the feature\",\n ],\n body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own\nrepository, which needs its own committed ./loam.json — if there is none,\n\\`loam init --docs <path-to-docs-repo> --service $2\\` then \\`loam doctor\\` first.\n\n0. \\`loam status $1 --json\\` — where this feature actually is. Run it before\n anything else if you joined halfway or lost the session: it says which\n artifacts are still owed, whether another feature has to archive first, and\n what the next step is, each \\`next[]\\` entry carrying the literal command. It\n writes nothing, so it is always safe to re-run.\n1. \\`loam context $2 --feature $1 --json\\` — the briefing to load before touching\n code: the service's living requirements and arch requirements verbatim, its\n operations and messages as they stand today, the permissions and capabilities\n its requirements join to, the fleet edges around it, and this feature's delta\n over it (\\`--feature $1\\` narrows the in-flight section; drop it to see every\n feature working over this service). The delta below is WHAT CHANGES; the pack\n is what it changes INTO — read it first so a MODIFIED requirement lands as an\n edit rather than a rewrite, and an operation you are about to add is caught\n when the living contract already defines it. Exit 1 with \\`ok: true\\` means a\n document behind the pack did not parse; the empty section beside the flag is\n the parse failure, not \"nothing here\".\n2. \\`loam delta $1 --service $2 --json\\` (drop \\`--service\\` to use the service configured\n in ./loam.json). That output IS the task:\n - \\`intent\\` — why this exists\n - \\`requirements[]\\` — what to build, with \\`scenarios[].lines\\` verbatim\n - \\`archRequirements[]\\` — the architectural obligations (outbox, retries, alerts),\n same shape; their scenarios become integration/ops tests, and \\`covers\\` names\n the model objects each exercises\n - \\`architecture\\` — whether this service is new, and the calls in and out of it\n - \\`api\\` — the endpoints this feature adds or retires for this service: path,\n method, operationId and summary, with removals spelled \\`REMOVE <METHOD> <path>\\`\n - \\`openapi\\` — whether that contract could be read at all: \\`unreadable\\`, plus an\n \\`error\\` when the parser gave a message. It rides beside \\`api\\` rather than\n inside it because \\`api\\` stays the operations array it has always been, and it\n is what tells an empty \\`api\\` apart from a contract delta that did not parse\n - \\`services\\` — every service this feature projects onto, so a run without\n \\`--service\\` tells you which ones to ask for rather than guessing\n Exit 1 with \\`ok: true\\` means one of the two authored documents behind this brief\n did not parse: \\`architecture.errors\\` non-empty (delta.likec4), or\n \\`openapi.unreadable\\` true (the feature's openapi.yaml for this service). The empty\n slice is the parse failure itself, not \"nothing changes there\". Stop and fix that\n document before building anything — for the delta, \\`loam validate $1 --json\\` names\n the error; the contract delta is not graded by validate, so read the parser message\n the payload carries.\n3. In the service's repo, \\`loam gherkin $1 --json\\` — one \\`.feature\\` file per changed\n requirement lands under \\`<gherkinDir>/loam/\\` (default \\`features/loam/\\`), scenarios\n digest-stamped, arch requirements tagged \\`@architecture\\`. Those files ARE the\n acceptance criteria. Never edit them: regeneration rewrites the directory, and\n \\`loam validate\\` reports the suite stale by digest, not by your intentions.\n4. Write step definitions for the generated scenarios FIRST — outside \\`loam/\\`.\n Do not paraphrase a scenario into something easier to pass; it is the acceptance\n criterion someone else reviews against.\n Run \\`loam steps --service $2 --json\\` before you write any: it collapses every\n written step onto the phrase a definition actually matches, so you see the size\n of the registry you owe and which phrases already exist. Write ONE definition per\n phrase row. If \\`nearDuplicates\\` is non-empty, two rows differ by an article or a\n trailing \\`because …\\` clause and one definition was meant — fix the SPEC's wording\n and regenerate, rather than writing the second definition.\n A step's argument arrives as an argument: a \\`\"\"\"\\` docstring is the payload, an\n indented table is a DataTable. Assert against them; do not re-parse the step text.\n5. Implement until the suite passes — run it with a JSON report\n (\\`cucumber-js --format json:report.json\\`):\n \\`loam verify $1 --service $2 --results report.json\\` consumes that report as the\n done-check's answer sheet. Record from THIS repo, with \\`--service\\` — the\n \\`--service\\`-less \\`--record\\` form writes the whole record from one place and is\n refused (\\`record-federated\\`) once another service has attested.\n6. Honour the contract: every operation in \\`architecture.inbound\\` must exist under\n exactly that operationId, and every one in \\`architecture.outbound\\` must be called.\n7. If building made you change the feature's documents at all — a requirement's\n wording, an operation in its openapi.yaml — **\\`loam rebase $1\\`** before you\n validate. Every edit you make in the docs repo while other features are in\n flight is written against a living document that may have moved since the\n feature directory was created, and the pins are the only thing that lets the\n merge tell an EDIT from a QUOTE — for operations, path-level keys and\n components alike. \\`delta.baseline-missing\\` and\n \\`openapi.baseline-missing\\` are the warnings that say you skipped it — archive\n refuses on them until you rebase (or a human \\`--approve\\`s the unpinned merge);\n \\`delta.baseline-stale\\` / \\`openapi.baseline-stale\\` are archive refusing because\n somebody landed a change underneath you — re-read theirs, fold in what you\n still mean, then rebase again. Re-pinning without re-reading is how you\n overwrite someone else's requirement with loam's blessing.\n8. \\`loam validate --feature $1 --json\\` before handing back.\n\nIf the requirement is ambiguous, say so and stop — do not invent behaviour and\nleave the spec disagreeing with the code.\n`,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/implement.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,sGAAsG;IACxG,YAAY,EAAE,qBAAqB;IACnC,OAAO,EACL,oMAAoM;IACtM,UAAU,EAAE,wCAAwC;IACpD,YAAY,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACpC,KAAK,EAAE;QACL,mFAAmF;QACnF,8FAA8F;QAC9F,0GAA0G;QAC1G,kIAAkI;QAClI,6FAA6F;QAC7F,2FAA2F;QAC3F,iEAAiE;QACjE,iGAAiG;QACjG,qGAAqG;KACtG;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwJP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/**\n * Building one service's slice: the delta brief, then a unit at a time —\n * generated gherkin, steps, code, verify.\n *\n * Steps 3-5 are a LOOP, not a sequence, and that is why `loam tasks` sits at\n * the head of them. They used to be three things done in order — generate the\n * suite, write the definitions, implement — which is only the right order for a\n * slice whose every requirement already owns a scenario. Where one does not,\n * the next thing owed is a sentence in the docs repo, and the body had no step\n * that could say so; where the suite is half written, nothing here answered\n * which half. `at` answers both: the projection names which of four states the\n * next unit is in, and each state names exactly one action, so the numbering\n * below is a table of destinations rather than an itinerary. An editor adding a\n * step must therefore say which `at` value routes to it, or it is unreachable.\n */\nexport const LOAM_IMPLEMENT: CommandContent = {\n name: \"loam-implement\",\n description:\n \"Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code\",\n argumentHint: \"<FEAT-id> [service]\",\n purpose:\n \"Build one service's part of a feature, in that service's own repository. The generated Gherkin is the acceptance criterion — it comes before the step definitions, and those come before the code.\",\n invocation: \"loam instructions loam-implement $1 $2\",\n placeholders: [\"feature\", \"service\"],\n spine: [\n \"`loam status` — where this feature actually is, and what is owed before you start\",\n \"`loam context` — the briefing: the service's living slice, and every delta in flight over it\",\n \"`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out\",\n \"`loam tasks` — the open units, ordered; `--next` is the single next unit, with the scenario verbatim and the fact that closes it\",\n \"`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them\",\n \"write step definitions for the generated scenarios first, outside the generated directory\",\n \"implement until the suite passes, running it with a JSON report\",\n \"honour the contract in both directions: expose every inbound operation, call every outbound one\",\n \"`loam rebase` if building made you change the feature's documents at all, then validate the feature\",\n ],\n body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own\nrepository, which needs its own committed ./loam.json — if there is none,\n\\`loam init --docs <path-to-docs-repo> --service $2 --agent-profile service\\` then\n\\`loam doctor\\` first.\n\n0. \\`loam status $1 --json\\` — where this feature actually is. Run it before\n anything else if you joined halfway or lost the session: it says which\n artifacts are still owed, whether another feature has to archive first, and\n what the next step is, each \\`next[]\\` entry carrying the literal command. It\n writes nothing, so it is always safe to re-run.\n1. \\`loam context $2 --feature $1 --json\\` — the briefing to load before touching\n code: the service's living requirements and arch requirements verbatim, its\n operations and messages as they stand today, the permissions and capabilities\n its requirements join to, the fleet edges around it, and this feature's delta\n over it (\\`--feature $1\\` narrows the in-flight section; drop it to see every\n feature working over this service). The delta below is WHAT CHANGES; the pack\n is what it changes INTO — read it first so a MODIFIED requirement lands as an\n edit rather than a rewrite, and an operation you are about to add is caught\n when the living contract already defines it. Exit 1 with \\`ok: true\\` means a\n document behind the pack did not parse; the empty section beside the flag is\n the parse failure, not \"nothing here\".\n2. \\`loam delta $1 --service $2 --json\\` (drop \\`--service\\` to use the service configured\n in ./loam.json). That output IS the task:\n - \\`intent\\` — why this exists\n - \\`requirements[]\\` — what to build, with \\`scenarios[].lines\\` verbatim\n - \\`archRequirements[]\\` — the architectural obligations (outbox, retries, alerts),\n same shape; their scenarios become integration/ops tests, and \\`covers\\` names\n the model objects each exercises\n - \\`architecture\\` — whether this service is new, and the calls in and out of it\n - \\`api\\` — the endpoints this feature adds or retires for this service: path,\n method, operationId and summary, with removals spelled \\`REMOVE <METHOD> <path>\\`\n - \\`openapi\\` — whether that contract could be read at all: \\`unreadable\\`, plus an\n \\`error\\` when the parser gave a message. It rides beside \\`api\\` rather than\n inside it because \\`api\\` stays the operations array it has always been, and it\n is what tells an empty \\`api\\` apart from a contract delta that did not parse\n - \\`services\\` — every service this feature projects onto, so a run without\n \\`--service\\` tells you which ones to ask for rather than guessing\n Exit 1 with \\`ok: true\\` means one of the two authored documents behind this brief\n did not parse: \\`architecture.errors\\` non-empty (delta.likec4), or\n \\`openapi.unreadable\\` true (the feature's openapi.yaml for this service). The empty\n slice is the parse failure itself, not \"nothing changes there\". Stop and fix that\n document before building anything — for the delta, \\`loam validate $1 --json\\` names\n the error; the contract delta is not graded by validate, so read the parser message\n the payload carries.\n3. \\`loam tasks $1 --service $2 --next --json\\` — ONE unit of work, and the loop\n every step below runs inside. Step 2 is the whole brief; this is the next thing\n to do in it. It writes nothing: the projection is derived from the verify\n checklist, the delta scans, the feature's verification record and — in this,\n the bound service repo — the digest stamps in the generated \\`.feature\\` files.\n Drop \\`--next\\` to see every open unit instead of only the head.\n Each entry of \\`units[]\\` carries its \\`id\\` (the same id the verify checklist uses\n for that claim), \\`kind\\` (\\`service.exists\\`, \\`api.exposes\\`, \\`event.declares\\`,\n \\`c4.calls\\`, \\`scenario.tested\\` or \\`requirement.described\\`), \\`subject\\`, \\`claim\\`,\n \\`digest\\`, \\`dependsOn\\`, \\`source\\` — the path, line, requirement and scenario it was\n derived from, with the scenario's own \\`lines\\` verbatim — and \\`done.check\\`.\n\n \\`at\\` is the instruction. It says what the unit NEEDS, and each of its four\n values names exactly one action:\n - \\`describe\\` — the requirement owns no scenarios yet. Write the Given/When/Then\n in the DOCS repo, on the requirement \\`source\\` names, and nothing else. loam\n does not author, and no amount of code closes a unit sitting here.\n - \\`generate\\` — no stamped \\`.feature\\` carries this scenario's digest. The only\n action is \\`loam gherkin $1\\` in this repo (step 4). Do not write code.\n - \\`implement\\` — the stamped scenario exists and no recorded run has confirmed\n it. Write step definitions outside \\`loam/\\`, implement until the suite passes,\n then \\`loam verify $1 --service $2 --results report.json\\` (step 5).\n - \\`attested\\` — the claim was closed on somebody's word rather than on a run.\n Run the suite and re-record it so it stops resting on an assertion. An\n agent-attested scenario stays visible at \\`attested\\` forever, deliberately: it\n is the one state that cannot be made to go away by ignoring it.\n\n \\`done.check\\` is the FACT that closes the unit, and the RUNNER decides whether\n that fact holds — never your own reading of the code you just wrote. Done means\n the unit no longer appears, and it stops appearing only once its claim is\n recorded confirmed in a verification record that is not stale. So re-run\n \\`loam tasks $1 --service $2 --json\\` after every recording instead of working\n down a list you copied out: \\`frontier\\` (the first ten open unit ids, in order)\n and \\`counts\\` (\\`open\\`, \\`done\\`, \\`attested\\`) are recomputed from the documents on\n every run, which is what makes taking the head of it always safe.\n \\`checklist\\` is the digest of the question set the whole projection derives from.\n If it differs from the one you started against, the question set moved under\n you — re-read the feature before continuing, because what you closed earlier may\n not be what is being asked now.\n \\`record\\` says whether the answers were found at all (\\`absent\\`, \\`recorded\\`,\n \\`stale\\`, \\`unreadable\\`) and \\`stamps\\` whether this repo's generated suite could be\n read (\\`read\\`, \\`unknown\\`); an \\`unknown\\` makes every \\`generate\\` verdict a guess,\n so fix the binding before acting on one. \\`contracts\\` restates step 6 as data\n (\\`expose[]\\` and \\`call[]\\`), \\`size\\` the shape of the packet, \\`review[]\\` what a\n reviewer of it will read, and \\`waitingOn\\` — whenever the packet is narrowed to one\n service: by \\`--service\\`, or without it to this repo's own service when the feature\n touches it — what another service still owes before your frontier can move.\n Exit 1 with \\`ok: true\\` is step 2's rule again: delta.likec4 or one of the\n contract axes did not parse, so the projection is SHORT by everything that\n document would have contributed. Fix the document; do not work the units that\n happened to survive it.\n4. \\`at: \"generate\"\\` — in the service's repo, \\`loam gherkin $1 --json\\`. One\n \\`.feature\\` file per changed requirement lands under \\`<gherkinDir>/loam/\\`\n (default \\`features/loam/\\`), scenarios digest-stamped, arch requirements tagged\n \\`@architecture\\`. Those files ARE the acceptance criteria. Never edit them:\n regeneration rewrites the directory, and \\`loam validate\\` reports the suite stale\n by digest, not by your intentions. Generating is the WHOLE action for a unit at\n \\`generate\\`: go back to step 3, where the same unit now reads \\`implement\\`.\n5. \\`at: \"implement\"\\` — step definitions FIRST, outside \\`loam/\\`, then the code.\n Do not paraphrase a scenario into something easier to pass; it is the acceptance\n criterion someone else reviews against.\n Run \\`loam steps --service $2 --json\\` before you write any: it collapses every\n written step onto the phrase a definition actually matches, so you see the size\n of the registry you owe and which phrases already exist. Write ONE definition per\n phrase row. If \\`nearDuplicates\\` is non-empty, two rows differ by an article or a\n trailing \\`because …\\` clause and one definition was meant — fix the SPEC's wording\n and regenerate, rather than writing the second definition.\n A step's argument arrives as an argument: a \\`\"\"\"\\` docstring is the payload, an\n indented table is a DataTable. Assert against them; do not re-parse the step text.\n Then implement until the suite passes — run it with a JSON report\n (\\`cucumber-js --format json:report.json\\`; cucumber-jvm, behave, Reqnroll,\n pytest-bdd \\`--cucumberjson\\` and godog write the same cucumber JSON):\n \\`loam verify $1 --service $2 --results report.json\\` consumes that report as the\n done-check's answer sheet. A runner with no cucumber formatter answers through\n loam's runner-neutral shape instead, keyed by each scenario's \\`@loam-digest\\`\n tag — adapting the runner's report into it is a build step you own:\n \\`{\"loamScenarioReport\": 1, \"results\": [{\"digest\": \"<16 hex>\", \"status\": \"passed\"}]}\\`.\n A cucumber run must have run every step of the stamped scenario: a report\n entry whose step count differs is not that scenario's run and stays\n unconfirmed. Record from THIS repo, with \\`--service\\` — the\n \\`--service\\`-less \\`--record\\` form writes the whole record from one place and is\n refused (\\`record-federated\\`) once another service has attested. Recording is what\n closes the unit, so step 3 is the command AFTER it, not the end of the run.\n6. Honour the contract: every operation in \\`architecture.inbound\\` must exist under\n exactly that operationId, and every one in \\`architecture.outbound\\` must be called.\n The code you just wrote is evidence about the delta's edges. If an edge the\n feature draws as \\`connects\\` is in fact a publish, a delivery, a read or a write,\n redraw it in delta.likec4 with that kind (\\`loam instructions loam-drawing\\`) —\n and step 7 applies, because that is a change to the feature's documents.\n7. If building made you change the feature's documents at all — a requirement's\n wording, an operation in its openapi.yaml — **\\`loam rebase $1\\`** before you\n validate. Every edit you make in the docs repo while other features are in\n flight is written against a living document that may have moved since the\n feature directory was created, and the pins are the only thing that lets the\n merge tell an EDIT from a QUOTE — for operations, path-level keys and\n components alike. \\`delta.baseline-missing\\` and\n \\`openapi.baseline-missing\\` are the warnings that say you skipped it — archive\n refuses on them until you rebase (or a human \\`--approve\\`s the unpinned merge);\n \\`delta.baseline-stale\\` / \\`openapi.baseline-stale\\` are archive refusing because\n somebody landed a change underneath you — re-read theirs, fold in what you\n still mean, then rebase again. Re-pinning without re-reading is how you\n overwrite someone else's requirement with loam's blessing.\n8. \\`loam validate --feature $1 --json\\` before handing back.\n\nIf the requirement is ambiguous, say so and stop — do not invent behaviour and\nleave the spec disagreeing with the code. Write the question under\n\\`## Open questions\\` in the feature's \\`intent.md\\`, where loam-feature's analyze\nstep put the ones it found, so a person answers it once for every service.\n`,\n};\n"]}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
export const LOAM_AUTHORING = {
|
|
2
2
|
name: "loam-authoring",
|
|
3
|
-
description: "Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter",
|
|
3
|
+
description: "Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter, and writing a feature a person can follow",
|
|
4
4
|
// No arguments: one document, printed whole. See ./spine.ts for why the hint
|
|
5
5
|
// is empty rather than a spelled-out "<none>".
|
|
6
6
|
argumentHint: "",
|
|
7
|
-
purpose: "What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite,
|
|
7
|
+
purpose: "What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, the frontmatter fields `loam vouch` stamps, and how to write a feature's documents so a reviewer can follow them.",
|
|
8
8
|
invocation: "loam instructions loam-authoring",
|
|
9
9
|
placeholders: [],
|
|
10
10
|
spine: [
|
|
11
11
|
"The architecture spec axis",
|
|
12
12
|
"The generated Gherkin suite",
|
|
13
13
|
"Frontmatter — who vouched for this, and from what",
|
|
14
|
+
"Writing for a person",
|
|
14
15
|
],
|
|
15
|
-
body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, and
|
|
16
|
+
body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, frontmatter, and writing a feature a person can follow.
|
|
16
17
|
|
|
17
18
|
## The architecture spec axis
|
|
18
19
|
|
|
@@ -161,7 +162,9 @@ the forgery — editing a spec after it was vouched used to leave \`status: veri
|
|
|
161
162
|
standing over words nobody read. \`loam validate\` recomputes it wherever it can
|
|
162
163
|
read the doc (no service repo needed, so it fires from the docs repo too) and
|
|
163
164
|
reports \`content.stale\` (warn): only a person can say whether verified still
|
|
164
|
-
holds of the new words.
|
|
165
|
+
holds of the new words. The fleet readouts say the same: \`loam list\` shows
|
|
166
|
+
\`vouched (stale)\` and owes the row a re-vouch, and \`loam status\` emits
|
|
167
|
+
\`next.revouch\` — a step for a person, never for you.
|
|
165
168
|
|
|
166
169
|
\`vouch_scope\` appears only when the person vouched after reading a SAMPLE of the
|
|
167
170
|
document — \`loam vouch --sample <n>\`, whose whole purpose is that a partial read
|
|
@@ -204,6 +207,105 @@ exists for a person's own scripted run; typing it on someone's behalf is
|
|
|
204
207
|
writing their name. The generated command and skill files pre-approve loam's
|
|
205
208
|
read-only and authoring verbs one by one and deliberately not this one: when
|
|
206
209
|
the work is done, hand back and say a vouch is owed.
|
|
210
|
+
|
|
211
|
+
## Writing for a person
|
|
212
|
+
|
|
213
|
+
A feature is read by a reviewer before anyone builds it, and its requirements
|
|
214
|
+
are read for years after \`loam archive\` copies them into the living docs. loam
|
|
215
|
+
grades the joins and never the prose, so nothing in this section is checked: a
|
|
216
|
+
delta can validate clean and still be one nobody can follow.
|
|
217
|
+
|
|
218
|
+
**intent.md** opens with the problem in business terms — \`## Why\` and
|
|
219
|
+
\`## Scope\`, the two sections the archive gate reads — and then carries the three
|
|
220
|
+
things a reviewer looks for first:
|
|
221
|
+
|
|
222
|
+
- \`## How to read this feature\`: two or three sentences saying which services
|
|
223
|
+
change, which document to open first, and which picture shows the change (the
|
|
224
|
+
delta's own view, or a flow under the feature's \`usecases/\`).
|
|
225
|
+
- a business-requirement coverage table, one row per business requirement the
|
|
226
|
+
feature was asked to meet, naming what keeps it:
|
|
227
|
+
|
|
228
|
+
| Business requirement | Kept by | Where |
|
|
229
|
+
|---|---|---|
|
|
230
|
+
| A customer can split one payment between two cards | PAY-SPLIT-1 | payment-split-service spec.md |
|
|
231
|
+
| Every payee gets a receipt | uc_split_receipt | usecases/split-receipt.likec4 |
|
|
232
|
+
|
|
233
|
+
- \`## Open questions\` (the scaffold already writes the heading) as a table, so
|
|
234
|
+
that a person can answer each question and a reader can see what each blocks:
|
|
235
|
+
|
|
236
|
+
| ID | Question | Blocks | Owner | Current default |
|
|
237
|
+
|---|---|---|---|---|
|
|
238
|
+
| Q1 | Is a split refunded per card or as a whole? | PAY-SPLIT-3 | payments-team | per card |
|
|
239
|
+
|
|
240
|
+
The current default is what gets built if nobody answers, so write one for
|
|
241
|
+
every question.
|
|
242
|
+
|
|
243
|
+
**Each spec delta opens with a plain-language \`## Purpose\`**: what the service
|
|
244
|
+
does in this change, written for someone who has never opened its code. Where
|
|
245
|
+
the delta CREATES the living document — a new service's spec.md, a first
|
|
246
|
+
arch.spec.md, a new capability — \`loam archive\` copies that section into the
|
|
247
|
+
new document as its narrative. Where the living document already exists, the
|
|
248
|
+
section stays with the archived delta, and the archive plan says so on that
|
|
249
|
+
file's line; if the service's own narrative should change, edit the living
|
|
250
|
+
document in the same change.
|
|
251
|
+
|
|
252
|
+
**Write a long requirement body as a lead and bullets.** A new requirement
|
|
253
|
+
states one behaviour. A requirement carried over from another source often
|
|
254
|
+
arrives as one paragraph of SHALL sentences. Keep every sentence, but open with
|
|
255
|
+
one line that says what the requirement is for, and give each SHALL sentence a
|
|
256
|
+
bullet of its own:
|
|
257
|
+
|
|
258
|
+
### Requirement: Split a payment
|
|
259
|
+
Requirement-ID: PAY-SPLIT-1
|
|
260
|
+
|
|
261
|
+
A payment can be divided between several payees.
|
|
262
|
+
|
|
263
|
+
- The service SHALL accept between two and five payees per split.
|
|
264
|
+
- The service SHALL reject a split whose shares do not add up to the authorized amount.
|
|
265
|
+
|
|
266
|
+
**Expand every abbreviation the first time a document uses it**, in words a new
|
|
267
|
+
reader knows: "service-level objective (SLO)", then "SLO".
|
|
268
|
+
|
|
269
|
+
**Keep review-time wording out of what the archive copies.** "This delta", "this
|
|
270
|
+
feature", "the new endpoint" and "we now" read correctly in review. But
|
|
271
|
+
\`loam archive\` copies requirement bodies, scenarios and contract descriptions
|
|
272
|
+
into living documents, where "this feature" points at a pull request that merged
|
|
273
|
+
long ago. Write what the service does, not what the change does. Prose about the
|
|
274
|
+
change belongs in \`intent.md\`, which stays with the feature.
|
|
275
|
+
|
|
276
|
+
**A feature's vocabulary, decisions and flows travel with it.**
|
|
277
|
+
|
|
278
|
+
- A word the feature brings is \`features/<FEAT>/glossary/<term>.md\`, which the
|
|
279
|
+
archive copies into \`glossary/\`. A term the living glossary already defines is
|
|
280
|
+
edited there instead, because the copy never overwrites
|
|
281
|
+
(\`glossary.term-exists\`).
|
|
282
|
+
- A decision is \`features/<FEAT>/adrs/NNNN-<slug>.md\`. It stays with the
|
|
283
|
+
feature under \`features/archive/\`, and the living documents that link to it go
|
|
284
|
+
on resolving. A decision meant to outlive the change belongs in
|
|
285
|
+
\`architecture/adrs/\` or the service's own \`adrs/\` instead.
|
|
286
|
+
- A flow that keeps a promise across services is
|
|
287
|
+
\`features/<FEAT>/usecases/<name>.likec4\`: a \`dynamic view\` tagged
|
|
288
|
+
\`#cap-<capability>\`, naming a capability the fleet declares, and
|
|
289
|
+
\`#req-<Requirement-ID>\`, naming the promise it keeps. A promise the feature's
|
|
290
|
+
own capability delta adds resolves too. \`usecase.capability-unresolved\` and
|
|
291
|
+
\`usecase.requirement-unresolved\` grade both tags before the archive.
|
|
292
|
+
|
|
293
|
+
Link to all three from the deltas, written relative to the file you write in:
|
|
294
|
+
\`loam archive\` re-points every link into the feature for the move.
|
|
295
|
+
|
|
296
|
+
**Write a \`Covers:\` edge by service name**:
|
|
297
|
+
\`Covers: order-service -> payment-service\`. An edge spelled by its endpoints'
|
|
298
|
+
service names resolves the same before and after the archive. A delta's own
|
|
299
|
+
element id may not, and \`covers.unknown\` at feature scope says when it would not.
|
|
300
|
+
A kinded spelling such as \`order-service -[calls]-> payment-service\` is accepted,
|
|
301
|
+
but the kind is read past rather than compared: it covers every edge from the
|
|
302
|
+
first service to the second, whatever its kind. So write the plain arrow.
|
|
303
|
+
|
|
304
|
+
**Draw a producer outside the fleet as an \`#external\` element**, with the edge
|
|
305
|
+
it publishes on carrying \`metadata { publishes }\`, so that the consumer's
|
|
306
|
+
\`Consumes:\` line has a producer to join to. \`loam instructions loam-spine\`
|
|
307
|
+
("A message produced outside the fleet") has the join, and
|
|
308
|
+
\`loam instructions loam-drawing\` has the drawing.
|
|
207
309
|
`,
|
|
208
310
|
};
|
|
209
311
|
//# sourceMappingURL=authoring.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authoring.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/authoring.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,qGAAqG;IACvG,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,0MAA0M;IAC5M,UAAU,EAAE,kCAAkC;IAC9C,YAAY,EAAE,EAAE;IAChB,KAAK,EAAE;QACL,4BAA4B;QAC5B,6BAA6B;QAC7B,mDAAmD;KACpD;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgMP;CACA,CAAC","sourcesContent":["/**\n * The `loam-authoring` reference page: the grammars of the documents you write.\n *\n * The architecture spec axis (`arch.spec.md` and its `Covers:` line), the\n * generated Gherkin suite, and the frontmatter/vouch chain that ties a\n * document to the code it was written from.\n *\n * All three are consulted at a moment you can name — while authoring one file\n * — and none of them is needed to form the question. That is the split this\n * page exists to make; ./reference.ts records why it had to be made at all.\n *\n * The text is the three AGENTS.md sections verbatim, in their original order,\n * so a cross-reference elsewhere in the corpus still names the same headings.\n */\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_AUTHORING: CommandContent = {\n name: \"loam-authoring\",\n description:\n \"Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, and the frontmatter fields `loam vouch` stamps.\",\n invocation: \"loam instructions loam-authoring\",\n placeholders: [],\n spine: [\n \"The architecture spec axis\",\n \"The generated Gherkin suite\",\n \"Frontmatter — who vouched for this, and from what\",\n ],\n body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, and frontmatter.\n\n## The architecture spec axis\n\nThe business spec will never mention the transactional outbox — that is\narchitecture. Retries, idempotency, metrics, alerts: real obligations no business\nscenario states, and exactly where generated code cuts corners unless the\nobligations are derived mechanically. They live in \\`arch.spec.md\\` — living and\ndelta, same grammar, same delta algebra, merged by \\`loam archive\\` through the\nsame code path (the two files are separate requirement namespaces).\n\nWhere a business requirement carries \\`Operations:\\`, an arch requirement carries\n\\`Covers:\\` — the model objects its scenarios exercise, comma-separated:\n\n\\`\\`\\`\nCovers: paymentService.db, paymentService -> kafka, alert:payment_5xx, sli:availability\n\\`\\`\\`\n\na C4 element (id, or the service a bound element stands for), an edge\n(\\`source -> target\\`), or a health signal the service's health.yaml declares.\nEvery entry must resolve — \\`covers.unknown\\` (warn) is the typo guard, because a\nmistyped entry silently costs the coverage it was written for.\n\nCoverage is then derived, never trusted, as two warnings: a feature's NEW tagged\nelements and edges want a covering requirement in its arch.spec.md deltas\n(\\`c4.uncovered\\`), and every alert/SLI health.yaml declares wants one in the\nliving arch spec (\\`health.uncovered\\`). None of this gates \\`loam archive\\`;\n\\`--strict\\` is the CI escalation. An absent arch.spec.md is not a finding —\npartial adoption is supported — but write one for any service with real\narchitecture, or its obligations ship unchecked.\n\n**Effective configuration and dependency semantics live here too, by\nconvention.** Facts about the service that no artifact structurally holds —\nthe value a deploy chart actually sets, the retry budget a client library\nhardcodes (\"retries: -1 is unbounded\"), the delivery or idempotency guarantee\na driver decides — are ARCH REQUIREMENTS: prose with a \\`Covers:\\` line naming\nthe element or edge whose behaviour the fact decides. loam will never verify\nthe values; naming the home is the point. A service whose timeout comes from\nan env var in a chart in another repository is otherwise described by no file\nin this repo, and two adoptions will file the same fact two different ways.\n\n**Test levels, mapped once.** A business scenario is an acceptance test. An arch\nscenario is an integration/ops test — the outbox relay under a dead broker, the\nretry that stays idempotent, the alert rule that actually fires. \\`api.exposes\\`\nis a contract test. Unit tests sit below spec granularity and are your TDD\nconcern, not the specs'.\n\n## The generated Gherkin suite\n\nScenarios are the acceptance criteria, and \\`loam gherkin\\` makes them\nexecutable: real \\`.feature\\` files, written into the SERVICE'S repo — the one\nloam command that writes there, because tests live with the code they gate.\nOutput lands in \\`<gherkinDir>/loam/\\` (\\`gherkinDir\\` is an optional loam.json\nfact, default \\`features\\`), and that \\`loam/\\` subdirectory is loam's own\nderived space — and a committed one: an emission lands through the same lock\nand journal the docs repo's writers use, as \\`loam/.loam-lock\\` and\n\\`loam/.loam-commit\\` dotfiles that exist only while a run is in flight (or\nafter a kill, where the journal is what lets the next run finish the job).\nRegeneration rewrites its scope and deletes its orphans, so\nnever hand-edit inside it — step definitions and hand-written features belong\noutside it, and loam never touches a byte outside \\`loam/\\`.\n\n- \\`loam gherkin FEAT-101\\` — the feature's ADDED/MODIFIED requirements for this\n service, both spec axes. Files carry \\`@FEAT-101\\`; arch-axis files add\n \\`@architecture\\` and are named \\`arch--<slug>.feature\\` — their scenarios are\n integration/ops tests, not acceptance tests.\n- \\`loam gherkin --service <id>\\` (no feature) — the full living suite from\n spec.md + arch.spec.md: the regression skeleton a legacy service gets at\n adoption.\n\nOne file per requirement (\\`Feature:\\` is the requirement name). Bullet lines\nopening with Given/When/Then/And/But — the \\`- **WHEN** ...\\` convention\nincluded — become steps; every other body line is kept as scenario\ndescription. A valid Markdown table AT THE MARGIN becomes the \\`Examples:\\` of\na \\`Scenario Outline\\`; a malformed table stays in the description and is\nreported, because it will run once rather than once per row.\n\nA step takes an ARGUMENT by carrying it INDENTED underneath: an indented table\nbecomes that step's data table (the rows an outbox or a DB table must hold after\nthe pass), a fenced block becomes its docstring, indentation intact (the request\npayload). Indented under a step means this step's rows; at the margin means the\nscenario's cases. A block no step precedes stays description and is reported as\n\\`strandedBlocks\\` — the document reads, and the TEST lost its argument. Each scenario is\ntagged \\`@loam-digest-<16hex>\\`: the same body\nhash \\`loam verify\\` folds into its claim ids, riding into cucumber's JSON\nreport as a tag, so the suite, the claim and the report cannot quietly\ndisagree about what a scenario says. \\`loam validate\n--service <id>\\`, run in the service repo, grades the suite by those digests\n(\\`gherkin.missing\\` / \\`gherkin.stale\\` / \\`gherkin.orphaned\\`, all warn) — the\nfix is always regeneration, never editing a generated file.\n\nThe flow, closed end to end: \\`loam gherkin FEAT-101\\` → \\`loam steps --service\n<id>\\` (the phrase inventory: how many step definitions this suite needs, one\nper phrase row, and which phrases differ only by an article or a trailing\nclause) → write step definitions (outside \\`loam/\\`) → run the suite with a JSON report\n(\\`cucumber-js --format json:report.json\\`) → implement until green →\n\\`loam verify FEAT-101 --service <id> --results report.json [--contract-results contract.json] [--record rest.json]\\`,\nrun in that same service repo. The digest\ntags ride through the runner into the report, so the \\`scenario.tested\\` claims\nare answered mechanically from the passing report rather than anybody's word.\nThis proves which digest-matched report bytes loam accepted; it does not prove\nthe report was produced by executing the attested commit. See\n\\`loam instructions loam-done-check\\` for what \\`--record\\` still covers.\n\n## Frontmatter — who vouched for this, and from what\n\nEvery markdown artifact opens with a YAML block:\n\n\\`\\`\\`yaml\n---\nservice: payment-service # or feature: FEAT-101\nstatus: verified # services: draft -> verified\n # features: proposed -> in_progress -> built -> done\nowner: payments-team\nlast_verified: 2026-07-31 # written by \\`loam vouch\\` — do not hand-edit\nsources: # files/directories in the SERVICE'S repo this was written from — no globs\n - src/main/java/com/shop/payment/\nsources_digest: 6f1c0a… # written by \\`loam vouch\\` — do not hand-edit\ncontent_digest: 9b2f41… # written by \\`loam vouch\\` — do not hand-edit\nsources_files: | # written by \\`loam vouch\\` — do not hand-edit\n 9b2f41… src/main/java/com/shop/payment/Api.java\nvouch_scope: sampled 2/9 seed=1a2b3c4d5e6f7089 # only when the vouch read a SAMPLE\n---\n\\`\\`\\`\n\n\\`sources\\` matters more than it looks. Everything else loam checks is internal\nconsistency — and a corpus can agree with itself perfectly while describing nothing\nthat exists. \\`sources\\` is the one thing tying a document to code: \\`loam validate\\`,\nrun inside that service's repository, checks every listed path is still there.\nEntries are literal files and directories only — a directory covers everything\nbeneath it. Glob patterns are refused loudly (\\`loam vouch\\` will not stamp them,\n\\`loam validate\\` errors on them): a pattern dialect nobody can be sure of digests\na different file set than intended, corrupting the staleness signal silently.\n\n\\`sources_digest\\` is what makes that tie say something over time: a hash of the\nCONTENT of those files, taken when a human last vouched for the document. Every\nlater \\`loam validate\\` re-computes it, so it can tell a document nobody has checked\n(\\`sources.unvouched\\`) from one that still matches the code (\\`sources.current\\`) from\none the code has moved out from under (\\`sources.stale\\`). On \\`sources.stale\\` or\n\\`content.stale\\`, \\`loam vouch --pack --service <id>\\` (read-only, stamps nothing)\nprints exactly what to re-read before the human re-vouches — the body's diff since\nthe last vouch, the source files that moved, and the sections already covered.\n\n\\`content_digest\\` is the same promise about the document itself: a hash of the\nbody below the frontmatter, stamped by the same vouch. It closes the other half of\nthe forgery — editing a spec after it was vouched used to leave \\`status: verified\\`\nstanding over words nobody read. \\`loam validate\\` recomputes it wherever it can\nread the doc (no service repo needed, so it fires from the docs repo too) and\nreports \\`content.stale\\` (warn): only a person can say whether verified still\nholds of the new words.\n\n\\`vouch_scope\\` appears only when the person vouched after reading a SAMPLE of the\ndocument — \\`loam vouch --sample <n>\\`, whose whole purpose is that a partial read\nis recorded as a partial read. Its value is one flat string,\n\\`sampled <k>/<n> seed=<16 hex>\\`: k sections read of n, and the seed those k were\nchosen with. The seed is \\`sha256(<service> NUL <content_digest> NUL <sources_digest>)\\`\ntruncated to 16 hex characters, and the sections are ranked by\n\\`sha256(<seed> NUL <index> NUL <heading>)\\` with the lowest k taken, over every H2\nand H3 heading of the body outside code fences — so anybody holding the document\ncan recompute exactly which sections that person was shown, and an agent cannot\nsteer the pick without rewriting the document (which changes the seed and voids the\nstamp). \\`status\\` stays \\`verified\\` and the maturity rung stays \\`vouched\\`: the scope\nqualifies that claim, it is not a fourth status. \\`loam validate\\` reports\n\\`sources.sampled-vouch\\` (warn) while it is there, \\`loam list\\` shows\n\\`vouched (sampled)\\`, and a later FULL \\`loam vouch\\` deletes the field. Never write\nor delete it by hand: removing it turns a partial read into a full one on every\nsurface at once, which is the one forgery this field exists to make impossible.\n\nWrite \\`sources\\` for anything you author from reading code, and leave \\`status: draft\\`\nuntil a human has read it. Promoting draft to verified is their call, not yours, and\nit has its own command — \\`loam vouch --service <id>\\`, run inside that service's repo,\nwhich stamps the status, the date, the identity (\\`vouched_by\\`, from git), both digests\nand the per-file index\n(\\`sources_files\\`, which is what lets a later \\`sources.stale\\` name the paths that\nmoved) together — into the living spec.md\nand, when the service has one, arch.spec.md, in one all-or-nothing run: a file whose\nsources cannot be verified refuses the whole vouch. Never write those six fields by\nhand: a status with no digest behind it is a claim with nothing behind it. If the\ndocument changed under vouch between the read and the write, it refuses with\n\\`vouch-raced\\` and stamps nothing — re-read and re-run.\n\n**\\`loam vouch\\` is not yours to run**, and it is built so that it cannot be. It is\nthe one command whose output is a claim about a HUMAN act — everything else loam\nchecks is internal consistency, which fluent prose satisfies on its own — so it\nrefuses \\`vouch-unattended\\` when stdin is not a terminal (and in \\`--json\\` mode,\nwhere a question cannot be asked), answers \\`vouch-declined\\` when the person says\nno, and refuses \\`vouch-unattributable\\` when git can name nobody, because a stamp\nwith no \\`vouched_by\\` behind it records only that the word was written. \\`--yes\\`\nexists for a person's own scripted run; typing it on someone's behalf is\nwriting their name. The generated command and skill files pre-approve loam's\nread-only and authoring verbs one by one and deliberately not this one: when\nthe work is done, hand back and say a vouch is owed.\n`,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"authoring.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/authoring.ts"],"names":[],"mappings":"AAuBA,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,gJAAgJ;IAClJ,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,4QAA4Q;IAC9Q,UAAU,EAAE,kCAAkC;IAC9C,YAAY,EAAE,EAAE;IAChB,KAAK,EAAE;QACL,4BAA4B;QAC5B,6BAA6B;QAC7B,mDAAmD;QACnD,sBAAsB;KACvB;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqSP;CACA,CAAC","sourcesContent":["/**\n * The `loam-authoring` reference page: the grammars of the documents you write.\n *\n * The architecture spec axis (`arch.spec.md` and its `Covers:` line), the\n * generated Gherkin suite, and the frontmatter/vouch chain that ties a\n * document to the code it was written from.\n *\n * All three are consulted at a moment you can name — while authoring one file\n * — and none of them is needed to form the question. That is the split this\n * page exists to make; ./reference.ts records why it had to be made at all.\n *\n * The first three sections are the three AGENTS.md sections verbatim, in their\n * original order, so a cross-reference elsewhere in the corpus still names the\n * same headings. The fourth, \"Writing for a person\", was written for this page\n * and never stood in AGENTS.md. A large real fleet was migrated into one feature\n * whose every delta validated, and its reviewers still could not follow it: no\n * purpose said what a service did, requirement bodies were a source document\n * pasted whole, and \"this delta\" was copied into the living docs by the\n * archive. No check reads prose, so this is where that lesson lives. Its\n * examples are neutral; nothing from that fleet may enter this repository.\n */\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_AUTHORING: CommandContent = {\n name: \"loam-authoring\",\n description:\n \"Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter, and writing a feature a person can follow\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, the frontmatter fields `loam vouch` stamps, and how to write a feature's documents so a reviewer can follow them.\",\n invocation: \"loam instructions loam-authoring\",\n placeholders: [],\n spine: [\n \"The architecture spec axis\",\n \"The generated Gherkin suite\",\n \"Frontmatter — who vouched for this, and from what\",\n \"Writing for a person\",\n ],\n body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, frontmatter, and writing a feature a person can follow.\n\n## The architecture spec axis\n\nThe business spec will never mention the transactional outbox — that is\narchitecture. Retries, idempotency, metrics, alerts: real obligations no business\nscenario states, and exactly where generated code cuts corners unless the\nobligations are derived mechanically. They live in \\`arch.spec.md\\` — living and\ndelta, same grammar, same delta algebra, merged by \\`loam archive\\` through the\nsame code path (the two files are separate requirement namespaces).\n\nWhere a business requirement carries \\`Operations:\\`, an arch requirement carries\n\\`Covers:\\` — the model objects its scenarios exercise, comma-separated:\n\n\\`\\`\\`\nCovers: paymentService.db, paymentService -> kafka, alert:payment_5xx, sli:availability\n\\`\\`\\`\n\na C4 element (id, or the service a bound element stands for), an edge\n(\\`source -> target\\`), or a health signal the service's health.yaml declares.\nEvery entry must resolve — \\`covers.unknown\\` (warn) is the typo guard, because a\nmistyped entry silently costs the coverage it was written for.\n\nCoverage is then derived, never trusted, as two warnings: a feature's NEW tagged\nelements and edges want a covering requirement in its arch.spec.md deltas\n(\\`c4.uncovered\\`), and every alert/SLI health.yaml declares wants one in the\nliving arch spec (\\`health.uncovered\\`). None of this gates \\`loam archive\\`;\n\\`--strict\\` is the CI escalation. An absent arch.spec.md is not a finding —\npartial adoption is supported — but write one for any service with real\narchitecture, or its obligations ship unchecked.\n\n**Effective configuration and dependency semantics live here too, by\nconvention.** Facts about the service that no artifact structurally holds —\nthe value a deploy chart actually sets, the retry budget a client library\nhardcodes (\"retries: -1 is unbounded\"), the delivery or idempotency guarantee\na driver decides — are ARCH REQUIREMENTS: prose with a \\`Covers:\\` line naming\nthe element or edge whose behaviour the fact decides. loam will never verify\nthe values; naming the home is the point. A service whose timeout comes from\nan env var in a chart in another repository is otherwise described by no file\nin this repo, and two adoptions will file the same fact two different ways.\n\n**Test levels, mapped once.** A business scenario is an acceptance test. An arch\nscenario is an integration/ops test — the outbox relay under a dead broker, the\nretry that stays idempotent, the alert rule that actually fires. \\`api.exposes\\`\nis a contract test. Unit tests sit below spec granularity and are your TDD\nconcern, not the specs'.\n\n## The generated Gherkin suite\n\nScenarios are the acceptance criteria, and \\`loam gherkin\\` makes them\nexecutable: real \\`.feature\\` files, written into the SERVICE'S repo — the one\nloam command that writes there, because tests live with the code they gate.\nOutput lands in \\`<gherkinDir>/loam/\\` (\\`gherkinDir\\` is an optional loam.json\nfact, default \\`features\\`), and that \\`loam/\\` subdirectory is loam's own\nderived space — and a committed one: an emission lands through the same lock\nand journal the docs repo's writers use, as \\`loam/.loam-lock\\` and\n\\`loam/.loam-commit\\` dotfiles that exist only while a run is in flight (or\nafter a kill, where the journal is what lets the next run finish the job).\nRegeneration rewrites its scope and deletes its orphans, so\nnever hand-edit inside it — step definitions and hand-written features belong\noutside it, and loam never touches a byte outside \\`loam/\\`.\n\n- \\`loam gherkin FEAT-101\\` — the feature's ADDED/MODIFIED requirements for this\n service, both spec axes. Files carry \\`@FEAT-101\\`; arch-axis files add\n \\`@architecture\\` and are named \\`arch--<slug>.feature\\` — their scenarios are\n integration/ops tests, not acceptance tests.\n- \\`loam gherkin --service <id>\\` (no feature) — the full living suite from\n spec.md + arch.spec.md: the regression skeleton a legacy service gets at\n adoption.\n\nOne file per requirement (\\`Feature:\\` is the requirement name). Bullet lines\nopening with Given/When/Then/And/But — the \\`- **WHEN** ...\\` convention\nincluded — become steps; every other body line is kept as scenario\ndescription. A valid Markdown table AT THE MARGIN becomes the \\`Examples:\\` of\na \\`Scenario Outline\\`; a malformed table stays in the description and is\nreported, because it will run once rather than once per row.\n\nA step takes an ARGUMENT by carrying it INDENTED underneath: an indented table\nbecomes that step's data table (the rows an outbox or a DB table must hold after\nthe pass), a fenced block becomes its docstring, indentation intact (the request\npayload). Indented under a step means this step's rows; at the margin means the\nscenario's cases. A block no step precedes stays description and is reported as\n\\`strandedBlocks\\` — the document reads, and the TEST lost its argument. Each scenario is\ntagged \\`@loam-digest-<16hex>\\`: the same body\nhash \\`loam verify\\` folds into its claim ids, riding into cucumber's JSON\nreport as a tag, so the suite, the claim and the report cannot quietly\ndisagree about what a scenario says. \\`loam validate\n--service <id>\\`, run in the service repo, grades the suite by those digests\n(\\`gherkin.missing\\` / \\`gherkin.stale\\` / \\`gherkin.orphaned\\`, all warn) — the\nfix is always regeneration, never editing a generated file.\n\nThe flow, closed end to end: \\`loam gherkin FEAT-101\\` → \\`loam steps --service\n<id>\\` (the phrase inventory: how many step definitions this suite needs, one\nper phrase row, and which phrases differ only by an article or a trailing\nclause) → write step definitions (outside \\`loam/\\`) → run the suite with a JSON report\n(\\`cucumber-js --format json:report.json\\`) → implement until green →\n\\`loam verify FEAT-101 --service <id> --results report.json [--contract-results contract.json] [--record rest.json]\\`,\nrun in that same service repo. The digest\ntags ride through the runner into the report, so the \\`scenario.tested\\` claims\nare answered mechanically from the passing report rather than anybody's word.\nThis proves which digest-matched report bytes loam accepted; it does not prove\nthe report was produced by executing the attested commit. See\n\\`loam instructions loam-done-check\\` for what \\`--record\\` still covers.\n\n## Frontmatter — who vouched for this, and from what\n\nEvery markdown artifact opens with a YAML block:\n\n\\`\\`\\`yaml\n---\nservice: payment-service # or feature: FEAT-101\nstatus: verified # services: draft -> verified\n # features: proposed -> in_progress -> built -> done\nowner: payments-team\nlast_verified: 2026-07-31 # written by \\`loam vouch\\` — do not hand-edit\nsources: # files/directories in the SERVICE'S repo this was written from — no globs\n - src/main/java/com/shop/payment/\nsources_digest: 6f1c0a… # written by \\`loam vouch\\` — do not hand-edit\ncontent_digest: 9b2f41… # written by \\`loam vouch\\` — do not hand-edit\nsources_files: | # written by \\`loam vouch\\` — do not hand-edit\n 9b2f41… src/main/java/com/shop/payment/Api.java\nvouch_scope: sampled 2/9 seed=1a2b3c4d5e6f7089 # only when the vouch read a SAMPLE\n---\n\\`\\`\\`\n\n\\`sources\\` matters more than it looks. Everything else loam checks is internal\nconsistency — and a corpus can agree with itself perfectly while describing nothing\nthat exists. \\`sources\\` is the one thing tying a document to code: \\`loam validate\\`,\nrun inside that service's repository, checks every listed path is still there.\nEntries are literal files and directories only — a directory covers everything\nbeneath it. Glob patterns are refused loudly (\\`loam vouch\\` will not stamp them,\n\\`loam validate\\` errors on them): a pattern dialect nobody can be sure of digests\na different file set than intended, corrupting the staleness signal silently.\n\n\\`sources_digest\\` is what makes that tie say something over time: a hash of the\nCONTENT of those files, taken when a human last vouched for the document. Every\nlater \\`loam validate\\` re-computes it, so it can tell a document nobody has checked\n(\\`sources.unvouched\\`) from one that still matches the code (\\`sources.current\\`) from\none the code has moved out from under (\\`sources.stale\\`). On \\`sources.stale\\` or\n\\`content.stale\\`, \\`loam vouch --pack --service <id>\\` (read-only, stamps nothing)\nprints exactly what to re-read before the human re-vouches — the body's diff since\nthe last vouch, the source files that moved, and the sections already covered.\n\n\\`content_digest\\` is the same promise about the document itself: a hash of the\nbody below the frontmatter, stamped by the same vouch. It closes the other half of\nthe forgery — editing a spec after it was vouched used to leave \\`status: verified\\`\nstanding over words nobody read. \\`loam validate\\` recomputes it wherever it can\nread the doc (no service repo needed, so it fires from the docs repo too) and\nreports \\`content.stale\\` (warn): only a person can say whether verified still\nholds of the new words. The fleet readouts say the same: \\`loam list\\` shows\n\\`vouched (stale)\\` and owes the row a re-vouch, and \\`loam status\\` emits\n\\`next.revouch\\` — a step for a person, never for you.\n\n\\`vouch_scope\\` appears only when the person vouched after reading a SAMPLE of the\ndocument — \\`loam vouch --sample <n>\\`, whose whole purpose is that a partial read\nis recorded as a partial read. Its value is one flat string,\n\\`sampled <k>/<n> seed=<16 hex>\\`: k sections read of n, and the seed those k were\nchosen with. The seed is \\`sha256(<service> NUL <content_digest> NUL <sources_digest>)\\`\ntruncated to 16 hex characters, and the sections are ranked by\n\\`sha256(<seed> NUL <index> NUL <heading>)\\` with the lowest k taken, over every H2\nand H3 heading of the body outside code fences — so anybody holding the document\ncan recompute exactly which sections that person was shown, and an agent cannot\nsteer the pick without rewriting the document (which changes the seed and voids the\nstamp). \\`status\\` stays \\`verified\\` and the maturity rung stays \\`vouched\\`: the scope\nqualifies that claim, it is not a fourth status. \\`loam validate\\` reports\n\\`sources.sampled-vouch\\` (warn) while it is there, \\`loam list\\` shows\n\\`vouched (sampled)\\`, and a later FULL \\`loam vouch\\` deletes the field. Never write\nor delete it by hand: removing it turns a partial read into a full one on every\nsurface at once, which is the one forgery this field exists to make impossible.\n\nWrite \\`sources\\` for anything you author from reading code, and leave \\`status: draft\\`\nuntil a human has read it. Promoting draft to verified is their call, not yours, and\nit has its own command — \\`loam vouch --service <id>\\`, run inside that service's repo,\nwhich stamps the status, the date, the identity (\\`vouched_by\\`, from git), both digests\nand the per-file index\n(\\`sources_files\\`, which is what lets a later \\`sources.stale\\` name the paths that\nmoved) together — into the living spec.md\nand, when the service has one, arch.spec.md, in one all-or-nothing run: a file whose\nsources cannot be verified refuses the whole vouch. Never write those six fields by\nhand: a status with no digest behind it is a claim with nothing behind it. If the\ndocument changed under vouch between the read and the write, it refuses with\n\\`vouch-raced\\` and stamps nothing — re-read and re-run.\n\n**\\`loam vouch\\` is not yours to run**, and it is built so that it cannot be. It is\nthe one command whose output is a claim about a HUMAN act — everything else loam\nchecks is internal consistency, which fluent prose satisfies on its own — so it\nrefuses \\`vouch-unattended\\` when stdin is not a terminal (and in \\`--json\\` mode,\nwhere a question cannot be asked), answers \\`vouch-declined\\` when the person says\nno, and refuses \\`vouch-unattributable\\` when git can name nobody, because a stamp\nwith no \\`vouched_by\\` behind it records only that the word was written. \\`--yes\\`\nexists for a person's own scripted run; typing it on someone's behalf is\nwriting their name. The generated command and skill files pre-approve loam's\nread-only and authoring verbs one by one and deliberately not this one: when\nthe work is done, hand back and say a vouch is owed.\n\n## Writing for a person\n\nA feature is read by a reviewer before anyone builds it, and its requirements\nare read for years after \\`loam archive\\` copies them into the living docs. loam\ngrades the joins and never the prose, so nothing in this section is checked: a\ndelta can validate clean and still be one nobody can follow.\n\n**intent.md** opens with the problem in business terms — \\`## Why\\` and\n\\`## Scope\\`, the two sections the archive gate reads — and then carries the three\nthings a reviewer looks for first:\n\n- \\`## How to read this feature\\`: two or three sentences saying which services\n change, which document to open first, and which picture shows the change (the\n delta's own view, or a flow under the feature's \\`usecases/\\`).\n- a business-requirement coverage table, one row per business requirement the\n feature was asked to meet, naming what keeps it:\n\n | Business requirement | Kept by | Where |\n |---|---|---|\n | A customer can split one payment between two cards | PAY-SPLIT-1 | payment-split-service spec.md |\n | Every payee gets a receipt | uc_split_receipt | usecases/split-receipt.likec4 |\n\n- \\`## Open questions\\` (the scaffold already writes the heading) as a table, so\n that a person can answer each question and a reader can see what each blocks:\n\n | ID | Question | Blocks | Owner | Current default |\n |---|---|---|---|---|\n | Q1 | Is a split refunded per card or as a whole? | PAY-SPLIT-3 | payments-team | per card |\n\n The current default is what gets built if nobody answers, so write one for\n every question.\n\n**Each spec delta opens with a plain-language \\`## Purpose\\`**: what the service\ndoes in this change, written for someone who has never opened its code. Where\nthe delta CREATES the living document — a new service's spec.md, a first\narch.spec.md, a new capability — \\`loam archive\\` copies that section into the\nnew document as its narrative. Where the living document already exists, the\nsection stays with the archived delta, and the archive plan says so on that\nfile's line; if the service's own narrative should change, edit the living\ndocument in the same change.\n\n**Write a long requirement body as a lead and bullets.** A new requirement\nstates one behaviour. A requirement carried over from another source often\narrives as one paragraph of SHALL sentences. Keep every sentence, but open with\none line that says what the requirement is for, and give each SHALL sentence a\nbullet of its own:\n\n ### Requirement: Split a payment\n Requirement-ID: PAY-SPLIT-1\n\n A payment can be divided between several payees.\n\n - The service SHALL accept between two and five payees per split.\n - The service SHALL reject a split whose shares do not add up to the authorized amount.\n\n**Expand every abbreviation the first time a document uses it**, in words a new\nreader knows: \"service-level objective (SLO)\", then \"SLO\".\n\n**Keep review-time wording out of what the archive copies.** \"This delta\", \"this\nfeature\", \"the new endpoint\" and \"we now\" read correctly in review. But\n\\`loam archive\\` copies requirement bodies, scenarios and contract descriptions\ninto living documents, where \"this feature\" points at a pull request that merged\nlong ago. Write what the service does, not what the change does. Prose about the\nchange belongs in \\`intent.md\\`, which stays with the feature.\n\n**A feature's vocabulary, decisions and flows travel with it.**\n\n- A word the feature brings is \\`features/<FEAT>/glossary/<term>.md\\`, which the\n archive copies into \\`glossary/\\`. A term the living glossary already defines is\n edited there instead, because the copy never overwrites\n (\\`glossary.term-exists\\`).\n- A decision is \\`features/<FEAT>/adrs/NNNN-<slug>.md\\`. It stays with the\n feature under \\`features/archive/\\`, and the living documents that link to it go\n on resolving. A decision meant to outlive the change belongs in\n \\`architecture/adrs/\\` or the service's own \\`adrs/\\` instead.\n- A flow that keeps a promise across services is\n \\`features/<FEAT>/usecases/<name>.likec4\\`: a \\`dynamic view\\` tagged\n \\`#cap-<capability>\\`, naming a capability the fleet declares, and\n \\`#req-<Requirement-ID>\\`, naming the promise it keeps. A promise the feature's\n own capability delta adds resolves too. \\`usecase.capability-unresolved\\` and\n \\`usecase.requirement-unresolved\\` grade both tags before the archive.\n\nLink to all three from the deltas, written relative to the file you write in:\n\\`loam archive\\` re-points every link into the feature for the move.\n\n**Write a \\`Covers:\\` edge by service name**:\n\\`Covers: order-service -> payment-service\\`. An edge spelled by its endpoints'\nservice names resolves the same before and after the archive. A delta's own\nelement id may not, and \\`covers.unknown\\` at feature scope says when it would not.\nA kinded spelling such as \\`order-service -[calls]-> payment-service\\` is accepted,\nbut the kind is read past rather than compared: it covers every edge from the\nfirst service to the second, whatever its kind. So write the plain arrow.\n\n**Draw a producer outside the fleet as an \\`#external\\` element**, with the edge\nit publishes on carrying \\`metadata { publishes }\\`, so that the consumer's\n\\`Consumes:\\` line has a producer to join to. \\`loam instructions loam-spine\\`\n(\"A message produced outside the fleet\") has the join, and\n\\`loam instructions loam-drawing\\` has the drawing.\n`,\n};\n"]}
|
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
* written — every byte comes from ../../agents-md/, which is where the sections
|
|
15
15
|
* already lived and where they stayed. The parts still carry their own trailing
|
|
16
16
|
* newlines and are joined with no separator, so the printed page is the old
|
|
17
|
-
* section byte for byte.
|
|
17
|
+
* section byte for byte. That is the assembly contract every part's header
|
|
18
|
+
* points back at: each starts at the first character of its opening line and
|
|
19
|
+
* ends with the newline that closes its last one, or two parts glue onto one
|
|
20
|
+
* line on the printed page.
|
|
18
21
|
*
|
|
19
22
|
* WHAT IS AND IS NOT DUPLICATED. `## Reading loam's output` still exists in
|
|
20
|
-
* AGENTS.md (../../agents-md
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* below appears in exactly one place.
|
|
23
|
+
* AGENTS.md (../../agents-md.ts's ORIENTATION), and it is orientation, not a
|
|
24
|
+
* summary of this page: the envelope's keys, branching on codes rather than
|
|
25
|
+
* prose, severity versus gating, and a pointer here. The per-invocation
|
|
26
|
+
* inventory below appears in exactly one place.
|
|
25
27
|
*/
|
|
26
28
|
import { CODE_MAP } from "../../agents-md/command-map.js";
|
|
27
29
|
import { CONTEXT_COMMAND } from "../../agents-md/map/lenses/context.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codes.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/codes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"codes.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGvD,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,sEAAsE;IACnF,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,iRAAiR;IACnR,UAAU,EAAE,8BAA8B;IAC1C,YAAY,EAAE,EAAE;IAChB,2EAA2E;IAC3E,4EAA4E;IAC5E,+CAA+C;IAC/C,KAAK,EAAE;QACL,wCAAwC;QACxC,qDAAqD;QACrD,8DAA8D;QAC9D,6DAA6D;KAC9D;IACD,0EAA0E;IAC1E,gDAAgD;IAChD,IAAI,EACF,QAAQ;QACR,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,aAAa;QACb,YAAY;QACZ,eAAe;QACf,WAAW;QACX,QAAQ;CACX,CAAC","sourcesContent":["/**\n * The `loam-codes` reference page: which codes each INVOCATION can raise.\n *\n * The largest of the four pages and the one this migration is mostly about. As\n * a section of AGENTS.md it was 44,433 bytes — 41% of a 109,399-byte file that\n * Codex truncates at 32,768 and Windsurf at 12,000 characters, both silently.\n * It is also the half a reader consults at a moment it can NAME (a run reported\n * something) rather than the half it needs to form a question at all, which is\n * what decided which side of the split it went. ./reference.ts carries the rest\n * of that argument.\n *\n * This module does one thing: it CONCATENATES, in the order ../../agents-md.ts\n * used to. Nothing here reformats a part on the way past, and nothing here is\n * written — every byte comes from ../../agents-md/, which is where the sections\n * already lived and where they stayed. The parts still carry their own trailing\n * newlines and are joined with no separator, so the printed page is the old\n * section byte for byte. That is the assembly contract every part's header\n * points back at: each starts at the first character of its opening line and\n * ends with the newline that closes its last one, or two parts glue onto one\n * line on the printed page.\n *\n * WHAT IS AND IS NOT DUPLICATED. `## Reading loam's output` still exists in\n * AGENTS.md (../../agents-md.ts's ORIENTATION), and it is orientation, not a\n * summary of this page: the envelope's keys, branching on codes rather than\n * prose, severity versus gating, and a pointer here. The per-invocation\n * inventory below appears in exactly one place.\n */\nimport { CODE_MAP } from \"../../agents-md/command-map.js\";\nimport { CONTEXT_COMMAND } from \"../../agents-md/map/lenses/context.js\";\nimport { DIFF_COMMAND } from \"../../agents-md/map/lenses/diff.js\";\nimport { GATE_COMMAND } from \"../../agents-md/map/lenses/gate.js\";\nimport { EXPLAIN_COMMAND } from \"../../agents-md/map/explain.js\";\nimport { MCP_COMMAND } from \"../../agents-md/map/mcp.js\";\nimport { SUBSYSTEM_COMMANDS } from \"../../agents-md/map/subsystem.js\";\nimport { USECASE_VIEWS } from \"../../agents-md/map/usecases.js\";\nimport { REFUSALS } from \"../../agents-md/refusals.js\";\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_CODES: CommandContent = {\n name: \"loam-codes\",\n description: \"Reference: which codes each invocation can raise, command by command\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"The per-invocation inventory: which findings `validate --service` / `--feature` / `--all`, `status`, `doctor`, `gate`, `context`, `diff`, `explore`, `dependencies`, `rebase`, `seed`, `subsystem` and `mcp` can report, and the refusals the containment surface answers with.\",\n invocation: \"loam instructions loam-codes\",\n placeholders: [],\n // The page carries no `## ` headings — it is one list, and the bullets are\n // the structure. The spine names the invocations it walks instead, which is\n // what a reader is actually looking one of up.\n spine: [\n \"validate --service / --feature / --all\",\n \"status, doctor, rebase, dependencies, explore, seed\",\n \"context, gate, subsystem, use-case views, diff, explain, mcp\",\n \"the containment refusals and the OpenSpec migration surface\",\n ],\n // CODE_MAP already opens with the page's own \"**What this page is.**\" and\n // leads with `status`, the orientation command.\n body:\n CODE_MAP +\n CONTEXT_COMMAND +\n GATE_COMMAND +\n SUBSYSTEM_COMMANDS +\n USECASE_VIEWS +\n DIFF_COMMAND +\n EXPLAIN_COMMAND +\n MCP_COMMAND +\n REFUSALS,\n};\n"]}
|
|
@@ -30,9 +30,12 @@ so a JUnit or pytest fleet is not held at \`attested\` by a file format —
|
|
|
30
30
|
\`loam verify <FEAT> --results report.json\`. A claim is confirmed only when a
|
|
31
31
|
report scenario carrying its \`@loam-digest-<16hex>\` tag ran at least one step
|
|
32
32
|
and every step passed — every occurrence, when the report holds a re-run, and
|
|
33
|
-
every before/after hook with it
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
every before/after hook with it — and, in a cucumber report, ran exactly as
|
|
34
|
+
many steps as the stamped scenario has: a hand-tagged stub is not that
|
|
35
|
+
scenario's run. A failed, undefined, pending or skipped step, a failed hook, a
|
|
36
|
+
step count that differs, or no matching scenario at all, is \`unconfirmed\` with
|
|
37
|
+
the reason. A report that is not JSON (a JUnit XML file) is refused
|
|
38
|
+
\`answers-unreadable\`, naming both shapes. The digest is the only identity: a reworded spec scenario matches
|
|
36
39
|
nothing until the suite is regenerated and re-run. When a report exists,
|
|
37
40
|
ALWAYS pass \`--results\` — under it the runner owns every scenario claim, and
|
|
38
41
|
an answers-file entry for one is refused.
|
|
@@ -92,9 +95,12 @@ re-checks the pins and reports drift under the \`evidence.*\` findings; nothing
|
|
|
92
95
|
there moves a verdict either.
|
|
93
96
|
|
|
94
97
|
Two more codes belong to the record itself. \`verify.record-miscounted\` (error):
|
|
95
|
-
a
|
|
96
|
-
record is refused as unreadable rather than believed in either half, and
|
|
97
|
-
|
|
98
|
+
a record file whose \`summary\` block contradicts its own \`claims[]\` — the
|
|
99
|
+
record is refused as unreadable rather than believed in either half, and the
|
|
100
|
+
repair is never editing the counts: a service's own \`verification/<id>.yaml\`
|
|
101
|
+
is deleted and recorded again by that service, and the one-file
|
|
102
|
+
\`verification.yaml\` is restored from version control and then recorded over.
|
|
103
|
+
\`verify.digest-contested\`
|
|
98
104
|
(warn): two or more services word a scenario identically, so they share one
|
|
99
105
|
\`@loam-digest-…\` tag and no single cucumber report can say whose suite ran it —
|
|
100
106
|
those scenario claims are left unconfirmed, and each service records its own
|
|
@@ -113,7 +119,10 @@ services that all answered a since-rewritten delta agree with each other and are
|
|
|
113
119
|
every one of them stale. Differing \`docsCommit\` values are NOT a finding:
|
|
114
120
|
recording a week apart is normal for a feature in flight.
|
|
115
121
|
Normal mid-rollout and it gates nothing; re-record the services on the older
|
|
116
|
-
version from their own repositories
|
|
122
|
+
version from their own repositories. In a record kept as per-service files the
|
|
123
|
+
answers of the services it names do not count until they do: the record
|
|
124
|
+
answers the newest version its files answered, and an answer filed against an
|
|
125
|
+
older one could otherwise fill the slot of the question that replaced it.
|
|
117
126
|
Attestations written before the field existed carry no \`checklist\` and are not
|
|
118
127
|
counted as a third version — silence is not disagreement.
|
|
119
128
|
|
|
@@ -126,8 +135,9 @@ commit. It does not prove the file came from executing that commit; no digest
|
|
|
126
135
|
can.
|
|
127
136
|
|
|
128
137
|
Everything else you answer from the code, and \`--record answers.json\` takes
|
|
129
|
-
those back
|
|
130
|
-
|
|
138
|
+
those back — into \`features/<FEAT>/verification/<svc>.yaml\` with \`--service\`,
|
|
139
|
+
into the one file \`features/<FEAT>/verification.yaml\` without — and either
|
|
140
|
+
travels into the archive with the feature and reads without loam. Alongside the mechanical
|
|
131
141
|
flags, the answers file must answer exactly the claims no report owns: an
|
|
132
142
|
entry for a report-owned claim is refused (\`answers-mismatch\`), and a
|
|
133
143
|
mechanical flag alone is refused while claims outside its kind are
|
|
@@ -147,9 +157,16 @@ loam verify FEAT-101 --service payment-service --results report.json --contract-
|
|
|
147
157
|
\`\`\`
|
|
148
158
|
|
|
149
159
|
\`--service <id>\` narrows the checklist to that service's claims and binds the
|
|
150
|
-
answers to this repository's commit, producing
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
answers to this repository's commit, producing that service's **attestation**
|
|
161
|
+
as a file of its own, \`features/<FEAT>/verification/<id>.yaml\`. The directory
|
|
162
|
+
is the record: loam adds the files up when it reads, and the verdict and
|
|
163
|
+
counts are computed from them, never stored. Re-running it in the next repo
|
|
164
|
+
writes that repo's file and touches no other — which is why two teams'
|
|
165
|
+
attestations on two docs-repo branches merge cleanly, where one shared file
|
|
166
|
+
conflicted every time. A one-file federated \`verification.yaml\` written
|
|
167
|
+
before the directory is still read; a service that records again supersedes
|
|
168
|
+
its share of it, and the file goes once every service it names has its own.
|
|
169
|
+
Omitting
|
|
153
170
|
\`--service\` in a repo whose \`loam.json\` declares one substitutes it, so the
|
|
154
171
|
short form is safe there; a \`--service\` naming a service this repo does not
|
|
155
172
|
declare is refused (\`service-mismatch\`), and \`--service\` from a repo that
|
|
@@ -161,9 +178,14 @@ no \`--service\` writes the whole record from one place.** Over a record that
|
|
|
161
178
|
already carries other services' attestations it is refused outright
|
|
162
179
|
(\`record-federated\`, naming the attestors) rather than merged or migrated — the
|
|
163
180
|
alternative was one repo silently erasing nine others' evidence. Use it only for
|
|
164
|
-
a single-service feature that has never been recorded federated. A
|
|
165
|
-
|
|
166
|
-
never overwritten and never reported as "no
|
|
181
|
+
a single-service feature that has never been recorded federated. A record file
|
|
182
|
+
that exists but cannot be read — broken YAML, git conflict markers, a miscount
|
|
183
|
+
— is \`record-unreadable\`: it is never overwritten and never reported as "no
|
|
184
|
+
record", and the message names the file and the repair that is safe for it. A
|
|
185
|
+
service's own \`verification/<id>.yaml\` holds only that service's word, so that
|
|
186
|
+
service may delete it and record again; the one-file \`verification.yaml\` may
|
|
187
|
+
hold other services' attestations, so it is restored from version control
|
|
188
|
+
(after a merge, the copy on the branch you merged into) and never deleted.
|
|
167
189
|
|
|
168
190
|
Reading is not writing: \`loam verify <FEAT> --service <id>\` **without**
|
|
169
191
|
\`--record\` is a pure lens on the checklist. A read-only verify checklist needs no
|