@ybotok/loam 0.1.0-beta.2 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2570 -61
- package/COMPARISON.md +80 -63
- package/CONTRIBUTING.md +84 -0
- package/MIGRATING-from-OpenSpec.md +213 -54
- package/QUICKSTART.md +125 -0
- package/README.md +450 -150
- package/ROADMAP.md +494 -0
- package/SCHEMA.md +2362 -245
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +701 -0
- package/dist/cli.js +113 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +209 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +268 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +77 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +159 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +317 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +161 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +111 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +237 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +27 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +251 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/context/context.js +99 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +283 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +279 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +205 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +9 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +93 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +5 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +151 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +29 -24
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +115 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +54 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +146 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +246 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +149 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +28 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +146 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +82 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +65 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +157 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +343 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +301 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/views.js +105 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +183 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +34 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +170 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +19 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/commit.js +76 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/new.js +283 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +355 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +203 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +275 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +192 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +133 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +172 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +178 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/marks.js +24 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/{show.js → show/service.js} +63 -152
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +77 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/json.js +45 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +157 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +119 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +189 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +265 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +115 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +101 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +103 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +94 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +70 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +160 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +67 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +194 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +296 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +55 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +254 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +76 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/checks/vocabulary.js +31 -0
- package/dist/commands/validate/checks/vocabulary.js.map +1 -0
- package/dist/commands/validate/feature.js +216 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +69 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +353 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +52 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +236 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +63 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/steps.js +197 -0
- package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +40 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +59 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +92 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/report.js +269 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/service/api.js +338 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +219 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +131 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/service.js +250 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +219 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +113 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/validate.js +338 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +182 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +72 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +241 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +226 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +223 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +246 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +217 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +271 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +142 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +285 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +125 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +123 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +176 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/artifacts.js +220 -0
- package/dist/core/agent/agents-md/artifacts.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +324 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/cycle.js +165 -0
- package/dist/core/agent/agents-md/cycle.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +34 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +41 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +62 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +32 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +60 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +246 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
- package/dist/core/agent/agents-md/spine.js +40 -0
- package/dist/core/agent/agents-md/spine.js.map +1 -0
- package/dist/core/agent/agents-md.js +170 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/agent/agents-stamp.js +155 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +259 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +103 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +150 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +228 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +133 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +334 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +262 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +105 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +105 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +209 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +65 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +188 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +16 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +297 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +110 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +141 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +91 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +33 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +308 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +215 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +107 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/asyncapi/read.js +239 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +225 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +250 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +194 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/targets.js +226 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +47 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +282 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +88 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +57 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +75 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/project/architecture.js +45 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/documents.js +58 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +183 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/resolve/service.js +113 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +109 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/source-mask.js +82 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +227 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +101 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +10 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +126 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +36 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +269 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +194 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/workspace.js +172 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +50 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +342 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +181 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +143 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +199 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +126 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +277 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +177 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +74 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/coherence.js +251 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/declared.js +269 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +206 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +204 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +166 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +122 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/merged.js +40 -0
- package/dist/core/coherence/events/merged.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +155 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +296 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/diff/base-git.js +148 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +209 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/current-state.js +96 -0
- package/dist/core/diff/current-state.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +188 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/semantic.js +243 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/diff/victims.js +247 -0
- package/dist/core/diff/victims.js.map +1 -0
- package/dist/core/docs.js +59 -55
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +222 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +135 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +275 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +77 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +263 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +221 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +241 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +79 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +175 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +175 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +181 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms.js +144 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/{explore.js → explore/explore.js} +50 -101
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +132 -77
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +201 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +205 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +113 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +234 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +106 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +86 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +68 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +104 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +236 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +111 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +72 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +314 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +166 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +112 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +175 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/depth.js +122 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +189 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +44 -106
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +234 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +26 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +208 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +256 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +128 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +221 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +76 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +65 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +235 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +200 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +260 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +133 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +118 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +76 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/provenance/findings.js +208 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +225 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +182 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +263 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +232 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +192 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +236 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +248 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +52 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +64 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/views.js +172 -0
- package/dist/core/repo/tree/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +234 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +99 -2
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +131 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +241 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +206 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +98 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +126 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot.js +202 -0
- package/dist/core/staging/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +171 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +49 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +102 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +171 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +207 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +150 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +187 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +207 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +201 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/usecases/capability.js +169 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +116 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +103 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +235 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +137 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/operations.js +111 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +173 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +150 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +201 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/file.js +257 -0
- package/dist/core/verify/file.js.map +1 -0
- package/dist/core/verify/pins/lint.js +157 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/record.js +142 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +89 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +57 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +55 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +145 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/{report.js → vocabulary/report.js} +30 -2
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +189 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +280 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/subsystems.likec4 +11 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +9 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +109 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +127 -0
- package/examples/docs/services/order-service/asyncapi.yaml +108 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +138 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +73 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +67 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
- package/examples/docs/services/platform/notification-service/health.yaml +35 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -291
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -254
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1591
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -343
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2065
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js +0 -68
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/brief.js +0 -733
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -559
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -479
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -720
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -436
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -481
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1104
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
- /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
- /package/dist/core/{records.js → kernel/records.js} +0 -0
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { PROTOCOLS, WORKFLOWS, protocolFor } from "../core/agent.js";
|
|
2
|
-
import { emitJson, fail } from "../core/json.js";
|
|
3
|
-
import { LOAM_VERSION } from "../core/version.js";
|
|
1
|
+
import { PROTOCOLS, REFERENCE_PAGES, SUPPORT_PAGES, WORKFLOWS, placeholderProblems, protocolFor, } from "../core/agent/protocol.js";
|
|
2
|
+
import { emitJson, fail } from "../core/envelope/json.js";
|
|
3
|
+
import { LOAM_VERSION } from "../core/envelope/version.js";
|
|
4
|
+
import { withoutFixTables } from "../core/explain/fix-tables.js";
|
|
4
5
|
/**
|
|
5
|
-
* The workflow protocols, from the binary rather than
|
|
6
|
-
* generated once.
|
|
6
|
+
* The workflow protocols and the reference pages, from the binary rather than
|
|
7
|
+
* from a file somebody generated once.
|
|
8
|
+
*
|
|
9
|
+
* The pages are the newer half and the reason this command now has two lists.
|
|
10
|
+
* They are the sections that left the scaffolded AGENTS.md — a file every
|
|
11
|
+
* agents.md-aware host auto-loads on every session, which two hosts truncate
|
|
12
|
+
* silently — and they are printed here instead. That trade only works if they
|
|
13
|
+
* can be FOUND, so the bare menu names them; `core/agent/workflows/reference/
|
|
14
|
+
* reference.ts` carries the rest of the argument.
|
|
7
15
|
*
|
|
8
16
|
* This is the only command in loam that reads nothing: no `loam.json`, no docs
|
|
9
17
|
* repo, no service. That is deliberate and it is the point — an agent runs this
|
|
@@ -16,10 +24,25 @@ import { LOAM_VERSION } from "../core/version.js";
|
|
|
16
24
|
export function registerInstructions(program) {
|
|
17
25
|
program
|
|
18
26
|
.command("instructions")
|
|
19
|
-
|
|
27
|
+
// Still spelled `workflow`, not `page`: the positional is in every
|
|
28
|
+
// generated command file loam has ever written (`loam instructions
|
|
29
|
+
// loam-adopt $1`) and in `--help` output people have copied. Renaming it
|
|
30
|
+
// buys a more accurate word in one usage line and costs nothing anywhere
|
|
31
|
+
// the rename would be visible, so the accuracy goes in the menu text instead.
|
|
32
|
+
.argument("[workflow]", "workflow or reference page (loam-adopt, loam-codes, …); omit to list them")
|
|
20
33
|
.argument("[args...]", "values substituted for the protocol's $1, $2, … placeholders")
|
|
21
|
-
.description("Print a workflow protocol, version-matched to this binary")
|
|
34
|
+
.description("Print a workflow protocol or reference page, version-matched to this binary")
|
|
22
35
|
.option("--json", "emit the machine contract instead of the human view")
|
|
36
|
+
// Opt-in, and off by default, so the default page of every lifecycle protocol
|
|
37
|
+
// stays byte-identical: this narrows what an agent CAN ask for, it does not
|
|
38
|
+
// change what it gets when it asks for nothing. The one protocol this is
|
|
39
|
+
// about is /loam-check, whose fix tables are 83 KB of the 84 it prints —
|
|
40
|
+
// about a fifth of a 100k-token window spent before the first check has
|
|
41
|
+
// run — while `loam explain <code>` answers any one of those rows in under
|
|
42
|
+
// 500 bytes. The narrowed page keeps every paragraph that INTRODUCES a
|
|
43
|
+
// table, because that sentence is what says which scope a code was graded
|
|
44
|
+
// in; only the rows go.
|
|
45
|
+
.option("--no-fix-tables", "drop the per-code fix tables; `loam explain <code>` answers any code a run reports")
|
|
23
46
|
// Every positional here is DATA — a feature id, a service id, a validate
|
|
24
47
|
// target — and one of those targets is spelled `--all`. Without this,
|
|
25
48
|
// commander reads a leading-dash argument as an option it does not have and
|
|
@@ -31,32 +54,77 @@ export function registerInstructions(program) {
|
|
|
31
54
|
const json = opts.json === true;
|
|
32
55
|
if (workflow === undefined) {
|
|
33
56
|
if (json) {
|
|
34
|
-
|
|
57
|
+
// `support` and `references` are ADDITIVE beside the `workflows` key
|
|
58
|
+
// a consumer already reads. Appending either kind to `workflows`
|
|
59
|
+
// would have been the smaller diff and the wrong one: a caller
|
|
60
|
+
// iterating that array to drive the cycle would start running
|
|
61
|
+
// diagnostics or documentation as steps.
|
|
62
|
+
emitJson({
|
|
63
|
+
command: "instructions",
|
|
64
|
+
version: LOAM_VERSION,
|
|
65
|
+
workflows: WORKFLOWS,
|
|
66
|
+
support: SUPPORT_PAGES,
|
|
67
|
+
references: REFERENCE_PAGES,
|
|
68
|
+
});
|
|
35
69
|
return;
|
|
36
70
|
}
|
|
71
|
+
// One column width across all three lists, so the blocks line up as one
|
|
72
|
+
// menu — they are separate KINDS, not separate tables.
|
|
73
|
+
const width = Math.max(...[...WORKFLOWS, ...SUPPORT_PAGES, ...REFERENCE_PAGES].map((w) => w.name.length));
|
|
37
74
|
console.log(`loam ${LOAM_VERSION} — workflows\n`);
|
|
38
|
-
const width = Math.max(...WORKFLOWS.map((w) => w.name.length));
|
|
39
75
|
for (const w of WORKFLOWS) {
|
|
40
76
|
console.log(` ${w.name.padEnd(width)} ${w.description}`);
|
|
41
77
|
}
|
|
42
|
-
console.log(`\
|
|
78
|
+
console.log(`\nsupport — use when a run or agent integration behaves unexpectedly\n`);
|
|
79
|
+
for (const s of SUPPORT_PAGES) {
|
|
80
|
+
console.log(` ${s.name.padEnd(width)} ${s.description}`);
|
|
81
|
+
}
|
|
82
|
+
// Under their own heading, and never merged into the six above. A page
|
|
83
|
+
// has no steps and is not part of the cycle; a flat list of ten would
|
|
84
|
+
// read as a ten-step process, which is the one thing the cycle must not
|
|
85
|
+
// be confused with. The sentence says what they are FOR, because a name
|
|
86
|
+
// alone does not distinguish "reference" from "seventh step".
|
|
87
|
+
console.log(`\nreference pages — printed whole, no arguments\n`);
|
|
88
|
+
for (const r of REFERENCE_PAGES) {
|
|
89
|
+
console.log(` ${r.name.padEnd(width)} ${r.description}`);
|
|
90
|
+
}
|
|
91
|
+
console.log(`\nloam instructions <workflow> [args...] prints one, placeholders filled in.` +
|
|
92
|
+
`\nloam instructions loam-report prints the local incident-reporting protocol.` +
|
|
93
|
+
`\nloam instructions <page> prints a reference page. The pages carry what AGENTS.md` +
|
|
94
|
+
`\nleaves out; \`loam explain <code>\` answers a single code without opening one.`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Before the substitution, not after: a rendered protocol is a page of
|
|
98
|
+
// instructions an agent acts on, and a `$1` that cannot be a service id
|
|
99
|
+
// makes every command on that page unrunnable. The refusal reaches the
|
|
100
|
+
// caller in the same shape a mistyped workflow name does.
|
|
101
|
+
const problems = placeholderProblems(workflow, args);
|
|
102
|
+
if (problems !== null) {
|
|
103
|
+
fail(json, "invalid-option", `${problems.join(" ")} Nothing was printed: every command in the ${workflow} protocol ` +
|
|
104
|
+
"interpolates that value, so the page would name a target no loam command can accept.");
|
|
43
105
|
return;
|
|
44
106
|
}
|
|
45
107
|
const body = protocolFor(workflow, args);
|
|
46
108
|
if (body === null) {
|
|
47
109
|
// `unknown-target`, the same code `show` uses for a name that resolves
|
|
48
110
|
// to nothing. The known set is small and closed, so it is listed rather
|
|
49
|
-
// than described: a caller that mistyped
|
|
50
|
-
//
|
|
111
|
+
// than described: a caller that mistyped a known name should not have
|
|
112
|
+
// to run a second command to see the choices.
|
|
51
113
|
fail(json, "unknown-target", `No workflow '${workflow}'. Known: ${Object.keys(PROTOCOLS).join(", ")}.`);
|
|
52
114
|
return;
|
|
53
115
|
}
|
|
116
|
+
// The narrowing composes with `--json` rather than forking the envelope:
|
|
117
|
+
// the shorter page rides in the same `body` field, so no key is added or
|
|
118
|
+
// renamed and a consumer that never passes the flag cannot tell the
|
|
119
|
+
// difference. `--json` is the larger of the two views (the whole table is
|
|
120
|
+
// one JSON string), which is exactly why it needs this too.
|
|
121
|
+
const page = opts.fixTables === false ? withoutFixTables(body) : body;
|
|
54
122
|
if (json) {
|
|
55
123
|
// `body` is the substituted text, not the template: a consumer that
|
|
56
124
|
// asked for `loam instructions loam-adopt payment-service --json` wants
|
|
57
125
|
// the protocol it is about to follow, and re-implementing the
|
|
58
126
|
// substitution on the other side is a second copy of the rule.
|
|
59
|
-
emitJson({ command: "instructions", version: LOAM_VERSION, workflow, args, body });
|
|
127
|
+
emitJson({ command: "instructions", version: LOAM_VERSION, workflow, args, body: page });
|
|
60
128
|
return;
|
|
61
129
|
}
|
|
62
130
|
// `console.log`, like every other command, rather than a raw stdout
|
|
@@ -64,7 +132,7 @@ export function registerInstructions(program) {
|
|
|
64
132
|
// invisible to it — an untestable print is how a protocol nobody notices
|
|
65
133
|
// went missing would ship. The body already ends in a newline, so the
|
|
66
134
|
// one console.log adds is trimmed rather than doubled.
|
|
67
|
-
console.log(
|
|
135
|
+
console.log(page.replace(/\n+$/, ""));
|
|
68
136
|
});
|
|
69
137
|
}
|
|
70
138
|
//# sourceMappingURL=instructions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/commands/instructions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,CAAC,YAAY,EAAE,gEAAgE,CAAC;SACxF,QAAQ,CAAC,WAAW,EAAE,8DAA8D,CAAC;SACrF,WAAW,CAAC,2DAA2D,CAAC;SACxE,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;QACxE,yEAAyE;QACzE,sEAAsE;QACtE,4EAA4E;QAC5E,2EAA2E;QAC3E,4EAA4E;QAC5E,6EAA6E;SAC5E,kBAAkB,EAAE;SACpB,MAAM,CAAC,CAAC,QAA4B,EAAE,IAAc,EAAE,IAAyB,EAAE,EAAE;QAClF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAEhC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,IAAI,EAAE,CAAC;gBACT,QAAQ,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;gBACnF,OAAO;YACT,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,QAAQ,YAAY,gBAAgB,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/D,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,uEAAuE;YACvE,wEAAwE;YACxE,qEAAqE;YACrE,4CAA4C;YAC5C,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,gBAAgB,QAAQ,aAAa,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1E,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,IAAI,EAAE,CAAC;YACT,oEAAoE;YACpE,wEAAwE;YACxE,8DAA8D;YAC9D,+DAA+D;YAC/D,QAAQ,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,OAAO;QACT,CAAC;QACD,oEAAoE;QACpE,qEAAqE;QACrE,yEAAyE;QACzE,sEAAsE;QACtE,uDAAuD;QACvD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import type { Command } from \"commander\";\nimport { PROTOCOLS, WORKFLOWS, protocolFor } from \"../core/agent.js\";\nimport { emitJson, fail } from \"../core/json.js\";\nimport { LOAM_VERSION } from \"../core/version.js\";\n\ninterface InstructionsOptions {\n json?: boolean;\n}\n\n/**\n * The workflow protocols, from the binary rather than from a file somebody\n * generated once.\n *\n * This is the only command in loam that reads nothing: no `loam.json`, no docs\n * repo, no service. That is deliberate and it is the point — an agent runs this\n * BEFORE the repository is wired, and a protocol that refused with `no-config`\n * would be unreachable exactly when it is most needed, which is the first\n * minute in an unfamiliar repository. `loam-adopt`'s own first step is to run\n * `loam init` when there is no config, and it cannot be the step that requires\n * one.\n */\nexport function registerInstructions(program: Command): void {\n program\n .command(\"instructions\")\n .argument(\"[workflow]\", \"workflow name (loam-adopt, loam-feature, …); omit to list them\")\n .argument(\"[args...]\", \"values substituted for the protocol's $1, $2, … placeholders\")\n .description(\"Print a workflow protocol, version-matched to this binary\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n // Every positional here is DATA — a feature id, a service id, a validate\n // target — and one of those targets is spelled `--all`. Without this,\n // commander reads a leading-dash argument as an option it does not have and\n // refuses the whole invocation, so `/loam-check --all` (the first form the\n // command file's own argument hint offers) got a usage error instead of the\n // protocol. `--json` still parses as the flag it is, because it is declared.\n .allowUnknownOption()\n .action((workflow: string | undefined, args: string[], opts: InstructionsOptions) => {\n const json = opts.json === true;\n\n if (workflow === undefined) {\n if (json) {\n emitJson({ command: \"instructions\", version: LOAM_VERSION, workflows: WORKFLOWS });\n return;\n }\n console.log(`loam ${LOAM_VERSION} — workflows\\n`);\n const width = Math.max(...WORKFLOWS.map((w) => w.name.length));\n for (const w of WORKFLOWS) {\n console.log(` ${w.name.padEnd(width)} ${w.description}`);\n }\n console.log(`\\nloam instructions <workflow> [args...] prints one, placeholders filled in.`);\n return;\n }\n\n const body = protocolFor(workflow, args);\n if (body === null) {\n // `unknown-target`, the same code `show` uses for a name that resolves\n // to nothing. The known set is small and closed, so it is listed rather\n // than described: a caller that mistyped one of six names should not\n // have to run a second command to see them.\n fail(\n json,\n \"unknown-target\",\n `No workflow '${workflow}'. Known: ${Object.keys(PROTOCOLS).join(\", \")}.`,\n );\n return;\n }\n\n if (json) {\n // `body` is the substituted text, not the template: a consumer that\n // asked for `loam instructions loam-adopt payment-service --json` wants\n // the protocol it is about to follow, and re-implementing the\n // substitution on the other side is a second copy of the rule.\n emitJson({ command: \"instructions\", version: LOAM_VERSION, workflow, args, body });\n return;\n }\n // `console.log`, like every other command, rather than a raw stdout\n // write: the test harness captures the console and a direct write is\n // invisible to it — an untestable print is how a protocol nobody notices\n // went missing would ship. The body already ends in a newline, so the\n // one console.log adds is trimmed rather than doubled.\n console.log(body.replace(/\\n+$/, \"\"));\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/commands/instructions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport {\n PROTOCOLS,\n REFERENCE_PAGES,\n SUPPORT_PAGES,\n WORKFLOWS,\n placeholderProblems,\n protocolFor,\n} from \"../core/agent/protocol.js\";\nimport { emitJson, fail } from \"../core/envelope/json.js\";\nimport { LOAM_VERSION } from \"../core/envelope/version.js\";\nimport { withoutFixTables } from \"../core/explain/fix-tables.js\";\n\ninterface InstructionsOptions {\n json?: boolean;\n /**\n * Commander's negated-boolean shape: absent means `true`, and only\n * `--no-fix-tables` on the command line makes it `false`. Read as\n * `=== false` at the call site so an undefined — a caller constructing the\n * options object itself, in a test — keeps the default page.\n */\n fixTables?: boolean;\n}\n\n/**\n * The workflow protocols and the reference pages, from the binary rather than\n * from a file somebody generated once.\n *\n * The pages are the newer half and the reason this command now has two lists.\n * They are the sections that left the scaffolded AGENTS.md — a file every\n * agents.md-aware host auto-loads on every session, which two hosts truncate\n * silently — and they are printed here instead. That trade only works if they\n * can be FOUND, so the bare menu names them; `core/agent/workflows/reference/\n * reference.ts` carries the rest of the argument.\n *\n * This is the only command in loam that reads nothing: no `loam.json`, no docs\n * repo, no service. That is deliberate and it is the point — an agent runs this\n * BEFORE the repository is wired, and a protocol that refused with `no-config`\n * would be unreachable exactly when it is most needed, which is the first\n * minute in an unfamiliar repository. `loam-adopt`'s own first step is to run\n * `loam init` when there is no config, and it cannot be the step that requires\n * one.\n */\nexport function registerInstructions(program: Command): void {\n program\n .command(\"instructions\")\n // Still spelled `workflow`, not `page`: the positional is in every\n // generated command file loam has ever written (`loam instructions\n // loam-adopt $1`) and in `--help` output people have copied. Renaming it\n // buys a more accurate word in one usage line and costs nothing anywhere\n // the rename would be visible, so the accuracy goes in the menu text instead.\n .argument(\"[workflow]\", \"workflow or reference page (loam-adopt, loam-codes, …); omit to list them\")\n .argument(\"[args...]\", \"values substituted for the protocol's $1, $2, … placeholders\")\n .description(\"Print a workflow protocol or reference page, version-matched to this binary\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n // Opt-in, and off by default, so the default page of every lifecycle protocol\n // stays byte-identical: this narrows what an agent CAN ask for, it does not\n // change what it gets when it asks for nothing. The one protocol this is\n // about is /loam-check, whose fix tables are 83 KB of the 84 it prints —\n // about a fifth of a 100k-token window spent before the first check has\n // run — while `loam explain <code>` answers any one of those rows in under\n // 500 bytes. The narrowed page keeps every paragraph that INTRODUCES a\n // table, because that sentence is what says which scope a code was graded\n // in; only the rows go.\n .option(\n \"--no-fix-tables\",\n \"drop the per-code fix tables; `loam explain <code>` answers any code a run reports\",\n )\n // Every positional here is DATA — a feature id, a service id, a validate\n // target — and one of those targets is spelled `--all`. Without this,\n // commander reads a leading-dash argument as an option it does not have and\n // refuses the whole invocation, so `/loam-check --all` (the first form the\n // command file's own argument hint offers) got a usage error instead of the\n // protocol. `--json` still parses as the flag it is, because it is declared.\n .allowUnknownOption()\n .action((workflow: string | undefined, args: string[], opts: InstructionsOptions) => {\n const json = opts.json === true;\n\n if (workflow === undefined) {\n if (json) {\n // `support` and `references` are ADDITIVE beside the `workflows` key\n // a consumer already reads. Appending either kind to `workflows`\n // would have been the smaller diff and the wrong one: a caller\n // iterating that array to drive the cycle would start running\n // diagnostics or documentation as steps.\n emitJson({\n command: \"instructions\",\n version: LOAM_VERSION,\n workflows: WORKFLOWS,\n support: SUPPORT_PAGES,\n references: REFERENCE_PAGES,\n });\n return;\n }\n // One column width across all three lists, so the blocks line up as one\n // menu — they are separate KINDS, not separate tables.\n const width = Math.max(\n ...[...WORKFLOWS, ...SUPPORT_PAGES, ...REFERENCE_PAGES].map((w) => w.name.length),\n );\n console.log(`loam ${LOAM_VERSION} — workflows\\n`);\n for (const w of WORKFLOWS) {\n console.log(` ${w.name.padEnd(width)} ${w.description}`);\n }\n console.log(`\\nsupport — use when a run or agent integration behaves unexpectedly\\n`);\n for (const s of SUPPORT_PAGES) {\n console.log(` ${s.name.padEnd(width)} ${s.description}`);\n }\n // Under their own heading, and never merged into the six above. A page\n // has no steps and is not part of the cycle; a flat list of ten would\n // read as a ten-step process, which is the one thing the cycle must not\n // be confused with. The sentence says what they are FOR, because a name\n // alone does not distinguish \"reference\" from \"seventh step\".\n console.log(`\\nreference pages — printed whole, no arguments\\n`);\n for (const r of REFERENCE_PAGES) {\n console.log(` ${r.name.padEnd(width)} ${r.description}`);\n }\n console.log(\n `\\nloam instructions <workflow> [args...] prints one, placeholders filled in.` +\n `\\nloam instructions loam-report prints the local incident-reporting protocol.` +\n `\\nloam instructions <page> prints a reference page. The pages carry what AGENTS.md` +\n `\\nleaves out; \\`loam explain <code>\\` answers a single code without opening one.`,\n );\n return;\n }\n\n // Before the substitution, not after: a rendered protocol is a page of\n // instructions an agent acts on, and a `$1` that cannot be a service id\n // makes every command on that page unrunnable. The refusal reaches the\n // caller in the same shape a mistyped workflow name does.\n const problems = placeholderProblems(workflow, args);\n if (problems !== null) {\n fail(\n json,\n \"invalid-option\",\n `${problems.join(\" \")} Nothing was printed: every command in the ${workflow} protocol ` +\n \"interpolates that value, so the page would name a target no loam command can accept.\",\n );\n return;\n }\n\n const body = protocolFor(workflow, args);\n if (body === null) {\n // `unknown-target`, the same code `show` uses for a name that resolves\n // to nothing. The known set is small and closed, so it is listed rather\n // than described: a caller that mistyped a known name should not have\n // to run a second command to see the choices.\n fail(\n json,\n \"unknown-target\",\n `No workflow '${workflow}'. Known: ${Object.keys(PROTOCOLS).join(\", \")}.`,\n );\n return;\n }\n\n // The narrowing composes with `--json` rather than forking the envelope:\n // the shorter page rides in the same `body` field, so no key is added or\n // renamed and a consumer that never passes the flag cannot tell the\n // difference. `--json` is the larger of the two views (the whole table is\n // one JSON string), which is exactly why it needs this too.\n const page = opts.fixTables === false ? withoutFixTables(body) : body;\n\n if (json) {\n // `body` is the substituted text, not the template: a consumer that\n // asked for `loam instructions loam-adopt payment-service --json` wants\n // the protocol it is about to follow, and re-implementing the\n // substitution on the other side is a second copy of the rule.\n emitJson({ command: \"instructions\", version: LOAM_VERSION, workflow, args, body: page });\n return;\n }\n // `console.log`, like every other command, rather than a raw stdout\n // write: the test harness captures the console and a direct write is\n // invisible to it — an untestable print is how a protocol nobody notices\n // went missing would ship. The body already ends in a newline, so the\n // one console.log adds is trimmed rather than doubled.\n console.log(page.replace(/\\n+$/, \"\"));\n });\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `--subsystem` slice behind `loam list`: what the flag's name denotes,
|
|
3
|
+
* and which services the filter keeps. A sub-package of list/ because the
|
|
4
|
+
* list package proper stands at its five-file limit (review.ts records
|
|
5
|
+
* that), and the adoption-campaign flag surface is its own subject beside
|
|
6
|
+
* the section renderers. The dependency direction is list → list/campaign,
|
|
7
|
+
* never back — this package imports core only, the same rule repo → repo/tree
|
|
8
|
+
* already keeps.
|
|
9
|
+
*
|
|
10
|
+
* Resolution reuses the tree machinery verbatim (`findInTree`,
|
|
11
|
+
* `servicesUnder`, `nearestTreeNames`), so `list --subsystem` and every
|
|
12
|
+
* `loam subsystem` verb read the flat namespace the same way — two spellings
|
|
13
|
+
* of "what does this name mean" would drift.
|
|
14
|
+
*/
|
|
15
|
+
import { fail } from "../../../core/envelope/json.js";
|
|
16
|
+
import { findInTree, nearestTreeNames, servicesUnder, subsystemsUnder } from "../../../core/repo/tree/find.js";
|
|
17
|
+
/**
|
|
18
|
+
* Resolve `--subsystem <name>` against the flat namespace, or report the
|
|
19
|
+
* refusal and return null. The reserved name `unfiled` selects the services
|
|
20
|
+
* filed under no subsystem — the tree's own concept, otherwise unreachable —
|
|
21
|
+
* but only while nothing in the tree claims that name: a REAL subsystem or
|
|
22
|
+
* service spelled `unfiled` wins, the same concrete-name-wins precedence
|
|
23
|
+
* `findInTree` already applies to service/subsystem ties. An unknown name
|
|
24
|
+
* refuses `unknown-target` with close-name hints rather than succeeding
|
|
25
|
+
* emptily — an empty table over a typo would read as a finished campaign —
|
|
26
|
+
* and a service name refuses `invalid-option` exactly as `loam adopt
|
|
27
|
+
* --subsystem` does: a service never contains other services.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveSubsystemSlice(tree, name, json) {
|
|
30
|
+
const hit = findInTree(tree, name);
|
|
31
|
+
if (hit === null && name === "unfiled") {
|
|
32
|
+
return {
|
|
33
|
+
members: new Set(tree.services.filter((s) => s.subsystem.length === 0).map((s) => s.dir)),
|
|
34
|
+
subsystems: [],
|
|
35
|
+
label: "unfiled services (directly under services/)",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (hit === null) {
|
|
39
|
+
// The Set: a real subsystem named 'unfiled' would otherwise sit in the
|
|
40
|
+
// hint pool twice and could be offered twice in one hint.
|
|
41
|
+
const close = nearestTreeNames(name, [...new Set([...tree.subsystems.map((s) => s.name), "unfiled"])]);
|
|
42
|
+
fail(json, "unknown-target", `No subsystem '${name}' in the tree.` +
|
|
43
|
+
(close.length > 0
|
|
44
|
+
? ` Close names: ${close.join(", ")}.`
|
|
45
|
+
: " `loam subsystem list` shows what exists; `unfiled` selects the services filed under none."));
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (hit.kind === "service") {
|
|
49
|
+
// With a SERVICE claiming the name 'unfiled' the reserved reading has no
|
|
50
|
+
// spelling at all, so the refusal must say what is shadowed — otherwise
|
|
51
|
+
// the message reads as loam misunderstanding the request.
|
|
52
|
+
const shadowed = name === "unfiled"
|
|
53
|
+
? " While a service claims this name, the reserved unfiled-services reading is shadowed; rename the service to reach it."
|
|
54
|
+
: "";
|
|
55
|
+
fail(json, "invalid-option", `--subsystem names the service '${name}' — a service never contains other services.${shadowed}`);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const sub = hit.subsystem;
|
|
59
|
+
return {
|
|
60
|
+
members: new Set(servicesUnder(tree, sub).map((s) => s.dir)),
|
|
61
|
+
subsystems: [sub, ...subsystemsUnder(tree, sub)],
|
|
62
|
+
label: `subsystem '${sub.name}' (services/${sub.path.join("/")}/)`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=campaign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign.js","sourceRoot":"","sources":["../../../../src/commands/list/campaign/campaign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAqB/G;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAe,EAAE,IAAY,EAAE,IAAa;IAChF,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,IAAI,GAAG,CAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACjG,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,6CAA6C;SACrD,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,uEAAuE;QACvE,0DAA0D;QAC1D,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACvG,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,iBAAiB,IAAI,gBAAgB;YACnC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBACf,CAAC,CAAC,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBACtC,CAAC,CAAC,4FAA4F,CAAC,CACpG,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3B,yEAAyE;QACzE,wEAAwE;QACxE,0DAA0D;QAC1D,MAAM,QAAQ,GACZ,IAAI,KAAK,SAAS;YAChB,CAAC,CAAC,uHAAuH;YACzH,CAAC,CAAC,EAAE,CAAC;QACT,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,kCAAkC,IAAI,+CAA+C,QAAQ,EAAE,CAChG,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC;IAC1B,OAAO;QACL,OAAO,EAAE,IAAI,GAAG,CAAS,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACpE,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAChD,KAAK,EAAE,cAAc,GAAG,CAAC,IAAI,eAAe,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;KACnE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The `--subsystem` slice behind `loam list`: what the flag's name denotes,\n * and which services the filter keeps. A sub-package of list/ because the\n * list package proper stands at its five-file limit (review.ts records\n * that), and the adoption-campaign flag surface is its own subject beside\n * the section renderers. The dependency direction is list → list/campaign,\n * never back — this package imports core only, the same rule repo → repo/tree\n * already keeps.\n *\n * Resolution reuses the tree machinery verbatim (`findInTree`,\n * `servicesUnder`, `nearestTreeNames`), so `list --subsystem` and every\n * `loam subsystem` verb read the flat namespace the same way — two spellings\n * of \"what does this name mean\" would drift.\n */\nimport { fail } from \"../../../core/envelope/json.js\";\nimport { findInTree, nearestTreeNames, servicesUnder, subsystemsUnder } from \"../../../core/repo/tree/find.js\";\nimport type { FleetTree, SubsystemEntry } from \"../../../core/repo/tree/walk.js\";\n\nexport interface SubsystemSlice {\n /**\n * DIRECTORIES of the member services, at any depth beneath the filter\n * target — the directory, not the id, because the id is a leaf name the\n * fleet does not guarantee unique: a `subsystem.name-collision` tree still\n * enumerates both claimants on purpose, and an id-keyed slice would let\n * each of two disjoint slices claim the other's service.\n */\n readonly members: ReadonlySet<string>;\n /**\n * The subsystem rows the filtered payload shows — the named subsystem and\n * its descendants; `[]` for the unfiled slice, which sits under no group.\n */\n readonly subsystems: SubsystemEntry[];\n /** The human filter line's description of what the slice is. */\n readonly label: string;\n}\n\n/**\n * Resolve `--subsystem <name>` against the flat namespace, or report the\n * refusal and return null. The reserved name `unfiled` selects the services\n * filed under no subsystem — the tree's own concept, otherwise unreachable —\n * but only while nothing in the tree claims that name: a REAL subsystem or\n * service spelled `unfiled` wins, the same concrete-name-wins precedence\n * `findInTree` already applies to service/subsystem ties. An unknown name\n * refuses `unknown-target` with close-name hints rather than succeeding\n * emptily — an empty table over a typo would read as a finished campaign —\n * and a service name refuses `invalid-option` exactly as `loam adopt\n * --subsystem` does: a service never contains other services.\n */\nexport function resolveSubsystemSlice(tree: FleetTree, name: string, json: boolean): SubsystemSlice | null {\n const hit = findInTree(tree, name);\n if (hit === null && name === \"unfiled\") {\n return {\n members: new Set<string>(tree.services.filter((s) => s.subsystem.length === 0).map((s) => s.dir)),\n subsystems: [],\n label: \"unfiled services (directly under services/)\",\n };\n }\n if (hit === null) {\n // The Set: a real subsystem named 'unfiled' would otherwise sit in the\n // hint pool twice and could be offered twice in one hint.\n const close = nearestTreeNames(name, [...new Set([...tree.subsystems.map((s) => s.name), \"unfiled\"])]);\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${name}' in the tree.` +\n (close.length > 0\n ? ` Close names: ${close.join(\", \")}.`\n : \" `loam subsystem list` shows what exists; `unfiled` selects the services filed under none.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n // With a SERVICE claiming the name 'unfiled' the reserved reading has no\n // spelling at all, so the refusal must say what is shadowed — otherwise\n // the message reads as loam misunderstanding the request.\n const shadowed =\n name === \"unfiled\"\n ? \" While a service claims this name, the reserved unfiled-services reading is shadowed; rename the service to reach it.\"\n : \"\";\n fail(\n json,\n \"invalid-option\",\n `--subsystem names the service '${name}' — a service never contains other services.${shadowed}`,\n );\n return null;\n }\n const sub = hit.subsystem;\n return {\n members: new Set<string>(servicesUnder(tree, sub).map((s) => s.dir)),\n subsystems: [sub, ...subsystemsUnder(tree, sub)],\n label: `subsystem '${sub.name}' (services/${sub.path.join(\"/\")}/)`,\n };\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `--owners` join behind `loam list`: read the user-named CODEOWNERS
|
|
3
|
+
* file, bucket the CURRENT listing's rows under the teams it names, and
|
|
4
|
+
* refuse — `owners-unreadable` — when the file cannot be read or a line in
|
|
5
|
+
* it cannot be parsed as `pattern owner…`. The parse and the matching are
|
|
6
|
+
* `core/owners/codeowners.ts`'s (pure; its header records the implemented
|
|
7
|
+
* subset and the skip-don't-guess rule); this module owns the filesystem
|
|
8
|
+
* read and the refusal, because core never prints.
|
|
9
|
+
*
|
|
10
|
+
* The join runs over the rows the listing is about to show, in the order it
|
|
11
|
+
* will show them — after `--subsystem`/`--needs-work` filtering and any
|
|
12
|
+
* `--review-order` ranking — so each team's array IS that team's campaign
|
|
13
|
+
* worklist, not a second, differently-ordered opinion of the fleet.
|
|
14
|
+
*/
|
|
15
|
+
import { readFile } from "node:fs/promises";
|
|
16
|
+
import { fail } from "../../../core/envelope/json.js";
|
|
17
|
+
import { ownersFor, parseCodeowners } from "../../../core/owners/codeowners.js";
|
|
18
|
+
/**
|
|
19
|
+
* Read, parse and join, or report the refusal and return null. An empty or
|
|
20
|
+
* all-skipped file is NOT a refusal: every row lands in `unowned`, honestly —
|
|
21
|
+
* the file said nothing, and saying so is the answer.
|
|
22
|
+
*/
|
|
23
|
+
export async function ownersJoin(req) {
|
|
24
|
+
let content;
|
|
25
|
+
try {
|
|
26
|
+
content = await readFile(req.path, "utf8");
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
30
|
+
fail(req.json, "owners-unreadable", `Cannot read the CODEOWNERS file at ${req.path}: ${detail}. Nothing was joined; re-run with the path of the file the forge actually uses.`);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const parsed = parseCodeowners(content);
|
|
34
|
+
if (!parsed.ok) {
|
|
35
|
+
fail(req.json, "owners-unreadable", `${req.path}:${parsed.line}: ${parsed.problem}. A rule loam cannot read is never guessed at or silently skipped — fix the line, then re-run.`);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const byOwner = new Map();
|
|
39
|
+
const unowned = [];
|
|
40
|
+
for (const row of req.rows) {
|
|
41
|
+
const owners = ownersFor(row.repoDir.split("/"), parsed.rules);
|
|
42
|
+
if (owners.length === 0) {
|
|
43
|
+
unowned.push(row);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// A rule may name several owners; the service files under EACH — a shared
|
|
47
|
+
// directory is two teams' work, not half of either's. The Set: a rule
|
|
48
|
+
// repeating one owner (`@a @a`) must not list the service twice.
|
|
49
|
+
for (const owner of new Set(owners)) {
|
|
50
|
+
byOwner.set(owner, [...(byOwner.get(owner) ?? []), row]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
path: req.path,
|
|
55
|
+
// Plain lexicographic on the owner string: deterministic across machines,
|
|
56
|
+
// and owner handles are not ids, so compareIds' numeric tokenizing has
|
|
57
|
+
// nothing to add.
|
|
58
|
+
teams: [...byOwner.entries()]
|
|
59
|
+
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
60
|
+
.map(([owner, services]) => ({ owner, services })),
|
|
61
|
+
unowned,
|
|
62
|
+
skipped: parsed.skipped,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=owners.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owners.js","sourceRoot":"","sources":["../../../../src/commands/list/campaign/owners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAoB,MAAM,oCAAoC,CAAC;AA4BlG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAIhC;IACC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,CACF,GAAG,CAAC,IAAI,EACR,mBAAmB,EACnB,sCAAsC,GAAG,CAAC,IAAI,KAAK,MAAM,iFAAiF,CAC3I,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,IAAI,CACF,GAAG,CAAC,IAAI,EACR,mBAAmB,EACnB,GAAG,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,gGAAgG,CAC9I,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC9C,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,0EAA0E;QAC1E,sEAAsE;QACtE,iEAAiE;QACjE,KAAK,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,0EAA0E;QAC1E,uEAAuE;QACvE,kBAAkB;QAClB,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpD,OAAO;QACP,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The `--owners` join behind `loam list`: read the user-named CODEOWNERS\n * file, bucket the CURRENT listing's rows under the teams it names, and\n * refuse — `owners-unreadable` — when the file cannot be read or a line in\n * it cannot be parsed as `pattern owner…`. The parse and the matching are\n * `core/owners/codeowners.ts`'s (pure; its header records the implemented\n * subset and the skip-don't-guess rule); this module owns the filesystem\n * read and the refusal, because core never prints.\n *\n * The join runs over the rows the listing is about to show, in the order it\n * will show them — after `--subsystem`/`--needs-work` filtering and any\n * `--review-order` ranking — so each team's array IS that team's campaign\n * worklist, not a second, differently-ordered opinion of the fleet.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { fail } from \"../../../core/envelope/json.js\";\nimport { ownersFor, parseCodeowners, type SkippedRule } from \"../../../core/owners/codeowners.js\";\n\n/** One row of the listing, reduced to what the join reads. */\nexport interface OwnedRow {\n readonly id: string;\n /** The service's docs-repo-relative directory, forward slashes (`repoPath`). */\n readonly repoDir: string;\n}\n\nexport interface OwnersJoin {\n /** The path exactly as the user named it — the file is theirs, not loam's. */\n readonly path: string;\n /**\n * One bucket per owning team, sorted by owner; rows in row order. The full\n * row, not the id: leaf ids can collide across a broken tree, and the\n * renderers join back to their views by `repoDir` — the row's identity.\n */\n readonly teams: { readonly owner: string; readonly services: readonly OwnedRow[] }[];\n /**\n * Rows no rule matched, or whose LAST matching rule named no owner —\n * GitHub's ownership-clearing form. Listed explicitly, because a service\n * silently absent from every team's queue reads as somebody else's work.\n */\n readonly unowned: readonly OwnedRow[];\n /** Recognised rules outside the implemented subset — reported, never guessed. */\n readonly skipped: readonly SkippedRule[];\n}\n\n/**\n * Read, parse and join, or report the refusal and return null. An empty or\n * all-skipped file is NOT a refusal: every row lands in `unowned`, honestly —\n * the file said nothing, and saying so is the answer.\n */\nexport async function ownersJoin(req: {\n path: string;\n rows: readonly OwnedRow[];\n json: boolean;\n}): Promise<OwnersJoin | null> {\n let content: string;\n try {\n content = await readFile(req.path, \"utf8\");\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n fail(\n req.json,\n \"owners-unreadable\",\n `Cannot read the CODEOWNERS file at ${req.path}: ${detail}. Nothing was joined; re-run with the path of the file the forge actually uses.`,\n );\n return null;\n }\n const parsed = parseCodeowners(content);\n if (!parsed.ok) {\n fail(\n req.json,\n \"owners-unreadable\",\n `${req.path}:${parsed.line}: ${parsed.problem}. A rule loam cannot read is never guessed at or silently skipped — fix the line, then re-run.`,\n );\n return null;\n }\n const byOwner = new Map<string, OwnedRow[]>();\n const unowned: OwnedRow[] = [];\n for (const row of req.rows) {\n const owners = ownersFor(row.repoDir.split(\"/\"), parsed.rules);\n if (owners.length === 0) {\n unowned.push(row);\n continue;\n }\n // A rule may name several owners; the service files under EACH — a shared\n // directory is two teams' work, not half of either's. The Set: a rule\n // repeating one owner (`@a @a`) must not list the service twice.\n for (const owner of new Set(owners)) {\n byOwner.set(owner, [...(byOwner.get(owner) ?? []), row]);\n }\n }\n return {\n path: req.path,\n // Plain lexicographic on the owner string: deterministic across machines,\n // and owner handles are not ids, so compareIds' numeric tokenizing has\n // nothing to add.\n teams: [...byOwner.entries()]\n .sort(([a], [b]) => (a < b ? -1 : 1))\n .map(([owner, services]) => ({ owner, services })),\n unowned,\n skipped: parsed.skipped,\n };\n}\n"]}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `--json` rows. Separate from `./print.ts` because only this side is a
|
|
3
|
+
* contract: the payload keys are frozen, the columns beside them are not.
|
|
4
|
+
*/
|
|
5
|
+
import { repoPath } from "../../core/envelope/json.js";
|
|
6
|
+
import {} from "../../core/capabilities/rollup.js";
|
|
7
|
+
import {} from "../../core/repo/entries.js";
|
|
8
|
+
import { servicesUnder } from "../../core/repo/tree/find.js";
|
|
9
|
+
import {} from "./views.js";
|
|
10
|
+
/**
|
|
11
|
+
* The `services[]` rows: ranked and decorated under `--review-order`, plain
|
|
12
|
+
* otherwise — as a VARIANT, so a call carrying both a plain list and a ranked
|
|
13
|
+
* queue is unrepresentable rather than resolved by precedence. `fanIn`/
|
|
14
|
+
* `reviewRank` are ADDITIVE and appear ONLY under the flag — bare
|
|
15
|
+
* `loam list --json` and `--needs-work --json` stay byte-identical and
|
|
16
|
+
* cost-identical, the frozen-default doctrine the explicit-only capabilities
|
|
17
|
+
* section also follows. The spread keeps serviceJson at its two-param
|
|
18
|
+
* contract; `reviewRank` is 1-based and equals the row's position, so the
|
|
19
|
+
* array order IS the queue.
|
|
20
|
+
*/
|
|
21
|
+
export function serviceRows(docsDir, rows) {
|
|
22
|
+
if (Array.isArray(rows))
|
|
23
|
+
return rows.map((v) => serviceJson(docsDir, v));
|
|
24
|
+
return rows.queue.map((v, i) => ({
|
|
25
|
+
...serviceJson(docsDir, v),
|
|
26
|
+
fanIn: rows.fanIn.get(v.entry.id) ?? 0,
|
|
27
|
+
reviewRank: i + 1,
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
export function serviceJson(docsDir, v) {
|
|
31
|
+
const s = v.entry;
|
|
32
|
+
return {
|
|
33
|
+
id: s.id,
|
|
34
|
+
path: repoPath(docsDir, s.dir),
|
|
35
|
+
// Names from services/ down, outermost first; [] = unfiled. `path` above
|
|
36
|
+
// already truthfully reflects placement — this is the same fact as data
|
|
37
|
+
// instead of a string to split.
|
|
38
|
+
subsystem: s.subsystem,
|
|
39
|
+
has: { ...s.has, archSpec: v.archSpec },
|
|
40
|
+
adrs: s.adrs,
|
|
41
|
+
status: s.status,
|
|
42
|
+
maturity: v.maturity,
|
|
43
|
+
missing: v.missing,
|
|
44
|
+
apiExpected: v.apiExpected,
|
|
45
|
+
// Never omitted when true: a consumer that filters this table into a
|
|
46
|
+
// worklist has to be able to tell "checked and fine" from "not checkable
|
|
47
|
+
// from here", and absence reads as the first one.
|
|
48
|
+
...(v.unverifiableFromHere ? { provenance: "unverifiable-from-here" } : {}),
|
|
49
|
+
// Additive, and only when there IS a scope — omission is the fine case
|
|
50
|
+
// here, exactly as it is for `provenance` above, and `maturity` stays the
|
|
51
|
+
// frozen `vouched` beside it. A dashboard counting `maturity: "vouched"`
|
|
52
|
+
// rows keeps counting them; one that cares whether a person read the
|
|
53
|
+
// document subtracts these.
|
|
54
|
+
...(s.vouchScope === "sampled" ? { vouchScope: "sampled" } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The subsystem rows beside the service table, sorted by path. `memberCount`
|
|
59
|
+
* is TRANSITIVE — every service beneath, at any depth — matching the
|
|
60
|
+
* generated views file's membership, so the two numbers a consumer can
|
|
61
|
+
* cross-check never disagree about what "in this group" means.
|
|
62
|
+
*/
|
|
63
|
+
export function subsystemsJson(docsDir, tree) {
|
|
64
|
+
return [...tree.subsystems]
|
|
65
|
+
.sort((a, b) => (a.path.join("/") < b.path.join("/") ? -1 : 1))
|
|
66
|
+
.map((sub) => ({
|
|
67
|
+
name: sub.name,
|
|
68
|
+
path: repoPath(docsDir, sub.dir),
|
|
69
|
+
title: sub.meta.title ?? null,
|
|
70
|
+
memberCount: servicesUnder(tree, sub).length,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The additive `owners` payload key under `--owners` — the join result as a
|
|
75
|
+
* contract: `path` (the file exactly as the user named it), `teams[]` (owner
|
|
76
|
+
* plus that team's services, in the LISTING's own filtered-and-ordered row
|
|
77
|
+
* order, so each array is that team's campaign worklist), `unowned[]` (rows
|
|
78
|
+
* no rule matched — explicit, because absence would read as owned-somewhere),
|
|
79
|
+
* and `skippedRules[]` (recognised rules outside the implemented CODEOWNERS
|
|
80
|
+
* subset, each with its line — reported, never guessed at). Key spellings
|
|
81
|
+
* frozen once shipped; the join itself lives in campaign/owners.ts.
|
|
82
|
+
*
|
|
83
|
+
* The service arrays carry IDS. On a `subsystem.name-collision` fleet —
|
|
84
|
+
* already an error finding — two rows can share an id, so a consumer cannot
|
|
85
|
+
* tell them apart here; if that ever needs disambiguating, the fix is a new
|
|
86
|
+
* ADDITIVE key carrying paths, never a change to these.
|
|
87
|
+
*/
|
|
88
|
+
export function ownersJson(join) {
|
|
89
|
+
return {
|
|
90
|
+
path: join.path,
|
|
91
|
+
teams: join.teams.map((team) => ({ owner: team.owner, services: team.services.map((row) => row.id) })),
|
|
92
|
+
unowned: join.unowned.map((row) => row.id),
|
|
93
|
+
skippedRules: join.skipped.map((rule) => ({ line: rule.line, pattern: rule.pattern })),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* One `capabilities[]` row — additive payload, explicit `loam list
|
|
98
|
+
* capabilities` only, and diff-stable: the rollup already sorts rows,
|
|
99
|
+
* realizedBy and statuses' keys deterministically, and this projection adds
|
|
100
|
+
* nothing that could vary between machines. Optional keys are omitted rather
|
|
101
|
+
* than nulled so a declaration that never carried a description does not grow
|
|
102
|
+
* one in the diff.
|
|
103
|
+
*/
|
|
104
|
+
export function capabilityJson(row) {
|
|
105
|
+
return {
|
|
106
|
+
id: row.id,
|
|
107
|
+
...(row.description !== undefined ? { description: row.description } : {}),
|
|
108
|
+
...(row.owner !== undefined ? { owner: row.owner } : {}),
|
|
109
|
+
realizedBy: row.realizedBy,
|
|
110
|
+
services: row.services,
|
|
111
|
+
statuses: row.statuses,
|
|
112
|
+
// Present only for a capability that HAS a document, and absent rather than
|
|
113
|
+
// `[]` for one that does not — the same optional-key rule the two fields
|
|
114
|
+
// above follow, and here it carries a distinction a reader needs: an empty
|
|
115
|
+
// array means the document declares no requirements, while no key at all
|
|
116
|
+
// means there is no document to declare any.
|
|
117
|
+
//
|
|
118
|
+
// Each row inside carries `realizedBy` (the service requirements whose
|
|
119
|
+
// `Realizes:` line names it) and `keptBy` (the flows whose `#cap-`/`#req-`
|
|
120
|
+
// tags resolve to it) — two independent corpora, NEITHER derived from the
|
|
121
|
+
// other, because a cross-service promise can only be kept by a flow and a
|
|
122
|
+
// per-service one is normally kept by a requirement. `keptBy` follows the
|
|
123
|
+
// same three-state rule one level down and `rollup.ts` states it: absent
|
|
124
|
+
// means nobody looked, `[]` means loam looked and no flow keeps it. The
|
|
125
|
+
// payload's own `useCases.unreadable` says which of the two absences it is.
|
|
126
|
+
...(row.requirements === undefined ? {} : { requirements: row.requirements }),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export function featureJson(docsDir, f, verification) {
|
|
130
|
+
return {
|
|
131
|
+
id: f.id,
|
|
132
|
+
dirName: f.dirName,
|
|
133
|
+
path: repoPath(docsDir, f.dir),
|
|
134
|
+
archived: f.archived,
|
|
135
|
+
services: f.services,
|
|
136
|
+
has: f.has,
|
|
137
|
+
verification,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/* ------------------------------------------------------------------ */
|
|
141
|
+
/* Verification */
|
|
142
|
+
/* ------------------------------------------------------------------ */
|
|
143
|
+
/** What the features table says about verification without N `loam verify` runs. */
|
|
144
|
+
/**
|
|
145
|
+
* One `glossary[]` row — additive payload, explicit `loam list glossary` only.
|
|
146
|
+
*
|
|
147
|
+
* `linkedBy` is the whole reason the section exists: "which documents use this
|
|
148
|
+
* term" is a grep today and a join here, and it is the same answer
|
|
149
|
+
* `glossary.unlinked` grades. Repo-relative and sorted by the index itself, so
|
|
150
|
+
* the payload is diff-stable across machines. Empty means loam read every
|
|
151
|
+
* authored document and none of them cites the term — never "nobody looked",
|
|
152
|
+
* which is what the sibling `links.unreadable` list is for.
|
|
153
|
+
*/
|
|
154
|
+
export function glossaryJson(term, linkedBy, docsDir) {
|
|
155
|
+
return { id: term.id, path: repoPath(docsDir, term.path), linkedBy };
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/commands/list/json.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The `--json` rows. Separate from `./print.ts` because only this side is a\n * contract: the payload keys are frozen, the columns beside them are not.\n */\nimport { repoPath } from \"../../core/envelope/json.js\";\nimport { type CapabilityRow } from \"../../core/capabilities/rollup.js\";\nimport { type FeatureEntry } from \"../../core/repo/entries.js\";\nimport { servicesUnder } from \"../../core/repo/tree/find.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport type { OwnersJoin } from \"./campaign/owners.js\";\nimport { type ServiceView, type VerificationCell } from \"./views.js\";\n\n/**\n * The `services[]` rows: ranked and decorated under `--review-order`, plain\n * otherwise — as a VARIANT, so a call carrying both a plain list and a ranked\n * queue is unrepresentable rather than resolved by precedence. `fanIn`/\n * `reviewRank` are ADDITIVE and appear ONLY under the flag — bare\n * `loam list --json` and `--needs-work --json` stay byte-identical and\n * cost-identical, the frozen-default doctrine the explicit-only capabilities\n * section also follows. The spread keeps serviceJson at its two-param\n * contract; `reviewRank` is 1-based and equals the row's position, so the\n * array order IS the queue.\n */\nexport function serviceRows(\n docsDir: string,\n rows: ServiceView[] | { queue: ServiceView[]; fanIn: ReadonlyMap<string, number> },\n): Record<string, unknown>[] {\n if (Array.isArray(rows)) return rows.map((v) => serviceJson(docsDir, v));\n return rows.queue.map((v, i) => ({\n ...serviceJson(docsDir, v),\n fanIn: rows.fanIn.get(v.entry.id) ?? 0,\n reviewRank: i + 1,\n }));\n}\n\nexport function serviceJson(docsDir: string, v: ServiceView): Record<string, unknown> {\n const s = v.entry;\n return {\n id: s.id,\n path: repoPath(docsDir, s.dir),\n // Names from services/ down, outermost first; [] = unfiled. `path` above\n // already truthfully reflects placement — this is the same fact as data\n // instead of a string to split.\n subsystem: s.subsystem,\n has: { ...s.has, archSpec: v.archSpec },\n adrs: s.adrs,\n status: s.status,\n maturity: v.maturity,\n missing: v.missing,\n apiExpected: v.apiExpected,\n // Never omitted when true: a consumer that filters this table into a\n // worklist has to be able to tell \"checked and fine\" from \"not checkable\n // from here\", and absence reads as the first one.\n ...(v.unverifiableFromHere ? { provenance: \"unverifiable-from-here\" } : {}),\n // Additive, and only when there IS a scope — omission is the fine case\n // here, exactly as it is for `provenance` above, and `maturity` stays the\n // frozen `vouched` beside it. A dashboard counting `maturity: \"vouched\"`\n // rows keeps counting them; one that cares whether a person read the\n // document subtracts these.\n ...(s.vouchScope === \"sampled\" ? { vouchScope: \"sampled\" } : {}),\n };\n}\n\n/**\n * The subsystem rows beside the service table, sorted by path. `memberCount`\n * is TRANSITIVE — every service beneath, at any depth — matching the\n * generated views file's membership, so the two numbers a consumer can\n * cross-check never disagree about what \"in this group\" means.\n */\nexport function subsystemsJson(docsDir: string, tree: FleetTree): Record<string, unknown>[] {\n return [...tree.subsystems]\n .sort((a, b) => (a.path.join(\"/\") < b.path.join(\"/\") ? -1 : 1))\n .map((sub) => ({\n name: sub.name,\n path: repoPath(docsDir, sub.dir),\n title: sub.meta.title ?? null,\n memberCount: servicesUnder(tree, sub).length,\n }));\n}\n\n/**\n * The additive `owners` payload key under `--owners` — the join result as a\n * contract: `path` (the file exactly as the user named it), `teams[]` (owner\n * plus that team's services, in the LISTING's own filtered-and-ordered row\n * order, so each array is that team's campaign worklist), `unowned[]` (rows\n * no rule matched — explicit, because absence would read as owned-somewhere),\n * and `skippedRules[]` (recognised rules outside the implemented CODEOWNERS\n * subset, each with its line — reported, never guessed at). Key spellings\n * frozen once shipped; the join itself lives in campaign/owners.ts.\n *\n * The service arrays carry IDS. On a `subsystem.name-collision` fleet —\n * already an error finding — two rows can share an id, so a consumer cannot\n * tell them apart here; if that ever needs disambiguating, the fix is a new\n * ADDITIVE key carrying paths, never a change to these.\n */\nexport function ownersJson(join: OwnersJoin): Record<string, unknown> {\n return {\n path: join.path,\n teams: join.teams.map((team) => ({ owner: team.owner, services: team.services.map((row) => row.id) })),\n unowned: join.unowned.map((row) => row.id),\n skippedRules: join.skipped.map((rule) => ({ line: rule.line, pattern: rule.pattern })),\n };\n}\n\n/**\n * One `capabilities[]` row — additive payload, explicit `loam list\n * capabilities` only, and diff-stable: the rollup already sorts rows,\n * realizedBy and statuses' keys deterministically, and this projection adds\n * nothing that could vary between machines. Optional keys are omitted rather\n * than nulled so a declaration that never carried a description does not grow\n * one in the diff.\n */\nexport function capabilityJson(row: CapabilityRow): Record<string, unknown> {\n return {\n id: row.id,\n ...(row.description !== undefined ? { description: row.description } : {}),\n ...(row.owner !== undefined ? { owner: row.owner } : {}),\n realizedBy: row.realizedBy,\n services: row.services,\n statuses: row.statuses,\n // Present only for a capability that HAS a document, and absent rather than\n // `[]` for one that does not — the same optional-key rule the two fields\n // above follow, and here it carries a distinction a reader needs: an empty\n // array means the document declares no requirements, while no key at all\n // means there is no document to declare any.\n //\n // Each row inside carries `realizedBy` (the service requirements whose\n // `Realizes:` line names it) and `keptBy` (the flows whose `#cap-`/`#req-`\n // tags resolve to it) — two independent corpora, NEITHER derived from the\n // other, because a cross-service promise can only be kept by a flow and a\n // per-service one is normally kept by a requirement. `keptBy` follows the\n // same three-state rule one level down and `rollup.ts` states it: absent\n // means nobody looked, `[]` means loam looked and no flow keeps it. The\n // payload's own `useCases.unreadable` says which of the two absences it is.\n ...(row.requirements === undefined ? {} : { requirements: row.requirements }),\n };\n}\n\nexport function featureJson(\n docsDir: string,\n f: FeatureEntry,\n verification: VerificationCell | null,\n): Record<string, unknown> {\n return {\n id: f.id,\n dirName: f.dirName,\n path: repoPath(docsDir, f.dir),\n archived: f.archived,\n services: f.services,\n has: f.has,\n verification,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Verification */\n/* ------------------------------------------------------------------ */\n\n/** What the features table says about verification without N `loam verify` runs. */\n\n/**\n * One `glossary[]` row — additive payload, explicit `loam list glossary` only.\n *\n * `linkedBy` is the whole reason the section exists: \"which documents use this\n * term\" is a grep today and a join here, and it is the same answer\n * `glossary.unlinked` grades. Repo-relative and sorted by the index itself, so\n * the payload is diff-stable across machines. Empty means loam read every\n * authored document and none of them cites the term — never \"nobody looked\",\n * which is what the sibling `links.unreadable` list is for.\n */\nexport function glossaryJson(term: { id: string; path: string }, linkedBy: string[], docsDir: string): Record<string, unknown> {\n return { id: term.id, path: repoPath(docsDir, term.path), linkedBy };\n}\n"]}
|