@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5992 -82
- package/COMPARISON.md +168 -63
- package/CONTRIBUTING.md +121 -0
- package/MIGRATING-from-OpenSpec.md +238 -55
- package/QUICKSTART.md +302 -0
- package/README.md +653 -144
- package/ROADMAP.md +1035 -0
- package/SCHEMA.md +3916 -263
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +927 -0
- package/dist/cli.js +133 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +204 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +309 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +74 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/closing.js +42 -0
- package/dist/commands/archive/closing.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/consumers.js +56 -0
- package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +193 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
- package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
- package/dist/commands/archive/plan/document/head.js +151 -0
- package/dist/commands/archive/plan/document/head.js.map +1 -0
- package/dist/commands/archive/plan/document/links.js +284 -0
- package/dist/commands/archive/plan/document/links.js.map +1 -0
- package/dist/commands/archive/plan/document/run.js +136 -0
- package/dist/commands/archive/plan/document/run.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +319 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +298 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/model/extending.js +85 -0
- package/dist/commands/archive/plan/model/extending.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +106 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +318 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +30 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +355 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/archive/shipped.js +49 -0
- package/dist/commands/archive/shipped.js.map +1 -0
- package/dist/commands/context/context.js +166 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +305 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +367 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +221 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +6 -8
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +86 -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 +65 -5
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +227 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +39 -28
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +152 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +66 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +105 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +262 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +146 -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 +72 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +142 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +63 -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 +155 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +358 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +344 -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/suites/suites.js +140 -0
- package/dist/commands/list/suites/suites.js.map +1 -0
- package/dist/commands/list/views.js +108 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +238 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +75 -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 +175 -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 +143 -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 +86 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +18 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +40 -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/capability-template.js +118 -0
- package/dist/commands/new/capability-template.js.map +1 -0
- package/dist/commands/new/commit.js +62 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/modifies.js +206 -0
- package/dist/commands/new/modifies.js.map +1 -0
- package/dist/commands/new/new.js +328 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +279 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +199 -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} +38 -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 +300 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +221 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +278 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +174 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +182 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/introduced.js +157 -0
- package/dist/commands/show/introduced.js.map +1 -0
- package/dist/commands/show/marks.js +53 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/show/service.js +239 -0
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +87 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/fleet-next.js +90 -0
- package/dist/commands/status/fleet-next.js.map +1 -0
- package/dist/commands/status/json.js +47 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +209 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +115 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +269 -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 +325 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +113 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +98 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +318 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/exclude.js +132 -0
- package/dist/commands/subsystem/txn/exclude.js.map +1 -0
- package/dist/commands/subsystem/txn/links.js +128 -0
- package/dist/commands/subsystem/txn/links.js.map +1 -0
- package/dist/commands/subsystem/txn/report.js +174 -0
- package/dist/commands/subsystem/txn/report.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +196 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +249 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/tasks/actions.js +107 -0
- package/dist/commands/tasks/actions.js.map +1 -0
- package/dist/commands/tasks/render.js +253 -0
- package/dist/commands/tasks/render.js.map +1 -0
- package/dist/commands/tasks/tasks.js +119 -0
- package/dist/commands/tasks/tasks.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +176 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/unarchive/restore.js +254 -0
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +59 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +245 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +204 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +58 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/introduced.js +102 -0
- package/dist/commands/validate/checks/introduced.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +264 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +85 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/coverage/covers-after.js +105 -0
- package/dist/commands/validate/coverage/covers-after.js.map +1 -0
- package/dist/commands/validate/feature.js +222 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +93 -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 +371 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +118 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/map/attest.js +98 -0
- package/dist/commands/validate/fleet/map/attest.js.map +1 -0
- package/dist/commands/validate/fleet/map/bindings.js +107 -0
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
- package/dist/commands/validate/fleet/map/consumers.js +244 -0
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
- package/dist/commands/validate/fleet/map/isolation.js +116 -0
- package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
- package/dist/commands/validate/fleet/map/usecases.js +54 -0
- package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +266 -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 +71 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.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/views/fleet-project.js +217 -0
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +75 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/projects.js +278 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/root-documents.js +83 -0
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +52 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +89 -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/render/repeats.js +63 -0
- package/dist/commands/validate/render/repeats.js.map +1 -0
- package/dist/commands/validate/render/rollups.js +115 -0
- package/dist/commands/validate/render/rollups.js.map +1 -0
- package/dist/commands/validate/render/text.js +199 -0
- package/dist/commands/validate/render/text.js.map +1 -0
- package/dist/commands/validate/report.js +145 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/scope.js +113 -0
- package/dist/commands/validate/scope.js.map +1 -0
- package/dist/commands/validate/service/api.js +252 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/contracts/generated.js +134 -0
- package/dist/commands/validate/service/contracts/generated.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +241 -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 +177 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/model/diverged.js +226 -0
- package/dist/commands/validate/service/model/diverged.js.map +1 -0
- package/dist/commands/validate/service/model/grade.js +163 -0
- package/dist/commands/validate/service/model/grade.js.map +1 -0
- package/dist/commands/validate/service/service.js +310 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +279 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +148 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/service/usecases/tags.js +113 -0
- package/dist/commands/validate/service/usecases/tags.js.map +1 -0
- package/dist/commands/validate/service/usecases/usecases.js +209 -0
- package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/validate.js +363 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +178 -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 +81 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +263 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +278 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +206 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +328 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +220 -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 +266 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +141 -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 +230 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +111 -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 +155 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +169 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +299 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +46 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +44 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +78 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +104 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +138 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +273 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md.js +203 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -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 +254 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +144 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +151 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +193 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +280 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +373 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +323 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +220 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +188 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +311 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +67 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +210 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
- package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +19 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +338 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +43 -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 +146 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +92 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +38 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +290 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +195 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +83 -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 +263 -0
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +285 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +385 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +273 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/map/extend.js +84 -0
- package/dist/core/brief/map/extend.js.map +1 -0
- package/dist/core/brief/map/owed.js +266 -0
- package/dist/core/brief/map/owed.js.map +1 -0
- package/dist/core/brief/targets.js +304 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +58 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +190 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/direction/direction.js +114 -0
- package/dist/core/c4/direction/direction.js.map +1 -0
- package/dist/core/c4/likec4.js +243 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/locate/unlocated.js +150 -0
- package/dist/core/c4/locate/unlocated.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +160 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +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 +110 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +113 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/prefetch/fleet.js +134 -0
- package/dist/core/c4/prefetch/fleet.js.map +1 -0
- package/dist/core/c4/project/architecture.js +161 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/batch.js +140 -0
- package/dist/core/c4/project/batch.js.map +1 -0
- package/dist/core/c4/project/documents.js +89 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +219 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +277 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/attested.js +0 -0
- package/dist/core/c4/resolve/attested.js.map +1 -0
- package/dist/core/c4/resolve/external.js +51 -0
- package/dist/core/c4/resolve/external.js.map +1 -0
- package/dist/core/c4/resolve/service.js +174 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +290 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/resolve/systems.js +154 -0
- package/dist/core/c4/resolve/systems.js.map +1 -0
- package/dist/core/c4/root-project/exclude.js +352 -0
- package/dist/core/c4/root-project/exclude.js.map +1 -0
- package/dist/core/c4/seed/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 +173 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/service-model/created/models.js +96 -0
- package/dist/core/c4/service-model/created/models.js.map +1 -0
- package/dist/core/c4/service-model/documents.js +47 -0
- package/dist/core/c4/service-model/documents.js.map +1 -0
- package/dist/core/c4/service-model/fleet/extending.js +82 -0
- package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
- package/dist/core/c4/service-model/load.js +165 -0
- package/dist/core/c4/service-model/load.js.map +1 -0
- package/dist/core/c4/service-model/renderer.js +128 -0
- package/dist/core/c4/service-model/renderer.js.map +1 -0
- package/dist/core/c4/service-model/shape.js +106 -0
- package/dist/core/c4/service-model/shape.js.map +1 -0
- package/dist/core/c4/service-model/slice.js +188 -0
- package/dist/core/c4/service-model/slice.js.map +1 -0
- package/dist/core/c4/source-mask.js +369 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +308 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +167 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +30 -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/declared.js +87 -0
- package/dist/core/c4/splice/identity/declared.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +73 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/identity/existing.js +80 -0
- package/dist/core/c4/splice/identity/existing.js.map +1 -0
- package/dist/core/c4/splice/identity/interior.js +80 -0
- package/dist/core/c4/splice/identity/interior.js.map +1 -0
- package/dist/core/c4/splice/identity/owner.js +50 -0
- package/dist/core/c4/splice/identity/owner.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +337 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/model/merge.js +151 -0
- package/dist/core/c4/splice/model/merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +298 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/splice/text/spot.js +131 -0
- package/dist/core/c4/splice/text/spot.js.map +1 -0
- package/dist/core/c4/workspace.js +166 -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 +47 -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 +338 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +174 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +123 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +205 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +104 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +267 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +185 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +75 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/calls/called.js +52 -0
- package/dist/core/coherence/calls/called.js.map +1 -0
- package/dist/core/coherence/coherence.js +332 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/consumed/operations.js +70 -0
- package/dist/core/coherence/consumed/operations.js.map +1 -0
- package/dist/core/coherence/consumed/refusal.js +38 -0
- package/dist/core/coherence/consumed/refusal.js.map +1 -0
- package/dist/core/coherence/covers/health.js +85 -0
- package/dist/core/coherence/covers/health.js.map +1 -0
- package/dist/core/coherence/declared.js +295 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +191 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +335 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +189 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +63 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/produced.js +100 -0
- package/dist/core/coherence/events/produced.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 +95 -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/coherence/retired/archived.js +285 -0
- package/dist/core/coherence/retired/archived.js.map +1 -0
- package/dist/core/coherence/retired/event-pair.js +62 -0
- package/dist/core/coherence/retired/event-pair.js.map +1 -0
- package/dist/core/coherence/retired/merged.js +79 -0
- package/dist/core/coherence/retired/merged.js.map +1 -0
- package/dist/core/coherence/retired/retirement.js +49 -0
- package/dist/core/coherence/retired/retirement.js.map +1 -0
- package/dist/core/coherence/retired/revival/arrivals.js +131 -0
- package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
- package/dist/core/coherence/retired/revival/revived.js +297 -0
- package/dist/core/coherence/retired/revival/revived.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/consumers/after.js +113 -0
- package/dist/core/consumers/after.js.map +1 -0
- package/dist/core/consumers/consumers.js +296 -0
- package/dist/core/consumers/consumers.js.map +1 -0
- package/dist/core/consumers/current.js +211 -0
- package/dist/core/consumers/current.js.map +1 -0
- package/dist/core/consumers/scan.js +46 -0
- package/dist/core/consumers/scan.js.map +1 -0
- package/dist/core/consumers/state.js +27 -0
- package/dist/core/consumers/state.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +341 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/deployment/delta.js +191 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +230 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +237 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/joins.js +136 -0
- package/dist/core/diff/joins.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +204 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/scope/edges.js +82 -0
- package/dist/core/diff/scope/edges.js.map +1 -0
- package/dist/core/diff/semantic.js +312 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/docs.js +37 -85
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +238 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +139 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +355 -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/reports/scan.js +242 -0
- package/dist/core/doctor/reports/scan.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 +224 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -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 +286 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +238 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +234 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +89 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +209 -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 +180 -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 +194 -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/documents.js +227 -0
- package/dist/core/explain/terms/documents.js.map +1 -0
- package/dist/core/explain/terms/done-check.js +144 -0
- package/dist/core/explain/terms/done-check.js.map +1 -0
- package/dist/core/explain/terms/entry.js +14 -0
- package/dist/core/explain/terms/entry.js.map +1 -0
- package/dist/core/explain/terms/stages.js +71 -0
- package/dist/core/explain/terms/stages.js.map +1 -0
- package/dist/core/explain/terms/tasks.js +97 -0
- package/dist/core/explain/terms/tasks.js.map +1 -0
- package/dist/core/explain/terms.js +103 -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/explore.js +204 -0
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +174 -146
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +208 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +246 -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 +176 -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 +210 -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 +109 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +73 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -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/fqn/ancestors.js +65 -0
- package/dist/core/kernel/ids/fqn/ancestors.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} +56 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/{records.js → kernel/records.js} +11 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +66 -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 +118 -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 +265 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +212 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +73 -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 +324 -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 +207 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +142 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +174 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/contract-text.js +33 -0
- package/dist/core/openapi/contract-text.js.map +1 -0
- package/dist/core/openapi/contract-tree.js +301 -0
- package/dist/core/openapi/contract-tree.js.map +1 -0
- package/dist/core/openapi/depth.js +136 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +239 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +54 -108
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +199 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +16 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +204 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +232 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +110 -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 +220 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +78 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +70 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +241 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +191 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +304 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +116 -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 +157 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +120 -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/projection/introduced.js +14 -0
- package/dist/core/projection/introduced.js.map +1 -0
- package/dist/core/provenance/findings.js +244 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +201 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +139 -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 +280 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +220 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +322 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +308 -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 +61 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +90 -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/render/body.js +258 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +182 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +42 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/render/views.js +293 -0
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +255 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +146 -14
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +239 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/legacy.js +271 -0
- package/dist/core/scaffold/legacy.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 +252 -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 +268 -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 +95 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +204 -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/manifest.js +188 -0
- package/dist/core/staging/snapshot/manifest.js.map +1 -0
- package/dist/core/staging/snapshot/snapshot.js +196 -0
- package/dist/core/staging/snapshot/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +181 -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 +60 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +126 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +214 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +163 -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/feature/words.js +96 -0
- package/dist/core/status/feature/words.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +216 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +302 -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 +216 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/tasks/packet.js +199 -0
- package/dist/core/tasks/packet.js.map +1 -0
- package/dist/core/tasks/record.js +43 -0
- package/dist/core/tasks/record.js.map +1 -0
- package/dist/core/tasks/sources.js +181 -0
- package/dist/core/tasks/sources.js.map +1 -0
- package/dist/core/tasks/stamps.js +76 -0
- package/dist/core/tasks/stamps.js.map +1 -0
- package/dist/core/tasks/unit.js +0 -0
- package/dist/core/tasks/unit.js.map +1 -0
- package/dist/core/usecases/capability.js +166 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +140 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +101 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/modified.js +315 -0
- package/dist/core/usecases/delta/modified.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +76 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +296 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/grade/capability-tag.js +93 -0
- package/dist/core/usecases/grade/capability-tag.js.map +1 -0
- package/dist/core/usecases/grade/feature.js +88 -0
- package/dist/core/usecases/grade/feature.js.map +1 -0
- package/dist/core/usecases/grade/requirement-tag.js +94 -0
- package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
- package/dist/core/usecases/grade/steps.js +266 -0
- package/dist/core/usecases/grade/steps.js.map +1 -0
- package/dist/core/usecases/grade/usecases.js +112 -0
- package/dist/core/usecases/grade/usecases.js.map +1 -0
- package/dist/core/usecases/operations.js +123 -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/service/exclude.js +119 -0
- package/dist/core/usecases/service/exclude.js.map +1 -0
- package/dist/core/usecases/service/flows.js +164 -0
- package/dist/core/usecases/service/flows.js.map +1 -0
- package/dist/core/usecases/suites/participants.js +83 -0
- package/dist/core/usecases/suites/participants.js.map +1 -0
- package/dist/core/usecases/suites/suites.js +45 -0
- package/dist/core/usecases/suites/suites.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +180 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +170 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +259 -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/location.js +67 -0
- package/dist/core/verify/location.js.map +1 -0
- package/dist/core/verify/pins/lint.js +158 -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/read/file.js +224 -0
- package/dist/core/verify/read/file.js.map +1 -0
- package/dist/core/verify/read/shape.js +169 -0
- package/dist/core/verify/read/shape.js.map +1 -0
- package/dist/core/verify/read/union.js +105 -0
- package/dist/core/verify/read/union.js.map +1 -0
- package/dist/core/verify/record.js +165 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +99 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +61 -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 +59 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +216 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/vocabulary/report.js +90 -0
- 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 +232 -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 +336 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +18 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +74 -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 +132 -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 +31 -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 +73 -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 +8 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +92 -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 +134 -0
- package/examples/docs/services/order-service/asyncapi.yaml +109 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +126 -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 +76 -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 +68 -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 +120 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +81 -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 +200 -0
- package/examples/docs/services/platform/notification-service/health.yaml +40 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js +0 -320
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js +0 -317
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js +0 -253
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js +0 -225
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js +0 -47
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which drawn elements are SERVICES — asked of a feature's delta, the way the
|
|
3
|
+
* fleet census asks it of the map.
|
|
4
|
+
*
|
|
5
|
+
* The census (`commands/validate/fleet/census.ts`, `drawnSystems`) is the one
|
|
6
|
+
* answer `validate --all` gives: an element is graded as a service when no
|
|
7
|
+
* ancestor already stands for one, unless it is a person, somebody else's
|
|
8
|
+
* system (`#external`), infrastructure the fleet runs, or a GROUPING — an
|
|
9
|
+
* element that contains a service rather than being one. The feature-scope
|
|
10
|
+
* graders asked a narrower question of their own. `service.no-requirement-delta`
|
|
11
|
+
* asked only "is it a `softwareSystem`", so a delta's `#external` producer was
|
|
12
|
+
* called a new service that owes a requirement delta; the checklist's
|
|
13
|
+
* `service.exists` asked "is its id dotted", so the same producer became a unit
|
|
14
|
+
* of work in `loam tasks`, a top-level grouping became a service called after
|
|
15
|
+
* its title, and the new service FEAT-101 draws inside the map's own group
|
|
16
|
+
* became a container nobody had to build (the real-fleet review, 2026-10-21).
|
|
17
|
+
* After the archive, the fleet called every one of those differently.
|
|
18
|
+
*
|
|
19
|
+
* It lives in core because those graders do (`core/coherence/`,
|
|
20
|
+
* `core/verify/`), and core may not import the census. `standsForService`
|
|
21
|
+
* below is the census's own predicate rung for rung, and the census still
|
|
22
|
+
* spells its copy: the two must keep answering alike until it imports this
|
|
23
|
+
* one.
|
|
24
|
+
*
|
|
25
|
+
* THREE DELIBERATE NARROWINGS against the census, all because a delta is not a
|
|
26
|
+
* whole map. An element is looked at only through ancestors the delta DECLARES
|
|
27
|
+
* and that are themselves groupings — the map's domain or boundary drawn around
|
|
28
|
+
* the services it re-declares. A level the delta does not declare may be a
|
|
29
|
+
* living service's own element, and one that stands for no service yet groups
|
|
30
|
+
* none — a new system's box, an `#external` vendor — is what its children
|
|
31
|
+
* belong to: a container of a service with no directory yet is that service's,
|
|
32
|
+
* and an endpoint inside a vendor is the vendor's (`core/gate/partners.ts`
|
|
33
|
+
* reads it so). And a grouping must stand for no service itself: an element
|
|
34
|
+
* bound to a service IS one, whatever it contains — the census's answer too
|
|
35
|
+
* wherever it matters, since a bound or directory-titled element never reaches
|
|
36
|
+
* its undocumented pass.
|
|
37
|
+
*
|
|
38
|
+
* WHAT THE DELTA'S TAGS CANNOT SAY. A delta re-declares the living elements it
|
|
39
|
+
* attaches to as stubs, usually untagged and always without their living tags,
|
|
40
|
+
* and the merge keeps the living element's tags — so "is this #external" is a
|
|
41
|
+
* question about the map the merge leaves, not about the stub. For an element
|
|
42
|
+
* no directory answers for, `readDeltaSystem` finds the living element it
|
|
43
|
+
* stands for and asks it the same question.
|
|
44
|
+
*/
|
|
45
|
+
import { existsSync } from "node:fs";
|
|
46
|
+
import {} from "../likec4.js";
|
|
47
|
+
import { properAncestorIds } from "../../kernel/ids/fqn/ancestors.js";
|
|
48
|
+
import { ACTOR_KINDS, EXTERNAL_TAG, INFRA_KINDS } from "../../vocabulary/maturity.js";
|
|
49
|
+
import { drawnServiceElements, elementService } from "./service.js";
|
|
50
|
+
/**
|
|
51
|
+
* Does this element stand for a `services/<id>/` directory — an explicit
|
|
52
|
+
* `metadata { service }` binding, or a title naming one `known` holds?
|
|
53
|
+
*/
|
|
54
|
+
function standsForService(e, known) {
|
|
55
|
+
return e.service !== undefined || known.has(e.title);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A GROUPING: an element that stands for no service and contains one that
|
|
59
|
+
* does — a domain, a boundary, an enterprise. There is nothing to bind on it,
|
|
60
|
+
* no requirement for it to carry and no repository that builds it; the
|
|
61
|
+
* services under it answer for themselves.
|
|
62
|
+
*/
|
|
63
|
+
export function groupsServices(e, elements, known) {
|
|
64
|
+
if (standsForService(e, known))
|
|
65
|
+
return false;
|
|
66
|
+
const prefix = `${e.id}.`;
|
|
67
|
+
return elements.some((c) => c.id.startsWith(prefix) && standsForService(c, known));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Is this element a service-level SYSTEM of ours in the document `elements`
|
|
71
|
+
* comes from: not a person, not `#external`, not unbound infrastructure, not a
|
|
72
|
+
* grouping, and drawn only inside groupings that document declares.
|
|
73
|
+
*/
|
|
74
|
+
function isServiceSystem(e, elements, known) {
|
|
75
|
+
const kind = e.kind.toLowerCase();
|
|
76
|
+
if (ACTOR_KINDS.has(kind) || e.tags.includes(EXTERNAL_TAG))
|
|
77
|
+
return false;
|
|
78
|
+
if (INFRA_KINDS.has(kind) && !standsForService(e, known))
|
|
79
|
+
return false;
|
|
80
|
+
const byId = new Map(elements.map((el) => [el.id, el]));
|
|
81
|
+
for (const id of properAncestorIds(e.id)) {
|
|
82
|
+
const parent = byId.get(id);
|
|
83
|
+
if (parent === undefined || !groupsServices(parent, elements, known))
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return !groupsServices(e, elements, known);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* What a tagged delta element will be on the map the merge leaves:
|
|
90
|
+
*
|
|
91
|
+
* - `none` — not a service: the delta draws it as a person, somebody else's
|
|
92
|
+
* system, infrastructure, a grouping or something inside another element —
|
|
93
|
+
* or it is the stub of a living element the map draws as one of those;
|
|
94
|
+
* - `living` — the stub of a service that already has a `services/<id>/`:
|
|
95
|
+
* this feature changes it, it does not introduce it;
|
|
96
|
+
* - `drawn` — a service with no directory that the living map ALREADY draws,
|
|
97
|
+
* so this feature re-declares it rather than introducing it either;
|
|
98
|
+
* - `service` — a service this feature introduces: its directory is the
|
|
99
|
+
* feature's own `specs/<id>/`, or nothing has drawn it before.
|
|
100
|
+
*
|
|
101
|
+
* The living map is read only for an element no directory answers for — the
|
|
102
|
+
* one case where the stub's missing tags can be the whole answer — so the
|
|
103
|
+
* common delta, whose new services all have `specs/`, never parses it. A map
|
|
104
|
+
* that is absent or does not parse leaves the delta to answer alone, which is
|
|
105
|
+
* how every element was read before the map was asked.
|
|
106
|
+
*/
|
|
107
|
+
export async function readDeltaSystem(e, scope) {
|
|
108
|
+
const { elements, known } = scope;
|
|
109
|
+
if (!isServiceSystem(e, elements, known))
|
|
110
|
+
return "none";
|
|
111
|
+
const service = elementService(e);
|
|
112
|
+
if (scope.living.has(service))
|
|
113
|
+
return "living";
|
|
114
|
+
if (known.has(service))
|
|
115
|
+
return "service";
|
|
116
|
+
const map = await scope.livingMap();
|
|
117
|
+
const counterpart = map === null ? undefined : livingCounterpart(e, map, known);
|
|
118
|
+
if (map === null || counterpart === undefined)
|
|
119
|
+
return "service";
|
|
120
|
+
return isServiceSystem(counterpart, map.elements, known) ? "drawn" : "none";
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The living map as `readDeltaSystem` reads it — the caller's
|
|
124
|
+
* `architecture/landscape.likec4` (`landscapePath`; the path arrives as an
|
|
125
|
+
* argument because `core/repo/` already imports this package), parsed at most
|
|
126
|
+
* once per reader and only when first asked; null when there is none or it
|
|
127
|
+
* does not parse. One reader for every grader that asks, so two of them can
|
|
128
|
+
* never see different maps for one element.
|
|
129
|
+
*/
|
|
130
|
+
export function livingMapOf(path, load) {
|
|
131
|
+
let read;
|
|
132
|
+
return () => (read ??= (async () => {
|
|
133
|
+
if (!existsSync(path))
|
|
134
|
+
return null;
|
|
135
|
+
const doc = await load(path);
|
|
136
|
+
return doc.errors.length === 0 ? doc : null;
|
|
137
|
+
})());
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The element of the living map a delta element stands for: the same id, else
|
|
141
|
+
* the box the map DRAWS for the same service (`drawnServiceElements` — never a
|
|
142
|
+
* container of some other service that happens to share a title). Undefined
|
|
143
|
+
* when the map draws nothing of the kind, which for an element no directory
|
|
144
|
+
* answers for is what makes it new.
|
|
145
|
+
*/
|
|
146
|
+
function livingCounterpart(e, living, known) {
|
|
147
|
+
const byId = new Map(living.elements.map((el) => [el.id, el]));
|
|
148
|
+
const same = byId.get(e.id);
|
|
149
|
+
if (same !== undefined)
|
|
150
|
+
return same;
|
|
151
|
+
const drawn = drawnServiceElements(living.elements, known).get(elementService(e));
|
|
152
|
+
return drawn === undefined ? undefined : byId.get(drawn);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=systems.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systems.js","sourceRoot":"","sources":["../../../../src/core/c4/resolve/systems.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Which drawn elements are SERVICES — asked of a feature's delta, the way the\n * fleet census asks it of the map.\n *\n * The census (`commands/validate/fleet/census.ts`, `drawnSystems`) is the one\n * answer `validate --all` gives: an element is graded as a service when no\n * ancestor already stands for one, unless it is a person, somebody else's\n * system (`#external`), infrastructure the fleet runs, or a GROUPING — an\n * element that contains a service rather than being one. The feature-scope\n * graders asked a narrower question of their own. `service.no-requirement-delta`\n * asked only \"is it a `softwareSystem`\", so a delta's `#external` producer was\n * called a new service that owes a requirement delta; the checklist's\n * `service.exists` asked \"is its id dotted\", so the same producer became a unit\n * of work in `loam tasks`, a top-level grouping became a service called after\n * its title, and the new service FEAT-101 draws inside the map's own group\n * became a container nobody had to build (the real-fleet review, 2026-10-21).\n * After the archive, the fleet called every one of those differently.\n *\n * It lives in core because those graders do (`core/coherence/`,\n * `core/verify/`), and core may not import the census. `standsForService`\n * below is the census's own predicate rung for rung, and the census still\n * spells its copy: the two must keep answering alike until it imports this\n * one.\n *\n * THREE DELIBERATE NARROWINGS against the census, all because a delta is not a\n * whole map. An element is looked at only through ancestors the delta DECLARES\n * and that are themselves groupings — the map's domain or boundary drawn around\n * the services it re-declares. A level the delta does not declare may be a\n * living service's own element, and one that stands for no service yet groups\n * none — a new system's box, an `#external` vendor — is what its children\n * belong to: a container of a service with no directory yet is that service's,\n * and an endpoint inside a vendor is the vendor's (`core/gate/partners.ts`\n * reads it so). And a grouping must stand for no service itself: an element\n * bound to a service IS one, whatever it contains — the census's answer too\n * wherever it matters, since a bound or directory-titled element never reaches\n * its undocumented pass.\n *\n * WHAT THE DELTA'S TAGS CANNOT SAY. A delta re-declares the living elements it\n * attaches to as stubs, usually untagged and always without their living tags,\n * and the merge keeps the living element's tags — so \"is this #external\" is a\n * question about the map the merge leaves, not about the stub. For an element\n * no directory answers for, `readDeltaSystem` finds the living element it\n * stands for and asks it the same question.\n */\nimport { existsSync } from \"node:fs\";\nimport { type Elem, type LoadedDoc } from \"../likec4.js\";\nimport { properAncestorIds } from \"../../kernel/ids/fqn/ancestors.js\";\nimport { ACTOR_KINDS, EXTERNAL_TAG, INFRA_KINDS } from \"../../vocabulary/maturity.js\";\nimport { drawnServiceElements, elementService } from \"./service.js\";\n\n/**\n * Does this element stand for a `services/<id>/` directory — an explicit\n * `metadata { service }` binding, or a title naming one `known` holds?\n */\nfunction standsForService(e: Elem, known: ReadonlySet<string>): boolean {\n return e.service !== undefined || known.has(e.title);\n}\n\n/**\n * A GROUPING: an element that stands for no service and contains one that\n * does — a domain, a boundary, an enterprise. There is nothing to bind on it,\n * no requirement for it to carry and no repository that builds it; the\n * services under it answer for themselves.\n */\nexport function groupsServices(e: Elem, elements: readonly Elem[], known: ReadonlySet<string>): boolean {\n if (standsForService(e, known)) return false;\n const prefix = `${e.id}.`;\n return elements.some((c) => c.id.startsWith(prefix) && standsForService(c, known));\n}\n\n/**\n * Is this element a service-level SYSTEM of ours in the document `elements`\n * comes from: not a person, not `#external`, not unbound infrastructure, not a\n * grouping, and drawn only inside groupings that document declares.\n */\nfunction isServiceSystem(e: Elem, elements: readonly Elem[], known: ReadonlySet<string>): boolean {\n const kind = e.kind.toLowerCase();\n if (ACTOR_KINDS.has(kind) || e.tags.includes(EXTERNAL_TAG)) return false;\n if (INFRA_KINDS.has(kind) && !standsForService(e, known)) return false;\n const byId = new Map(elements.map((el) => [el.id, el]));\n for (const id of properAncestorIds(e.id)) {\n const parent = byId.get(id);\n if (parent === undefined || !groupsServices(parent, elements, known)) return false;\n }\n return !groupsServices(e, elements, known);\n}\n\n/** What `readDeltaSystem` reads a tagged delta element against. */\nexport interface DeltaSystemScope {\n /** Every element the delta declares — where its ancestors and children are looked up. */\n elements: readonly Elem[];\n /** The directories the merge leaves: the enumerated fleet plus the feature's own `specs/`. */\n known: ReadonlySet<string>;\n /** The enumerated fleet alone — the services that already have a `services/<id>/`. */\n living: ReadonlySet<string>;\n /** The living map (`livingMapOf`), read only when no directory answers for an element. */\n livingMap: () => Promise<LoadedDoc | null>;\n}\n\n/**\n * What a tagged delta element will be on the map the merge leaves:\n *\n * - `none` — not a service: the delta draws it as a person, somebody else's\n * system, infrastructure, a grouping or something inside another element —\n * or it is the stub of a living element the map draws as one of those;\n * - `living` — the stub of a service that already has a `services/<id>/`:\n * this feature changes it, it does not introduce it;\n * - `drawn` — a service with no directory that the living map ALREADY draws,\n * so this feature re-declares it rather than introducing it either;\n * - `service` — a service this feature introduces: its directory is the\n * feature's own `specs/<id>/`, or nothing has drawn it before.\n *\n * The living map is read only for an element no directory answers for — the\n * one case where the stub's missing tags can be the whole answer — so the\n * common delta, whose new services all have `specs/`, never parses it. A map\n * that is absent or does not parse leaves the delta to answer alone, which is\n * how every element was read before the map was asked.\n */\nexport async function readDeltaSystem(e: Elem, scope: DeltaSystemScope): Promise<\"none\" | \"living\" | \"drawn\" | \"service\"> {\n const { elements, known } = scope;\n if (!isServiceSystem(e, elements, known)) return \"none\";\n const service = elementService(e);\n if (scope.living.has(service)) return \"living\";\n if (known.has(service)) return \"service\";\n const map = await scope.livingMap();\n const counterpart = map === null ? undefined : livingCounterpart(e, map, known);\n if (map === null || counterpart === undefined) return \"service\";\n return isServiceSystem(counterpart, map.elements, known) ? \"drawn\" : \"none\";\n}\n\n/**\n * The living map as `readDeltaSystem` reads it — the caller's\n * `architecture/landscape.likec4` (`landscapePath`; the path arrives as an\n * argument because `core/repo/` already imports this package), parsed at most\n * once per reader and only when first asked; null when there is none or it\n * does not parse. One reader for every grader that asks, so two of them can\n * never see different maps for one element.\n */\nexport function livingMapOf(path: string, load: (path: string) => Promise<LoadedDoc>): () => Promise<LoadedDoc | null> {\n let read: Promise<LoadedDoc | null> | undefined;\n return () =>\n (read ??= (async () => {\n if (!existsSync(path)) return null;\n const doc = await load(path);\n return doc.errors.length === 0 ? doc : null;\n })());\n}\n\n/**\n * The element of the living map a delta element stands for: the same id, else\n * the box the map DRAWS for the same service (`drawnServiceElements` — never a\n * container of some other service that happens to share a title). Undefined\n * when the map draws nothing of the kind, which for an element no directory\n * answers for is what makes it new.\n */\nfunction livingCounterpart(e: Elem, living: LoadedDoc, known: ReadonlySet<string>): Elem | undefined {\n const byId = new Map(living.elements.map((el) => [el.id, el]));\n const same = byId.get(e.id);\n if (same !== undefined) return same;\n const drawn = drawnServiceElements(living.elements, known).get(elementService(e));\n return drawn === undefined ? undefined : byId.get(drawn);\n}\n"]}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE literal fact loam reads out of the root `likec4.config.json`: which
|
|
3
|
+
* paths that file excludes from the renderer's root project, and whether a
|
|
4
|
+
* given directory or document is one of them.
|
|
5
|
+
*
|
|
6
|
+
* Until this module existed loam read NOTHING out of that file. It wrote it
|
|
7
|
+
* once (`core/docs.ts`, `loam init --create`), never re-read it, and the team
|
|
8
|
+
* owned it from then on — the ownership rule `core/repo/tree/render/projects.ts`
|
|
9
|
+
* still states for the per-service files. That rule is kept everywhere it still
|
|
10
|
+
* applies; this is the one exception, and it is earned by what report #05
|
|
11
|
+
* measured: a model that EXTENDS the fleet map lives in the ROOT project, so
|
|
12
|
+
* the root's `exclude` decides whether the renderer can see it at all. A repo
|
|
13
|
+
* whose root config still says `services/**` — every repo scaffolded before
|
|
14
|
+
* this axis — renders such a model as a box with nothing inside it, and no
|
|
15
|
+
* check could say why, because nothing here had ever opened the file.
|
|
16
|
+
*
|
|
17
|
+
* READ here, and written back by one command only (`loam subsystem sync`,
|
|
18
|
+
* through `standaloneExclude` in `../service-model/renderer.ts`). Nothing else
|
|
19
|
+
* about the file is interpreted: `exclude` is a glob list in a tool's own
|
|
20
|
+
* config, and the entries loam does not recognise as naming a directory are
|
|
21
|
+
* left exactly where the team put them.
|
|
22
|
+
*
|
|
23
|
+
* IT LIVES BELOW `../project/` BECAUSE THE PROJECT LOADER IS A READER. The
|
|
24
|
+
* architecture document set is the one list every reader shares, and it has to
|
|
25
|
+
* drop a `.likec4` the root project excludes — a palette under an excluded path
|
|
26
|
+
* otherwise yields a `global style` reference the fleet project cannot resolve,
|
|
27
|
+
* `likec4 validate` Invalid on every run and `loam validate --all` at 0 errors
|
|
28
|
+
* (verification 2026-09-04, W5). `../service-model/` already imports
|
|
29
|
+
* `../project/`, so this could not stay there without reversing that edge.
|
|
30
|
+
*/
|
|
31
|
+
import { readFile } from "node:fs/promises";
|
|
32
|
+
import { isRecord } from "../../kernel/records.js";
|
|
33
|
+
import { rootProjectPath } from "../../repo/paths.js";
|
|
34
|
+
/** The `services/` prefix every tree path is spelled under, in the config and on disk alike. */
|
|
35
|
+
const SERVICES = "services";
|
|
36
|
+
/**
|
|
37
|
+
* The root project's `exclude` list, or null when the file cannot be read as a
|
|
38
|
+
* project config at all.
|
|
39
|
+
*
|
|
40
|
+
* The three answers are deliberately distinct, because two of them mean
|
|
41
|
+
* opposite things to a grader:
|
|
42
|
+
*
|
|
43
|
+
* - `[]` — the file is a JSON object that excludes nothing (or names no
|
|
44
|
+
* `exclude` key at all, which is the same thing to the renderer). Every
|
|
45
|
+
* extending model is visible; a standalone one is in the root project where
|
|
46
|
+
* it cannot parse.
|
|
47
|
+
* - a list — the entries as written, in file order.
|
|
48
|
+
* - `null` — absent, unreadable, not JSON, or JSON whose `exclude` is not a
|
|
49
|
+
* list of strings. loam does not know what the renderer will do, so it says
|
|
50
|
+
* nothing rather than guessing: the findings that read this list are silent
|
|
51
|
+
* on null, `subsystem sync` leaves such a file alone, and the project loader
|
|
52
|
+
* filters nothing. Failing closed here means the team keeps a file loam
|
|
53
|
+
* cannot parse; failing open would mean loam asserting the renderer excludes
|
|
54
|
+
* something on evidence it does not have.
|
|
55
|
+
*/
|
|
56
|
+
export async function readRootExclude(docsDir) {
|
|
57
|
+
const parsed = await readRootProject(docsDir);
|
|
58
|
+
if (parsed === null)
|
|
59
|
+
return null;
|
|
60
|
+
const exclude = parsed["exclude"];
|
|
61
|
+
if (exclude === undefined)
|
|
62
|
+
return [];
|
|
63
|
+
if (!Array.isArray(exclude))
|
|
64
|
+
return null;
|
|
65
|
+
// A predicate rather than a cast, so the narrowing below is the compiler's
|
|
66
|
+
// conclusion from a check that actually ran: an `exclude` holding a number is
|
|
67
|
+
// a file loam does not understand, and understanding it half way is how a
|
|
68
|
+
// grader ends up asserting a glob nobody wrote.
|
|
69
|
+
const entries = exclude;
|
|
70
|
+
return entries.every((entry) => typeof entry === "string") ? [...entries] : null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The root project file as a JSON object, or null when it is absent or is not
|
|
74
|
+
* one — the ONE reader, shared with the one writer that re-parses it before a
|
|
75
|
+
* rewrite (`commands/subsystem/txn/exclude.ts`).
|
|
76
|
+
*
|
|
77
|
+
* A LEADING BYTE-ORDER MARK IS STRIPPED, and that is not tidiness: PowerShell's
|
|
78
|
+
* `Out-File` writes `ef bb bf` by default on this platform, so a Windows shell
|
|
79
|
+
* saving the very file loam wrote left `JSON.parse` throwing while the renderer
|
|
80
|
+
* — whose reader tolerates the mark — went on applying every entry in the list.
|
|
81
|
+
* loam then graded nothing at all: `validate --all` silent about an exclusion in
|
|
82
|
+
* full force, `doctor` healthy, `subsystem sync` reporting the list unreadable
|
|
83
|
+
* and naming a fault (`not a JSON object with a string exclude list`) that was
|
|
84
|
+
* not the one present (re-verification 2026-09-04, area C item 3). One reader
|
|
85
|
+
* means the grade and the rewrite can never disagree about whether the file
|
|
86
|
+
* parses.
|
|
87
|
+
*/
|
|
88
|
+
async function readRootProject(docsDir) {
|
|
89
|
+
let text;
|
|
90
|
+
try {
|
|
91
|
+
text = await readFile(rootProjectPath(docsDir), "utf8");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Absent reads as "loam cannot say", not as "excludes nothing": a docs repo
|
|
95
|
+
// with no root project file has no root project either, and the renderer
|
|
96
|
+
// opened there shows nothing at all — a different problem, with a different
|
|
97
|
+
// finding (`doctor.likec4-config-missing`).
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return parseRootProject(text);
|
|
101
|
+
}
|
|
102
|
+
/** The byte-order mark PowerShell's `Out-File` prepends by default on this platform. */
|
|
103
|
+
const BOM = "";
|
|
104
|
+
/** The same parse, over bytes a caller already read. Exported for the rewrite path only. */
|
|
105
|
+
export function parseRootProject(text) {
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(text.startsWith(BOM) ? text.slice(BOM.length) : text);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Not JSON is the team's file to fix, and nothing here may rewrite it.
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return isRecord(parsed) ? parsed : null;
|
|
115
|
+
}
|
|
116
|
+
/** A PATH as segments — `/` or `\`, either spelling, no empty parts, no `.`. Never an ENTRY: see `rendererEntry`. */
|
|
117
|
+
function segments(path) {
|
|
118
|
+
return path.split(/[\\/]/).filter((s) => s.length > 0 && s !== ".");
|
|
119
|
+
}
|
|
120
|
+
function rendererEntry(entry) {
|
|
121
|
+
if (entry.includes("\\"))
|
|
122
|
+
return null;
|
|
123
|
+
let rest = entry;
|
|
124
|
+
let anchored = false;
|
|
125
|
+
if (rest.startsWith("./")) {
|
|
126
|
+
rest = rest.slice(2);
|
|
127
|
+
anchored = true;
|
|
128
|
+
// `.//x` — the dot survives as a literal directory name, so the pattern
|
|
129
|
+
// names a path nothing on disk has.
|
|
130
|
+
if (rest.startsWith("/"))
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
else if (rest.startsWith("../")) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const trailing = rest.endsWith("/");
|
|
137
|
+
const parts = [];
|
|
138
|
+
for (const part of rest.split("/")) {
|
|
139
|
+
if (part.length === 0 || part === ".")
|
|
140
|
+
continue;
|
|
141
|
+
if (part === "..") {
|
|
142
|
+
if (parts.pop() === undefined)
|
|
143
|
+
return null;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
parts.push(part);
|
|
147
|
+
}
|
|
148
|
+
// An entry that normalises to nothing at all is the project folder itself,
|
|
149
|
+
// which `contains: true` makes a match for every document under it.
|
|
150
|
+
const glob = parts.length === 0 ? "**" : `${parts.join("/")}${trailing ? "/" : ""}`;
|
|
151
|
+
return { glob, anchored: anchored && parts.length > 0 };
|
|
152
|
+
}
|
|
153
|
+
/** The expression one entry matches with, or null when it matches nothing — `rendererEntry` says which. */
|
|
154
|
+
function matcherFor(parsed, glob) {
|
|
155
|
+
return new RegExp(`^${globSource(parsed.anchored ? glob : prefixed(glob))}`);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* An entry's segments with the trailing bare wildcards taken off — the question
|
|
159
|
+
* "which directory is this line ABOUT", asked of the four spellings that name
|
|
160
|
+
* one: `services/pay` doubled-star, that entry with a trailing `/*` after it,
|
|
161
|
+
* `services/pay/*` and `services/pay/` all reduce to `services/pay`. A wildcard
|
|
162
|
+
* that is NOT trailing survives — one segment of its own — because a starred
|
|
163
|
+
* middle segment picks one directory level and no more.
|
|
164
|
+
*
|
|
165
|
+
* It is NOT the covering rule. What an entry HIDES is `entryRegex` below, and
|
|
166
|
+
* the two answer differently on purpose: `services/pay/**` is about the
|
|
167
|
+
* directory `services/pay`, while the bare `services/pay` hides
|
|
168
|
+
* `services/payment-service` as well (measured — see below).
|
|
169
|
+
*
|
|
170
|
+
* It takes the NORMALISED glob, never the raw entry: an entry is split on `/`
|
|
171
|
+
* alone, because a backslash is a literal to the renderer and splitting on it
|
|
172
|
+
* here was what made `services\order-service\**` read as naming a directory it
|
|
173
|
+
* hides nothing in.
|
|
174
|
+
*/
|
|
175
|
+
function patternSegments(glob) {
|
|
176
|
+
const parts = glob.split("/").filter((part) => part.length > 0);
|
|
177
|
+
while (parts.length > 0 && (parts.at(-1) === "*" || parts.at(-1) === "**"))
|
|
178
|
+
parts.pop();
|
|
179
|
+
return parts;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* One `exclude` entry as the expression the RENDERER matches paths with:
|
|
183
|
+
* anchored at the start of a path segment, and NOT anchored at the end.
|
|
184
|
+
*
|
|
185
|
+
* MEASURED, at the 1.59.2 pin, on a scratch fleet of five documents —
|
|
186
|
+
* `architecture/landscape.likec4`, `architecture/usecases/uc.likec4`,
|
|
187
|
+
* `services/payment-service/model.likec4`,
|
|
188
|
+
* `services/payments/payment-service/model.likec4` and
|
|
189
|
+
* `services/order-service/model.likec4` — counting the "N files" `npx likec4
|
|
190
|
+
* validate .` reports with one entry in the list:
|
|
191
|
+
*
|
|
192
|
+
* services/zzz 5 services/pay 3
|
|
193
|
+
* services/payment-service 4 a star as the middle segment 4
|
|
194
|
+
* services/pay/** 5 architect 3
|
|
195
|
+
* architecture/*.likec4 4 *.likec4 0
|
|
196
|
+
* ervices 5 ces/payment-service 5
|
|
197
|
+
* payment-service 3 services/** 2
|
|
198
|
+
* services 2 services/payment-service/* hides a nested file too
|
|
199
|
+
*
|
|
200
|
+
* Four rules come out of that table, and every one of them contradicts what
|
|
201
|
+
* this module asserted before (verification 2026-09-04, review C): the match is
|
|
202
|
+
* a raw PREFIX with no end anchor (`services/pay` takes both payment trees,
|
|
203
|
+
* `architect` takes all of `architecture/`); it must START on a `/` boundary
|
|
204
|
+
* (`ervices` and `ces/payment-service` take nothing); `*` stays inside one
|
|
205
|
+
* segment (`architecture/*.likec4` leaves `architecture/usecases/uc.likec4`);
|
|
206
|
+
* and a glob form does NOT prefix-match (`services/pay/**` needs the literal
|
|
207
|
+
* separator, so it takes nothing from `services/payment-service`).
|
|
208
|
+
*
|
|
209
|
+
* The shape falls out of what LikeC4 does with the list: an entry that does not
|
|
210
|
+
* already begin with a doubled star is prefixed with one, joined onto the
|
|
211
|
+
* project folder and handed to picomatch with `contains: true` — and `contains`
|
|
212
|
+
* is exactly the missing end anchor. So the optional any-directories group
|
|
213
|
+
* `globSource` emits for a leading doubled star IS that prefix, and the absent
|
|
214
|
+
* `$` is that option.
|
|
215
|
+
*
|
|
216
|
+
* NULL when the entry hides nothing at all — `rendererEntry` names the two
|
|
217
|
+
* spellings that do, and every caller has to skip such an entry rather than
|
|
218
|
+
* treat it as covering: a warning derived from one sent a team after a line the
|
|
219
|
+
* renderer ignores, and `subsystem sync` then deleted it.
|
|
220
|
+
*/
|
|
221
|
+
function entryRegex(entry) {
|
|
222
|
+
const parsed = rendererEntry(entry);
|
|
223
|
+
return parsed === null ? null : matcherFor(parsed, parsed.glob);
|
|
224
|
+
}
|
|
225
|
+
/** An entry as LikeC4 spells it before matching: a doubled star in front, unless it has one. */
|
|
226
|
+
function prefixed(entry) {
|
|
227
|
+
return entry.startsWith("**") ? entry : `**/${entry}`;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A glob as a regular-expression SOURCE. `**` crosses `/` and, followed by a
|
|
231
|
+
* separator, may stand for no directory at all (a doubled star between two literals matches with no directory between them, which
|
|
232
|
+
* is what makes a doubled-star-then-star entry cover a model directly under `services/`);
|
|
233
|
+
* `*` and `?` never cross one.
|
|
234
|
+
*/
|
|
235
|
+
function globSource(pattern) {
|
|
236
|
+
let source = "";
|
|
237
|
+
let i = 0;
|
|
238
|
+
while (i < pattern.length) {
|
|
239
|
+
if (pattern.startsWith("**/", i)) {
|
|
240
|
+
source += "(?:.*/)?";
|
|
241
|
+
i += 3;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (pattern.startsWith("**", i)) {
|
|
245
|
+
source += ".*";
|
|
246
|
+
i += 2;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const c = pattern[i];
|
|
250
|
+
if (c === "*")
|
|
251
|
+
source += "[^/]*";
|
|
252
|
+
else if (c === "?")
|
|
253
|
+
source += "[^/]";
|
|
254
|
+
else
|
|
255
|
+
source += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
256
|
+
i += 1;
|
|
257
|
+
}
|
|
258
|
+
return source;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The entry that hides `relPath` from the root project, or null when nothing in
|
|
262
|
+
* the list does. `relPath` is a docs-relative FILE path, spelled either way
|
|
263
|
+
* round the slash.
|
|
264
|
+
*
|
|
265
|
+
* Returned VERBATIM because every message that carries it asks its reader to
|
|
266
|
+
* delete or narrow THAT line, and an entry re-spelled by loam is a line they
|
|
267
|
+
* would go looking for and not find.
|
|
268
|
+
*/
|
|
269
|
+
export function excludingPath(exclude, relPath) {
|
|
270
|
+
const path = segments(relPath).join("/");
|
|
271
|
+
if (path.length === 0)
|
|
272
|
+
return null;
|
|
273
|
+
for (const entry of exclude) {
|
|
274
|
+
if (entryRegex(entry)?.test(path) === true)
|
|
275
|
+
return entry;
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* The entry that hides a SERVICE TREE — the directory and everything under it —
|
|
281
|
+
* or null. The tree's spelling is normalised here because the repository writes
|
|
282
|
+
* it both ways: `serviceTreePath` includes the leading `services/` and the
|
|
283
|
+
* entries `standaloneExclude` writes are built from the part under it, and
|
|
284
|
+
* getting that wrong would silently answer "not excluded" for every service.
|
|
285
|
+
*
|
|
286
|
+
* A DIRECTORY IS NOT A FILE, and that is why this is not `excludingPath` on the
|
|
287
|
+
* directory's own path. `services/payment-service/**` hides every document in
|
|
288
|
+
* that tree while matching no prefix of the directory string itself — the
|
|
289
|
+
* pattern wants the separator the directory path ends before. So a second arm
|
|
290
|
+
* asks the other half: does the directory the entry NAMES (`patternSegments`,
|
|
291
|
+
* the trailing wildcards off) contain this tree? Asking it of the named
|
|
292
|
+
* directory rather than of the raw prefix is what keeps `services/pay/**` about
|
|
293
|
+
* `services/pay` and away from `services/payment-service`, which is exactly
|
|
294
|
+
* where the renderer leaves it.
|
|
295
|
+
*
|
|
296
|
+
* What this deliberately does NOT report is an entry that hides only PART of a
|
|
297
|
+
* tree (`services/x/model`, say). The four findings that read this answer are
|
|
298
|
+
* about a directory the renderer either loads or does not, and half of one is a
|
|
299
|
+
* state `subsystem sync` has no entry to write for.
|
|
300
|
+
*/
|
|
301
|
+
export function excludingEntry(exclude, treePath) {
|
|
302
|
+
const tree = segments(treePath).join("/");
|
|
303
|
+
if (tree.length === 0)
|
|
304
|
+
return null;
|
|
305
|
+
const full = tree === SERVICES || tree.startsWith(`${SERVICES}/`) ? tree : `${SERVICES}/${tree}`;
|
|
306
|
+
for (const entry of exclude) {
|
|
307
|
+
if (coversTree(entry, full))
|
|
308
|
+
return entry;
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
/** Does one entry hide `dir` and everything under it? The two arms `excludingEntry` documents. */
|
|
313
|
+
function coversTree(entry, dir) {
|
|
314
|
+
const parsed = rendererEntry(entry);
|
|
315
|
+
// An entry that hides nothing covers nothing — the backslash spelling, which
|
|
316
|
+
// loam used to read as covering the tree while the renderer loaded every file
|
|
317
|
+
// in it (measured: 8 of 8), warning `service.model-excluded` about a healthy
|
|
318
|
+
// service and then deleting the team's line on the next sync.
|
|
319
|
+
if (parsed === null)
|
|
320
|
+
return false;
|
|
321
|
+
if (matcherFor(parsed, parsed.glob).test(dir))
|
|
322
|
+
return true;
|
|
323
|
+
const named = patternSegments(parsed.glob);
|
|
324
|
+
if (named.length === 0)
|
|
325
|
+
return false;
|
|
326
|
+
// The named directory, or an ancestor of it, matched on a segment boundary —
|
|
327
|
+
// never mid-segment, which is the whole difference between this arm and the
|
|
328
|
+
// prefix one above.
|
|
329
|
+
return new RegExp(`${matcherFor(parsed, named.join("/")).source}(?:/|$)`).test(dir);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The DIRECTORY an entry names, `/`-joined, or null when the entry does not
|
|
333
|
+
* plainly name one — a wildcard segment between two literal ones, or the
|
|
334
|
+
* leading doubled star of the `node_modules` glob.
|
|
335
|
+
*
|
|
336
|
+
* The trailing wildcards are what get stripped: `services/pay` doubled-star and
|
|
337
|
+
* the three other spellings `patternSegments` lists all name `services/pay`. It
|
|
338
|
+
* is the AUTHORSHIP question the writer asks — "did loam write this line, and is
|
|
339
|
+
* it about a directory the enumeration returns?" — never the covering one, which
|
|
340
|
+
* is `excludingEntry`'s.
|
|
341
|
+
*/
|
|
342
|
+
export function excludedDirectory(entry) {
|
|
343
|
+
const parsed = rendererEntry(entry);
|
|
344
|
+
// An entry that hides nothing names nothing either, so a backslash spelling is
|
|
345
|
+
// never loam's to rewrite: `subsystem sync` leaves it exactly where the team
|
|
346
|
+
// put it, which is the only honest answer about a line the renderer ignores.
|
|
347
|
+
if (parsed === null)
|
|
348
|
+
return null;
|
|
349
|
+
const parts = patternSegments(parsed.glob);
|
|
350
|
+
return parts.some((part) => part.includes("*")) ? null : parts.join("/");
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=exclude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exclude.js","sourceRoot":"","sources":["../../../../src/core/c4/root-project/exclude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,gGAAgG;AAChG,MAAM,QAAQ,GAAG,UAAU,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAgB;IACpD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,2EAA2E;IAC3E,8EAA8E;IAC9E,0EAA0E;IAC1E,gDAAgD;IAChD,MAAM,OAAO,GAAc,OAAO,CAAC;IACnC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACpG,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,eAAe,CAAC,OAAgB;IAC7C,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,yEAAyE;QACzE,4EAA4E;QAC5E,4CAA4C;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,wFAAwF;AACxF,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC;AAED,qHAAqH;AACrH,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACtE,CAAC;AAqDD,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,wEAAwE;QACxE,oCAAoC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACxC,CAAC;SAAM,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,GAAG;YAAE,SAAS;QAChD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC;YAC3C,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,2GAA2G;AAC3G,SAAS,UAAU,CAAC,MAAqB,EAAE,IAAY;IACrD,OAAO,IAAI,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IACxF,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,SAAS,UAAU,CAAC,KAAa;IAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,gGAAgG;AAChG,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,OAAe;IACjC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,UAAU,CAAC;YACrB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,IAAI,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG;YAAE,MAAM,IAAI,OAAO,CAAC;aAC5B,IAAI,CAAC,KAAK,GAAG;YAAE,MAAM,IAAI,MAAM,CAAC;;YAChC,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,OAA0B,EAAE,OAAe;IACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;IAC3D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE,QAAgB;IACzE,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;IACjG,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kGAAkG;AAClG,SAAS,UAAU,CAAC,KAAa,EAAE,GAAW;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,8DAA8D;IAC9D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,6EAA6E;IAC7E,4EAA4E;IAC5E,oBAAoB;IACpB,OAAO,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["/**\n * The ONE literal fact loam reads out of the root `likec4.config.json`: which\n * paths that file excludes from the renderer's root project, and whether a\n * given directory or document is one of them.\n *\n * Until this module existed loam read NOTHING out of that file. It wrote it\n * once (`core/docs.ts`, `loam init --create`), never re-read it, and the team\n * owned it from then on — the ownership rule `core/repo/tree/render/projects.ts`\n * still states for the per-service files. That rule is kept everywhere it still\n * applies; this is the one exception, and it is earned by what report #05\n * measured: a model that EXTENDS the fleet map lives in the ROOT project, so\n * the root's `exclude` decides whether the renderer can see it at all. A repo\n * whose root config still says `services/**` — every repo scaffolded before\n * this axis — renders such a model as a box with nothing inside it, and no\n * check could say why, because nothing here had ever opened the file.\n *\n * READ here, and written back by one command only (`loam subsystem sync`,\n * through `standaloneExclude` in `../service-model/renderer.ts`). Nothing else\n * about the file is interpreted: `exclude` is a glob list in a tool's own\n * config, and the entries loam does not recognise as naming a directory are\n * left exactly where the team put them.\n *\n * IT LIVES BELOW `../project/` BECAUSE THE PROJECT LOADER IS A READER. The\n * architecture document set is the one list every reader shares, and it has to\n * drop a `.likec4` the root project excludes — a palette under an excluded path\n * otherwise yields a `global style` reference the fleet project cannot resolve,\n * `likec4 validate` Invalid on every run and `loam validate --all` at 0 errors\n * (verification 2026-09-04, W5). `../service-model/` already imports\n * `../project/`, so this could not stay there without reversing that edge.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { isRecord } from \"../../kernel/records.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\nimport { rootProjectPath } from \"../../repo/paths.js\";\n\n/** The `services/` prefix every tree path is spelled under, in the config and on disk alike. */\nconst SERVICES = \"services\";\n\n/**\n * The root project's `exclude` list, or null when the file cannot be read as a\n * project config at all.\n *\n * The three answers are deliberately distinct, because two of them mean\n * opposite things to a grader:\n *\n * - `[]` — the file is a JSON object that excludes nothing (or names no\n * `exclude` key at all, which is the same thing to the renderer). Every\n * extending model is visible; a standalone one is in the root project where\n * it cannot parse.\n * - a list — the entries as written, in file order.\n * - `null` — absent, unreadable, not JSON, or JSON whose `exclude` is not a\n * list of strings. loam does not know what the renderer will do, so it says\n * nothing rather than guessing: the findings that read this list are silent\n * on null, `subsystem sync` leaves such a file alone, and the project loader\n * filters nothing. Failing closed here means the team keeps a file loam\n * cannot parse; failing open would mean loam asserting the renderer excludes\n * something on evidence it does not have.\n */\nexport async function readRootExclude(docsDir: DocsDir): Promise<string[] | null> {\n const parsed = await readRootProject(docsDir);\n if (parsed === null) return null;\n const exclude = parsed[\"exclude\"];\n if (exclude === undefined) return [];\n if (!Array.isArray(exclude)) return null;\n // A predicate rather than a cast, so the narrowing below is the compiler's\n // conclusion from a check that actually ran: an `exclude` holding a number is\n // a file loam does not understand, and understanding it half way is how a\n // grader ends up asserting a glob nobody wrote.\n const entries: unknown[] = exclude;\n return entries.every((entry): entry is string => typeof entry === \"string\") ? [...entries] : null;\n}\n\n/**\n * The root project file as a JSON object, or null when it is absent or is not\n * one — the ONE reader, shared with the one writer that re-parses it before a\n * rewrite (`commands/subsystem/txn/exclude.ts`).\n *\n * A LEADING BYTE-ORDER MARK IS STRIPPED, and that is not tidiness: PowerShell's\n * `Out-File` writes `ef bb bf` by default on this platform, so a Windows shell\n * saving the very file loam wrote left `JSON.parse` throwing while the renderer\n * — whose reader tolerates the mark — went on applying every entry in the list.\n * loam then graded nothing at all: `validate --all` silent about an exclusion in\n * full force, `doctor` healthy, `subsystem sync` reporting the list unreadable\n * and naming a fault (`not a JSON object with a string exclude list`) that was\n * not the one present (re-verification 2026-09-04, area C item 3). One reader\n * means the grade and the rewrite can never disagree about whether the file\n * parses.\n */\nasync function readRootProject(docsDir: DocsDir): Promise<Record<string, unknown> | null> {\n let text: string;\n try {\n text = await readFile(rootProjectPath(docsDir), \"utf8\");\n } catch {\n // Absent reads as \"loam cannot say\", not as \"excludes nothing\": a docs repo\n // with no root project file has no root project either, and the renderer\n // opened there shows nothing at all — a different problem, with a different\n // finding (`doctor.likec4-config-missing`).\n return null;\n }\n return parseRootProject(text);\n}\n\n/** The byte-order mark PowerShell's `Out-File` prepends by default on this platform. */\nconst BOM = \"\";\n\n/** The same parse, over bytes a caller already read. Exported for the rewrite path only. */\nexport function parseRootProject(text: string): Record<string, unknown> | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text.startsWith(BOM) ? text.slice(BOM.length) : text);\n } catch {\n // Not JSON is the team's file to fix, and nothing here may rewrite it.\n return null;\n }\n return isRecord(parsed) ? parsed : null;\n}\n\n/** A PATH as segments — `/` or `\\`, either spelling, no empty parts, no `.`. Never an ENTRY: see `rendererEntry`. */\nfunction segments(path: string): string[] {\n return path.split(/[\\\\/]/).filter((s) => s.length > 0 && s !== \".\");\n}\n\n/**\n * One `exclude` entry as the RENDERER will match it — the glob with the\n * spellings that mean nothing to it taken out — or null when the entry can hide\n * nothing loam is able to spell.\n *\n * WHY IT EXISTS. Every matcher below used to build its expression from the entry\n * exactly as written while normalising only the PATH, so four spellings of one\n * line disagreed with the renderer in loam's favour: `./architecture/palette.likec4`,\n * `architecture/./palette.likec4` and `architecture//palette.likec4` each hid the\n * palette from `likec4 validate` (8 source files, down from 9) and from nothing\n * in loam — the census loaded it, `subsystem sync` wrote a `global style\n * subsystems` line naming a group the fleet project cannot resolve, and the run\n * reported 0 errors while every render was Invalid. `./architecture/**` did the\n * same to the whole map with `landscape.excluded` silent (re-verification\n * 2026-09-04, area C items 1-2).\n *\n * MEASURED, at the 1.59.2 pin, against the renderer's own matcher — likec4\n * builds `withoutDoubleSlashes(joinRelativeURL(<project folder>, entry))` (a\n * doubled star and a slash joined in front unless the entry already leads with\n * one or is spelled relative) and hands it to picomatch with `contains: true,\n * dot: true`. The rules that fall out, each pinned in\n * `test/root-exclude.test.ts` against a `npx likec4 validate .` file count:\n *\n * - a leading `./` is resolved, and it ANCHORS the entry at the docs root —\n * the any-directories prefix is not added, so `./architecture/**` is about that one\n * directory and `architecture/**` is about one at any depth;\n * - `/./` and `//` inside the entry collapse (`architecture//palette.likec4`\n * hides the palette exactly as the plain spelling does);\n * - a TRAILING `/` does not: `architecture` hides `architecture-old/old.likec4`\n * as a raw prefix and `architecture/` does not (measured 5 files vs 6), so\n * the slash is kept rather than stripped;\n * - `.//` keeps a literal `.` directory in the pattern and matches NOTHING\n * (measured: 10 files of 10);\n * - a BACKSLASH is a literal character to picomatch, never a separator, so\n * `services\\order-service\\**` hides nothing at all (measured: 8 files of 8)\n * — loam used to read it as covering the tree, warn `service.model-excluded`\n * about a service the renderer loads perfectly well, and then DELETE the\n * team's line on the next `subsystem sync`.\n *\n * The two arms that answer null are the entries loam declines to reason about:\n * a backslash-bearing one (it covers nothing, so nothing may be graded on it)\n * and one whose `..` walks above the docs root, where the renderer's pattern\n * stops describing this tree at all.\n */\ninterface RendererEntry {\n /** The glob, `/`-separated, `.` segments resolved and `//` collapsed, any trailing `/` kept. */\n glob: string;\n /** True when a leading `./` anchored the entry at the docs root instead of at any depth. */\n anchored: boolean;\n}\n\nfunction rendererEntry(entry: string): RendererEntry | null {\n if (entry.includes(\"\\\\\")) return null;\n let rest = entry;\n let anchored = false;\n if (rest.startsWith(\"./\")) {\n rest = rest.slice(2);\n anchored = true;\n // `.//x` — the dot survives as a literal directory name, so the pattern\n // names a path nothing on disk has.\n if (rest.startsWith(\"/\")) return null;\n } else if (rest.startsWith(\"../\")) {\n return null;\n }\n const trailing = rest.endsWith(\"/\");\n const parts: string[] = [];\n for (const part of rest.split(\"/\")) {\n if (part.length === 0 || part === \".\") continue;\n if (part === \"..\") {\n if (parts.pop() === undefined) return null;\n continue;\n }\n parts.push(part);\n }\n // An entry that normalises to nothing at all is the project folder itself,\n // which `contains: true` makes a match for every document under it.\n const glob = parts.length === 0 ? \"**\" : `${parts.join(\"/\")}${trailing ? \"/\" : \"\"}`;\n return { glob, anchored: anchored && parts.length > 0 };\n}\n\n/** The expression one entry matches with, or null when it matches nothing — `rendererEntry` says which. */\nfunction matcherFor(parsed: RendererEntry, glob: string): RegExp {\n return new RegExp(`^${globSource(parsed.anchored ? glob : prefixed(glob))}`);\n}\n\n/**\n * An entry's segments with the trailing bare wildcards taken off — the question\n * \"which directory is this line ABOUT\", asked of the four spellings that name\n * one: `services/pay` doubled-star, that entry with a trailing `/*` after it,\n * `services/pay/*` and `services/pay/` all reduce to `services/pay`. A wildcard\n * that is NOT trailing survives — one segment of its own — because a starred\n * middle segment picks one directory level and no more.\n *\n * It is NOT the covering rule. What an entry HIDES is `entryRegex` below, and\n * the two answer differently on purpose: `services/pay/**` is about the\n * directory `services/pay`, while the bare `services/pay` hides\n * `services/payment-service` as well (measured — see below).\n *\n * It takes the NORMALISED glob, never the raw entry: an entry is split on `/`\n * alone, because a backslash is a literal to the renderer and splitting on it\n * here was what made `services\\order-service\\**` read as naming a directory it\n * hides nothing in.\n */\nfunction patternSegments(glob: string): string[] {\n const parts = glob.split(\"/\").filter((part) => part.length > 0);\n while (parts.length > 0 && (parts.at(-1) === \"*\" || parts.at(-1) === \"**\")) parts.pop();\n return parts;\n}\n\n/**\n * One `exclude` entry as the expression the RENDERER matches paths with:\n * anchored at the start of a path segment, and NOT anchored at the end.\n *\n * MEASURED, at the 1.59.2 pin, on a scratch fleet of five documents —\n * `architecture/landscape.likec4`, `architecture/usecases/uc.likec4`,\n * `services/payment-service/model.likec4`,\n * `services/payments/payment-service/model.likec4` and\n * `services/order-service/model.likec4` — counting the \"N files\" `npx likec4\n * validate .` reports with one entry in the list:\n *\n * services/zzz 5 services/pay 3\n * services/payment-service 4 a star as the middle segment 4\n * services/pay/** 5 architect 3\n * architecture/*.likec4 4 *.likec4 0\n * ervices 5 ces/payment-service 5\n * payment-service 3 services/** 2\n * services 2 services/payment-service/* hides a nested file too\n *\n * Four rules come out of that table, and every one of them contradicts what\n * this module asserted before (verification 2026-09-04, review C): the match is\n * a raw PREFIX with no end anchor (`services/pay` takes both payment trees,\n * `architect` takes all of `architecture/`); it must START on a `/` boundary\n * (`ervices` and `ces/payment-service` take nothing); `*` stays inside one\n * segment (`architecture/*.likec4` leaves `architecture/usecases/uc.likec4`);\n * and a glob form does NOT prefix-match (`services/pay/**` needs the literal\n * separator, so it takes nothing from `services/payment-service`).\n *\n * The shape falls out of what LikeC4 does with the list: an entry that does not\n * already begin with a doubled star is prefixed with one, joined onto the\n * project folder and handed to picomatch with `contains: true` — and `contains`\n * is exactly the missing end anchor. So the optional any-directories group\n * `globSource` emits for a leading doubled star IS that prefix, and the absent\n * `$` is that option.\n *\n * NULL when the entry hides nothing at all — `rendererEntry` names the two\n * spellings that do, and every caller has to skip such an entry rather than\n * treat it as covering: a warning derived from one sent a team after a line the\n * renderer ignores, and `subsystem sync` then deleted it.\n */\nfunction entryRegex(entry: string): RegExp | null {\n const parsed = rendererEntry(entry);\n return parsed === null ? null : matcherFor(parsed, parsed.glob);\n}\n\n/** An entry as LikeC4 spells it before matching: a doubled star in front, unless it has one. */\nfunction prefixed(entry: string): string {\n return entry.startsWith(\"**\") ? entry : `**/${entry}`;\n}\n\n/**\n * A glob as a regular-expression SOURCE. `**` crosses `/` and, followed by a\n * separator, may stand for no directory at all (a doubled star between two literals matches with no directory between them, which\n * is what makes a doubled-star-then-star entry cover a model directly under `services/`);\n * `*` and `?` never cross one.\n */\nfunction globSource(pattern: string): string {\n let source = \"\";\n let i = 0;\n while (i < pattern.length) {\n if (pattern.startsWith(\"**/\", i)) {\n source += \"(?:.*/)?\";\n i += 3;\n continue;\n }\n if (pattern.startsWith(\"**\", i)) {\n source += \".*\";\n i += 2;\n continue;\n }\n const c = pattern[i]!;\n if (c === \"*\") source += \"[^/]*\";\n else if (c === \"?\") source += \"[^/]\";\n else source += c.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n i += 1;\n }\n return source;\n}\n\n/**\n * The entry that hides `relPath` from the root project, or null when nothing in\n * the list does. `relPath` is a docs-relative FILE path, spelled either way\n * round the slash.\n *\n * Returned VERBATIM because every message that carries it asks its reader to\n * delete or narrow THAT line, and an entry re-spelled by loam is a line they\n * would go looking for and not find.\n */\nexport function excludingPath(exclude: readonly string[], relPath: string): string | null {\n const path = segments(relPath).join(\"/\");\n if (path.length === 0) return null;\n for (const entry of exclude) {\n if (entryRegex(entry)?.test(path) === true) return entry;\n }\n return null;\n}\n\n/**\n * The entry that hides a SERVICE TREE — the directory and everything under it —\n * or null. The tree's spelling is normalised here because the repository writes\n * it both ways: `serviceTreePath` includes the leading `services/` and the\n * entries `standaloneExclude` writes are built from the part under it, and\n * getting that wrong would silently answer \"not excluded\" for every service.\n *\n * A DIRECTORY IS NOT A FILE, and that is why this is not `excludingPath` on the\n * directory's own path. `services/payment-service/**` hides every document in\n * that tree while matching no prefix of the directory string itself — the\n * pattern wants the separator the directory path ends before. So a second arm\n * asks the other half: does the directory the entry NAMES (`patternSegments`,\n * the trailing wildcards off) contain this tree? Asking it of the named\n * directory rather than of the raw prefix is what keeps `services/pay/**` about\n * `services/pay` and away from `services/payment-service`, which is exactly\n * where the renderer leaves it.\n *\n * What this deliberately does NOT report is an entry that hides only PART of a\n * tree (`services/x/model`, say). The four findings that read this answer are\n * about a directory the renderer either loads or does not, and half of one is a\n * state `subsystem sync` has no entry to write for.\n */\nexport function excludingEntry(exclude: readonly string[], treePath: string): string | null {\n const tree = segments(treePath).join(\"/\");\n if (tree.length === 0) return null;\n const full = tree === SERVICES || tree.startsWith(`${SERVICES}/`) ? tree : `${SERVICES}/${tree}`;\n for (const entry of exclude) {\n if (coversTree(entry, full)) return entry;\n }\n return null;\n}\n\n/** Does one entry hide `dir` and everything under it? The two arms `excludingEntry` documents. */\nfunction coversTree(entry: string, dir: string): boolean {\n const parsed = rendererEntry(entry);\n // An entry that hides nothing covers nothing — the backslash spelling, which\n // loam used to read as covering the tree while the renderer loaded every file\n // in it (measured: 8 of 8), warning `service.model-excluded` about a healthy\n // service and then deleting the team's line on the next sync.\n if (parsed === null) return false;\n if (matcherFor(parsed, parsed.glob).test(dir)) return true;\n const named = patternSegments(parsed.glob);\n if (named.length === 0) return false;\n // The named directory, or an ancestor of it, matched on a segment boundary —\n // never mid-segment, which is the whole difference between this arm and the\n // prefix one above.\n return new RegExp(`${matcherFor(parsed, named.join(\"/\")).source}(?:/|$)`).test(dir);\n}\n\n/**\n * The DIRECTORY an entry names, `/`-joined, or null when the entry does not\n * plainly name one — a wildcard segment between two literal ones, or the\n * leading doubled star of the `node_modules` glob.\n *\n * The trailing wildcards are what get stripped: `services/pay` doubled-star and\n * the three other spellings `patternSegments` lists all name `services/pay`. It\n * is the AUTHORSHIP question the writer asks — \"did loam write this line, and is\n * it about a directory the enumeration returns?\" — never the covering one, which\n * is `excludingEntry`'s.\n */\nexport function excludedDirectory(entry: string): string | null {\n const parsed = rendererEntry(entry);\n // An entry that hides nothing names nothing either, so a backslash spelling is\n // never loam's to rewrite: `subsystem sync` leaves it exactly where the team\n // put it, which is the only honest answer about a line the renderer ignores.\n if (parsed === null) return null;\n const parts = patternSegments(parsed.glob);\n return parts.some((part) => part.includes(\"*\")) ? null : parts.join(\"/\");\n}\n"]}
|