@ybotok/loam 0.2.0-alpha.6 → 0.2.0-alpha.9
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 +1477 -1
- package/COMPARISON.md +91 -3
- package/CONTRIBUTING.md +37 -0
- package/MIGRATING-from-OpenSpec.md +40 -22
- package/QUICKSTART.md +181 -9
- package/README.md +256 -57
- package/ROADMAP.md +108 -11
- package/SCHEMA.md +721 -130
- package/WORKFLOW.md +272 -62
- 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/archive/archive.js +15 -18
- package/dist/commands/archive/archive.js.map +1 -1
- package/dist/commands/archive/plan/contracts/asyncapi.js +27 -41
- 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 +25 -42
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
- package/dist/commands/archive/plan/contracts/verdict-lines.js +41 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +3 -7
- package/dist/commands/archive/plan/gate.js.map +1 -1
- package/dist/commands/archive/plan/landscape.js +4 -4
- package/dist/commands/archive/plan/landscape.js.map +1 -1
- package/dist/commands/archive/plan/refusal.js +8 -18
- package/dist/commands/archive/plan/refusal.js.map +1 -1
- package/dist/commands/archive/plan/specs.js +134 -25
- package/dist/commands/archive/plan/specs.js.map +1 -1
- package/dist/commands/archive/plan/state.js +1 -0
- package/dist/commands/archive/plan/state.js.map +1 -1
- package/dist/commands/archive/run.js +82 -33
- 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 +4 -7
- package/dist/commands/context/context.js.map +1 -1
- package/dist/commands/context/print.js +2 -2
- package/dist/commands/context/print.js.map +1 -1
- package/dist/commands/delta/delta.js +44 -12
- package/dist/commands/delta/delta.js.map +1 -1
- package/dist/commands/delta/print.js +1 -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/explore.js +4 -8
- 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 +0 -4
- package/dist/commands/list/json.js.map +1 -1
- package/dist/commands/list/list.js +38 -23
- package/dist/commands/list/list.js.map +1 -1
- package/dist/commands/list/print.js +38 -6
- 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 +28 -33
- 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 +64 -13
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/seed/seed.js +6 -9
- package/dist/commands/seed/seed.js.map +1 -1
- package/dist/commands/show/show.js +3 -7
- package/dist/commands/show/show.js.map +1 -1
- package/dist/commands/status/print.js +13 -4
- 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 +3 -7
- 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 +60 -25
- 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 +141 -71
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/report.js +55 -5
- package/dist/commands/subsystem/txn/report.js.map +1 -1
- package/dist/commands/subsystem/txn/txn.js +121 -45
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +82 -12
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/tasks/render.js +116 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +113 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +6 -9
- package/dist/commands/unarchive/manifest.js.map +1 -1
- package/dist/commands/unarchive/restore.js +17 -28
- 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 +6 -15
- package/dist/commands/validate/arch-coverage.js.map +1 -1
- package/dist/commands/validate/checks/fleet-shape.js +4 -49
- 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/requirements.js +18 -8
- package/dist/commands/validate/checks/requirements.js.map +1 -1
- package/dist/commands/validate/checks/sources.js +6 -2
- package/dist/commands/validate/checks/sources.js.map +1 -1
- package/dist/commands/validate/feature.js +23 -19
- package/dist/commands/validate/feature.js.map +1 -1
- package/dist/commands/validate/fleet/census.js +26 -3
- package/dist/commands/validate/fleet/census.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +35 -32
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/map/attest.js +7 -12
- package/dist/commands/validate/fleet/map/attest.js.map +1 -1
- package/dist/commands/validate/fleet/map/bindings.js +16 -5
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -1
- package/dist/commands/validate/fleet/map/consumers.js +43 -122
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -1
- package/dist/commands/validate/fleet/map/usecases.js +5 -11
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -1
- package/dist/commands/validate/fleet/obligations.js +1 -5
- package/dist/commands/validate/fleet/obligations.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/print.js +5 -1
- 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/usecases.js +6 -4
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -1
- package/dist/commands/validate/fleet/views/ids.js +33 -7
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/root-documents.js +17 -35
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -1
- package/dist/commands/validate/fleet/views/stale.js +31 -14
- 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/report.js +5 -4
- 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 +16 -104
- 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 +1 -1
- 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/service.js +16 -26
- package/dist/commands/validate/service/service.js.map +1 -1
- package/dist/commands/validate/service/specs.js +31 -38
- package/dist/commands/validate/service/specs.js.map +1 -1
- package/dist/commands/validate/service/spine.js +8 -11
- package/dist/commands/validate/service/spine.js.map +1 -1
- package/dist/commands/validate/service/usecases/usecases.js +3 -3
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -1
- package/dist/commands/validate/validate.js +44 -26
- 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 +54 -51
- 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 +57 -102
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/explain.js +4 -3
- package/dist/core/agent/agents-md/map/explain.js.map +1 -1
- package/dist/core/agent/agents-md/map/lenses/context.js +4 -3
- 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 +9 -3
- package/dist/core/agent/agents-md/map/status.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +31 -17
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md/map/usecases.js +24 -6
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
- package/dist/core/agent/agents-md/refusals.js +37 -21
- package/dist/core/agent/agents-md/refusals.js.map +1 -1
- package/dist/core/agent/agents-md.js +25 -10
- 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/scaffold.js +10 -15
- package/dist/core/agent/scaffold.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 +5 -3
- package/dist/core/agent/workflows/adopt.js.map +1 -1
- package/dist/core/agent/workflows/check.js +25 -22
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/agent/workflows/closing.js +54 -21
- package/dist/core/agent/workflows/closing.js.map +1 -1
- package/dist/core/agent/workflows/feature.js +79 -11
- package/dist/core/agent/workflows/feature.js.map +1 -1
- package/dist/core/agent/workflows/implement.js +91 -13
- package/dist/core/agent/workflows/implement.js.map +1 -1
- package/dist/core/agent/workflows/reference/authoring.js +3 -1
- 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/reference.js.map +1 -1
- package/dist/core/agent/workflows/reference/spine.js +62 -24
- 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 +30 -50
- package/dist/core/asyncapi/merge/markers.js.map +1 -1
- package/dist/core/asyncapi/merge/merge.js +31 -53
- package/dist/core/asyncapi/merge/merge.js.map +1 -1
- package/dist/core/asyncapi/merge/pin.js +10 -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 +30 -25
- package/dist/core/brief/brief.js.map +1 -1
- package/dist/core/brief/landscape.js +8 -12
- package/dist/core/brief/landscape.js.map +1 -1
- package/dist/core/brief/map/extend.js +8 -5
- package/dist/core/brief/map/extend.js.map +1 -1
- package/dist/core/brief/map/owed.js +8 -26
- package/dist/core/brief/map/owed.js.map +1 -1
- package/dist/core/brief/targets.js +79 -5
- package/dist/core/brief/targets.js.map +1 -1
- package/dist/core/brief/unchecked.js +1 -1
- package/dist/core/brief/unchecked.js.map +1 -1
- package/dist/core/c4/likec4.js +147 -16
- 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/values.js +54 -1
- package/dist/core/c4/parsed/values.js.map +1 -1
- package/dist/core/c4/prefetch/fleet.js +1 -9
- package/dist/core/c4/prefetch/fleet.js.map +1 -1
- package/dist/core/c4/project/architecture.js +31 -9
- package/dist/core/c4/project/architecture.js.map +1 -1
- package/dist/core/c4/project/documents.js +36 -10
- package/dist/core/c4/project/documents.js.map +1 -1
- package/dist/core/c4/project/load.js +14 -21
- package/dist/core/c4/project/load.js.map +1 -1
- package/dist/core/c4/project/staged.js +7 -3
- package/dist/core/c4/project/staged.js.map +1 -1
- 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 +25 -1
- package/dist/core/c4/resolve/service.js.map +1 -1
- package/dist/core/c4/seed/template.js +15 -1
- package/dist/core/c4/seed/template.js.map +1 -1
- package/dist/core/c4/service-model/shape.js +2 -22
- package/dist/core/c4/service-model/shape.js.map +1 -1
- package/dist/core/c4/source-mask.js +288 -4
- package/dist/core/c4/source-mask.js.map +1 -1
- package/dist/core/c4/source-scan.js +203 -147
- package/dist/core/c4/source-scan.js.map +1 -1
- package/dist/core/c4/splice/authored-source.js +19 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -1
- package/dist/core/c4/splice/delta-blocks.js +5 -18
- package/dist/core/c4/splice/delta-blocks.js.map +1 -1
- package/dist/core/c4/splice/landscape-merge.js +13 -8
- package/dist/core/c4/splice/landscape-merge.js.map +1 -1
- package/dist/core/c4/splice/model/merge.js +10 -6
- package/dist/core/c4/splice/model/merge.js.map +1 -1
- package/dist/core/c4/splice/placement.js +108 -18
- package/dist/core/c4/splice/placement.js.map +1 -1
- package/dist/core/c4/workspace.js +13 -22
- 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/findings.js +15 -20
- 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/coherence.js +30 -16
- 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/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 +119 -8
- 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 +14 -82
- package/dist/core/coherence/events/lookups.js.map +1 -1
- 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 +1 -1
- package/dist/core/delta/delta.js.map +1 -1
- package/dist/core/deployment/delta.js +15 -16
- package/dist/core/deployment/delta.js.map +1 -1
- 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 +28 -16
- 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/doctor/agents.js +34 -18
- package/dist/core/doctor/agents.js.map +1 -1
- package/dist/core/doctor/report.js.map +1 -1
- package/dist/core/document/apply.js +10 -2
- 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 +17 -12
- package/dist/core/explain/families.js.map +1 -1
- package/dist/core/explain/refusals.js +3 -3
- package/dist/core/explain/refusals.js.map +1 -1
- package/dist/core/explain/terms.js +18 -9
- package/dist/core/explain/terms.js.map +1 -1
- package/dist/core/explore/explore.js +2 -7
- package/dist/core/explore/explore.js.map +1 -1
- package/dist/core/fleet-context.js +34 -95
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +10 -3
- package/dist/core/gate/checks.js.map +1 -1
- package/dist/core/gate/partners.js +64 -19
- 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/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/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 +5 -36
- package/dist/core/links/corpus.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 +22 -8
- 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 +56 -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 +26 -52
- package/dist/core/openapi/merge/merge.js.map +1 -1
- package/dist/core/openapi/merge/pin.js +15 -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 +2 -16
- package/dist/core/pack/living.js.map +1 -1
- 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/entries.js.map +1 -1
- package/dist/core/repo/paths.js +34 -29
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/repo.js +24 -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 +45 -6
- package/dist/core/repo/tree/render/body.js.map +1 -1
- 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 +19 -2
- package/dist/core/repo/tree/render/stale.js.map +1 -1
- package/dist/core/repo/tree/render/views.js +102 -33
- package/dist/core/repo/tree/render/views.js.map +1 -1
- package/dist/core/repo/tree/walk.js +8 -30
- 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/staging/commit.js +10 -12
- 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 +60 -1
- package/dist/core/staging/recovery/recover.js.map +1 -1
- package/dist/core/staging/snapshot/manifest.js +152 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +10 -34
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/status/actions/execution.js +11 -0
- package/dist/core/status/actions/execution.js.map +1 -1
- package/dist/core/status/feature/artifacts.js +2 -2
- package/dist/core/status/feature/artifacts.js.map +1 -1
- package/dist/core/status/feature/feature.js +5 -11
- package/dist/core/status/feature/feature.js.map +1 -1
- package/dist/core/status/fleet/fleet.js +6 -2
- package/dist/core/status/fleet/fleet.js.map +1 -1
- package/dist/core/status/fleet/next.js +26 -3
- package/dist/core/status/fleet/next.js.map +1 -1
- package/dist/core/status/report.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 +174 -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/flows.js +5 -7
- package/dist/core/usecases/delta/flows.js.map +1 -1
- package/dist/core/usecases/fleet.js +178 -31
- package/dist/core/usecases/fleet.js.map +1 -1
- package/dist/core/usecases/operations.js +5 -4
- package/dist/core/usecases/operations.js.map +1 -1
- package/dist/core/usecases/service/flows.js +9 -6
- package/dist/core/usecases/service/flows.js.map +1 -1
- 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 +45 -10
- 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 +1 -0
- package/dist/core/vocabulary/issue.js.map +1 -1
- package/dist/core/vocabulary/maturity.js +53 -3
- package/dist/core/vocabulary/maturity.js.map +1 -1
- package/examples/README.md +28 -9
- package/examples/docs/architecture/landscape.likec4 +21 -7
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +3 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +6 -2
- 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/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
- package/examples/docs/services/order-service/asyncapi.yaml +3 -2
- package/examples/docs/services/order-service/model.likec4 +10 -8
- package/examples/docs/services/payment-service/model.likec4 +6 -4
- package/examples/docs/services/platform/identity-service/model.likec4 +9 -7
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
- package/examples/docs/services/platform/notification-service/model.likec4 +4 -5
- package/package.json +1 -1
- package/dist/commands/validate/checks/vocabulary.js +0 -16
- package/dist/commands/validate/checks/vocabulary.js.map +0 -1
- package/dist/core/agent/agents-md/artifacts.js +0 -221
- package/dist/core/agent/agents-md/artifacts.js.map +0 -1
- package/dist/core/agent/agents-md/cycle.js +0 -180
- 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 -256
- package/dist/core/diff/victims.js.map +0 -1
- package/dist/core/staging/snapshot.js.map +0 -1
- package/dist/core/verify/file.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
[](https://github.com/ybotok/loam/actions/workflows/ci.yml)
|
|
8
8
|
[](https://www.npmjs.com/package/@ybotok/loam)
|
|
9
9
|
|
|
10
|
-
> **Pre-release: `0.2.0-alpha.
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
>
|
|
14
|
-
>
|
|
15
|
-
>
|
|
10
|
+
> **Pre-release: `0.2.0-alpha.9`** is the version this checkout's `package.json` names, on the 0.2
|
|
11
|
+
> line of [`@ybotok/loam`](https://www.npmjs.com/package/@ybotok/loam). Whether npm serves it is not
|
|
12
|
+
> something this file can know — a version is cut before its publish runs, and a publish can fail
|
|
13
|
+
> after — so **the npm dist-tags are the source of truth**: the badge above reads the `alpha` tag, and
|
|
14
|
+
> `npm view @ybotok/loam dist-tags` prints every tag. Prereleases publish under `alpha`, so
|
|
15
|
+
> `npm i @ybotok/loam@alpha` installs the newest one that did. `latest` is moved onto a release by
|
|
16
|
+
> hand once it has published, so a plain `npm i @ybotok/loam` resolves to an earlier release until it
|
|
17
|
+
> is moved. See [Status](#status).
|
|
16
18
|
|
|
17
19
|
`loam` keeps an authored C4 model, requirements, API and event contracts, permissions, domain
|
|
18
20
|
vocabulary and verification evidence in explicit agreement as a system changes. The same lifecycle
|
|
@@ -109,7 +111,7 @@ and says what its architecture *means*, and a model that was guessed is worse th
|
|
|
109
111
|
downstream has to re-derive it to know whether to believe it. So loam takes the half of the job that
|
|
110
112
|
is mechanical: it **states the work** and it **checks the result**. An agent does the reading, and
|
|
111
113
|
both halves are written down: the question in the brief or the checklist, the answer in `sources` or
|
|
112
|
-
|
|
114
|
+
the verification record.
|
|
113
115
|
|
|
114
116
|
### What green means here, and what it does not
|
|
115
117
|
|
|
@@ -220,22 +222,42 @@ a contract spelling it `authorizePayment` fails here and nowhere else a team nor
|
|
|
220
222
|
**Expect a red run, and read it correctly.** Five seeded services with no C4 centre report
|
|
221
223
|
`service.no-model` (error) five times, and `service.no-spec` (warn) five times. Those are not
|
|
222
224
|
misconfiguration: they are a truthful reading of a fleet where adoption has not started, and they
|
|
223
|
-
stay until you write those documents. The finding you came for is the spine one.
|
|
225
|
+
stay until you write those documents. The finding you came for is the spine one. Under the `--base`
|
|
226
|
+
PR gate [below](#guard-the-fleets-edges-on-every-pr), a PR that adds a service's `openapi.yaml`
|
|
227
|
+
stays red until that service has a `model.likec4` — the gate grades the service the PR touched, and
|
|
228
|
+
`service.no-model` is that ratchet working as designed — while a PR that only names operations on
|
|
229
|
+
the map is graded on those edges alone.
|
|
224
230
|
[`test/spine-first.test.ts`](https://github.com/ybotok/loam/blob/main/test/spine-first.test.ts)
|
|
225
231
|
pins this whole sequence against the shipped `examples/fleet.yaml`, so the recipe cannot drift from
|
|
226
232
|
the binary.
|
|
227
233
|
|
|
228
234
|
From here, [WORKFLOW.md's day zero](WORKFLOW.md#day-zero-onboarding-a-fleet) is the rest: bind each
|
|
229
|
-
service repo, adopt, grade, promote.
|
|
235
|
+
service repo, adopt, grade, promote. Bind each one with the service profile:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# in each service checkout, beside the docs repo
|
|
239
|
+
loam init --docs ../docs --service payment-service --agent-profile service
|
|
240
|
+
loam doctor
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Pass the profile explicitly. `--agent-profile` defaults to `full`, with `--service` or without it,
|
|
244
|
+
and `full` writes all seven entry points into the checkout — `loam-feature` and `loam-ship` among
|
|
245
|
+
them, the two workflows that author a feature and archive it into the living docs, which the `docs`
|
|
246
|
+
profile gives to the docs repo. `service` writes the five that run beside the code: `loam-adopt`,
|
|
247
|
+
`loam-implement`, `loam-check`, `loam-verify` and `loam-report`. Across a hundred service repos that
|
|
248
|
+
is the difference between one place a cross-service change starts and a hundred places an agent
|
|
249
|
+
can be told to start one. The people in those service repos need about a screen of this:
|
|
250
|
+
[docs/SERVICE-TEAMS.md](https://github.com/ybotok/loam/blob/main/docs/SERVICE-TEAMS.md).
|
|
230
251
|
|
|
231
252
|
### Guard the fleet's edges on every PR
|
|
232
253
|
|
|
233
254
|
Two commands, each installable on its own with no part of the workflow above adopted. **`loam diff`
|
|
234
255
|
exits 1 when a pull request removes an operation or an event message the fleet still consumes**,
|
|
235
|
-
and names the consumers
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
the
|
|
256
|
+
and names the consumers — of a removal, a deprecation, or a change to what an operation or message
|
|
257
|
+
returns. That question — *who is joined to this?* — is the one a fleet answers wrong, and it is
|
|
258
|
+
answerable only from a document that knows the whole fleet. **`loam validate --all --base <ref>`
|
|
259
|
+
grades only the boundaries the branch touched**, which is what lets a strict gate go in on the
|
|
260
|
+
first day of adoption and tighten as the system gets written down.
|
|
239
261
|
|
|
240
262
|
```yaml
|
|
241
263
|
# .github/workflows/fleet-edges.yml — in the docs repo
|
|
@@ -244,34 +266,198 @@ on: pull_request
|
|
|
244
266
|
jobs:
|
|
245
267
|
edges:
|
|
246
268
|
runs-on: ubuntu-latest
|
|
269
|
+
env:
|
|
270
|
+
LOAM: "@ybotok/loam@0.2.0-alpha.9" # an exact version: bump it in a PR of its own
|
|
271
|
+
BASE: origin/${{ github.base_ref }}
|
|
247
272
|
steps:
|
|
248
273
|
- uses: actions/checkout@v4
|
|
249
|
-
with: { fetch-depth: 0 } #
|
|
274
|
+
with: { fetch-depth: 0 } # every step reads the base out of git history
|
|
250
275
|
- uses: actions/setup-node@v4
|
|
251
276
|
with: { node-version: 22 }
|
|
252
|
-
# did you
|
|
253
|
-
|
|
277
|
+
# did you remove something an authored consumer still names? (fails) — and
|
|
278
|
+
# who is joined to each operation or message you changed? (warns, naming them)
|
|
279
|
+
- run: npx -y "$LOAM" diff --base "$BASE"
|
|
254
280
|
# did you document what you touched?
|
|
255
|
-
- run: npx -y
|
|
281
|
+
- run: npx -y "$LOAM" validate --all --base "$BASE" --strict
|
|
282
|
+
# does a changed operation break its readers? oasdiff answers that; loam does not
|
|
283
|
+
- run: |
|
|
284
|
+
for spec in $(git diff --name-only --diff-filter=M "$BASE"... -- 'services/*openapi.yaml'); do
|
|
285
|
+
git show "$BASE:./$spec" > "$RUNNER_TEMP/base.yaml"
|
|
286
|
+
docker run --rm -v "$RUNNER_TEMP:/base:ro" -v "$PWD:/head:ro" tufin/oasdiff \
|
|
287
|
+
breaking /base/base.yaml "/head/$spec" --fail-on ERR
|
|
288
|
+
done
|
|
256
289
|
```
|
|
257
290
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
291
|
+
**Pin loam, and move the pin on purpose.** An unpinned `npx -y @ybotok/loam` runs whatever the
|
|
292
|
+
`latest` tag points at on the day the job starts, so a release can change what gates your pull
|
|
293
|
+
requests in the middle of a review. Bump `LOAM` in a pull request of its own: run
|
|
294
|
+
`loam subsystem sync` with the new version, update the `<!-- generated by loam vX.Y.Z -->` stamp
|
|
295
|
+
in the docs repo's `AGENTS.md`, and read the release's CHANGELOG entry, which opens with what a
|
|
296
|
+
repository notices after upgrading. Pin the oasdiff image's tag the same way.
|
|
297
|
+
|
|
298
|
+
Three steps, three different questions, and none is another's cheaper form. `diff` reports every
|
|
299
|
+
removal against the fleet's authored consumers — landscape edges, other services' living
|
|
300
|
+
requirements, use-case hops — rather than against a rule list, which is why it repays installation
|
|
301
|
+
before anything else exists. It names who is joined to a changed operation or message, and it never
|
|
302
|
+
says whether the change breaks them: loam does not read what a schema says, so a renamed required
|
|
303
|
+
field and a new optional one are the same warning to it. That half is oasdiff's, and
|
|
304
|
+
`asyncapi diff`'s for event contracts. A caller drawn on the map with no operation on its edge is
|
|
305
|
+
listed as one nobody could check, never counted as no caller. `validate --base` grades the
|
|
306
|
+
boundaries this branch changed, at full strictness, and says out loud how much of the system that
|
|
307
|
+
was — a run with nothing in scope prints that it graded nothing rather than the word valid.
|
|
308
|
+
Unscoped, neither setting is usable on a partly-documented system: `loam validate --all` is green
|
|
309
|
+
over boundaries nobody has written yet, because warnings do not gate, and `--strict` over all of
|
|
310
|
+
them is red from the first minute of adoption until the last one is done.
|
|
311
|
+
|
|
312
|
+
An archive's PR stays red under `--base --strict` until its re-vouches land: the merge moves every
|
|
313
|
+
vouched spec it touches under its vouch stamp, so `content.stale` follows, and `loam archive` names
|
|
314
|
+
each such spec and its owner (`revouchOwed`) so those re-vouches can join the same PR.
|
|
266
315
|
|
|
267
316
|
**A `--base`-scoped validate cannot see a victim boundary the change did not touch.** Remove an
|
|
268
317
|
operation `payment-service` owns, and `checkout-web` — whose living requirement still names it —
|
|
269
318
|
is not in scope, so nothing in that gate reports the broken join. That is `loam diff --base`'s
|
|
270
319
|
question, it stays `loam diff --base`'s, and a green scoped validate is not a statement about the
|
|
271
|
-
consumers of what changed.
|
|
320
|
+
consumers of what changed. A join the branch itself *wrote* is the other case: a call edge it adds
|
|
321
|
+
or edits in `architecture/` is graded against its provider's contract even with the provider out of
|
|
322
|
+
scope, so the one-letter `authorisePayment` above fails on the PR that introduces it.
|
|
323
|
+
[WORKFLOW.md](WORKFLOW.md#what-actually-gates) has what each does and
|
|
272
324
|
does not grade — including the oasdiff invocation for the byte-level OpenAPI breaking-change
|
|
273
325
|
catalogue, which loam deliberately does not reimplement.
|
|
274
326
|
|
|
327
|
+
### Check each service repo on its own pull requests
|
|
328
|
+
|
|
329
|
+
The docs repo's job cannot see provenance. `sources` resolve only inside a service's own
|
|
330
|
+
repository, so `sources.stale` — the code under a vouched spec moved — surfaces only in that
|
|
331
|
+
service repo's CI ([SCHEMA.md](SCHEMA.md), "Operating at fleet scale"). Its committed `loam.json`
|
|
332
|
+
reaches the docs repo through a relative `docsDir` such as `"../docs"`, so the job rebuilds the
|
|
333
|
+
side-by-side layout a laptop has. `actions/checkout` refuses `path: ../docs` — it writes only
|
|
334
|
+
beneath `GITHUB_WORKSPACE` — so check out **both** repositories as subdirectories of the workspace,
|
|
335
|
+
siblings, and run loam from the service's:
|
|
336
|
+
|
|
337
|
+
```yaml
|
|
338
|
+
# .github/workflows/loam.yml — in each service repo
|
|
339
|
+
name: loam
|
|
340
|
+
on: pull_request
|
|
341
|
+
jobs:
|
|
342
|
+
docs:
|
|
343
|
+
runs-on: ubuntu-latest
|
|
344
|
+
env:
|
|
345
|
+
LOAM: "@ybotok/loam@0.2.0-alpha.9" # the docs repo's pin: move them together
|
|
346
|
+
SERVICE: payment-service # this repo's "service" in its loam.json
|
|
347
|
+
steps:
|
|
348
|
+
# Both repositories as siblings under the workspace, the way a laptop holds
|
|
349
|
+
# them, so the committed "docsDir": "../docs" resolves unchanged.
|
|
350
|
+
- uses: actions/checkout@v4
|
|
351
|
+
with: { path: payment-service }
|
|
352
|
+
- uses: actions/checkout@v4
|
|
353
|
+
with:
|
|
354
|
+
repository: acme/docs # your docs repo
|
|
355
|
+
path: docs # the last segment of docsDir
|
|
356
|
+
token: ${{ secrets.LOAM_DOCS_READ_TOKEN }} # contents: read on the docs repo
|
|
357
|
+
- uses: actions/setup-node@v4
|
|
358
|
+
with: { node-version: 22 }
|
|
359
|
+
- name: loam validate --service
|
|
360
|
+
working-directory: payment-service
|
|
361
|
+
run: |
|
|
362
|
+
rc=0
|
|
363
|
+
npx -y "$LOAM" validate --service "$SERVICE" --json > "$RUNNER_TEMP/loam.json" || rc=$?
|
|
364
|
+
# one annotation per error and warning; a refusal (docs-missing, …) is one error
|
|
365
|
+
jq -r '
|
|
366
|
+
def esc: gsub("%"; "%25") | gsub("\r"; "%0D") | gsub("\n"; "%0A");
|
|
367
|
+
if .ok then
|
|
368
|
+
.targets[].findings[] | select(.severity != "ok")
|
|
369
|
+
| "::\(if .severity == "error" then "error" else "warning" end) title=\(.code)::\(.message | esc) (docs: \(.locations[0].path))"
|
|
370
|
+
else "::error title=\(.error.code)::\(.error.message | esc)" end
|
|
371
|
+
' "$RUNNER_TEMP/loam.json"
|
|
372
|
+
# the same findings as a table on the run's summary page
|
|
373
|
+
jq -r '
|
|
374
|
+
if .ok then
|
|
375
|
+
"### loam validate --service \(.targets[0].id) — \(.summary.errors) error(s), \(.summary.warnings) warning(s)",
|
|
376
|
+
"", "| severity | code | finding |", "|---|---|---|",
|
|
377
|
+
(.targets[].findings[] | select(.severity != "ok")
|
|
378
|
+
| "| \(.severity) | `\(.code)` | \(.message | gsub("\\|"; "\\|") | gsub("\n"; " ")) |")
|
|
379
|
+
else "### loam refused: `\(.error.code)`", "", .error.message end
|
|
380
|
+
' "$RUNNER_TEMP/loam.json" >> "$GITHUB_STEP_SUMMARY"
|
|
381
|
+
exit "$rc"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Run from a `payment-service` checkout beside `examples/docs`, in a repository with no
|
|
385
|
+
`src/main/java/` — the source that service's specs name — the step exits 1 and prints:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
::warning title=spine.op-link-missing::payment-service: landscape edge checkout-web → payment-service ("Calls the payment API") has no operation link (metadata { op }) (docs: services/payment-service)
|
|
389
|
+
::error title=sources.path-missing::payment-service: spec.md: 1 source(s) do not exist — src/main/java/ (docs: services/payment-service)
|
|
390
|
+
::error title=sources.path-missing::payment-service: arch.spec.md: 1 source(s) do not exist — src/main/java/ (docs: services/payment-service)
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
The annotations carry no `file=`, on purpose: every location loam reports is a path in the docs
|
|
394
|
+
repo, which is not the repository this pull request diffs, so GitHub could not place one on a line
|
|
395
|
+
here. They land on the check run and its summary instead. A docs repo that is private needs a token
|
|
396
|
+
that can read it — a fine-grained token or a GitHub App token with `contents: read` on that one
|
|
397
|
+
repository — because the workflow's own `GITHUB_TOKEN` reads only the repository it runs in. Add
|
|
398
|
+
`--strict` once the service is vouched and its warnings are ones you mean to keep at zero; before
|
|
399
|
+
that, the warnings are the adoption still to do.
|
|
400
|
+
|
|
401
|
+
The same layout answers the deploy question. In the deploy pipeline, check the docs repo out with
|
|
402
|
+
`fetch-depth: 0` — `--since` is read from its git history — and ask whether this service may ship:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
npx -y "$LOAM" gate --service "$SERVICE" --since "$DOCS_SHA_OF_LAST_DEPLOY"
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
`gate` executes nothing and writes nothing, and without `--strict` its warnings stay advisory;
|
|
409
|
+
[WORKFLOW.md](WORKFLOW.md#what-actually-gates) says what each finding of it means for a pipeline.
|
|
410
|
+
|
|
411
|
+
**Cloud agents in a service repo** need the same sibling on disk before they start: a lone clone
|
|
412
|
+
of the service answers every docs-reading command with `docs-missing`. GitHub's Copilot coding
|
|
413
|
+
agent and Codex cloud each start from the one repository the task names and run a setup step you
|
|
414
|
+
own, so clone the docs repo there, into the committed `docsDir`. Copilot reads the job
|
|
415
|
+
`copilot-setup-steps` from `.github/workflows/copilot-setup-steps.yml` on the default branch, and
|
|
416
|
+
an
|
|
417
|
+
[Agents secret](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-cloud-agent/configure-secrets-and-variables)
|
|
418
|
+
reaches those steps as an environment variable:
|
|
419
|
+
|
|
420
|
+
```yaml
|
|
421
|
+
# .github/workflows/copilot-setup-steps.yml — in each service repo
|
|
422
|
+
name: Copilot setup steps
|
|
423
|
+
on: workflow_dispatch
|
|
424
|
+
jobs:
|
|
425
|
+
copilot-setup-steps:
|
|
426
|
+
runs-on: ubuntu-latest
|
|
427
|
+
permissions: { contents: read }
|
|
428
|
+
steps:
|
|
429
|
+
- uses: actions/checkout@v4
|
|
430
|
+
- uses: actions/setup-node@v4
|
|
431
|
+
with: { node-version: 22 }
|
|
432
|
+
- run: npm install -g @ybotok/loam@0.2.0-alpha.9
|
|
433
|
+
# "../docs" is outside the workspace, so git clone rather than actions/checkout;
|
|
434
|
+
# the second command takes the token back out of the clone's config
|
|
435
|
+
- run: |
|
|
436
|
+
git clone --depth 1 "https://x-access-token:${LOAM_DOCS_READ_TOKEN}@github.com/acme/docs.git" ../docs
|
|
437
|
+
git -C ../docs remote set-url origin https://github.com/acme/docs.git
|
|
438
|
+
- run: loam doctor
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Codex cloud has no workflow file: the same commands go in the environment's setup script, with
|
|
442
|
+
the token as an environment **secret** — Codex hands secrets to the setup script only and removes
|
|
443
|
+
them before the agent phase, which is all a clone needs. Pin Node.js to 22 or newer in the
|
|
444
|
+
environment's package versions, and spell the target from the repository root, because where the
|
|
445
|
+
script starts is not documented:
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
npm install -g @ybotok/loam@0.2.0-alpha.9
|
|
449
|
+
DOCS="$(git rev-parse --show-toplevel)/../docs"
|
|
450
|
+
git clone --depth 1 "https://x-access-token:${LOAM_DOCS_READ_TOKEN}@github.com/acme/docs.git" "$DOCS"
|
|
451
|
+
git -C "$DOCS" remote set-url origin https://github.com/acme/docs.git
|
|
452
|
+
loam doctor
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The clone is the agent's reading, not a second place it can deliver. A cloud agent opens its pull
|
|
456
|
+
request against the repository it was started in, so anything it writes into the docs checkout —
|
|
457
|
+
a verification record, a spec edit — stays in its sandbox. `loam-implement`'s own outputs, the
|
|
458
|
+
generated Gherkin and the code, land in the service repo as usual; what belongs in the docs repo
|
|
459
|
+
goes there through that repo's own pull request.
|
|
460
|
+
|
|
275
461
|
### Try loam on one governed system in five minutes
|
|
276
462
|
|
|
277
463
|
The full model may be one application or a fleet; the trial is one repository. In the codebase you
|
|
@@ -350,29 +536,30 @@ cannot hold.
|
|
|
350
536
|
|---|---|---|
|
|
351
537
|
| `loam init` | `--docs <dir>` `--service <id>` `--create` `--force` `--tools <ids>` `--agent-profile <full\|service\|docs>` `--example <dir>` `--no-commands` `--no-skills` `--mcp` `--mcp-author` | Bind this repository to the single shared docs repo: a committed local `loam.json`, plus command and Agent Skill pointers for detected AI tools. Profiles narrow the six lifecycle workflows to a repo's role; the support-only `loam-report` stays in every profile. Re-running init refreshes only unchanged loam-owned pointers; edited files are preserved. `--mcp` writes the read-only host entry, while `--mcp-author` opts into the bounded authoring tools. `--create` scaffolds the docs repo; `--example` copies the packaged example and stops |
|
|
352
538
|
| `loam seed` | `--from <file>` | Template the fleet map and one `services/<id>/` directory per service from a tiny human-authored `fleet.yaml`. Mechanical, never a guess: a human stated every fact. Refuses once the landscape has been hand-edited |
|
|
353
|
-
| `loam list [services\|features\|capabilities\|glossary]` | `--archived` `--needs-work` `--review-order` `--subsystem <name>` `--owners <path>` | What is in the docs repo, and what is missing from it. `capabilities` rolls up who realizes each promise; `glossary` rolls up each term with the documents that cite it |
|
|
539
|
+
| `loam list [services\|features\|capabilities\|glossary\|suites]` | `--archived` `--needs-work` `--review-order` `--subsystem <name>` `--owners <path>` | What is in the docs repo, and what is missing from it. `capabilities` rolls up who realizes each promise; `glossary` rolls up each term with the documents that cite it; `suites` groups the use cases by `#suite-` tag and names the services each suite needs up (`loam list suites <name>` shows one) |
|
|
354
540
|
| `loam status [<FEAT>]` | `--service <id>` | Where the work stands and what to do next, as a projection over the two gates. Each `next[]` row has an `execution` object that says whether it is runnable, where, and what input or edit is still needed. Derived every run; writes nothing |
|
|
355
541
|
| `loam doctor` | — | Read-only preflight for runtime, config, docs-repo access, fleet roots, counts, and the current service binding. Blockers exit 1; incomplete optional bindings stay warnings |
|
|
356
542
|
| `loam dependencies [<FEAT>]` | — | The active-feature dependency graph and same-identity conflicts, derived from requirement deltas and OpenAPI operationIds |
|
|
357
|
-
| `loam diff` | `--base <ref>` | Semantic diff of the living docs against a base git ref of the docs repo — the review lens for a docs-repo PR, with the
|
|
543
|
+
| `loam diff` | `--base <ref>` | Semantic diff of the living docs against a base git ref of the docs repo — the review lens for a docs-repo PR, with the authored consumers of every removal, deprecation and contract change named. Exit 1 on a removal the fleet still consumes |
|
|
358
544
|
| `loam explore [<service>...]` | `--op <operationId>` `--capability <id>` `--as <FEAT>` | Read the fleet around a change nobody has written down yet: the ring one hop out, each service's maturity and living operations, the features already in flight over the same ground, and the `loam new` line the seeds imply |
|
|
359
545
|
| `loam context <service>` | `--feature <FEAT>` | Assemble one service's docs slice — living requirements verbatim, both contracts, the fleet edges around it, permissions, capabilities, provenance, and every active feature's delta over it — as one deterministic briefing |
|
|
360
546
|
| `loam steps` | `--service <id>` `--duplicates` `--json` | Inventory the step phrases of one service's scenarios: how many distinct steps its suite is written in, how few definitions cover most of them, and which phrases differ only by an article or a trailing clause. Reads the living specs, writes nothing — the work-list a team writes its step definitions from, diffed against the optional `services/<svc>/steps.yaml` catalogue when one exists |
|
|
361
|
-
| `loam instructions [<workflow>] [args...]` | `--no-fix-tables` | Print one of the six workflow protocols, the separate `loam-report` support protocol, or one of the four reference pages `loam-codes`, `loam-spine`, `loam-authoring` and `loam-done-check`, version-matched to this binary. Workflow `$1`/`$2` placeholders are filled; support/reference pages take no arguments. Reads no config. `--no-fix-tables` collapses the per-code fix tables to a line each, keeping the paragraph that says which scope graded them: `loam-check`'s page
|
|
362
|
-
| `loam explain [<subject>]` | `--codes` | Explain a finding code, a refusal code, or a concept term. Most finding prose is parsed at runtime from the shipped fix tables, so it cannot drift from the binary; the `doctor.*`, `next.*`, `diff.*` and `gate.*` families, which no fix table grades, are answered from a registry written beside them. Every text-mode refusal prints `<code> · loam explain <code>` on stderr and every non-`ok` finding line carries its code in parentheses, so the lookup is reachable without re-running under `--json`. Omit the subject to list the terms; `--codes` lists the whole vocabulary —
|
|
547
|
+
| `loam instructions [<workflow>] [args...]` | `--no-fix-tables` | Print one of the six workflow protocols, the separate `loam-report` support protocol, or one of the four reference pages `loam-codes`, `loam-spine`, `loam-authoring` and `loam-done-check`, version-matched to this binary. Workflow `$1`/`$2` placeholders are filled; support/reference pages take no arguments. Reads no config. `--no-fix-tables` collapses the per-code fix tables to a line each, keeping the paragraph that says which scope graded them: `loam-check`'s page, almost all of it fix tables, comes back in a few kilobytes, while a support/reference page holds no such table and comes back byte-identical |
|
|
548
|
+
| `loam explain [<subject>]` | `--codes` | Explain a finding code, a refusal code, or a concept term. Most finding prose is parsed at runtime from the shipped fix tables, so it cannot drift from the binary; the `doctor.*`, `next.*`, `diff.*` and `gate.*` families, which no fix table grades, are answered from a registry written beside them. Every text-mode refusal prints `<code> · loam explain <code>` on stderr and every non-`ok` finding line carries its code in parentheses, so the lookup is reachable without re-running under `--json`. Omit the subject to list the terms; `--codes` lists the whole vocabulary — every finding code and every refusal code it can answer, each row the same answer `explain <code> --json` gives for that one |
|
|
363
549
|
| `loam open` | `--root <dir>` `--out <file>` `--force` | Write a `.code-workspace` joining the docs repo and every service checkout whose committed `loam.json` binds to it. Never overwrites without `--force` |
|
|
364
|
-
| `loam mcp` | `--author` | Serve
|
|
365
|
-
| `loam new <FEAT>` | `--title <text>` `--touches <id>` `--new-service <id>` `--capability <id>` | Scaffold a feature: intent, C4 delta, a requirement delta per service named by `--touches`/`--new-service`, and a capability delta per promise named by `--capability` (all repeatable) |
|
|
550
|
+
| `loam mcp` | `--author` | Serve sixteen read tools, version-matched instruction resources and a declared envelope output schema over MCP. `--author` adds `new`, `rebase`, `gherkin` and an archive dry-run; it never exposes `vouch`, verification recording or a committing archive — [the MCP server](WORKFLOW.md#the-mcp-server) |
|
|
551
|
+
| `loam new <FEAT>` | `--title <text>` `--touches <id>` `--new-service <id>` `--capability <id>` `--modifies <Req-ID>` | Scaffold a feature: intent, C4 delta, a requirement delta per service named by `--touches`/`--new-service`, and a capability delta per promise named by `--capability` (all repeatable). `--modifies` copies a touched service's living requirement into an uncommented `## MODIFIED Requirements` block with its `Based-On:` pin already set, so a small change is new → edit → archive; when every touched service is rewritten that way and nothing is introduced, no `delta.likec4` is written |
|
|
366
552
|
| `loam show <service\|FEAT>` | `--type <kind>` | Everything loam knows about one service or feature. A feature's JSON includes a semantic `review` pack: intent, exact architecture objects, API/event slices, dependencies, artifacts, verification, blockers and next actions. `--type` forces an ambiguous reading |
|
|
367
553
|
| `loam subsystem <verb> [names...]` | `--into <name>` `--under <name>` `--title <text>` `--description <text>` `--owner <name>` | Manage the grouping tree under `services/` — a navigable tree no identity depends on. `new`/`rm`, `move … --into`, `rename`, `list`, `history`, `sync` |
|
|
368
|
-
| `loam adopt` | `--service <id>` `--subsystem <name>` `--targets` | Brief an agent to write this service's baseline into the docs repo as `draft`: the target paths, the grammar of each, what the landscape already says — and, for an element no edge touches, the edges the service's own model.likec4 attests — and the checks that follow. Writes nothing. `--targets` narrows it to what varies by service — the walk, the 52 checks and the seventeen statements of what nothing checks are the same bytes everywhere, so a `full` field names the one run that carries them
|
|
554
|
+
| `loam adopt` | `--service <id>` `--subsystem <name>` `--targets` | Brief an agent to write this service's baseline into the docs repo as `draft`: the target paths, the grammar of each, what the landscape already says — and, for an element no edge touches, the edges the service's own model.likec4 attests — and the checks that follow. Writes nothing. `--targets` narrows it to what varies by service — the walk, the 52 checks and the seventeen statements of what nothing checks are the same bytes everywhere, so a `full` field names the one run that carries them. Both sizes, for the example fleet's payment-service, are in the payload table of [docs/BENCHMARKS.md](https://github.com/ybotok/loam/blob/main/docs/BENCHMARKS.md#what-an-agent-is-handed--payload-sizes), which a test regenerates from the tree |
|
|
369
555
|
| `loam delta <FEAT>` | `--service <id>` | Project a feature onto one service: the intent, its requirement deltas with every body and Given/When/Then line verbatim, the endpoints it adds or retires, and the edges around it. Doubles as a coding-agent task |
|
|
556
|
+
| `loam tasks <FEAT>` | `--service <id>` `--next` | The same checklist `loam verify` grades, read forwards: one work unit per promise the feature makes, each carrying the step it waits on (`describe`, `generate`, `implement`, `attested`) and the fact that closes it — only a confirmed claim in a non-stale verification record retires one, and an attested scenario stays visible. Derived every run and writes nothing. `--service` is a pure lens that adds what this service is waiting on elsewhere; the frontier orders providers before consumers as advice, never a lock. The per-unit work packet, and `--next` is the single leaf packet an orchestrator hands a coding agent |
|
|
370
557
|
| `loam gherkin [<FEAT>]` | `--service <id>` `--dry-run` | Emit spec scenarios as digest-stamped Gherkin `.feature` files into the service repo's `<gherkinDir>/loam/` |
|
|
371
558
|
| `loam rebase [<FEAT>]` | `--service <id>` `--dry-run` `--living` | Pin the feature to the living versions it was written against, on the requirement axis and the contract axis. `--living` takes no feature: it pins the living corpus's `Realizes:` entries to the capability requirements they name, which is what makes `capability.realizes-stale` able to fire later |
|
|
372
559
|
| `loam validate [<id>]` | `--service <id>` `--feature <id>` `--all` `--base <ref>` `--strict` `--errors-only` | Validate one service or feature, or the whole fleet in one run. JSON findings carry `locations[]`: an exact primary location when the check knows one, otherwise the narrowest proved scope. `--base` is the adoption ratchet, not a substitute for `loam diff`; `--strict` exits 1 on warnings; `--errors-only` drops the `ok` confirmations from the text view, keeping every warning |
|
|
373
560
|
| `loam verify <FEAT>` | `--record <file>` `--results <file>` `--contract-results <file>` `--diff-answers <files...>` `--service <id>` | The done-check: derive a checklist of the feature's own promises, and record the answers with their evidence. `--results`/`--contract-results` answer claims from a test report; `--diff-answers` cross-examines two blind answer sets |
|
|
374
561
|
| `loam vouch` | `--service <id>` `--yes` `--pack` `--sample <n>` | The human promotion `draft` → `verified`: stamp a living spec against the code it was written from. `--pack` prints the re-vouch reading pack; `--sample <n>` records a partial read as one. Run in the service's own repo |
|
|
375
|
-
| `loam gate` | `--service <id>` `--strict` | Can this service deploy? A pure query over recorded evidence for deploy pipelines outside loam's lifecycle. Executes nothing, writes nothing; errors exit 1, warnings stay advisory |
|
|
562
|
+
| `loam gate` | `--service <id>` `--since <ref>` `--strict` | Can this service deploy? A pure query over recorded evidence for deploy pipelines outside loam's lifecycle. Executes nothing, writes nothing; errors exit 1, warnings stay advisory. Without `--since` it grades in-flight features only; `--since` (the docs commit the last deploy recorded) adds every feature archived after it |
|
|
376
563
|
| `loam archive <FEAT>` | `--approve` `--dry-run` | Merge a shipped feature into the living specs, API, events, business tree and landscape; gated on what only the computed merge can see. `--approve` overrides the judgement calls, never the mechanical losses |
|
|
377
564
|
| `loam unarchive <FEAT>` | `--force` | Take that back: restore the living docs from the snapshot archive left behind, and re-open the feature |
|
|
378
565
|
| `loam audit-openspec <root>` | `--write-mapping <path>` | Read-only inventory of an OpenSpec checkout/workspace/Store checkout. `--write-mapping` emits the decision skeleton you fill in |
|
|
@@ -398,7 +585,9 @@ repo it runs in, every `init` writes pointers for the six workflow bodies (`loam
|
|
|
398
585
|
twenty-one targets**: as a command file you type — `/loam-check` for most, `/loam:check` where the
|
|
399
586
|
tool namespaces by directory, `@loam-check` in Amazon Q's prompt library — and as an Agent Skill
|
|
400
587
|
at `<tool-dir>/skills/loam-<x>/SKILL.md`, which the model loads by itself when the task matches. Two
|
|
401
|
-
targets are skills only: Codex
|
|
588
|
+
targets are skills only: Codex loads no custom command files, and its target writes
|
|
589
|
+
`.codex/skills/` — a root Codex still reads but no longer documents (its skills page names only
|
|
590
|
+
`.agents/skills`; select `agents` too if you want the documented one) — and
|
|
402
591
|
`agents` is not a tool at all but the vendor-neutral `.agents/skills/` root that Cursor, GitHub
|
|
403
592
|
Copilot, Codex, Gemini CLI, Zed and Roo Code each document reading — one copy those six share
|
|
404
593
|
instead of six copies of the same bytes. `--no-commands` and `--no-skills` each suppress one
|
|
@@ -436,29 +625,31 @@ run. That split exists because the two go stale in opposite directions and only
|
|
|
436
625
|
fixable: embedded protocol text eventually describes a different loam with total confidence, while
|
|
437
626
|
the command cannot. Pointing at the binary is also what makes the protocol
|
|
438
627
|
affordable to load: `loam instructions loam-check --no-fix-tables` prints the same page with its
|
|
439
|
-
per-code fix tables collapsed to a line each —
|
|
440
|
-
`loam explain <code> --json` answers,
|
|
441
|
-
actually reported.
|
|
442
|
-
|
|
628
|
+
per-code fix tables collapsed to a line each — from a page that is almost all tables down to a few
|
|
629
|
+
kilobytes — and `loam explain <code> --json` answers, one code at a time, whichever two or three of
|
|
630
|
+
those rows a run actually reported. What each of those costs in bytes and tokens, page by page, is
|
|
631
|
+
[docs/BENCHMARKS.md](https://github.com/ybotok/loam/blob/main/docs/BENCHMARKS.md)'s payload table,
|
|
632
|
+
generated from the tree rather than typed. A copy frozen into the generated file would have charged
|
|
633
|
+
the whole page every session, and gone stale doing it. `AGENTS.md` itself was the one generated file that argument did
|
|
443
634
|
not reach — it was the process contract *and* the reference manual, and every session paid for all
|
|
444
635
|
of it — so four **reference pages** now come out of the binary instead, printed by
|
|
445
636
|
`loam instructions`: `loam-codes` (which codes each invocation can raise), `loam-spine` (every join
|
|
446
637
|
between the artifacts, and the `Based-On:` pins), `loam-authoring` (`arch.spec.md`, the generated
|
|
447
638
|
Gherkin suite, frontmatter) and `loam-done-check` (how `loam verify` derives its claims, and
|
|
448
639
|
verified versus attested). What stayed is what a reader needs to form a question at all: the layout,
|
|
449
|
-
the cycle, which element is which service, the validator's rules and the archive gate. The
|
|
450
|
-
orientation
|
|
451
|
-
workspace-rule ceiling. Detailed pages are fetched only when the task reaches them. `loam init`
|
|
640
|
+
the cycle, which element is which service, the validator's rules and the archive gate. The
|
|
641
|
+
orientation stays below both the 32,768-byte Codex chain limit and the smaller 12,000-byte
|
|
642
|
+
workspace-rule ceiling — `test/agents.test.ts` fails the build the day it does not. Detailed pages are fetched only when the task reaches them. `loam init`
|
|
452
643
|
writes **no file** for a reference page: a page printed on demand describes the loam you are
|
|
453
644
|
running, not the one that scaffolded the repository.
|
|
454
645
|
|
|
455
646
|
The code inventory is that same split applied twice, and the largest page is what it left behind.
|
|
456
|
-
`loam instructions loam-codes` lists which codes each invocation can raise —
|
|
457
|
-
scaffolded docs name
|
|
647
|
+
`loam instructions loam-codes` lists which codes each invocation can raise — nearly every code the
|
|
648
|
+
scaffolded docs name, and the one fact no other surface carries — and no longer says what
|
|
458
649
|
any of them means, because `loam explain <code>` answers that from the binary actually running and a
|
|
459
650
|
paragraph written once at `init` cannot. Dropping the duplicated gloss came first and took the file
|
|
460
651
|
from 120,896 bytes to 109,399; moving the inventory off it took the remaining 79,679. The OpenSpec
|
|
461
|
-
migration codes keep their notes inline on the page, because they are
|
|
652
|
+
migration codes keep their notes inline on the page, because they are almost all of the codes
|
|
462
653
|
`loam explain` does not answer yet, and a pointer to an explanation that does not exist is worse
|
|
463
654
|
than the prose it replaced.
|
|
464
655
|
|
|
@@ -488,15 +679,21 @@ always preserved byte for byte, with the entry printed for manual merge.
|
|
|
488
679
|
- [COMPARISON.md](COMPARISON.md) — where loam fits beside architecture-as-code tools, software and
|
|
489
680
|
event catalogs, contract verification and diff engines, requirements traceability, and code-level
|
|
490
681
|
architecture checks. Each is treated as a neighbouring specialist, not an opponent loam needs to
|
|
491
|
-
replace.
|
|
682
|
+
replace. One dated section sets out what the spec-driven change tools — OpenSpec, Spec Kit and
|
|
683
|
+
Kiro — each offer for a change that crosses repositories, what is still open upstream, and where
|
|
684
|
+
loam differs.
|
|
492
685
|
- [MIGRATING-from-OpenSpec.md](MIGRATING-from-OpenSpec.md) — moving an OpenSpec repo onto loam: what
|
|
493
686
|
maps, what is lost, what must be added.
|
|
494
687
|
- [ROADMAP.md](ROADMAP.md) — the evidence-backed improvement plan, priorities, non-goals and exit
|
|
495
688
|
criteria.
|
|
496
|
-
- [CHANGELOG.md](CHANGELOG.md) — released beta.1–alpha.
|
|
689
|
+
- [CHANGELOG.md](CHANGELOG.md) — released beta.1–alpha.9 plus the changes on `main` under
|
|
497
690
|
`[Unreleased]`.
|
|
691
|
+
- [docs/SERVICE-TEAMS.md](https://github.com/ybotok/loam/blob/main/docs/SERVICE-TEAMS.md) — one
|
|
692
|
+
screen for a team whose repository is one service in the fleet: the commands, the slash
|
|
693
|
+
commands, what to know before vouching, and the codes they will actually meet.
|
|
498
694
|
- [docs/BENCHMARKS.md](https://github.com/ybotok/loam/blob/main/docs/BENCHMARKS.md) — what a
|
|
499
|
-
fleet-sized run costs, with the method, the machine and the committed runs behind every number
|
|
695
|
+
fleet-sized run costs, with the method, the machine and the committed runs behind every number,
|
|
696
|
+
and what each payload loam hands an agent weighs in bytes and tokens.
|
|
500
697
|
|
|
501
698
|
## Development
|
|
502
699
|
|
|
@@ -509,9 +706,9 @@ npm run arch:check # package-level dependency graph stays acyclic
|
|
|
509
706
|
npm test # vitest
|
|
510
707
|
npm run test:coverage # full src/**/*.ts coverage with enforced thresholds
|
|
511
708
|
npm run test:package # clean, pack, install the tarball, run its loam binary
|
|
512
|
-
# optional, against the exact upstream checkout named in MIGRATING-from-OpenSpec.md
|
|
513
|
-
#
|
|
514
|
-
# at any other HEAD):
|
|
709
|
+
# optional, against the exact upstream checkout named in MIGRATING-from-OpenSpec.md
|
|
710
|
+
# (--baseline defaults to release, the certified pin; every pinned baseline refuses a
|
|
711
|
+
# checkout at any other HEAD, and only --baseline latest sweeps an unpinned one):
|
|
515
712
|
npm run test:openspec-corpus -- --baseline release /path/to/OpenSpec
|
|
516
713
|
```
|
|
517
714
|
|
|
@@ -529,15 +726,17 @@ authored-capability axes with the `Realizes:` join, use cases graded as `dynamic
|
|
|
529
726
|
`architecture/obligations.yaml` architectural obligations checked through `#obl-` tags and
|
|
530
727
|
`Covers:`. Known limits, each with its owner in [ROADMAP.md](ROADMAP.md): the scheduled CI
|
|
531
728
|
`stability` job has still to be observed green. Speculative `render`, health composition and UI
|
|
532
|
-
generation come later. Behind that status stand **
|
|
729
|
+
generation come later. Behind that status stand **190 test files** (counted 2026-10-20): the count is graded
|
|
533
730
|
against a live readdir by `test/docs-facts.test.ts`, so this sentence fails the suite the moment it
|
|
534
731
|
trails the tree.
|
|
535
732
|
|
|
536
|
-
The package is published as [`@ybotok/loam`](https://www.npmjs.com/package/@ybotok/loam)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
([CONTRIBUTING.md](CONTRIBUTING.md))
|
|
540
|
-
drift test, so it
|
|
733
|
+
The package is published as [`@ybotok/loam`](https://www.npmjs.com/package/@ybotok/loam): the
|
|
734
|
+
unscoped `loam` name is taken by an unrelated GDAL wrapper, so the package ships under the
|
|
735
|
+
maintainer's own npm user scope. Releases are tag-driven and maintainer-only
|
|
736
|
+
([CONTRIBUTING.md](CONTRIBUTING.md)). This checkout is `0.2.0-alpha.9` — a version pinned to
|
|
737
|
+
`package.json` by a drift test, so it is always the version of the checkout you are reading, and for
|
|
738
|
+
that reason it says nothing about whether that version reached npm.
|
|
739
|
+
`npm view @ybotok/loam dist-tags` is the answer to what installs.
|
|
541
740
|
|
|
542
741
|
## Contributing
|
|
543
742
|
|