@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,64 +1,18 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { CONFIG_FILENAME, findConfigPath, loadConfig, localConfigPath, saveConfig, } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function resolveTools(raw, json) {
|
|
17
|
-
const supported = Object.keys(AGENT_TOOLS);
|
|
18
|
-
if (raw === "all")
|
|
19
|
-
return supported;
|
|
20
|
-
const ids = [...new Set(raw.split(",").map((t) => t.trim()).filter((t) => t !== ""))];
|
|
21
|
-
const unknown = ids.filter((t) => !(t in AGENT_TOOLS));
|
|
22
|
-
if (ids.length === 0 || unknown.length > 0) {
|
|
23
|
-
fail(json, "invalid-option", (ids.length === 0
|
|
24
|
-
? "--tools names no tool."
|
|
25
|
-
: `--tools does not recognize: ${unknown.join(", ")}.`) +
|
|
26
|
-
` Supported: ${supported.join(", ")} — or "all".`);
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
return ids;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* `--docs` exactly as the caller wrote it, with separators normalised.
|
|
33
|
-
*
|
|
34
|
-
* Stored verbatim on purpose. `init` used to resolve it and write the absolute
|
|
35
|
-
* result, which meant a committed loam.json named a directory that existed on
|
|
36
|
-
* one laptop: every teammate who cloned the service repo got a docsDir under
|
|
37
|
-
* someone else's home directory, and `loam list` reported an empty fleet
|
|
38
|
-
* instead of saying so. `loadConfig` resolves relative paths against the config
|
|
39
|
-
* file's own directory, so `../docs` keeps meaning "next to this repo" wherever
|
|
40
|
-
* the pair is checked out. An absolute `--docs` is still stored absolute — that
|
|
41
|
-
* is the caller's explicit choice, and `loam doctor` warns about it.
|
|
42
|
-
*
|
|
43
|
-
* Backslashes become forward slashes so a config written on Windows resolves on
|
|
44
|
-
* POSIX; a trailing separator is dropped so the stored spelling is stable.
|
|
45
|
-
*/
|
|
46
|
-
function storedDocsDir(raw) {
|
|
47
|
-
const slashed = raw.split("\\").join("/");
|
|
48
|
-
if (slashed.length <= 1)
|
|
49
|
-
return slashed;
|
|
50
|
-
const trimmed = slashed.replace(/\/+$/, "");
|
|
51
|
-
return trimmed === "" ? "/" : trimmed;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —
|
|
55
|
-
* the two things every docs repo has and no service repo does. The pair is the
|
|
56
|
-
* whole point: a single marker would make `init --docs ../srv` (a typo for
|
|
57
|
-
* `../docs`) look like a join and adopt the service repo as the fleet.
|
|
58
|
-
*/
|
|
59
|
-
function isDocsRepo(dir) {
|
|
60
|
-
return docsRepoState(dir).kind === "ok" && existsSync(agentsPath(dir));
|
|
61
|
-
}
|
|
3
|
+
import { CONFIG_FILENAME, findConfigPath, loadConfig, localConfigPath, saveConfig, } from "../../core/envelope/config.js";
|
|
4
|
+
import { docsDirOf } from "../../core/kernel/ids/dirs.js";
|
|
5
|
+
import { emitJson, fail } from "../../core/envelope/json.js";
|
|
6
|
+
import { plannedDocsFiles, scaffoldDocs } from "../../core/docs.js";
|
|
7
|
+
import { docsRepoState } from "../../core/repo/state.js";
|
|
8
|
+
import { listServices } from "../../core/repo/repo.js";
|
|
9
|
+
import { InvalidIdError, assertServiceId } from "../../core/kernel/ids/service.js";
|
|
10
|
+
import { detectAgentTools, plannedCommandFiles, syncAgentCommands, updatedAgentFileManifest, } from "../../core/agent/scaffold.js";
|
|
11
|
+
import { AGENT_TOOLS } from "../../core/agent/tools/registry.js";
|
|
12
|
+
import { initExample } from "./example.js";
|
|
13
|
+
import { firstHour } from "./first-hour.js";
|
|
14
|
+
import { MCP_CONFIG_FILENAME, mcpConfigPath, mcpServerSnippet, writeMcpConfig } from "./mcp.js";
|
|
15
|
+
import { isDocsRepo, resolveAgentProfile, resolveTools, storedDocsDir } from "./options.js";
|
|
62
16
|
export function registerInit(program) {
|
|
63
17
|
program
|
|
64
18
|
.command("init")
|
|
@@ -69,12 +23,42 @@ export function registerInit(program) {
|
|
|
69
23
|
.option("--force", `write ${CONFIG_FILENAME} here even though one governs a parent directory`)
|
|
70
24
|
.option("--tools <ids>", "agent tools to generate for, overriding the scan of this directory: " +
|
|
71
25
|
`comma-separated (${Object.keys(AGENT_TOOLS).join(", ")}) or "all"`)
|
|
26
|
+
.option("--agent-profile <profile>", "workflow set: full | service | docs")
|
|
27
|
+
.option("--example <dir>", "copy the packaged example fleet to <dir> and stop: no repository is bound, nothing is scaffolded")
|
|
72
28
|
.option("--no-commands", "skip the slash commands for this repo entirely")
|
|
73
29
|
.option("--no-skills", "skip the agent skills for this repo entirely")
|
|
30
|
+
.option("--mcp", `also write ${MCP_CONFIG_FILENAME} here, so an MCP host launches \`loam mcp\` for this repo`)
|
|
31
|
+
.option("--mcp-author", `write ${MCP_CONFIG_FILENAME} with the opt-in authoring profile`)
|
|
74
32
|
.option("--json", "emit the machine contract instead of the human view")
|
|
75
33
|
.action(async (opts, command) => {
|
|
76
34
|
const json = opts.json === true;
|
|
77
35
|
const cwd = process.cwd();
|
|
36
|
+
// FIRST, before every guard below including the governing-config one:
|
|
37
|
+
// `--example` writes a fresh tree, it does not join a system. A
|
|
38
|
+
// loam.json in an ancestor governs the directories a repository is bound
|
|
39
|
+
// INTO, and this flag binds nothing — refusing here would be the tool
|
|
40
|
+
// declining to show itself working because of a config that has no
|
|
41
|
+
// bearing on the copy. Before the --service id check too, so a run
|
|
42
|
+
// combining the two answers the contradiction rather than grading an id
|
|
43
|
+
// it is about to refuse to use.
|
|
44
|
+
if (opts.example !== undefined) {
|
|
45
|
+
await initExample({
|
|
46
|
+
dir: opts.example,
|
|
47
|
+
conflicts: [
|
|
48
|
+
// `--docs` carries a default, so only its SOURCE can say whether
|
|
49
|
+
// anybody typed it — the same question the docsDir precedence
|
|
50
|
+
// below asks, for the same reason.
|
|
51
|
+
...(command.getOptionValueSource("docs") !== "default" ? ["--docs"] : []),
|
|
52
|
+
...(opts.service !== undefined ? ["--service"] : []),
|
|
53
|
+
...(opts.create === true ? ["--create"] : []),
|
|
54
|
+
...(opts.tools !== undefined ? ["--tools"] : []),
|
|
55
|
+
...(opts.agentProfile !== undefined ? ["--agent-profile"] : []),
|
|
56
|
+
...(opts.mcpAuthor === true ? ["--mcp-author"] : []),
|
|
57
|
+
],
|
|
58
|
+
json,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
78
62
|
// The id becomes services/<id>/ in the shared repo, so it is validated
|
|
79
63
|
// before anything is written — by the same rule adopt, vouch and gherkin
|
|
80
64
|
// use, never by a guard invented here.
|
|
@@ -103,7 +87,12 @@ export function registerInit(program) {
|
|
|
103
87
|
// Only THIS directory's config is spread forward. Under --force there is
|
|
104
88
|
// a config in an ancestor too, and inheriting its `service` would bind
|
|
105
89
|
// this repo to a service somebody else's repo declared.
|
|
106
|
-
|
|
90
|
+
// `kind: "invalid"` reads as null on purpose: init REPAIRS a corrupt
|
|
91
|
+
// loam.json by rewriting it, so a config nobody can read is treated
|
|
92
|
+
// exactly like no config at all. The old stderr line about it was
|
|
93
|
+
// core's side effect, promised nowhere.
|
|
94
|
+
const load = existsSync(localConfigPath(cwd)) ? await loadConfig(cwd) : null;
|
|
95
|
+
const existing = load?.kind === "loaded" ? load.config : null;
|
|
107
96
|
// A re-run must not move a committed pointer. `--docs` has a default
|
|
108
97
|
// (`.loam-docs`), so an init invoked for any OTHER reason — `--service`,
|
|
109
98
|
// a new `--tools`, the fix `doctor.agent-files-missing` prints — used to
|
|
@@ -118,7 +107,11 @@ export function registerInit(program) {
|
|
|
118
107
|
const docsTyped = command.getOptionValueSource("docs") !== "default";
|
|
119
108
|
const docsSource = docsTyped ? "flag" : committedDocs === undefined ? "default" : "config";
|
|
120
109
|
const docsOption = !docsTyped && committedDocs !== undefined ? committedDocs : opts.docs;
|
|
121
|
-
|
|
110
|
+
// Branded at the resolution, because the guards below are what validate
|
|
111
|
+
// it — the brand's provenance is "an explicit --docs a command
|
|
112
|
+
// validated", and this command is the one that does. The STORED spelling
|
|
113
|
+
// (`storedDocsDir` below) deliberately stays a plain string.
|
|
114
|
+
const docsDir = docsDirOf(resolve(cwd, docsOption));
|
|
122
115
|
// The one predictable failure: --docs naming a file. Refused here so the
|
|
123
116
|
// caller gets a clean envelope/message instead of mkdir's ENOTDIR throw.
|
|
124
117
|
if (existsSync(docsDir) && !statSync(docsDir).isDirectory()) {
|
|
@@ -165,33 +158,72 @@ export function registerInit(program) {
|
|
|
165
158
|
const tools = opts.tools === undefined ? scanned : resolveTools(opts.tools, json);
|
|
166
159
|
if (tools === null)
|
|
167
160
|
return;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
161
|
+
const profile = resolveAgentProfile(opts.agentProfile, existing?.agentProfile, json);
|
|
162
|
+
if (profile === null)
|
|
163
|
+
return;
|
|
164
|
+
// Probe the pre-existing paths in planned order. Managed files refreshed
|
|
165
|
+
// below are removed from `skipped`; custom and already-current files stay.
|
|
166
|
+
const plannedAgentFiles = delivery.length > 0 ? plannedCommandFiles(cwd, tools, delivery, profile) : [];
|
|
167
|
+
// `.mcp.json` joins the same list rather than being reported on the side:
|
|
168
|
+
// it is a scaffolded path like any other, so it must appear in `created`
|
|
169
|
+
// or in `skipped` by the one rule that governs both. Last, because it is
|
|
170
|
+
// written last.
|
|
171
|
+
const candidates = [
|
|
172
|
+
...plannedDocsFiles(docsDir),
|
|
173
|
+
...plannedAgentFiles.map((f) => f.path),
|
|
174
|
+
...(opts.mcp === true || opts.mcpAuthor === true ? [mcpConfigPath(cwd)] : []),
|
|
175
|
+
];
|
|
176
|
+
let skipped = candidates.filter((p) => existsSync(p));
|
|
177
177
|
// Joining touches the docs repo not at all: it is somebody's committed
|
|
178
178
|
// repository, and "point at it" must never mean "write to it".
|
|
179
179
|
const created = joining && opts.create !== true ? [] : (await scaffoldDocs(docsDir)).created;
|
|
180
180
|
const generatedFor = delivery.length > 0 ? tools : [];
|
|
181
|
+
let refreshed = [];
|
|
182
|
+
let managedFiles = {};
|
|
181
183
|
if (delivery.length > 0) {
|
|
182
|
-
|
|
184
|
+
const synced = await syncAgentCommands({
|
|
185
|
+
cwd,
|
|
186
|
+
toolIds: tools,
|
|
187
|
+
delivery,
|
|
188
|
+
profile,
|
|
189
|
+
known: existing?.agentFiles,
|
|
190
|
+
});
|
|
191
|
+
created.push(...synced.created);
|
|
192
|
+
refreshed = synced.refreshed;
|
|
193
|
+
managedFiles = synced.managed;
|
|
194
|
+
skipped = skipped.filter((path) => !refreshed.includes(path));
|
|
195
|
+
}
|
|
196
|
+
// The third delivery, and the only machine-readable one. It refuses out
|
|
197
|
+
// loud rather than being written best-effort: a `.mcp.json` half-landed
|
|
198
|
+
// is a host that starts a broken server, and the caller asked for it by
|
|
199
|
+
// name. Before saveConfig, so a run that cannot write this file has not
|
|
200
|
+
// yet moved the committed pointer either.
|
|
201
|
+
let mcpWritten = false;
|
|
202
|
+
if (opts.mcp === true || opts.mcpAuthor === true) {
|
|
203
|
+
const write = await writeMcpConfig(cwd, opts.mcpAuthor === true);
|
|
204
|
+
if (write.kind === "failed") {
|
|
205
|
+
fail(json, write.code, write.message);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
mcpWritten = write.kind === "created";
|
|
209
|
+
if (mcpWritten)
|
|
210
|
+
created.push(mcpConfigPath(cwd));
|
|
183
211
|
}
|
|
184
212
|
const stored = storedDocsDir(docsOption);
|
|
185
213
|
// Union, not replacement: this run's files join the ones earlier runs left
|
|
186
214
|
// on disk, and `agentTools` is a record of what the repo HOLDS. A run that
|
|
187
215
|
// generated nothing adds nothing and erases nothing.
|
|
188
216
|
const recordedTools = [...new Set([...(existing?.agentTools ?? []), ...generatedFor])];
|
|
217
|
+
const agentFileManifest = updatedAgentFileManifest(cwd, plannedAgentFiles, existing?.agentFiles, managedFiles);
|
|
189
218
|
const config = {
|
|
190
219
|
...existing,
|
|
191
220
|
docsDir: stored,
|
|
192
221
|
...(opts.service ? { service: opts.service } : {}),
|
|
193
222
|
...(recordedTools.length > 0 ? { agentTools: recordedTools } : {}),
|
|
223
|
+
agentProfile: profile,
|
|
194
224
|
};
|
|
225
|
+
if (Object.keys(agentFileManifest).length > 0)
|
|
226
|
+
config.agentFiles = agentFileManifest;
|
|
195
227
|
const configFile = await saveConfig(config, cwd);
|
|
196
228
|
const serviceCount = (await listServices(docsDir)).length;
|
|
197
229
|
if (json) {
|
|
@@ -204,6 +236,7 @@ export function registerInit(program) {
|
|
|
204
236
|
// changing: an agent comparing the two learns whether its selection
|
|
205
237
|
// matches the repo.
|
|
206
238
|
emitJson({
|
|
239
|
+
command: "init",
|
|
207
240
|
docsDir,
|
|
208
241
|
docsDirStored: stored,
|
|
209
242
|
// Where the pointer came from: `flag` (a --docs somebody typed),
|
|
@@ -213,8 +246,10 @@ export function registerInit(program) {
|
|
|
213
246
|
docsRepo: joining ? "existing" : "created",
|
|
214
247
|
services: serviceCount,
|
|
215
248
|
created,
|
|
249
|
+
refreshed,
|
|
216
250
|
skipped,
|
|
217
251
|
tools: generatedFor,
|
|
252
|
+
agentProfile: profile,
|
|
218
253
|
detected,
|
|
219
254
|
});
|
|
220
255
|
return;
|
|
@@ -240,11 +275,51 @@ export function registerInit(program) {
|
|
|
240
275
|
console.log(` commands: ${tools.join(", ")}`);
|
|
241
276
|
if (opts.skills)
|
|
242
277
|
console.log(` skills: ${tools.join(", ")}`);
|
|
278
|
+
console.log(` profile: ${profile}`);
|
|
243
279
|
if (created.length > 0) {
|
|
244
280
|
console.log(" scaffolded:");
|
|
245
281
|
for (const c of created)
|
|
246
282
|
console.log(` + ${c}`);
|
|
247
283
|
}
|
|
284
|
+
if (refreshed.length > 0) {
|
|
285
|
+
console.log(" refreshed (unchanged since loam last wrote them):");
|
|
286
|
+
for (const path of refreshed)
|
|
287
|
+
console.log(` ↻ ${path}`);
|
|
288
|
+
}
|
|
289
|
+
// The one skipped path that earns more than its line in `skipped`: loam
|
|
290
|
+
// will not merge into a `.mcp.json` a human owns, and the caller asked
|
|
291
|
+
// for this delivery by name — so they are handed the exact key to paste
|
|
292
|
+
// into their own `mcpServers` object. Nothing was read out of their file
|
|
293
|
+
// to produce it; the snippet is the same bytes a fresh write would have
|
|
294
|
+
// used, which is also why it names the launch form this install shape
|
|
295
|
+
// actually needs.
|
|
296
|
+
if ((opts.mcp === true || opts.mcpAuthor === true) && !mcpWritten) {
|
|
297
|
+
console.log(` mcp: ${MCP_CONFIG_FILENAME} is already here — left exactly as it is.`);
|
|
298
|
+
console.log(` paste this into its "mcpServers" object:`);
|
|
299
|
+
for (const line of mcpServerSnippet(cwd, opts.mcpAuthor === true))
|
|
300
|
+
console.log(` ${line}`);
|
|
301
|
+
}
|
|
302
|
+
// Printed ONLY for the single-repo trial composition: one run that both
|
|
303
|
+
// created the docs repo and left a service bound (the binding may
|
|
304
|
+
// predate the run — the config spread above carries an existing
|
|
305
|
+
// loam.json's `service` forward). `loam status` is NOT mute here — its
|
|
306
|
+
// first-hour ladder (core/status/fleet/next.ts) already answers
|
|
307
|
+
// `next.adopt-bound` in exactly this state — but status has to be run
|
|
308
|
+
// to say so, and no status rung ever names `loam vouch`, the one step
|
|
309
|
+
// of this loop that is a person's; init's output is already on screen,
|
|
310
|
+
// so it prints the whole hour once. A join stays silent on purpose: a
|
|
311
|
+
// joined fleet has other repositories already through this loop, and
|
|
312
|
+
// `loam status` in its docs repo is the working guide there. The --json
|
|
313
|
+
// path returned above, so the envelope is byte-identical to before
|
|
314
|
+
// this block existed.
|
|
315
|
+
if (!joining && config.service !== undefined) {
|
|
316
|
+
const steps = firstHour(config.service);
|
|
317
|
+
const width = Math.max(...steps.map(([command]) => command.length));
|
|
318
|
+
console.log(" next — the first hour:");
|
|
319
|
+
for (const [command, why] of steps) {
|
|
320
|
+
console.log(` ${command.padEnd(width)} # ${why}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
248
323
|
});
|
|
249
324
|
}
|
|
250
325
|
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport {\n CONFIG_FILENAME,\n findConfigPath,\n loadConfig,\n localConfigPath,\n saveConfig,\n type StoredConfig,\n} from \"../../core/envelope/config.js\";\nimport { docsDirOf } from \"../../core/kernel/ids/dirs.js\";\nimport { emitJson, fail } from \"../../core/envelope/json.js\";\nimport { plannedDocsFiles, scaffoldDocs } from \"../../core/docs.js\";\nimport { docsRepoState } from \"../../core/repo/state.js\";\nimport { listServices } from \"../../core/repo/repo.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport {\n detectAgentTools,\n plannedCommandFiles,\n syncAgentCommands,\n updatedAgentFileManifest,\n type Delivery,\n} from \"../../core/agent/scaffold.js\";\nimport { AGENT_TOOLS } from \"../../core/agent/tools/registry.js\";\nimport { initExample } from \"./example.js\";\nimport { firstHour } from \"./first-hour.js\";\nimport { MCP_CONFIG_FILENAME, mcpConfigPath, mcpServerSnippet, writeMcpConfig } from \"./mcp.js\";\nimport { isDocsRepo, resolveAgentProfile, resolveTools, storedDocsDir } from \"./options.js\";\n\ninterface InitOptions {\n docs: string;\n service?: string;\n /** --create: make a new docs repo at --docs instead of joining an existing one. */\n create?: boolean;\n /** --force: write loam.json here even though one already governs a parent directory. */\n force?: boolean;\n /** commander's --no-commands: true unless the flag is passed. */\n commands: boolean;\n /** commander's --no-skills: true unless the flag is passed. */\n skills: boolean;\n /**\n * --mcp: also write the repo-root `.mcp.json`. Opt-in and default off — a\n * third delivery, independent of the two `--no-*` flags rather than a\n * variation on them, so it neither contradicts them nor is suppressed by\n * either. See ./mcp.ts for why the file is opt-in at all.\n */\n mcp?: boolean;\n mcpAuthor?: boolean;\n /** --tools: comma-separated AGENT_TOOLS ids, or \"all\". Absent = autodetect. */\n tools?: string;\n /** Workflow subset to scaffold. */\n agentProfile?: string;\n /** --example: copy the packaged example fleet to this directory and do nothing else. */\n example?: string;\n json?: boolean;\n}\n\nexport function registerInit(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize loam: create/point at the shared docs repo and write local config\")\n .option(\"--docs <dir>\", \"path to the shared docs repo (the source of truth)\", \".loam-docs\")\n .option(\"--service <id>\", \"canonical id of the service in this repo\")\n .option(\"--create\", \"create a new docs repo at --docs instead of joining an existing one\")\n .option(\"--force\", `write ${CONFIG_FILENAME} here even though one governs a parent directory`)\n .option(\n \"--tools <ids>\",\n \"agent tools to generate for, overriding the scan of this directory: \" +\n `comma-separated (${Object.keys(AGENT_TOOLS).join(\", \")}) or \"all\"`,\n )\n .option(\"--agent-profile <profile>\", \"workflow set: full | service | docs\")\n .option(\n \"--example <dir>\",\n \"copy the packaged example fleet to <dir> and stop: no repository is bound, nothing is scaffolded\",\n )\n .option(\"--no-commands\", \"skip the slash commands for this repo entirely\")\n .option(\"--no-skills\", \"skip the agent skills for this repo entirely\")\n .option(\n \"--mcp\",\n `also write ${MCP_CONFIG_FILENAME} here, so an MCP host launches \\`loam mcp\\` for this repo`,\n )\n .option(\"--mcp-author\", `write ${MCP_CONFIG_FILENAME} with the opt-in authoring profile`)\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: InitOptions, command: Command) => {\n const json = opts.json === true;\n const cwd = process.cwd();\n\n // FIRST, before every guard below including the governing-config one:\n // `--example` writes a fresh tree, it does not join a system. A\n // loam.json in an ancestor governs the directories a repository is bound\n // INTO, and this flag binds nothing — refusing here would be the tool\n // declining to show itself working because of a config that has no\n // bearing on the copy. Before the --service id check too, so a run\n // combining the two answers the contradiction rather than grading an id\n // it is about to refuse to use.\n if (opts.example !== undefined) {\n await initExample({\n dir: opts.example,\n conflicts: [\n // `--docs` carries a default, so only its SOURCE can say whether\n // anybody typed it — the same question the docsDir precedence\n // below asks, for the same reason.\n ...(command.getOptionValueSource(\"docs\") !== \"default\" ? [\"--docs\"] : []),\n ...(opts.service !== undefined ? [\"--service\"] : []),\n ...(opts.create === true ? [\"--create\"] : []),\n ...(opts.tools !== undefined ? [\"--tools\"] : []),\n ...(opts.agentProfile !== undefined ? [\"--agent-profile\"] : []),\n ...(opts.mcpAuthor === true ? [\"--mcp-author\"] : []),\n ],\n json,\n });\n return;\n }\n\n // The id becomes services/<id>/ in the shared repo, so it is validated\n // before anything is written — by the same rule adopt, vouch and gherkin\n // use, never by a guard invented here.\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service);\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n }\n\n // A loam.json in an ancestor already governs this directory: every command\n // run from here resolves to it. Writing a second one below it would shadow\n // the first for this subtree only — the kind of split-brain nobody\n // discovers until two commands disagree about which docs repo is the fleet.\n const governing = findConfigPath(cwd);\n if (governing !== null && governing !== localConfigPath(cwd) && opts.force !== true) {\n fail(\n json,\n \"already-exists\",\n `${governing} already governs this directory. ` +\n `Run loam from ${resolve(governing, \"..\")}, or pass --force to give this ` +\n `subdirectory its own ${CONFIG_FILENAME}.`,\n );\n return;\n }\n\n // Only THIS directory's config is spread forward. Under --force there is\n // a config in an ancestor too, and inheriting its `service` would bind\n // this repo to a service somebody else's repo declared.\n // `kind: \"invalid\"` reads as null on purpose: init REPAIRS a corrupt\n // loam.json by rewriting it, so a config nobody can read is treated\n // exactly like no config at all. The old stderr line about it was\n // core's side effect, promised nowhere.\n const load = existsSync(localConfigPath(cwd)) ? await loadConfig(cwd) : null;\n const existing = load?.kind === \"loaded\" ? load.config : null;\n\n // A re-run must not move a committed pointer. `--docs` has a default\n // (`.loam-docs`), so an init invoked for any OTHER reason — `--service`,\n // a new `--tools`, the fix `doctor.agent-files-missing` prints — used to\n // arrive here carrying a docsDir nobody typed: the default then named no\n // docs repo, the refusal steered the caller to `--create`, and `--create`\n // rewrote `docsDir` in the committed loam.json to a freshly scaffolded\n // empty one. `validate --all` went green over an empty fleet, which is\n // the exact outcome `--create` exists to prevent. So the flag wins only\n // when it was actually passed; otherwise the file this repo already\n // committed does.\n const committedDocs = existing?.docsDirAsWritten;\n const docsTyped = command.getOptionValueSource(\"docs\") !== \"default\";\n const docsSource: \"flag\" | \"config\" | \"default\" =\n docsTyped ? \"flag\" : committedDocs === undefined ? \"default\" : \"config\";\n const docsOption = !docsTyped && committedDocs !== undefined ? committedDocs : opts.docs;\n // Branded at the resolution, because the guards below are what validate\n // it — the brand's provenance is \"an explicit --docs a command\n // validated\", and this command is the one that does. The STORED spelling\n // (`storedDocsDir` below) deliberately stays a plain string.\n const docsDir = docsDirOf(resolve(cwd, docsOption));\n\n // The one predictable failure: --docs naming a file. Refused here so the\n // caller gets a clean envelope/message instead of mkdir's ENOTDIR throw.\n if (existsSync(docsDir) && !statSync(docsDir).isDirectory()) {\n fail(json, \"invalid-option\", `--docs points at a file, not a directory: ${docsDir}`);\n return;\n }\n\n // Joining an existing docs repo and creating a new one are different\n // intentions, and `init` used to perform the second one whenever the first\n // was misspelled: `--docs ../dcos` scaffolded a second, empty docs repo\n // beside the real one, and the fleet quietly split in two. Creation is now\n // something the caller asks for.\n const joining = isDocsRepo(docsDir);\n if (!joining && opts.create !== true) {\n fail(\n json,\n \"invalid-option\",\n docsRepoState(docsDir).kind === \"missing\"\n ? `--docs points at a directory that does not exist: ${docsDir}. ` +\n \"If that is a typo, fix it; to create a new docs repo there, pass --create.\"\n : `--docs points at ${docsDir}, which is not a docs repo ` +\n \"(a docs repo has services/ and AGENTS.md). \" +\n \"Point --docs at the shared docs repo, or pass --create to make a new one here.\",\n );\n return;\n }\n\n // --tools selects the files to write; --no-commands and --no-skills each\n // say write none of that kind. Together they contradict — refused, not\n // arbitrated, in either combination.\n const suppressed = [\n ...(opts.commands ? [] : [\"--no-commands\"]),\n ...(opts.skills ? [] : [\"--no-skills\"]),\n ];\n if (opts.tools !== undefined && suppressed.length > 0) {\n fail(\n json,\n \"invalid-option\",\n `--tools contradicts ${suppressed.join(\" and \")}: ` +\n \"one selects the files to generate, the other suppresses them.\",\n );\n return;\n }\n const delivery: Delivery[] = [\n ...(opts.commands ? ([\"commands\"] as const) : []),\n ...(opts.skills ? ([\"skills\"] as const) : []),\n ];\n\n // Without --tools the repo decides: whichever tools have left their own\n // dot-directories here. Falling back to claude keeps a bare repo behaving\n // exactly as it did before the scan existed. `detected` is reported either\n // way — what the scan saw is a fact about the repo, not about the flags.\n const detected = detectAgentTools(cwd);\n const scanned = detected.length > 0 ? detected : [\"claude\"];\n const tools = opts.tools === undefined ? scanned : resolveTools(opts.tools, json);\n if (tools === null) return;\n const profile = resolveAgentProfile(opts.agentProfile, existing?.agentProfile, json);\n if (profile === null) return;\n\n // Probe the pre-existing paths in planned order. Managed files refreshed\n // below are removed from `skipped`; custom and already-current files stay.\n const plannedAgentFiles = delivery.length > 0 ? plannedCommandFiles(cwd, tools, delivery, profile) : [];\n // `.mcp.json` joins the same list rather than being reported on the side:\n // it is a scaffolded path like any other, so it must appear in `created`\n // or in `skipped` by the one rule that governs both. Last, because it is\n // written last.\n const candidates = [\n ...plannedDocsFiles(docsDir),\n ...plannedAgentFiles.map((f) => f.path),\n ...(opts.mcp === true || opts.mcpAuthor === true ? [mcpConfigPath(cwd)] : []),\n ];\n let skipped = candidates.filter((p) => existsSync(p));\n\n // Joining touches the docs repo not at all: it is somebody's committed\n // repository, and \"point at it\" must never mean \"write to it\".\n const created = joining && opts.create !== true ? [] : (await scaffoldDocs(docsDir)).created;\n const generatedFor = delivery.length > 0 ? tools : [];\n let refreshed: string[] = [];\n let managedFiles: Record<string, string> = {};\n if (delivery.length > 0) {\n const synced = await syncAgentCommands({\n cwd,\n toolIds: tools,\n delivery,\n profile,\n known: existing?.agentFiles,\n });\n created.push(...synced.created);\n refreshed = synced.refreshed;\n managedFiles = synced.managed;\n skipped = skipped.filter((path) => !refreshed.includes(path));\n }\n\n // The third delivery, and the only machine-readable one. It refuses out\n // loud rather than being written best-effort: a `.mcp.json` half-landed\n // is a host that starts a broken server, and the caller asked for it by\n // name. Before saveConfig, so a run that cannot write this file has not\n // yet moved the committed pointer either.\n let mcpWritten = false;\n if (opts.mcp === true || opts.mcpAuthor === true) {\n const write = await writeMcpConfig(cwd, opts.mcpAuthor === true);\n if (write.kind === \"failed\") {\n fail(json, write.code, write.message);\n return;\n }\n mcpWritten = write.kind === \"created\";\n if (mcpWritten) created.push(mcpConfigPath(cwd));\n }\n\n const stored = storedDocsDir(docsOption);\n // Union, not replacement: this run's files join the ones earlier runs left\n // on disk, and `agentTools` is a record of what the repo HOLDS. A run that\n // generated nothing adds nothing and erases nothing.\n const recordedTools = [...new Set([...(existing?.agentTools ?? []), ...generatedFor])];\n const agentFileManifest = updatedAgentFileManifest(cwd, plannedAgentFiles, existing?.agentFiles, managedFiles);\n const config: StoredConfig = {\n ...existing,\n docsDir: stored,\n ...(opts.service ? { service: opts.service } : {}),\n ...(recordedTools.length > 0 ? { agentTools: recordedTools } : {}),\n agentProfile: profile,\n };\n if (Object.keys(agentFileManifest).length > 0) config.agentFiles = agentFileManifest;\n const configFile = await saveConfig(config, cwd);\n\n const serviceCount = (await listServices(docsDir)).length;\n\n if (json) {\n // `docsDir` stays the resolved absolute path — it is what a consumer\n // needs to find the repo. `docsDirStored` is what was written to\n // loam.json, which is the fact this command is now careful about.\n // `tools` names what files were generated FOR — empty when every\n // delivery was suppressed and none were. `detected` is the separate\n // question of what the scan SAW, which `--tools` overrides without\n // changing: an agent comparing the two learns whether its selection\n // matches the repo.\n emitJson({\n command: \"init\",\n docsDir,\n docsDirStored: stored,\n // Where the pointer came from: `flag` (a --docs somebody typed),\n // `config` (the one this repo already committed — a re-run cannot\n // move it), or `default` (nothing said, nothing committed).\n docsDirSource: docsSource,\n docsRepo: joining ? \"existing\" : \"created\",\n services: serviceCount,\n created,\n refreshed,\n skipped,\n tools: generatedFor,\n agentProfile: profile,\n detected,\n });\n return;\n }\n\n console.log(\"loam initialized.\");\n if (joining) {\n console.log(` docs repo: ${docsDir}`);\n console.log(` pointing at existing docs repo (${serviceCount} services)`);\n } else {\n console.log(` docs repo: ${docsDir} (created)`);\n }\n console.log(\n ` docsDir: ${stored} (as stored in ${CONFIG_FILENAME}`\n + (docsSource === \"config\" ? \" — kept; no --docs was passed\" : \"\") + \")\",\n );\n if (config.service) console.log(` service: ${config.service}`);\n console.log(` config: ${configFile}`);\n console.log(` commit ${CONFIG_FILENAME} — docsDir is resolved relative to it`);\n if (opts.tools === undefined && detected.length > 0) {\n console.log(` detected: ${detected.join(\", \")}`);\n }\n if (opts.commands) console.log(` commands: ${tools.join(\", \")}`);\n if (opts.skills) console.log(` skills: ${tools.join(\", \")}`);\n console.log(` profile: ${profile}`);\n if (created.length > 0) {\n console.log(\" scaffolded:\");\n for (const c of created) console.log(` + ${c}`);\n }\n if (refreshed.length > 0) {\n console.log(\" refreshed (unchanged since loam last wrote them):\");\n for (const path of refreshed) console.log(` ↻ ${path}`);\n }\n\n // The one skipped path that earns more than its line in `skipped`: loam\n // will not merge into a `.mcp.json` a human owns, and the caller asked\n // for this delivery by name — so they are handed the exact key to paste\n // into their own `mcpServers` object. Nothing was read out of their file\n // to produce it; the snippet is the same bytes a fresh write would have\n // used, which is also why it names the launch form this install shape\n // actually needs.\n if ((opts.mcp === true || opts.mcpAuthor === true) && !mcpWritten) {\n console.log(` mcp: ${MCP_CONFIG_FILENAME} is already here — left exactly as it is.`);\n console.log(` paste this into its \"mcpServers\" object:`);\n for (const line of mcpServerSnippet(cwd, opts.mcpAuthor === true)) console.log(` ${line}`);\n }\n\n // Printed ONLY for the single-repo trial composition: one run that both\n // created the docs repo and left a service bound (the binding may\n // predate the run — the config spread above carries an existing\n // loam.json's `service` forward). `loam status` is NOT mute here — its\n // first-hour ladder (core/status/fleet/next.ts) already answers\n // `next.adopt-bound` in exactly this state — but status has to be run\n // to say so, and no status rung ever names `loam vouch`, the one step\n // of this loop that is a person's; init's output is already on screen,\n // so it prints the whole hour once. A join stays silent on purpose: a\n // joined fleet has other repositories already through this loop, and\n // `loam status` in its docs repo is the working guide there. The --json\n // path returned above, so the envelope is byte-identical to before\n // this block existed.\n if (!joining && config.service !== undefined) {\n const steps = firstHour(config.service);\n const width = Math.max(...steps.map(([command]) => command.length));\n console.log(\" next — the first hour:\");\n for (const [command, why] of steps) {\n console.log(` ${command.padEnd(width)} # ${why}`);\n }\n }\n });\n}\n"]}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `loam init --mcp`: the one MACHINE delivery `init` makes.
|
|
3
|
+
*
|
|
4
|
+
* Every other thing init writes is prose an agent reads — command files and
|
|
5
|
+
* Agent Skills, twenty tools' worth of dialects, all of them pointers at
|
|
6
|
+
* `loam instructions`. The MCP facade is the opposite: a typed read surface,
|
|
7
|
+
* four bounded authoring entries under `--author`, version-matched resources,
|
|
8
|
+
* and every result carrying the `--json` envelope as `structuredContent`. It
|
|
9
|
+
* was also the only delivery that required a human to hand-edit a JSON file
|
|
10
|
+
* before anything could reach it — the generated
|
|
11
|
+
* AGENTS.md said no more than "configure the host to launch `loam mcp` in the
|
|
12
|
+
* repository the tools should answer for", so a scaffolded repository reliably
|
|
13
|
+
* got the prose deliveries and never the typed one.
|
|
14
|
+
*
|
|
15
|
+
* OPT-IN, and that is not timidity. `.mcp.json` at the repo root is a file a
|
|
16
|
+
* host reads and then STARTS A PROCESS from, for everyone who checks the
|
|
17
|
+
* repository out. Writing one by default would mean `loam init` silently
|
|
18
|
+
* arranging for a binary to be launched on a teammate's machine, which is a
|
|
19
|
+
* decision that belongs to whoever runs the command, not to us.
|
|
20
|
+
*
|
|
21
|
+
* ## Why only the repo-root `.mcp.json`
|
|
22
|
+
*
|
|
23
|
+
* loam knows twenty agent tools and several of them read MCP configuration
|
|
24
|
+
* from a file of their own. None of the others is written here, and a future
|
|
25
|
+
* reader who wants to add them should meet the argument first:
|
|
26
|
+
*
|
|
27
|
+
* - `.github/.mcp.json` is already in the registry as a Copilot DETECTION
|
|
28
|
+
* marker (tools/registry.ts). Writing it would make the next `init` detect
|
|
29
|
+
* Copilot in a repository that has none, because we put the marker there —
|
|
30
|
+
* a scan reporting its own output back to itself.
|
|
31
|
+
* - `.cursor/mcp.json` and `.vscode/mcp.json` carry different schemas
|
|
32
|
+
* (`servers` rather than `mcpServers`, plus per-host keys), so a single set
|
|
33
|
+
* of bytes cannot serve all three, and one template per host is one more
|
|
34
|
+
* thing to keep true across releases of somebody else's product.
|
|
35
|
+
* - `.gemini/settings.json` is a GENERAL settings file. Its MCP block is one
|
|
36
|
+
* key among many, so loam could only land it by merging into a file the
|
|
37
|
+
* user owns — and merging into a file a human owns is the one thing every
|
|
38
|
+
* init delivery is built not to do.
|
|
39
|
+
*
|
|
40
|
+
* The repo-root `.mcp.json` is the form with none of those problems: it is a
|
|
41
|
+
* dedicated file, it is nobody's detection marker, and it is read by the hosts
|
|
42
|
+
* that matter without being owned by any of them.
|
|
43
|
+
*/
|
|
44
|
+
import { existsSync } from "node:fs";
|
|
45
|
+
import { join } from "node:path";
|
|
46
|
+
import { stageWrites } from "../../core/staging/commit.js";
|
|
47
|
+
import { commitStaged } from "../../core/staging/txn/transaction.js";
|
|
48
|
+
import { planWrite } from "../../core/staging/writes.js";
|
|
49
|
+
export const MCP_CONFIG_FILENAME = ".mcp.json";
|
|
50
|
+
/** The one file this delivery writes, so init's `skipped` probe and the writer cannot disagree. */
|
|
51
|
+
export function mcpConfigPath(cwd) {
|
|
52
|
+
return join(cwd, MCP_CONFIG_FILENAME);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* How `loam` is launched HERE, decided from how it is installed here.
|
|
56
|
+
*
|
|
57
|
+
* A fixed `"command": "loam"` would be an unlaunchable entry in exactly the
|
|
58
|
+
* repositories README tells people to make: the documented install is a
|
|
59
|
+
* per-repo devDependency, which puts the binary in `node_modules/.bin/` and on
|
|
60
|
+
* no PATH an MCP host inherits. So the local bin decides — `npx --no` when it
|
|
61
|
+
* is there, the bare name when it is not.
|
|
62
|
+
*
|
|
63
|
+
* `--no` and not a bare `npx loam mcp`: without it npx will FETCH `loam` from
|
|
64
|
+
* the registry when the local resolution misses, which turns a stale checkout
|
|
65
|
+
* into a silent download of a package with a name loam does not own. With it,
|
|
66
|
+
* a missing local binary is an error the host reports.
|
|
67
|
+
*
|
|
68
|
+
* The probe is the extensionless name on both platforms deliberately: npm's
|
|
69
|
+
* shim writer lays down `loam`, `loam.cmd` and `loam.ps1` together on Windows,
|
|
70
|
+
* the first of them for the POSIX shells that run there, so its presence is the
|
|
71
|
+
* portable question "is loam installed into this project".
|
|
72
|
+
*/
|
|
73
|
+
export function mcpLaunch(cwd, author = false) {
|
|
74
|
+
const localBin = join(cwd, "node_modules", ".bin", "loam");
|
|
75
|
+
const args = ["mcp", ...(author ? ["--author"] : [])];
|
|
76
|
+
return existsSync(localBin)
|
|
77
|
+
? { command: "npx", args: ["--no", "loam", ...args] }
|
|
78
|
+
: { command: "loam", args };
|
|
79
|
+
}
|
|
80
|
+
/** The whole file, exactly as it lands. */
|
|
81
|
+
export function mcpConfigContent(cwd, author = false) {
|
|
82
|
+
return `${JSON.stringify({ mcpServers: { loam: mcpLaunch(cwd, author) } }, null, 2)}\n`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The `"loam": { … }` entry alone, as lines — what init prints when the file
|
|
86
|
+
* is already there so a person can paste the one key into their own
|
|
87
|
+
* `mcpServers` object.
|
|
88
|
+
*
|
|
89
|
+
* Sliced out of the same object the file is made of rather than spelled a
|
|
90
|
+
* second time: a snippet that drifts from the bytes is worse than no snippet,
|
|
91
|
+
* because the reader has no way to tell which of the two is current.
|
|
92
|
+
*/
|
|
93
|
+
export function mcpServerSnippet(cwd, author = false) {
|
|
94
|
+
return JSON.stringify({ loam: mcpLaunch(cwd, author) }, null, 2)
|
|
95
|
+
.split("\n")
|
|
96
|
+
.slice(1, -1)
|
|
97
|
+
.map((line) => line.slice(2));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Write `.mcp.json`, or report why not.
|
|
101
|
+
*
|
|
102
|
+
* Through the journaled transaction every other loam writer uses, not a bare
|
|
103
|
+
* `writeFile`: the write is an exclusive create (the existsSync above proves
|
|
104
|
+
* the path is free), so two inits racing for the same repository serialise
|
|
105
|
+
* into the same "already there, left alone" answer instead of one of them
|
|
106
|
+
* silently burying the other's bytes. `root` is the repository being
|
|
107
|
+
* scaffolded, which is where a killed run's `.loam-commit` belongs — the same
|
|
108
|
+
* place `gherkin` journals its own writes into a service repo.
|
|
109
|
+
*/
|
|
110
|
+
export async function writeMcpConfig(cwd, author = false) {
|
|
111
|
+
const path = mcpConfigPath(cwd);
|
|
112
|
+
if (existsSync(path))
|
|
113
|
+
return { kind: "skipped" };
|
|
114
|
+
const staged = await stageWrites([planWrite(path, mcpConfigContent(cwd, author))]);
|
|
115
|
+
const committed = await commitStaged({
|
|
116
|
+
root: cwd,
|
|
117
|
+
command: "init",
|
|
118
|
+
rerun: author ? "loam init --mcp-author" : "loam init --mcp",
|
|
119
|
+
target: MCP_CONFIG_FILENAME,
|
|
120
|
+
}, staged, "written");
|
|
121
|
+
if (committed.ok)
|
|
122
|
+
return { kind: "created" };
|
|
123
|
+
// A lost exclusive create is the never-overwrite contract firing one layer
|
|
124
|
+
// down — somebody else's `.mcp.json` is there now, and "present, so skipped"
|
|
125
|
+
// is the answer the probe above would have given a moment later. Nothing of
|
|
126
|
+
// ours went in; there is no half-state to report.
|
|
127
|
+
if (committed.raced)
|
|
128
|
+
return { kind: "skipped" };
|
|
129
|
+
return { kind: "failed", code: committed.code, message: committed.message };
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/commands/init/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam init --mcp`: the one MACHINE delivery `init` makes.\n *\n * Every other thing init writes is prose an agent reads — command files and\n * Agent Skills, twenty tools' worth of dialects, all of them pointers at\n * `loam instructions`. The MCP facade is the opposite: a typed read surface,\n * four bounded authoring entries under `--author`, version-matched resources,\n * and every result carrying the `--json` envelope as `structuredContent`. It\n * was also the only delivery that required a human to hand-edit a JSON file\n * before anything could reach it — the generated\n * AGENTS.md said no more than \"configure the host to launch `loam mcp` in the\n * repository the tools should answer for\", so a scaffolded repository reliably\n * got the prose deliveries and never the typed one.\n *\n * OPT-IN, and that is not timidity. `.mcp.json` at the repo root is a file a\n * host reads and then STARTS A PROCESS from, for everyone who checks the\n * repository out. Writing one by default would mean `loam init` silently\n * arranging for a binary to be launched on a teammate's machine, which is a\n * decision that belongs to whoever runs the command, not to us.\n *\n * ## Why only the repo-root `.mcp.json`\n *\n * loam knows twenty agent tools and several of them read MCP configuration\n * from a file of their own. None of the others is written here, and a future\n * reader who wants to add them should meet the argument first:\n *\n * - `.github/.mcp.json` is already in the registry as a Copilot DETECTION\n * marker (tools/registry.ts). Writing it would make the next `init` detect\n * Copilot in a repository that has none, because we put the marker there —\n * a scan reporting its own output back to itself.\n * - `.cursor/mcp.json` and `.vscode/mcp.json` carry different schemas\n * (`servers` rather than `mcpServers`, plus per-host keys), so a single set\n * of bytes cannot serve all three, and one template per host is one more\n * thing to keep true across releases of somebody else's product.\n * - `.gemini/settings.json` is a GENERAL settings file. Its MCP block is one\n * key among many, so loam could only land it by merging into a file the\n * user owns — and merging into a file a human owns is the one thing every\n * init delivery is built not to do.\n *\n * The repo-root `.mcp.json` is the form with none of those problems: it is a\n * dedicated file, it is nobody's detection marker, and it is read by the hosts\n * that matter without being owned by any of them.\n */\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { planWrite } from \"../../core/staging/writes.js\";\n\nexport const MCP_CONFIG_FILENAME = \".mcp.json\";\n\n/** The one file this delivery writes, so init's `skipped` probe and the writer cannot disagree. */\nexport function mcpConfigPath(cwd: string): string {\n return join(cwd, MCP_CONFIG_FILENAME);\n}\n\n/** What a host is told to run: the `command`/`args` pair of the `loam` server entry. */\nexport interface McpLaunch {\n command: string;\n args: string[];\n}\n\n/**\n * How `loam` is launched HERE, decided from how it is installed here.\n *\n * A fixed `\"command\": \"loam\"` would be an unlaunchable entry in exactly the\n * repositories README tells people to make: the documented install is a\n * per-repo devDependency, which puts the binary in `node_modules/.bin/` and on\n * no PATH an MCP host inherits. So the local bin decides — `npx --no` when it\n * is there, the bare name when it is not.\n *\n * `--no` and not a bare `npx loam mcp`: without it npx will FETCH `loam` from\n * the registry when the local resolution misses, which turns a stale checkout\n * into a silent download of a package with a name loam does not own. With it,\n * a missing local binary is an error the host reports.\n *\n * The probe is the extensionless name on both platforms deliberately: npm's\n * shim writer lays down `loam`, `loam.cmd` and `loam.ps1` together on Windows,\n * the first of them for the POSIX shells that run there, so its presence is the\n * portable question \"is loam installed into this project\".\n */\nexport function mcpLaunch(cwd: string, author = false): McpLaunch {\n const localBin = join(cwd, \"node_modules\", \".bin\", \"loam\");\n const args = [\"mcp\", ...(author ? [\"--author\"] : [])];\n return existsSync(localBin)\n ? { command: \"npx\", args: [\"--no\", \"loam\", ...args] }\n : { command: \"loam\", args };\n}\n\n/** The whole file, exactly as it lands. */\nexport function mcpConfigContent(cwd: string, author = false): string {\n return `${JSON.stringify({ mcpServers: { loam: mcpLaunch(cwd, author) } }, null, 2)}\\n`;\n}\n\n/**\n * The `\"loam\": { … }` entry alone, as lines — what init prints when the file\n * is already there so a person can paste the one key into their own\n * `mcpServers` object.\n *\n * Sliced out of the same object the file is made of rather than spelled a\n * second time: a snippet that drifts from the bytes is worse than no snippet,\n * because the reader has no way to tell which of the two is current.\n */\nexport function mcpServerSnippet(cwd: string, author = false): string[] {\n return JSON.stringify({ loam: mcpLaunch(cwd, author) }, null, 2)\n .split(\"\\n\")\n .slice(1, -1)\n .map((line) => line.slice(2));\n}\n\n/**\n * What happened to `.mcp.json` on this run. `skipped` is the never-overwrite\n * contract every other init delivery follows, and for the same reason: loam\n * does not merge into a file a human owns, so an existing `.mcp.json` is\n * reported and left byte-for-byte alone — no parse, no key merge, no rewrite.\n */\nexport type McpWrite =\n | { kind: \"created\" }\n | { kind: \"skipped\" }\n | { kind: \"failed\"; code: \"merge-failed\" | \"rollback-incomplete\"; message: string };\n\n/**\n * Write `.mcp.json`, or report why not.\n *\n * Through the journaled transaction every other loam writer uses, not a bare\n * `writeFile`: the write is an exclusive create (the existsSync above proves\n * the path is free), so two inits racing for the same repository serialise\n * into the same \"already there, left alone\" answer instead of one of them\n * silently burying the other's bytes. `root` is the repository being\n * scaffolded, which is where a killed run's `.loam-commit` belongs — the same\n * place `gherkin` journals its own writes into a service repo.\n */\nexport async function writeMcpConfig(cwd: string, author = false): Promise<McpWrite> {\n const path = mcpConfigPath(cwd);\n if (existsSync(path)) return { kind: \"skipped\" };\n\n const staged = await stageWrites([planWrite(path, mcpConfigContent(cwd, author))]);\n const committed = await commitStaged(\n {\n root: cwd,\n command: \"init\",\n rerun: author ? \"loam init --mcp-author\" : \"loam init --mcp\",\n target: MCP_CONFIG_FILENAME,\n },\n staged,\n \"written\",\n );\n if (committed.ok) return { kind: \"created\" };\n // A lost exclusive create is the never-overwrite contract firing one layer\n // down — somebody else's `.mcp.json` is there now, and \"present, so skipped\"\n // is the answer the probe above would have given a moment later. Nothing of\n // ours went in; there is no half-state to report.\n if (committed.raced) return { kind: \"skipped\" };\n return { kind: \"failed\", code: committed.code, message: committed.message };\n}\n"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three questions `loam init` answers before it writes anything: which
|
|
3
|
+
* agent tools were asked for, where the docs are being recorded, and whether a
|
|
4
|
+
* directory already IS a docs repo.
|
|
5
|
+
*
|
|
6
|
+
* They are here rather than inline because each one has a default that is a
|
|
7
|
+
* decision. `--tools` has no commander default on purpose, so an explicit flag
|
|
8
|
+
* stays distinguishable from none — which is what lets the autodetection
|
|
9
|
+
* fallback and the `--no-*` contradiction be decided rather than silently
|
|
10
|
+
* arbitrated.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { fail } from "../../core/envelope/json.js";
|
|
14
|
+
import { agentsPath } from "../../core/repo/paths.js";
|
|
15
|
+
import { docsRepoState } from "../../core/repo/state.js";
|
|
16
|
+
import { AGENT_TOOLS } from "../../core/agent/tools/registry.js";
|
|
17
|
+
import { AGENT_PROFILES, } from "../../core/agent/scaffold.js";
|
|
18
|
+
export function resolveAgentProfile(raw, current, json) {
|
|
19
|
+
const value = raw ?? current ?? "full";
|
|
20
|
+
if (AGENT_PROFILES.includes(value))
|
|
21
|
+
return value;
|
|
22
|
+
fail(json, "invalid-option", `Unknown --agent-profile '${value}'. Expected: ${AGENT_PROFILES.join(" | ")}.`);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve --tools to registry ids, or null after reporting the refusal. The
|
|
27
|
+
* default (the cwd scan) lives at the call site, not in commander, so an
|
|
28
|
+
* explicit `--tools` is distinguishable from none — which is what lets both the
|
|
29
|
+
* autodetection fallback and the `--no-*` contradiction be decided instead of
|
|
30
|
+
* silently arbitrated.
|
|
31
|
+
*/
|
|
32
|
+
export function resolveTools(raw, json) {
|
|
33
|
+
const supported = Object.keys(AGENT_TOOLS);
|
|
34
|
+
if (raw === "all")
|
|
35
|
+
return supported;
|
|
36
|
+
const ids = [...new Set(raw.split(",").map((t) => t.trim()).filter((t) => t !== ""))];
|
|
37
|
+
const unknown = ids.filter((t) => !(t in AGENT_TOOLS));
|
|
38
|
+
if (ids.length === 0 || unknown.length > 0) {
|
|
39
|
+
fail(json, "invalid-option", (ids.length === 0
|
|
40
|
+
? "--tools names no tool."
|
|
41
|
+
: `--tools does not recognize: ${unknown.join(", ")}.`) +
|
|
42
|
+
` Supported: ${supported.join(", ")} — or "all".`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return ids;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `--docs` exactly as the caller wrote it, with separators normalised.
|
|
49
|
+
*
|
|
50
|
+
* Stored verbatim on purpose. `init` used to resolve it and write the absolute
|
|
51
|
+
* result, which meant a committed loam.json named a directory that existed on
|
|
52
|
+
* one laptop: every teammate who cloned the service repo got a docsDir under
|
|
53
|
+
* someone else's home directory, and `loam list` reported an empty fleet
|
|
54
|
+
* instead of saying so. `loadConfig` resolves relative paths against the config
|
|
55
|
+
* file's own directory, so `../docs` keeps meaning "next to this repo" wherever
|
|
56
|
+
* the pair is checked out. An absolute `--docs` is still stored absolute — that
|
|
57
|
+
* is the caller's explicit choice, and `loam doctor` warns about it.
|
|
58
|
+
*
|
|
59
|
+
* Backslashes become forward slashes so a config written on Windows resolves on
|
|
60
|
+
* POSIX; a trailing separator is dropped so the stored spelling is stable.
|
|
61
|
+
*/
|
|
62
|
+
export function storedDocsDir(raw) {
|
|
63
|
+
const slashed = raw.split("\\").join("/");
|
|
64
|
+
if (slashed.length <= 1)
|
|
65
|
+
return slashed;
|
|
66
|
+
const trimmed = slashed.replace(/\/+$/, "");
|
|
67
|
+
return trimmed === "" ? "/" : trimmed;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —
|
|
71
|
+
* the two things every docs repo has and no service repo does. The pair is the
|
|
72
|
+
* whole point: a single marker would make `init --docs ../srv` (a typo for
|
|
73
|
+
* `../docs`) look like a join and adopt the service repo as the fleet.
|
|
74
|
+
*/
|
|
75
|
+
export function isDocsRepo(dir) {
|
|
76
|
+
return docsRepoState(dir).kind === "ok" && existsSync(agentsPath(dir));
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/commands/init/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EACL,cAAc,GAEf,MAAM,8BAA8B,CAAC;AAEtC,MAAM,UAAU,mBAAmB,CACjC,GAAuB,EACvB,OAAiC,EACjC,IAAa;IAEb,MAAM,KAAK,GAAG,GAAG,IAAI,OAAO,IAAI,MAAM,CAAC;IACvC,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAqB,CAAC;QAAE,OAAO,KAAqB,CAAC;IACjF,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,4BAA4B,KAAK,gBAAgB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7G,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAa;IACrD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YACf,CAAC,CAAC,wBAAwB;YAC1B,CAAC,CAAC,+BAA+B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACvD,eAAe,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CACpD,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACzE,CAAC","sourcesContent":["/**\n * The three questions `loam init` answers before it writes anything: which\n * agent tools were asked for, where the docs are being recorded, and whether a\n * directory already IS a docs repo.\n *\n * They are here rather than inline because each one has a default that is a\n * decision. `--tools` has no commander default on purpose, so an explicit flag\n * stays distinguishable from none — which is what lets the autodetection\n * fallback and the `--no-*` contradiction be decided rather than silently\n * arbitrated.\n */\nimport { existsSync } from \"node:fs\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { fail } from \"../../core/envelope/json.js\";\nimport { agentsPath } from \"../../core/repo/paths.js\";\nimport { docsRepoState } from \"../../core/repo/state.js\";\nimport { AGENT_TOOLS } from \"../../core/agent/tools/registry.js\";\nimport {\n AGENT_PROFILES,\n type AgentProfile,\n} from \"../../core/agent/scaffold.js\";\n\nexport function resolveAgentProfile(\n raw: string | undefined,\n current: AgentProfile | undefined,\n json: boolean,\n): AgentProfile | null {\n const value = raw ?? current ?? \"full\";\n if (AGENT_PROFILES.includes(value as AgentProfile)) return value as AgentProfile;\n fail(json, \"invalid-option\", `Unknown --agent-profile '${value}'. Expected: ${AGENT_PROFILES.join(\" | \")}.`);\n return null;\n}\n\n/**\n * Resolve --tools to registry ids, or null after reporting the refusal. The\n * default (the cwd scan) lives at the call site, not in commander, so an\n * explicit `--tools` is distinguishable from none — which is what lets both the\n * autodetection fallback and the `--no-*` contradiction be decided instead of\n * silently arbitrated.\n */\nexport function resolveTools(raw: string, json: boolean): string[] | null {\n const supported = Object.keys(AGENT_TOOLS);\n if (raw === \"all\") return supported;\n const ids = [...new Set(raw.split(\",\").map((t) => t.trim()).filter((t) => t !== \"\"))];\n const unknown = ids.filter((t) => !(t in AGENT_TOOLS));\n if (ids.length === 0 || unknown.length > 0) {\n fail(\n json,\n \"invalid-option\",\n (ids.length === 0\n ? \"--tools names no tool.\"\n : `--tools does not recognize: ${unknown.join(\", \")}.`) +\n ` Supported: ${supported.join(\", \")} — or \"all\".`,\n );\n return null;\n }\n return ids;\n}\n\n/**\n * `--docs` exactly as the caller wrote it, with separators normalised.\n *\n * Stored verbatim on purpose. `init` used to resolve it and write the absolute\n * result, which meant a committed loam.json named a directory that existed on\n * one laptop: every teammate who cloned the service repo got a docsDir under\n * someone else's home directory, and `loam list` reported an empty fleet\n * instead of saying so. `loadConfig` resolves relative paths against the config\n * file's own directory, so `../docs` keeps meaning \"next to this repo\" wherever\n * the pair is checked out. An absolute `--docs` is still stored absolute — that\n * is the caller's explicit choice, and `loam doctor` warns about it.\n *\n * Backslashes become forward slashes so a config written on Windows resolves on\n * POSIX; a trailing separator is dropped so the stored spelling is stable.\n */\nexport function storedDocsDir(raw: string): string {\n const slashed = raw.split(\"\\\\\").join(\"/\");\n if (slashed.length <= 1) return slashed;\n const trimmed = slashed.replace(/\\/+$/, \"\");\n return trimmed === \"\" ? \"/\" : trimmed;\n}\n\n/**\n * Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —\n * the two things every docs repo has and no service repo does. The pair is the\n * whole point: a single marker would make `init --docs ../srv` (a typo for\n * `../docs`) look like a join and adopt the service repo as the fleet.\n */\nexport function isDocsRepo(dir: DocsDir): boolean {\n return docsRepoState(dir).kind === \"ok\" && existsSync(agentsPath(dir));\n}\n"]}
|