@cleocode/core 2026.9.20 → 2026.9.21
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/dist/adapters/discovery.d.ts.map +1 -1
- package/dist/adapters/discovery.js +3 -10
- package/dist/adapters/discovery.js.map +1 -1
- package/dist/adrs/link-pipeline.js +2 -2
- package/dist/adrs/link-pipeline.js.map +1 -1
- package/dist/adrs/parse.js +3 -3
- package/dist/adrs/parse.js.map +1 -1
- package/dist/agents/invoke-meta-agent.d.ts.map +1 -1
- package/dist/agents/invoke-meta-agent.js +8 -4
- package/dist/agents/invoke-meta-agent.js.map +1 -1
- package/dist/bootstrap.d.ts +5 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +41 -21
- package/dist/bootstrap.js.map +1 -1
- package/dist/cloud/crypto.d.ts +47 -0
- package/dist/cloud/crypto.d.ts.map +1 -0
- package/dist/cloud/crypto.js +223 -0
- package/dist/cloud/crypto.js.map +1 -0
- package/dist/cloud/http.d.ts +52 -0
- package/dist/cloud/http.d.ts.map +1 -0
- package/dist/cloud/http.js +98 -0
- package/dist/cloud/http.js.map +1 -0
- package/dist/cloud/index.d.ts +19 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +19 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/journal.d.ts +169 -0
- package/dist/cloud/journal.d.ts.map +1 -0
- package/dist/cloud/journal.js +428 -0
- package/dist/cloud/journal.js.map +1 -0
- package/dist/cloud/keys.d.ts +213 -0
- package/dist/cloud/keys.d.ts.map +1 -0
- package/dist/cloud/keys.js +362 -0
- package/dist/cloud/keys.js.map +1 -0
- package/dist/cloud/manifest-check.d.ts +36 -0
- package/dist/cloud/manifest-check.d.ts.map +1 -0
- package/dist/cloud/manifest-check.js +70 -0
- package/dist/cloud/manifest-check.js.map +1 -0
- package/dist/cloud/projects.d.ts +13 -0
- package/dist/cloud/projects.d.ts.map +1 -0
- package/dist/cloud/projects.js +11 -0
- package/dist/cloud/projects.js.map +1 -0
- package/dist/cloud/signing.d.ts +105 -0
- package/dist/cloud/signing.d.ts.map +1 -0
- package/dist/cloud/signing.js +117 -0
- package/dist/cloud/signing.js.map +1 -0
- package/dist/cloud/streams.d.ts +6 -0
- package/dist/cloud/streams.d.ts.map +1 -0
- package/dist/cloud/streams.js +5 -0
- package/dist/cloud/streams.js.map +1 -0
- package/dist/decide/audit.d.ts +131 -0
- package/dist/decide/audit.d.ts.map +1 -0
- package/dist/decide/audit.js +98 -0
- package/dist/decide/audit.js.map +1 -0
- package/dist/decide/budget.d.ts +91 -0
- package/dist/decide/budget.d.ts.map +1 -0
- package/dist/decide/budget.js +194 -0
- package/dist/decide/budget.js.map +1 -0
- package/dist/decide/cache.d.ts +49 -0
- package/dist/decide/cache.d.ts.map +1 -0
- package/dist/decide/cache.js +87 -0
- package/dist/decide/cache.js.map +1 -0
- package/dist/decide/client.d.ts +103 -0
- package/dist/decide/client.d.ts.map +1 -0
- package/dist/decide/client.js +262 -0
- package/dist/decide/client.js.map +1 -0
- package/dist/decide/credentials.d.ts +159 -0
- package/dist/decide/credentials.d.ts.map +1 -0
- package/dist/decide/credentials.js +383 -0
- package/dist/decide/credentials.js.map +1 -0
- package/dist/decide/index.d.ts +18 -0
- package/dist/decide/index.d.ts.map +1 -0
- package/dist/decide/index.js +18 -0
- package/dist/decide/index.js.map +1 -0
- package/dist/decide/jev-wire.d.ts +155 -0
- package/dist/decide/jev-wire.d.ts.map +1 -0
- package/dist/decide/jev-wire.js +420 -0
- package/dist/decide/jev-wire.js.map +1 -0
- package/dist/decide/operations.d.ts +152 -0
- package/dist/decide/operations.d.ts.map +1 -0
- package/dist/decide/operations.js +199 -0
- package/dist/decide/operations.js.map +1 -0
- package/dist/decide/provider.d.ts +90 -0
- package/dist/decide/provider.d.ts.map +1 -0
- package/dist/decide/provider.js +43 -0
- package/dist/decide/provider.js.map +1 -0
- package/dist/decide/site.d.ts +148 -0
- package/dist/decide/site.d.ts.map +1 -0
- package/dist/decide/site.js +181 -0
- package/dist/decide/site.js.map +1 -0
- package/dist/decide/transport.d.ts +67 -0
- package/dist/decide/transport.d.ts.map +1 -0
- package/dist/decide/transport.js +350 -0
- package/dist/decide/transport.js.map +1 -0
- package/dist/docs/export-document.js +5908 -2436
- package/dist/docs/export-document.js.map +3 -3
- package/dist/docs/index.d.ts +2 -2
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +1 -1
- package/dist/docs/index.js.map +1 -1
- package/dist/docs/projection.d.ts.map +1 -1
- package/dist/docs/projection.js +2 -3
- package/dist/docs/projection.js.map +1 -1
- package/dist/docs/publish-pr.d.ts +69 -1
- package/dist/docs/publish-pr.d.ts.map +1 -1
- package/dist/docs/publish-pr.js +112 -10
- package/dist/docs/publish-pr.js.map +1 -1
- package/dist/doctor/db-substrate.d.ts +13 -8
- package/dist/doctor/db-substrate.d.ts.map +1 -1
- package/dist/doctor/db-substrate.js +39 -26
- package/dist/doctor/db-substrate.js.map +1 -1
- package/dist/doctor/index.d.ts +2 -0
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/knowledge.d.ts.map +1 -1
- package/dist/doctor/knowledge.js +5 -15
- package/dist/doctor/knowledge.js.map +1 -1
- package/dist/doctor/nexus-schema-residency.d.ts +1 -1
- package/dist/doctor/nexus-schema-residency.d.ts.map +1 -1
- package/dist/doctor/nexus-schema-residency.js +3 -0
- package/dist/doctor/nexus-schema-residency.js.map +1 -1
- package/dist/doctor/project-identity.d.ts +44 -1
- package/dist/doctor/project-identity.d.ts.map +1 -1
- package/dist/doctor/project-identity.js +237 -10
- package/dist/doctor/project-identity.js.map +1 -1
- package/dist/doctor/projects.d.ts +170 -0
- package/dist/doctor/projects.d.ts.map +1 -0
- package/dist/doctor/projects.js +1075 -0
- package/dist/doctor/projects.js.map +1 -0
- package/dist/doctor/twin-collapse.d.ts +97 -0
- package/dist/doctor/twin-collapse.d.ts.map +1 -0
- package/dist/doctor/twin-collapse.js +168 -0
- package/dist/doctor/twin-collapse.js.map +1 -0
- package/dist/doctor/worktree-orphans.d.ts.map +1 -1
- package/dist/doctor/worktree-orphans.js +13 -29
- package/dist/doctor/worktree-orphans.js.map +1 -1
- package/dist/doctor/worktree-stores.d.ts +128 -0
- package/dist/doctor/worktree-stores.d.ts.map +1 -0
- package/dist/doctor/worktree-stores.js +374 -0
- package/dist/doctor/worktree-stores.js.map +1 -0
- package/dist/error-catalog.d.ts.map +1 -1
- package/dist/error-catalog.js +21 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +40 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/gc/cleanup.d.ts.map +1 -1
- package/dist/gc/cleanup.js +32 -19
- package/dist/gc/cleanup.js.map +1 -1
- package/dist/git/bounded-git.d.ts +170 -0
- package/dist/git/bounded-git.d.ts.map +1 -0
- package/dist/git/bounded-git.js +371 -0
- package/dist/git/bounded-git.js.map +1 -0
- package/dist/git/work-tree.d.ts +20 -0
- package/dist/git/work-tree.d.ts.map +1 -1
- package/dist/git/work-tree.js +20 -2
- package/dist/git/work-tree.js.map +1 -1
- package/dist/hooks/handlers/session-hooks.d.ts +11 -26
- package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/session-hooks.js +18 -47
- package/dist/hooks/handlers/session-hooks.js.map +1 -1
- package/dist/hooks/payload-schemas.d.ts +2 -2
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/init/engine-ops.d.ts.map +1 -1
- package/dist/init/engine-ops.js +23 -1
- package/dist/init/engine-ops.js.map +1 -1
- package/dist/init.d.ts +158 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +527 -42
- package/dist/init.js.map +1 -1
- package/dist/injection.d.ts +55 -0
- package/dist/injection.d.ts.map +1 -1
- package/dist/injection.js +102 -6
- package/dist/injection.js.map +1 -1
- package/dist/internal.d.ts +9 -5
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +8 -4
- package/dist/internal.js.map +1 -1
- package/dist/issue/diagnostics.d.ts.map +1 -1
- package/dist/issue/diagnostics.js +2 -1
- package/dist/issue/diagnostics.js.map +1 -1
- package/dist/lib/concurrency.d.ts +25 -0
- package/dist/lib/concurrency.d.ts.map +1 -0
- package/dist/lib/concurrency.js +43 -0
- package/dist/lib/concurrency.js.map +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lifecycle/engine-ops.d.ts.map +1 -1
- package/dist/lifecycle/engine-ops.js +4 -2
- package/dist/lifecycle/engine-ops.js.map +1 -1
- package/dist/lifecycle/stage-guidance.d.ts +5 -0
- package/dist/lifecycle/stage-guidance.d.ts.map +1 -1
- package/dist/lifecycle/stage-guidance.js +14 -4
- package/dist/lifecycle/stage-guidance.js.map +1 -1
- package/dist/llm/catalog-cache.d.ts +3 -2
- package/dist/llm/catalog-cache.d.ts.map +1 -1
- package/dist/llm/catalog-cache.js +5 -5
- package/dist/llm/catalog-cache.js.map +1 -1
- package/dist/llm/credentials.d.ts +4 -4
- package/dist/llm/credentials.js +6 -6
- package/dist/llm/credentials.js.map +1 -1
- package/dist/llm/plugin-facade.js +4312 -1798
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/llm/stable-device-id.d.ts.map +1 -1
- package/dist/llm/stable-device-id.js +3 -5
- package/dist/llm/stable-device-id.js.map +1 -1
- package/dist/memory/attention.d.ts.map +1 -1
- package/dist/memory/attention.js +30 -30
- package/dist/memory/attention.js.map +1 -1
- package/dist/memory/decision-contradiction.d.ts +152 -0
- package/dist/memory/decision-contradiction.d.ts.map +1 -0
- package/dist/memory/decision-contradiction.js +273 -0
- package/dist/memory/decision-contradiction.js.map +1 -0
- package/dist/memory/decisions.d.ts +42 -11
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/decisions.js +153 -56
- package/dist/memory/decisions.js.map +1 -1
- package/dist/memory/dialectic-evaluator.d.ts +7 -0
- package/dist/memory/dialectic-evaluator.d.ts.map +1 -1
- package/dist/memory/dialectic-evaluator.js +23 -8
- package/dist/memory/dialectic-evaluator.js.map +1 -1
- package/dist/memory/dispatch-trace-format.d.ts +39 -0
- package/dist/memory/dispatch-trace-format.d.ts.map +1 -0
- package/dist/memory/dispatch-trace-format.js +54 -0
- package/dist/memory/dispatch-trace-format.js.map +1 -0
- package/dist/memory/dispatch-trace.d.ts.map +1 -1
- package/dist/memory/dispatch-trace.js +1 -27
- package/dist/memory/dispatch-trace.js.map +1 -1
- package/dist/memory/engine-compat.d.ts +2 -0
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/engine-compat.js +1 -0
- package/dist/memory/engine-compat.js.map +1 -1
- package/dist/memory/import-from-provider.js +3 -3
- package/dist/memory/import-from-provider.js.map +1 -1
- package/dist/memory/learnings.d.ts +2 -2
- package/dist/memory/observation-type-decision.d.ts +96 -0
- package/dist/memory/observation-type-decision.d.ts.map +1 -0
- package/dist/memory/observation-type-decision.js +218 -0
- package/dist/memory/observation-type-decision.js.map +1 -0
- package/dist/memory/redaction.js +2 -0
- package/dist/memory/redaction.js.map +1 -1
- package/dist/memory/retrieval/build-retrieval-bundle.d.ts +9 -2
- package/dist/memory/retrieval/build-retrieval-bundle.d.ts.map +1 -1
- package/dist/memory/retrieval/build-retrieval-bundle.js +42 -11
- package/dist/memory/retrieval/build-retrieval-bundle.js.map +1 -1
- package/dist/memory/retrieval/get-current-session-id.d.ts +5 -0
- package/dist/memory/retrieval/get-current-session-id.d.ts.map +1 -1
- package/dist/memory/retrieval/get-current-session-id.js +7 -2
- package/dist/memory/retrieval/get-current-session-id.js.map +1 -1
- package/dist/memory/retrieval/observe.d.ts.map +1 -1
- package/dist/memory/retrieval/observe.js +30 -29
- package/dist/memory/retrieval/observe.js.map +1 -1
- package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
- package/dist/nexus/analyze-orchestrator.js +42 -29
- package/dist/nexus/analyze-orchestrator.js.map +1 -1
- package/dist/nexus/assessment-projection.d.ts +76 -0
- package/dist/nexus/assessment-projection.d.ts.map +1 -0
- package/dist/nexus/assessment-projection.js +143 -0
- package/dist/nexus/assessment-projection.js.map +1 -0
- package/dist/nexus/assessment-store.d.ts +14 -2
- package/dist/nexus/assessment-store.d.ts.map +1 -1
- package/dist/nexus/assessment-store.js +21 -3
- package/dist/nexus/assessment-store.js.map +1 -1
- package/dist/nexus/checkout-nonce.d.ts +48 -0
- package/dist/nexus/checkout-nonce.d.ts.map +1 -0
- package/dist/nexus/checkout-nonce.js +84 -0
- package/dist/nexus/checkout-nonce.js.map +1 -0
- package/dist/nexus/devices.d.ts +93 -0
- package/dist/nexus/devices.d.ts.map +1 -0
- package/dist/nexus/devices.js +141 -0
- package/dist/nexus/devices.js.map +1 -0
- package/dist/nexus/freshness.d.ts.map +1 -1
- package/dist/nexus/freshness.js +25 -6
- package/dist/nexus/freshness.js.map +1 -1
- package/dist/nexus/git-state.d.ts +225 -0
- package/dist/nexus/git-state.d.ts.map +1 -0
- package/dist/nexus/git-state.js +677 -0
- package/dist/nexus/git-state.js.map +1 -0
- package/dist/nexus/graph-manifest.d.ts +20 -4
- package/dist/nexus/graph-manifest.d.ts.map +1 -1
- package/dist/nexus/graph-manifest.js +40 -5
- package/dist/nexus/graph-manifest.js.map +1 -1
- package/dist/nexus/identity.d.ts +68 -23
- package/dist/nexus/identity.d.ts.map +1 -1
- package/dist/nexus/identity.js +99 -22
- package/dist/nexus/identity.js.map +1 -1
- package/dist/nexus/index.d.ts +5 -2
- package/dist/nexus/index.d.ts.map +1 -1
- package/dist/nexus/index.js +10 -4
- package/dist/nexus/index.js.map +1 -1
- package/dist/nexus/knowledge.d.ts +5 -0
- package/dist/nexus/knowledge.d.ts.map +1 -1
- package/dist/nexus/knowledge.js +26 -2
- package/dist/nexus/knowledge.js.map +1 -1
- package/dist/nexus/legacy-alias.d.ts +60 -0
- package/dist/nexus/legacy-alias.d.ts.map +1 -0
- package/dist/nexus/legacy-alias.js +68 -0
- package/dist/nexus/legacy-alias.js.map +1 -0
- package/dist/nexus/migrate-json-to-sqlite.js +2 -2
- package/dist/nexus/migrate-json-to-sqlite.js.map +1 -1
- package/dist/nexus/ops.d.ts +1 -0
- package/dist/nexus/ops.d.ts.map +1 -1
- package/dist/nexus/path-map.d.ts +264 -20
- package/dist/nexus/path-map.d.ts.map +1 -1
- package/dist/nexus/path-map.js +580 -44
- package/dist/nexus/path-map.js.map +1 -1
- package/dist/nexus/projects-clean.d.ts +9 -1
- package/dist/nexus/projects-clean.d.ts.map +1 -1
- package/dist/nexus/projects-clean.js +126 -14
- package/dist/nexus/projects-clean.js.map +1 -1
- package/dist/nexus/projects-scan.d.ts +56 -1
- package/dist/nexus/projects-scan.d.ts.map +1 -1
- package/dist/nexus/projects-scan.js +144 -3
- package/dist/nexus/projects-scan.js.map +1 -1
- package/dist/nexus/registry-hygiene.d.ts +18 -2
- package/dist/nexus/registry-hygiene.d.ts.map +1 -1
- package/dist/nexus/registry-hygiene.js +37 -11
- package/dist/nexus/registry-hygiene.js.map +1 -1
- package/dist/nexus/registry-roots.d.ts +47 -0
- package/dist/nexus/registry-roots.d.ts.map +1 -0
- package/dist/nexus/registry-roots.js +79 -0
- package/dist/nexus/registry-roots.js.map +1 -0
- package/dist/nexus/registry.d.ts +50 -9
- package/dist/nexus/registry.d.ts.map +1 -1
- package/dist/nexus/registry.js +311 -156
- package/dist/nexus/registry.js.map +1 -1
- package/dist/nexus/stored-roots.d.ts +106 -0
- package/dist/nexus/stored-roots.d.ts.map +1 -0
- package/dist/nexus/stored-roots.js +180 -0
- package/dist/nexus/stored-roots.js.map +1 -0
- package/dist/nexus/transfer.d.ts.map +1 -1
- package/dist/nexus/transfer.js +3 -0
- package/dist/nexus/transfer.js.map +1 -1
- package/dist/nexus/user-profile-hygiene.d.ts +168 -0
- package/dist/nexus/user-profile-hygiene.d.ts.map +1 -0
- package/dist/nexus/user-profile-hygiene.js +305 -0
- package/dist/nexus/user-profile-hygiene.js.map +1 -0
- package/dist/nexus/user-profile.d.ts +53 -2
- package/dist/nexus/user-profile.d.ts.map +1 -1
- package/dist/nexus/user-profile.js +106 -4
- package/dist/nexus/user-profile.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +5 -1
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/orchestrate/spawn-ops.d.ts +12 -0
- package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
- package/dist/orchestrate/spawn-ops.js +152 -57
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestration/classify-readiness.d.ts +37 -1
- package/dist/orchestration/classify-readiness.d.ts.map +1 -1
- package/dist/orchestration/classify-readiness.js +48 -19
- package/dist/orchestration/classify-readiness.js.map +1 -1
- package/dist/orchestration/index.d.ts +3 -2
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +2 -1
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/owner-decision-readiness.d.ts +88 -0
- package/dist/orchestration/owner-decision-readiness.d.ts.map +1 -0
- package/dist/orchestration/owner-decision-readiness.js +152 -0
- package/dist/orchestration/owner-decision-readiness.js.map +1 -0
- package/dist/orchestration/psyche-memory-budget.d.ts +105 -0
- package/dist/orchestration/psyche-memory-budget.d.ts.map +1 -0
- package/dist/orchestration/psyche-memory-budget.js +383 -0
- package/dist/orchestration/psyche-memory-budget.js.map +1 -0
- package/dist/orchestration/spawn-prompt.d.ts +12 -1
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +141 -179
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/spawn.d.ts +7 -0
- package/dist/orchestration/spawn.d.ts.map +1 -1
- package/dist/orchestration/spawn.js +1 -0
- package/dist/orchestration/spawn.js.map +1 -1
- package/dist/paths.d.ts +24 -8
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +135 -71
- package/dist/paths.js.map +1 -1
- package/dist/platform.d.ts +6 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +8 -19
- package/dist/platform.js.map +1 -1
- package/dist/project-info.d.ts +18 -0
- package/dist/project-info.d.ts.map +1 -1
- package/dist/project-info.js +29 -1
- package/dist/project-info.js.map +1 -1
- package/dist/project-lifecycle.d.ts +91 -32
- package/dist/project-lifecycle.d.ts.map +1 -1
- package/dist/project-lifecycle.js +639 -75
- package/dist/project-lifecycle.js.map +1 -1
- package/dist/project-scope.d.ts +86 -4
- package/dist/project-scope.d.ts.map +1 -1
- package/dist/project-scope.js +226 -13
- package/dist/project-scope.js.map +1 -1
- package/dist/project-tombstone.d.ts +111 -0
- package/dist/project-tombstone.d.ts.map +1 -0
- package/dist/project-tombstone.js +220 -0
- package/dist/project-tombstone.js.map +1 -0
- package/dist/release/artifacts.d.ts.map +1 -1
- package/dist/release/artifacts.js +14 -9
- package/dist/release/artifacts.js.map +1 -1
- package/dist/release/ci-evidence.d.ts +223 -0
- package/dist/release/ci-evidence.d.ts.map +1 -0
- package/dist/release/ci-evidence.js +652 -0
- package/dist/release/ci-evidence.js.map +1 -0
- package/dist/release/engine-ops.d.ts.map +1 -1
- package/dist/release/engine-ops.js +3 -3
- package/dist/release/engine-ops.js.map +1 -1
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +7 -6
- package/dist/release/plan.js.map +1 -1
- package/dist/release/pr-evidence.d.ts +38 -0
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +67 -11
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/release/reconcile.d.ts.map +1 -1
- package/dist/release/reconcile.js +3 -2
- package/dist/release/reconcile.js.map +1 -1
- package/dist/release/release-manifest.d.ts +2 -1
- package/dist/release/release-manifest.d.ts.map +1 -1
- package/dist/release/release-manifest.js +6 -5
- package/dist/release/release-manifest.js.map +1 -1
- package/dist/render/nexus/graph/index.d.ts +4 -0
- package/dist/render/nexus/graph/index.d.ts.map +1 -1
- package/dist/render/nexus/graph/index.js +57 -0
- package/dist/render/nexus/graph/index.js.map +1 -1
- package/dist/resources/spawn-wrapper.d.ts +8 -1
- package/dist/resources/spawn-wrapper.d.ts.map +1 -1
- package/dist/resources/spawn-wrapper.js +42 -5
- package/dist/resources/spawn-wrapper.js.map +1 -1
- package/dist/routing/build-command-groups.d.ts.map +1 -1
- package/dist/routing/build-command-groups.js +1 -0
- package/dist/routing/build-command-groups.js.map +1 -1
- package/dist/sagas/index.d.ts +1 -1
- package/dist/sagas/index.d.ts.map +1 -1
- package/dist/sagas/index.js +1 -1
- package/dist/sagas/index.js.map +1 -1
- package/dist/sagas/reconcile.d.ts +24 -4
- package/dist/sagas/reconcile.d.ts.map +1 -1
- package/dist/sagas/reconcile.js +226 -100
- package/dist/sagas/reconcile.js.map +1 -1
- package/dist/scaffold/ensure-config.d.ts.map +1 -1
- package/dist/scaffold/ensure-config.js +31 -1
- package/dist/scaffold/ensure-config.js.map +1 -1
- package/dist/scaffold/project-identity.d.ts +2 -8
- package/dist/scaffold/project-identity.d.ts.map +1 -1
- package/dist/scaffold/project-identity.js +5 -21
- package/dist/scaffold/project-identity.js.map +1 -1
- package/dist/security/input-sanitization.d.ts +9 -1
- package/dist/security/input-sanitization.d.ts.map +1 -1
- package/dist/security/input-sanitization.js +12 -2
- package/dist/security/input-sanitization.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +4321 -1807
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/sentient/propose-tick.d.ts.map +1 -1
- package/dist/sentient/propose-tick.js +4 -2
- package/dist/sentient/propose-tick.js.map +1 -1
- package/dist/sequence/index.d.ts.map +1 -1
- package/dist/sequence/index.js +6 -23
- package/dist/sequence/index.js.map +1 -1
- package/dist/session/engine-ops.d.ts +9 -0
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +110 -18
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/assumptions.d.ts.map +1 -1
- package/dist/sessions/assumptions.js +7 -4
- package/dist/sessions/assumptions.js.map +1 -1
- package/dist/sessions/briefing.d.ts +6 -0
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +12 -1
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/decisions.d.ts +38 -3
- package/dist/sessions/decisions.d.ts.map +1 -1
- package/dist/sessions/decisions.js +235 -21
- package/dist/sessions/decisions.js.map +1 -1
- package/dist/sessions/drift-watchdog.d.ts.map +1 -1
- package/dist/sessions/drift-watchdog.js +4 -2
- package/dist/sessions/drift-watchdog.js.map +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +33 -4
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/session-end-snapshot-entry.d.ts +26 -0
- package/dist/sessions/session-end-snapshot-entry.d.ts.map +1 -0
- package/dist/sessions/session-end-snapshot-entry.js +59 -0
- package/dist/sessions/session-end-snapshot-entry.js.map +1 -0
- package/dist/sessions/session-end-snapshot.d.ts +114 -0
- package/dist/sessions/session-end-snapshot.d.ts.map +1 -0
- package/dist/sessions/session-end-snapshot.js +446 -0
- package/dist/sessions/session-end-snapshot.js.map +1 -0
- package/dist/sessions/session-manifest-mirror.d.ts.map +1 -1
- package/dist/sessions/session-manifest-mirror.js +10 -17
- package/dist/sessions/session-manifest-mirror.js.map +1 -1
- package/dist/sessions/session-switch.d.ts.map +1 -1
- package/dist/sessions/session-switch.js +5 -3
- package/dist/sessions/session-switch.js.map +1 -1
- package/dist/sessions/snapshot.d.ts.map +1 -1
- package/dist/sessions/snapshot.js +5 -4
- package/dist/sessions/snapshot.js.map +1 -1
- package/dist/sessions/terminal-identity.d.ts +169 -0
- package/dist/sessions/terminal-identity.d.ts.map +1 -0
- package/dist/sessions/terminal-identity.js +273 -0
- package/dist/sessions/terminal-identity.js.map +1 -0
- package/dist/setup/sections/verification.d.ts +1 -1
- package/dist/setup/sections/verification.d.ts.map +1 -1
- package/dist/setup/sections/verification.js +11 -15
- package/dist/setup/sections/verification.js.map +1 -1
- package/dist/skills/discovery.d.ts +8 -2
- package/dist/skills/discovery.d.ts.map +1 -1
- package/dist/skills/discovery.js +15 -3
- package/dist/skills/discovery.js.map +1 -1
- package/dist/skills/dispatch.d.ts +5 -2
- package/dist/skills/dispatch.d.ts.map +1 -1
- package/dist/skills/dispatch.js +5 -2
- package/dist/skills/dispatch.js.map +1 -1
- package/dist/skills/doctor.d.ts.map +1 -1
- package/dist/skills/doctor.js +5 -1
- package/dist/skills/doctor.js.map +1 -1
- package/dist/skills/federated-search.js +2 -2
- package/dist/skills/federated-search.js.map +1 -1
- package/dist/skills/index.d.ts +3 -3
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/migration.d.ts +5 -5
- package/dist/skills/migration.d.ts.map +1 -1
- package/dist/skills/migration.js +7 -9
- package/dist/skills/migration.js.map +1 -1
- package/dist/skills/orchestrator/startup.d.ts.map +1 -1
- package/dist/skills/orchestrator/startup.js +4 -2
- package/dist/skills/orchestrator/startup.js.map +1 -1
- package/dist/skills/skill-paths.d.ts +30 -3
- package/dist/skills/skill-paths.d.ts.map +1 -1
- package/dist/skills/skill-paths.js +28 -9
- package/dist/skills/skill-paths.js.map +1 -1
- package/dist/skills/skill-root.d.ts +60 -11
- package/dist/skills/skill-root.d.ts.map +1 -1
- package/dist/skills/skill-root.js +100 -14
- package/dist/skills/skill-root.js.map +1 -1
- package/dist/skills/skills-guard.js +5 -5
- package/dist/skills/skills-guard.js.map +1 -1
- package/dist/skills/types.d.ts +23 -0
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/skills/types.js.map +1 -1
- package/dist/spawn/agent-identity.d.ts +51 -2
- package/dist/spawn/agent-identity.d.ts.map +1 -1
- package/dist/spawn/agent-identity.js +89 -26
- package/dist/spawn/agent-identity.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +56 -79
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/spawn/index.d.ts +2 -2
- package/dist/spawn/index.d.ts.map +1 -1
- package/dist/spawn/index.js +1 -1
- package/dist/spawn/index.js.map +1 -1
- package/dist/spawn/worktree-lock-holder.d.ts +37 -0
- package/dist/spawn/worktree-lock-holder.d.ts.map +1 -0
- package/dist/spawn/worktree-lock-holder.js +41 -0
- package/dist/spawn/worktree-lock-holder.js.map +1 -0
- package/dist/sticky/convert.d.ts.map +1 -1
- package/dist/sticky/convert.js +16 -4
- package/dist/sticky/convert.js.map +1 -1
- package/dist/store/attachment-store.d.ts +14 -0
- package/dist/store/attachment-store.d.ts.map +1 -1
- package/dist/store/attachment-store.js +11 -1
- package/dist/store/attachment-store.js.map +1 -1
- package/dist/store/backup-inspect.d.ts +7 -3
- package/dist/store/backup-inspect.d.ts.map +1 -1
- package/dist/store/backup-inspect.js +18 -7
- package/dist/store/backup-inspect.js.map +1 -1
- package/dist/store/backup-sidecar.d.ts +60 -0
- package/dist/store/backup-sidecar.d.ts.map +1 -0
- package/dist/store/backup-sidecar.js +96 -0
- package/dist/store/backup-sidecar.js.map +1 -0
- package/dist/store/data-accessor.d.ts +1 -1
- package/dist/store/data-accessor.d.ts.map +1 -1
- package/dist/store/data-accessor.js +6 -6
- package/dist/store/data-accessor.js.map +1 -1
- package/dist/store/data-safety-central.d.ts +13 -4
- package/dist/store/data-safety-central.d.ts.map +1 -1
- package/dist/store/data-safety-central.js +31 -4
- package/dist/store/data-safety-central.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +10 -0
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/__fixtures__/representative-fixture.d.ts.map +1 -1
- package/dist/store/exodus/__fixtures__/representative-fixture.js +4 -0
- package/dist/store/exodus/__fixtures__/representative-fixture.js.map +1 -1
- package/dist/store/exodus/migrate.js +1 -1
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/exodus/reconcile.js +1 -1
- package/dist/store/exodus/reconcile.js.map +1 -1
- package/dist/store/exodus/runtime-targets.d.ts +4 -3
- package/dist/store/exodus/runtime-targets.d.ts.map +1 -1
- package/dist/store/exodus/runtime-targets.js +4 -3
- package/dist/store/exodus/runtime-targets.js.map +1 -1
- package/dist/store/import-logging.d.ts.map +1 -1
- package/dist/store/import-logging.js +5 -4
- package/dist/store/import-logging.js.map +1 -1
- package/dist/store/legacy-tasks-lineage.d.ts.map +1 -1
- package/dist/store/legacy-tasks-lineage.js +2 -7
- package/dist/store/legacy-tasks-lineage.js.map +1 -1
- package/dist/store/lock.d.ts +1 -0
- package/dist/store/lock.d.ts.map +1 -1
- package/dist/store/lock.js +1 -0
- package/dist/store/lock.js.map +1 -1
- package/dist/store/memory-accessor.d.ts +8 -3
- package/dist/store/memory-accessor.d.ts.map +1 -1
- package/dist/store/memory-accessor.js +29 -13
- package/dist/store/memory-accessor.js.map +1 -1
- package/dist/store/memory-sqlite.d.ts.map +1 -1
- package/dist/store/memory-sqlite.js +5 -0
- package/dist/store/memory-sqlite.js.map +1 -1
- package/dist/store/open-cleo-db.d.ts.map +1 -1
- package/dist/store/open-cleo-db.js +11 -6
- package/dist/store/open-cleo-db.js.map +1 -1
- package/dist/store/portable-bundle-relocate.d.ts +13 -8
- package/dist/store/portable-bundle-relocate.d.ts.map +1 -1
- package/dist/store/portable-bundle-relocate.js +75 -31
- package/dist/store/portable-bundle-relocate.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +2 -1
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/portable-bundle.d.ts.map +1 -1
- package/dist/store/portable-bundle.js +7 -3
- package/dist/store/portable-bundle.js.map +1 -1
- package/dist/store/pre-repair-snapshot.d.ts +77 -0
- package/dist/store/pre-repair-snapshot.d.ts.map +1 -0
- package/dist/store/pre-repair-snapshot.js +122 -0
- package/dist/store/pre-repair-snapshot.js.map +1 -0
- package/dist/store/regenerators.d.ts +2 -1
- package/dist/store/regenerators.d.ts.map +1 -1
- package/dist/store/regenerators.js +17 -3
- package/dist/store/regenerators.js.map +1 -1
- package/dist/store/relocated-store-guard.d.ts +71 -0
- package/dist/store/relocated-store-guard.d.ts.map +1 -0
- package/dist/store/relocated-store-guard.js +138 -0
- package/dist/store/relocated-store-guard.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +2 -2
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +2 -2
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/schema/attachments.d.ts +2 -2
- package/dist/store/schema/audit.d.ts +5 -5
- package/dist/store/schema/background-jobs.d.ts +1 -1
- package/dist/store/schema/cleo-global/models-catalog.d.ts +1 -1
- package/dist/store/schema/cleo-global/nexus.d.ts +686 -0
- package/dist/store/schema/cleo-global/nexus.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/nexus.js +175 -7
- package/dist/store/schema/cleo-global/nexus.js.map +1 -1
- package/dist/store/schema/cleo-global/skills.d.ts +2 -2
- package/dist/store/schema/cleo-project/audit.d.ts +5 -5
- package/dist/store/schema/cleo-project/docs.d.ts +3 -3
- package/dist/store/schema/cleo-project/lifecycle.d.ts +3 -3
- package/dist/store/schema/cleo-project/provenance-commits.d.ts +2 -2
- package/dist/store/schema/cleo-project/provenance-rest.d.ts +3 -3
- package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts +1 -1
- package/dist/store/schema/cleo-project/tasks-core.d.ts +6 -6
- package/dist/store/schema/cleo-shared/brain.d.ts +26 -26
- package/dist/store/schema/lifecycle.d.ts +3 -3
- package/dist/store/schema/manifest.d.ts +1 -1
- package/dist/store/schema/memory-schema.d.ts +26 -26
- package/dist/store/schema/nexus-schema.d.ts +696 -2
- package/dist/store/schema/nexus-schema.d.ts.map +1 -1
- package/dist/store/schema/nexus-schema.js +175 -19
- package/dist/store/schema/nexus-schema.js.map +1 -1
- package/dist/store/schema/provenance/releases.d.ts +1 -1
- package/dist/store/schema/skills-schema.d.ts +2 -2
- package/dist/store/schema/tasks.d.ts +5 -5
- package/dist/store/session-binding-schema.d.ts +132 -0
- package/dist/store/session-binding-schema.d.ts.map +1 -0
- package/dist/store/session-binding-schema.js +53 -0
- package/dist/store/session-binding-schema.js.map +1 -0
- package/dist/store/session-store.d.ts +262 -4
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +486 -26
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/snapshot-gate.d.ts +239 -0
- package/dist/store/snapshot-gate.d.ts.map +1 -0
- package/dist/store/snapshot-gate.js +398 -0
- package/dist/store/snapshot-gate.js.map +1 -0
- package/dist/store/split-brain-import.js +2 -2
- package/dist/store/split-brain-import.js.map +1 -1
- package/dist/store/sqlite-backup.d.ts +55 -13
- package/dist/store/sqlite-backup.d.ts.map +1 -1
- package/dist/store/sqlite-backup.js +414 -106
- package/dist/store/sqlite-backup.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +15 -0
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +63 -4
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sqlite.d.ts +1 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +53 -5
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/store-write-guard.d.ts +28 -0
- package/dist/store/store-write-guard.d.ts.map +1 -0
- package/dist/store/store-write-guard.js +50 -0
- package/dist/store/store-write-guard.js.map +1 -0
- package/dist/store/table-classification.d.ts +143 -0
- package/dist/store/table-classification.d.ts.map +1 -0
- package/dist/store/table-classification.js +1866 -0
- package/dist/store/table-classification.js.map +1 -0
- package/dist/store/task-version.d.ts +72 -0
- package/dist/store/task-version.d.ts.map +1 -0
- package/dist/store/task-version.js +93 -0
- package/dist/store/task-version.js.map +1 -0
- package/dist/store/tasks-schema.d.ts +1 -0
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/tasks-schema.js +13 -0
- package/dist/store/tasks-schema.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts +10 -3
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +12 -3
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/twin-collapse.d.ts +275 -0
- package/dist/store/twin-collapse.d.ts.map +1 -0
- package/dist/store/twin-collapse.js +805 -0
- package/dist/store/twin-collapse.js.map +1 -0
- package/dist/store/umbrella-data-accessor.d.ts +2 -2
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +2 -2
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +63 -63
- package/dist/store/worktree-isolation-guard.d.ts +46 -24
- package/dist/store/worktree-isolation-guard.d.ts.map +1 -1
- package/dist/store/worktree-isolation-guard.js +69 -50
- package/dist/store/worktree-isolation-guard.js.map +1 -1
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/backup.js +3 -67
- package/dist/system/backup.js.map +1 -1
- package/dist/system/cleo-link.d.ts +163 -0
- package/dist/system/cleo-link.d.ts.map +1 -0
- package/dist/system/cleo-link.js +246 -0
- package/dist/system/cleo-link.js.map +1 -0
- package/dist/system/dependencies.d.ts.map +1 -1
- package/dist/system/dependencies.js +3 -6
- package/dist/system/dependencies.js.map +1 -1
- package/dist/system/global-delivery.d.ts +205 -0
- package/dist/system/global-delivery.d.ts.map +1 -0
- package/dist/system/global-delivery.js +320 -0
- package/dist/system/global-delivery.js.map +1 -0
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +29 -6
- package/dist/system/health.js.map +1 -1
- package/dist/system/project-health.d.ts.map +1 -1
- package/dist/system/project-health.js +1 -20
- package/dist/system/project-health.js.map +1 -1
- package/dist/system/runtime.d.ts.map +1 -1
- package/dist/system/runtime.js +2 -12
- package/dist/system/runtime.js.map +1 -1
- package/dist/system/safestop.d.ts.map +1 -1
- package/dist/system/safestop.js +5 -2
- package/dist/system/safestop.js.map +1 -1
- package/dist/system/skill-fixtures.d.ts +200 -0
- package/dist/system/skill-fixtures.d.ts.map +1 -0
- package/dist/system/skill-fixtures.js +331 -0
- package/dist/system/skill-fixtures.js.map +1 -0
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +4 -2
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/affected-packages.d.ts +173 -0
- package/dist/tasks/affected-packages.d.ts.map +1 -0
- package/dist/tasks/affected-packages.js +389 -0
- package/dist/tasks/affected-packages.js.map +1 -0
- package/dist/tasks/change-set.d.ts +151 -0
- package/dist/tasks/change-set.d.ts.map +1 -0
- package/dist/tasks/change-set.js +634 -0
- package/dist/tasks/change-set.js.map +1 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +10 -5
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/done-plan.d.ts +103 -0
- package/dist/tasks/done-plan.d.ts.map +1 -0
- package/dist/tasks/done-plan.js +541 -0
- package/dist/tasks/done-plan.js.map +1 -0
- package/dist/tasks/done-record.d.ts +127 -0
- package/dist/tasks/done-record.d.ts.map +1 -0
- package/dist/tasks/done-record.js +373 -0
- package/dist/tasks/done-record.js.map +1 -0
- package/dist/tasks/duplicate-detector.d.ts +68 -11
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +314 -58
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/tasks/evidence-paths.d.ts +78 -0
- package/dist/tasks/evidence-paths.d.ts.map +1 -0
- package/dist/tasks/evidence-paths.js +150 -0
- package/dist/tasks/evidence-paths.js.map +1 -0
- package/dist/tasks/evidence.d.ts +55 -0
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +223 -26
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/gate-preview.d.ts +5 -0
- package/dist/tasks/gate-preview.d.ts.map +1 -1
- package/dist/tasks/gate-preview.js +25 -21
- package/dist/tasks/gate-preview.js.map +1 -1
- package/dist/tasks/gate-result-cache.d.ts +205 -0
- package/dist/tasks/gate-result-cache.d.ts.map +1 -0
- package/dist/tasks/gate-result-cache.js +285 -0
- package/dist/tasks/gate-result-cache.js.map +1 -0
- package/dist/tasks/gate-runner.d.ts +126 -3
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +483 -28
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/session-scope.d.ts +3 -1
- package/dist/tasks/session-scope.d.ts.map +1 -1
- package/dist/tasks/session-scope.js +18 -3
- package/dist/tasks/session-scope.js.map +1 -1
- package/dist/tasks/tool-resolver.d.ts +23 -6
- package/dist/tasks/tool-resolver.d.ts.map +1 -1
- package/dist/tasks/tool-resolver.js +146 -8
- package/dist/tasks/tool-resolver.js.map +1 -1
- package/dist/tasks/tool-vacuity.d.ts +71 -0
- package/dist/tasks/tool-vacuity.d.ts.map +1 -0
- package/dist/tasks/tool-vacuity.js +334 -0
- package/dist/tasks/tool-vacuity.js.map +1 -0
- package/dist/tasks/update.d.ts +8 -0
- package/dist/tasks/update.d.ts.map +1 -1
- package/dist/tasks/update.js +159 -78
- package/dist/tasks/update.js.map +1 -1
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +18 -2
- package/dist/upgrade.js.map +1 -1
- package/dist/validation/doctor/checks.d.ts +20 -2
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/doctor/checks.js +64 -4
- package/dist/validation/doctor/checks.js.map +1 -1
- package/dist/validation/doctor/index.d.ts +1 -1
- package/dist/validation/doctor/index.d.ts.map +1 -1
- package/dist/validation/doctor/index.js +1 -1
- package/dist/validation/doctor/index.js.map +1 -1
- package/dist/validation/doctor/utils.d.ts.map +1 -1
- package/dist/validation/doctor/utils.js +7 -2
- package/dist/validation/doctor/utils.js.map +1 -1
- package/dist/validation/engine-ops.d.ts +15 -0
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +249 -98
- package/dist/validation/engine-ops.js.map +1 -1
- package/migrations/drizzle-cleo-global/20260927000000_t12469-project-locations/migration.sql +121 -0
- package/migrations/drizzle-cleo-global/20260927010000_t12543-user-profile-project-scope/migration.sql +23 -0
- package/migrations/drizzle-cleo-global/20260928010000_t12470-location-candidates/migration.sql +72 -0
- package/migrations/drizzle-cleo-global/20260928020000_t12510-nexus-devices/migration.sql +34 -0
- package/migrations/drizzle-cleo-global/20260928030000_t12511-project-git-state/migration.sql +62 -0
- package/migrations/drizzle-cleo-project/20260927000000_t12499-session-terminal-bindings/migration.sql +34 -0
- package/migrations/drizzle-cleo-project/20260928000000_t12500-binding-provider-flag/migration.sql +15 -0
- package/package.json +23 -13
- package/schemas/config.schema.json +54 -0
- package/schemas/project-context.schema.json +51 -3
- package/schemas/project-info.schema.json +28 -1
- package/templates/CLEO-INJECTION.md +40 -332
- package/templates/CLEO-REFERENCE.md +303 -0
- package/templates/workflows/README.md +36 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project lifecycle engine — move, rename, and re-register CLEO projects.
|
|
2
|
+
* Project lifecycle engine — move, reroot, rename, and re-register CLEO projects.
|
|
3
3
|
*
|
|
4
4
|
* Provides the core operations for relocating a CLEO project on disk,
|
|
5
5
|
* renaming it, and reconciling the nexus registry after manual moves.
|
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
* All functions accept explicit absolute paths — no CWD-walk-up (AC7).
|
|
8
8
|
*
|
|
9
9
|
* @task T11010 — T10298-1
|
|
10
|
+
* @task T12552 — dry runs are pure
|
|
11
|
+
* @task T12556 — relocations RENAME; nothing is copied, so no stale copy exists
|
|
12
|
+
* @task T12558 — `rerootProject`, child/ancestor targets refused, tombstone
|
|
10
13
|
*/
|
|
11
|
-
import { existsSync } from 'node:fs';
|
|
12
|
-
import {
|
|
13
|
-
import { basename, dirname, join, resolve as resolvePath } from 'node:path';
|
|
14
|
+
import { existsSync, statSync } from 'node:fs';
|
|
15
|
+
import { copyFile, mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
16
|
+
import { basename, dirname, join, relative, resolve as resolvePath, sep } from 'node:path';
|
|
17
|
+
import { ExitCode } from '@cleocode/contracts';
|
|
18
|
+
import { canonicalizePath, computeProjectHash, readPortableProjectId, resolveWorktreeRootForHash, } from '@cleocode/paths';
|
|
19
|
+
import { withStrippedFieldsReceipt } from './doctor/project-identity.js';
|
|
14
20
|
import { engineError, engineSuccess } from './engine-result.js';
|
|
15
21
|
import { generateProjectHash, nexusReconcile, nexusRenameProject } from './nexus/index.js';
|
|
22
|
+
import { computeStableProjectHash } from './project-scope.js';
|
|
16
23
|
// ── Internal helpers ─────────────────────────────────────────────────
|
|
17
24
|
/**
|
|
18
25
|
* Read and parse project-info.json from the given project root.
|
|
@@ -51,103 +58,650 @@ function validateAbsolutePath(label, p) {
|
|
|
51
58
|
}
|
|
52
59
|
return null; // valid
|
|
53
60
|
}
|
|
54
|
-
// ──
|
|
61
|
+
// ── Relocation helpers (T12552 · T12556 · T12558) ─────────────────────
|
|
55
62
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
* Top-level entries `reroot` renames into the child, in order. `.github` is
|
|
64
|
+
* included only when it holds nothing but CLEO's own init templates (see
|
|
65
|
+
* {@link isCleoOwnedGithubDir}); a parent repository's real `.github` stays.
|
|
66
|
+
*/
|
|
67
|
+
const REROOT_ENTRIES = ['.cleo', '.worktreeinclude', '.github'];
|
|
68
|
+
/** Nearest existing ancestor of `p` (itself when it exists). */
|
|
69
|
+
function nearestExisting(p) {
|
|
70
|
+
let head = resolvePath(p);
|
|
71
|
+
while (!existsSync(head)) {
|
|
72
|
+
const parent = dirname(head);
|
|
73
|
+
if (parent === head)
|
|
74
|
+
break;
|
|
75
|
+
head = parent;
|
|
76
|
+
}
|
|
77
|
+
return head;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Canonical form of a path whose tail may not exist yet: the nearest existing
|
|
81
|
+
* ancestor is resolved through symlinks (macOS `/tmp` → `/private/tmp`) and
|
|
82
|
+
* the missing tail is appended, so containment compares like with like.
|
|
83
|
+
*/
|
|
84
|
+
function canonicalTarget(p) {
|
|
85
|
+
const resolved = resolvePath(p);
|
|
86
|
+
const head = nearestExisting(resolved);
|
|
87
|
+
return join(canonicalizePath(head), relative(head, resolved));
|
|
88
|
+
}
|
|
89
|
+
/** `true` when `inner` is strictly inside `outer` (both canonical). */
|
|
90
|
+
function isStrictlyInside(outer, inner) {
|
|
91
|
+
const rel = relative(outer, inner);
|
|
92
|
+
return rel.length > 0 && !rel.startsWith(`..${sep}`) && rel !== '..' && !rel.startsWith(sep);
|
|
93
|
+
}
|
|
94
|
+
/** `true` when `target` (or its nearest existing ancestor) is on `source`'s device. */
|
|
95
|
+
function sameDevice(source, target) {
|
|
96
|
+
return statSync(source).dev === statSync(nearestExisting(target)).dev;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* `E_CROSS_DEVICE`: a relocation only renames within one device. The fix says
|
|
100
|
+
* to quiesce the project first — a plain `mv` across devices is a copy, so a
|
|
101
|
+
* live writer during it tears the database exactly as the old copy did.
|
|
102
|
+
*/
|
|
103
|
+
function crossDeviceRefusal(source, target, command) {
|
|
104
|
+
return engineError('E_CROSS_DEVICE', `"${target}" is on another device than "${source}"; cleo only relocates by rename within one device`, {
|
|
105
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
106
|
+
fix: `First end every session (\`cleo session end\`), stop every process writing to the project, and run \`cleo backup add\`. Then: ${command}`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** Read `projectId` from project-info.json, or the failure to return. */
|
|
110
|
+
async function readRelocatableIdentity(projectRoot) {
|
|
111
|
+
const info = await readProjectInfo(projectRoot);
|
|
112
|
+
if (!info) {
|
|
113
|
+
return engineError('E_PROJECT_INFO_MISSING', `Failed to read project-info.json at "${projectRoot}"`, { exitCode: ExitCode.CONFIG_ERROR });
|
|
114
|
+
}
|
|
115
|
+
const projectId = typeof info.projectId === 'string' ? info.projectId : '';
|
|
116
|
+
if (!projectId) {
|
|
117
|
+
return engineError('E_NO_PROJECT_ID', `project-info.json at "${projectRoot}" is missing projectId`, { fix: 'Run `cleo init` to generate a projectId', exitCode: ExitCode.CONFIG_ERROR });
|
|
118
|
+
}
|
|
119
|
+
return { projectId };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* CLEO worktrees provisioned for the project at `projectRoot`, plus git
|
|
123
|
+
* worktrees registered in its `.git/`. Both are keyed by absolute path, so a
|
|
124
|
+
* relocation would strand them.
|
|
125
|
+
*/
|
|
126
|
+
async function listBoundWorktrees(projectRoot, includeGit) {
|
|
127
|
+
const found = new Set();
|
|
128
|
+
const dir = resolveWorktreeRootForHash(computeProjectHash(projectRoot));
|
|
129
|
+
if (existsSync(dir)) {
|
|
130
|
+
for (const entry of await readdir(dir))
|
|
131
|
+
found.add(`CLEO worktree ${join(dir, entry)}`);
|
|
132
|
+
}
|
|
133
|
+
const { readSentinelIndex } = await import('./worktree/sentinel-index.js');
|
|
134
|
+
for (const entry of readSentinelIndex(projectRoot)) {
|
|
135
|
+
if (existsSync(entry.path))
|
|
136
|
+
found.add(`CLEO worktree ${entry.path}`);
|
|
137
|
+
}
|
|
138
|
+
const gitWorktrees = join(projectRoot, '.git', 'worktrees');
|
|
139
|
+
if (includeGit && existsSync(gitWorktrees)) {
|
|
140
|
+
for (const entry of await readdir(gitWorktrees)) {
|
|
141
|
+
found.add(`git worktree ${join(gitWorktrees, entry)}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return [...found].sort();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The refusal for a relocation while something is bound to the project. The
|
|
148
|
+
* fix names the exact command for each session, bound by `CLEO_SESSION_ID` so
|
|
149
|
+
* it ends THAT session rather than the caller's (T12500).
|
|
150
|
+
*/
|
|
151
|
+
function blockedError(code, worktrees, activeSessions) {
|
|
152
|
+
const steps = [
|
|
153
|
+
...activeSessions.map((id) => `CLEO_SESSION_ID=${id} cleo session end`),
|
|
154
|
+
...(worktrees.length > 0 ? ['remove each worktree listed in details.worktrees'] : []),
|
|
155
|
+
...(worktrees.some((w) => w.startsWith('git worktree '))
|
|
156
|
+
? ['for a git worktree whose directory is already gone, run `git worktree prune`']
|
|
157
|
+
: []),
|
|
158
|
+
];
|
|
159
|
+
return engineError(code, `Cannot relocate while bound: ${[...worktrees, ...activeSessions.map((s) => `active session ${s}`)].join('; ')}`, {
|
|
160
|
+
exitCode: ExitCode.CONCURRENT_MODIFICATION,
|
|
161
|
+
details: { worktrees, activeSessions },
|
|
162
|
+
fix: `${steps.join(' && ')}, then retry`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/** Ids of active sessions in the project store at `projectRoot`. */
|
|
166
|
+
async function activeSessionIds(projectRoot) {
|
|
167
|
+
const { listSessions } = await import('./store/session-store.js');
|
|
168
|
+
return (await listSessions({ active: true }, projectRoot)).map((s) => s.id);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Required checkpoint before a relocation: the `cleo backup add` snapshot,
|
|
172
|
+
* then COPIED to `<cleoHome>/backups/<projectId>/<backupId>/` so it does not
|
|
173
|
+
* share fate with the tree it protects.
|
|
174
|
+
*/
|
|
175
|
+
async function takeCheckpoint(projectRoot, projectId, kind, target) {
|
|
176
|
+
try {
|
|
177
|
+
const { createBackup } = await import('./system/backup.js');
|
|
178
|
+
const backup = await createBackup(projectRoot, {
|
|
179
|
+
type: kind,
|
|
180
|
+
note: `before cleo project ${kind} ${target}`,
|
|
181
|
+
});
|
|
182
|
+
if (!backup.files.includes('tasks.db')) {
|
|
183
|
+
throw new Error('the project database was not captured');
|
|
184
|
+
}
|
|
185
|
+
const { getCleoHome } = await import('./paths.js');
|
|
186
|
+
const outside = join(getCleoHome(), 'backups', projectId, backup.backupId);
|
|
187
|
+
await mkdir(outside, { recursive: true });
|
|
188
|
+
const names = [
|
|
189
|
+
...backup.files.map((f) => `${f}.${backup.backupId}`),
|
|
190
|
+
`${backup.backupId}.meta.json`,
|
|
191
|
+
];
|
|
192
|
+
for (const name of names) {
|
|
193
|
+
const src = join(backup.path, name);
|
|
194
|
+
if (existsSync(src))
|
|
195
|
+
await copyFile(src, join(outside, name));
|
|
196
|
+
}
|
|
197
|
+
return engineSuccess({ id: backup.backupId, path: outside });
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
return engineError('E_CHECKPOINT_FAILED', `Checkpoint before ${kind} failed: ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Run `cleo backup add` to diagnose, then retry' });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/** Where the checkpoint will be written, for a plan (nothing is created). */
|
|
204
|
+
async function checkpointLocation(projectId) {
|
|
205
|
+
const { getCleoHome } = await import('./paths.js');
|
|
206
|
+
return join(getCleoHome(), 'backups', projectId, '<backupId>');
|
|
207
|
+
}
|
|
208
|
+
/** Open the global registry (dynamic: keeps the store graph off import). */
|
|
209
|
+
async function openRegistry() {
|
|
210
|
+
const { getNexusRegistryDb } = await import('./store/nexus-sqlite.js');
|
|
211
|
+
const { getCleoHome } = await import('./paths.js');
|
|
212
|
+
return getNexusRegistryDb(getCleoHome());
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Rebind the registry to `livePath` explicitly, then demote `demotedPath` to
|
|
216
|
+
* `missing` — exactly one live location remains.
|
|
71
217
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
218
|
+
* Runs with the project scope pinned to `livePath`: the nexus handle is the
|
|
219
|
+
* AMBIENT project's `cleo.db`, and the ambient root is still the caller's cwd
|
|
220
|
+
* (the old root). Opening it there would create an empty store beside the
|
|
221
|
+
* moved one.
|
|
222
|
+
*/
|
|
223
|
+
async function rebindRegistry(projectId, livePath, demotedPath) {
|
|
224
|
+
const { captureProjectScope, worktreeScope } = await import('./project-scope.js');
|
|
225
|
+
const scope = captureProjectScope(livePath, worktreeScope.getStore());
|
|
226
|
+
try {
|
|
227
|
+
const reconcile = await worktreeScope.run(scope, () => nexusReconcile(livePath, { forceRebind: true }));
|
|
228
|
+
const { demoteProjectLocation } = await import('./nexus/path-map.js');
|
|
229
|
+
demoteProjectLocation(await openRegistry(), { projectId, projectPath: demotedPath, now: new Date().toISOString() }, 'missing');
|
|
230
|
+
return engineSuccess(reconcile.status);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
return engineError('E_NEXUS_RECONCILE_FAILED', `Files were relocated to "${livePath}" but the registry rebind failed: ${err.message}`, {
|
|
234
|
+
exitCode: ExitCode.GENERAL_ERROR,
|
|
235
|
+
details: { originalError: err.message },
|
|
236
|
+
fix: `Run \`cleo nexus reconcile --force-rebind\` in ${livePath}`,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** Every file under `dir`, relative to it. */
|
|
241
|
+
async function listFiles(dir, prefix = '') {
|
|
242
|
+
const out = [];
|
|
243
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
244
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
245
|
+
if (entry.isDirectory())
|
|
246
|
+
out.push(...(await listFiles(join(dir, entry.name), rel)));
|
|
247
|
+
else
|
|
248
|
+
out.push(rel);
|
|
249
|
+
}
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* `true` when `<root>/.github` holds only files byte-identical to the GitHub
|
|
254
|
+
* templates `cleo init` installs — i.e. CLEO created it, not the repository.
|
|
255
|
+
*/
|
|
256
|
+
async function isCleoOwnedGithubDir(root) {
|
|
257
|
+
const { getPackageRoot } = await import('./scaffold/ensure-config.js');
|
|
258
|
+
const templates = join(getPackageRoot(), 'templates', 'github');
|
|
259
|
+
const githubDir = join(root, '.github');
|
|
260
|
+
if (!existsSync(templates))
|
|
261
|
+
return false;
|
|
262
|
+
const files = await listFiles(githubDir);
|
|
263
|
+
if (files.length === 0)
|
|
264
|
+
return false;
|
|
265
|
+
for (const file of files) {
|
|
266
|
+
const template = join(templates, file);
|
|
267
|
+
if (!existsSync(template))
|
|
268
|
+
return false;
|
|
269
|
+
const [a, b] = await Promise.all([readFile(join(githubDir, file)), readFile(template)]);
|
|
270
|
+
if (!a.equals(b))
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Split CLEO's top-level entries at `root` into those reroot moves and those
|
|
277
|
+
* it must leave, given what `childDir` already holds.
|
|
79
278
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
279
|
+
async function rerootEntries(root, childDir) {
|
|
280
|
+
const entries = [];
|
|
281
|
+
const excluded = [];
|
|
282
|
+
const clashes = [];
|
|
283
|
+
for (const entry of REROOT_ENTRIES) {
|
|
284
|
+
if (!existsSync(join(root, entry)))
|
|
285
|
+
continue;
|
|
286
|
+
if (entry === '.github') {
|
|
287
|
+
if (!(await isCleoOwnedGithubDir(root))) {
|
|
288
|
+
excluded.push({ entry, reason: 'holds files that are not CLEO init templates' });
|
|
289
|
+
}
|
|
290
|
+
else if (existsSync(join(childDir, entry))) {
|
|
291
|
+
excluded.push({ entry, reason: 'the child already has its own .github' });
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
entries.push(entry);
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (existsSync(join(childDir, entry)))
|
|
299
|
+
clashes.push(entry);
|
|
300
|
+
else
|
|
301
|
+
entries.push(entry);
|
|
302
|
+
}
|
|
303
|
+
return { entries, excluded, clashes };
|
|
304
|
+
}
|
|
305
|
+
/** Rename `entries` from `from` to `to`; on any failure put back what moved. */
|
|
306
|
+
async function renameEntries(from, to, entries) {
|
|
307
|
+
const done = [];
|
|
308
|
+
try {
|
|
309
|
+
for (const entry of entries) {
|
|
310
|
+
await rename(join(from, entry), join(to, entry));
|
|
311
|
+
done.push(entry);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
await renameBack(from, to, done);
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/** Undo {@link renameEntries} for `entries` (best effort, reverse order). */
|
|
320
|
+
async function renameBack(from, to, entries) {
|
|
321
|
+
for (const entry of [...entries].reverse()) {
|
|
322
|
+
await rename(join(to, entry), join(from, entry)).catch(() => undefined);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
export async function moveProject(newPath, projectRoot, opts = {}) {
|
|
82
326
|
const pathErr = validateAbsolutePath('newPath', newPath);
|
|
83
327
|
if (pathErr)
|
|
84
328
|
return pathErr;
|
|
85
329
|
const rootErr = validateAbsolutePath('projectRoot', projectRoot);
|
|
86
330
|
if (rootErr)
|
|
87
331
|
return rootErr;
|
|
88
|
-
|
|
332
|
+
newPath = resolvePath(newPath);
|
|
89
333
|
if (!existsSync(join(projectRoot, '.cleo', 'project-info.json'))) {
|
|
90
334
|
return engineError('E_NOT_CLEO_PROJECT', `No CLEO project found at "${projectRoot}"`, {
|
|
91
335
|
fix: 'Ensure the project was initialized with `cleo init`',
|
|
336
|
+
exitCode: ExitCode.CONFIG_ERROR,
|
|
92
337
|
});
|
|
93
338
|
}
|
|
94
|
-
|
|
95
|
-
|
|
339
|
+
const source = canonicalizePath(projectRoot);
|
|
340
|
+
const target = canonicalTarget(newPath);
|
|
341
|
+
if (newPath === resolvePath(projectRoot) || source === target) {
|
|
342
|
+
return engineError('E_SAME_PATH', `newPath and projectRoot resolve to the same location: "${projectRoot}"`, { exitCode: ExitCode.INVALID_INPUT });
|
|
96
343
|
}
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
344
|
+
// Refused before any IO: a directory cannot be renamed into its own subtree
|
|
345
|
+
// or onto an ancestor.
|
|
346
|
+
const targetIsFile = existsSync(newPath) && !statSync(newPath).isDirectory();
|
|
347
|
+
if (isStrictlyInside(source, target)) {
|
|
348
|
+
return engineError('E_INVALID_TARGET', `newPath "${newPath}" is inside the project at "${projectRoot}"; a project cannot move into itself`, {
|
|
349
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
350
|
+
fix: targetIsFile
|
|
351
|
+
? 'Choose a directory outside the project tree'
|
|
352
|
+
: `To make that directory the project root, run \`cleo project reroot ${relative(source, target)}\` from ${projectRoot}`,
|
|
353
|
+
});
|
|
101
354
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return engineError('E_NO_PROJECT_ID', `project-info.json at "${projectRoot}" is missing projectId`, { fix: 'Run `cleo init` to generate a projectId' });
|
|
355
|
+
if (isStrictlyInside(target, source)) {
|
|
356
|
+
return engineError('E_INVALID_TARGET', `newPath "${newPath}" contains the project at "${projectRoot}"; a project cannot move onto its own ancestor`, { exitCode: ExitCode.INVALID_INPUT, fix: 'Choose a path outside the project tree' });
|
|
105
357
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
358
|
+
if (targetIsFile) {
|
|
359
|
+
return engineError('E_INVALID_TARGET', `newPath is an existing file: "${newPath}"`, {
|
|
360
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
361
|
+
fix: 'Choose a path that does not exist yet, or an empty directory',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (existsSync(newPath) && (await readdir(newPath)).length > 0) {
|
|
365
|
+
return engineError('E_INVALID_TARGET', `newPath is not empty: "${newPath}"`, {
|
|
366
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
367
|
+
fix: 'Choose a path that does not exist yet, or an empty directory',
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
const identity = await readRelocatableIdentity(projectRoot);
|
|
371
|
+
if ('success' in identity)
|
|
372
|
+
return identity;
|
|
373
|
+
const { projectId } = identity;
|
|
374
|
+
const crossDevice = !sameDevice(projectRoot, newPath);
|
|
375
|
+
const crossDeviceError = crossDeviceRefusal(projectRoot, newPath, `mv "${projectRoot}" "${newPath}" && cd "${newPath}" && cleo nexus reconcile — the carried nonce proves the move and git stays intact`);
|
|
376
|
+
const worktrees = await listBoundWorktrees(projectRoot, true);
|
|
377
|
+
if (opts.dryRun) {
|
|
378
|
+
return engineSuccess({
|
|
379
|
+
dryRun: true,
|
|
380
|
+
kind: 'move',
|
|
381
|
+
projectId,
|
|
382
|
+
source: projectRoot,
|
|
383
|
+
target: newPath,
|
|
384
|
+
transfer: 'rename',
|
|
385
|
+
entries: ['.'],
|
|
386
|
+
excluded: [],
|
|
387
|
+
writes: [],
|
|
388
|
+
registry: {
|
|
389
|
+
action: 'rebind',
|
|
390
|
+
livePath: newPath,
|
|
391
|
+
demotedPath: projectRoot,
|
|
392
|
+
demotedState: 'missing',
|
|
393
|
+
nonce: 'carried',
|
|
121
394
|
},
|
|
395
|
+
checkpoint: await checkpointLocation(projectId),
|
|
396
|
+
blockers: [
|
|
397
|
+
...(crossDevice ? ['E_CROSS_DEVICE: the target is on another device'] : []),
|
|
398
|
+
...worktrees,
|
|
399
|
+
],
|
|
400
|
+
deferredChecks: ['no active session (reads the project database)'],
|
|
122
401
|
});
|
|
123
402
|
}
|
|
124
|
-
|
|
125
|
-
return
|
|
403
|
+
if (crossDevice)
|
|
404
|
+
return crossDeviceError;
|
|
405
|
+
const sessions = await activeSessionIds(projectRoot);
|
|
406
|
+
if (worktrees.length > 0 || sessions.length > 0) {
|
|
407
|
+
return blockedError('E_MOVE_BLOCKED', worktrees, sessions);
|
|
126
408
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
projectHash: newProjectHash,
|
|
133
|
-
lastUpdated: new Date().toISOString(),
|
|
134
|
-
};
|
|
135
|
-
await writeProjectInfo(newPath, newInfo);
|
|
136
|
-
// Reconcile nexus registry with the new path
|
|
137
|
-
let reconcile;
|
|
409
|
+
const checkpoint = await takeCheckpoint(projectRoot, projectId, 'move', newPath);
|
|
410
|
+
if (!checkpoint.success)
|
|
411
|
+
return checkpoint;
|
|
412
|
+
const { closeAllDatabases } = await import('./store/sqlite.js');
|
|
413
|
+
await closeAllDatabases();
|
|
138
414
|
try {
|
|
139
|
-
|
|
415
|
+
await mkdir(dirname(newPath), { recursive: true });
|
|
416
|
+
await rename(projectRoot, newPath);
|
|
140
417
|
}
|
|
141
418
|
catch (err) {
|
|
142
|
-
|
|
419
|
+
if (err.code === 'EXDEV')
|
|
420
|
+
return crossDeviceError;
|
|
421
|
+
return engineError('E_MOVE_FAILED', `Failed to rename "${projectRoot}" to "${newPath}": ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Nothing was moved; check permissions and retry' });
|
|
143
422
|
}
|
|
423
|
+
const rebound = await rebindRegistry(projectId, newPath, projectRoot);
|
|
424
|
+
if (!rebound.success)
|
|
425
|
+
return rebound;
|
|
144
426
|
return engineSuccess({
|
|
427
|
+
dryRun: false,
|
|
145
428
|
projectId,
|
|
146
429
|
oldPath: projectRoot,
|
|
147
430
|
newPath,
|
|
148
|
-
|
|
149
|
-
|
|
431
|
+
checkpointId: checkpoint.data.id,
|
|
432
|
+
checkpointPath: checkpoint.data.path,
|
|
433
|
+
reconcileStatus: rebound.data,
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* The registry path of `projectId` when it is a strict ancestor of `childDir`
|
|
438
|
+
* that no longer holds the project — i.e. an earlier reroot renamed `.cleo/`
|
|
439
|
+
* into `childDir` and stopped before rebinding.
|
|
440
|
+
*/
|
|
441
|
+
async function interruptedRerootSource(projectId, childDir) {
|
|
442
|
+
const { projectRegistry } = await import('./store/schema/nexus-schema.js');
|
|
443
|
+
const { eq } = await import('drizzle-orm');
|
|
444
|
+
const row = (await openRegistry())
|
|
445
|
+
.select({ projectPath: projectRegistry.projectPath })
|
|
446
|
+
.from(projectRegistry)
|
|
447
|
+
.where(eq(projectRegistry.projectId, projectId))
|
|
448
|
+
.get();
|
|
449
|
+
const oldRoot = row?.projectPath;
|
|
450
|
+
if (!oldRoot || !existsSync(oldRoot))
|
|
451
|
+
return null;
|
|
452
|
+
if (!isStrictlyInside(canonicalizePath(oldRoot), canonicalizePath(childDir)))
|
|
453
|
+
return null;
|
|
454
|
+
return existsSync(join(oldRoot, '.cleo', 'project-info.json')) ? null : oldRoot;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Keep `entry` out of commits in the repository containing `root` (T12558).
|
|
458
|
+
*
|
|
459
|
+
* Asks git for the exclude file (`rev-parse --git-path info/exclude`) and for
|
|
460
|
+
* `root`'s path inside the work tree (`--show-prefix`), so it works when
|
|
461
|
+
* `root` is a subdirectory of a repository and when `.git` is a FILE (a
|
|
462
|
+
* linked worktree or a submodule). The line is anchored to that repo-relative
|
|
463
|
+
* path. Local to this checkout — nothing tracked changes. Best effort: `root`
|
|
464
|
+
* may not be in a repository, and a tombstone is validated on read anyway.
|
|
465
|
+
*/
|
|
466
|
+
async function excludeFromGit(root, entry) {
|
|
467
|
+
const { execFile } = await import('node:child_process');
|
|
468
|
+
const { promisify } = await import('node:util');
|
|
469
|
+
const git = async (...args) => (await promisify(execFile)('git', ['-C', root, ...args], { encoding: 'utf-8' })).stdout.trim();
|
|
470
|
+
try {
|
|
471
|
+
const exclude = resolvePath(root, await git('rev-parse', '--git-path', 'info/exclude'));
|
|
472
|
+
const line = `/${await git('rev-parse', '--show-prefix')}${entry}`;
|
|
473
|
+
await mkdir(dirname(exclude), { recursive: true });
|
|
474
|
+
const current = existsSync(exclude) ? await readFile(exclude, 'utf-8') : '';
|
|
475
|
+
if (current.split(/\r?\n/).includes(line))
|
|
476
|
+
return;
|
|
477
|
+
const joiner = current.length === 0 || current.endsWith('\n') ? '' : '\n';
|
|
478
|
+
await writeFile(exclude, `${current}${joiner}${line}\n`);
|
|
479
|
+
}
|
|
480
|
+
catch {
|
|
481
|
+
// Not in a repository, or git unavailable: the tombstone is still validated on read.
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Finish a reroot from the child: identity, tombstone, rebind. Shared by the
|
|
486
|
+
* normal path (after the rename) and a resume.
|
|
487
|
+
*/
|
|
488
|
+
async function completeReroot(projectId, childDir, oldRoot) {
|
|
489
|
+
const { ensurePortableProjectId } = await import('./scaffold/project-identity.js');
|
|
490
|
+
const idOutcome = await ensurePortableProjectId(childDir, projectId);
|
|
491
|
+
if (idOutcome !== 'present' && idOutcome !== 'written') {
|
|
492
|
+
throw new Error(`.cleo/project-id could not record ${projectId} (${idOutcome})`);
|
|
493
|
+
}
|
|
494
|
+
const { PROJECT_TOMBSTONE_FILE, writeProjectTombstone } = await import('./project-tombstone.js');
|
|
495
|
+
const tombstone = writeProjectTombstone(oldRoot, {
|
|
496
|
+
projectId,
|
|
497
|
+
movedTo: childDir,
|
|
498
|
+
at: new Date().toISOString(),
|
|
150
499
|
});
|
|
500
|
+
await excludeFromGit(oldRoot, PROJECT_TOMBSTONE_FILE);
|
|
501
|
+
const rebound = await rebindRegistry(projectId, childDir, oldRoot);
|
|
502
|
+
if (!rebound.success)
|
|
503
|
+
return rebound;
|
|
504
|
+
return engineSuccess({ projectIdFile: idOutcome, tombstone, status: rebound.data });
|
|
505
|
+
}
|
|
506
|
+
export async function rerootProject(childDir, projectRoot, opts = {}) {
|
|
507
|
+
const pathErr = validateAbsolutePath('childDir', childDir);
|
|
508
|
+
if (pathErr)
|
|
509
|
+
return pathErr;
|
|
510
|
+
const rootErr = validateAbsolutePath('projectRoot', projectRoot);
|
|
511
|
+
if (rootErr)
|
|
512
|
+
return rootErr;
|
|
513
|
+
if (!existsSync(join(projectRoot, '.cleo', 'project-info.json'))) {
|
|
514
|
+
return engineError('E_NOT_CLEO_PROJECT', `No CLEO project found at "${projectRoot}"`, {
|
|
515
|
+
fix: 'Run `cleo project reroot` from inside the project',
|
|
516
|
+
exitCode: ExitCode.CONFIG_ERROR,
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
if (!existsSync(childDir) || !statSync(childDir).isDirectory()) {
|
|
520
|
+
return engineError('E_INVALID_TARGET', `childDir is not an existing directory: "${childDir}"`, {
|
|
521
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
522
|
+
fix: 'Pass an existing subdirectory of the project',
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
const identity = await readRelocatableIdentity(projectRoot);
|
|
526
|
+
if ('success' in identity)
|
|
527
|
+
return identity;
|
|
528
|
+
const { projectId } = identity;
|
|
529
|
+
const source = canonicalizePath(projectRoot);
|
|
530
|
+
const target = canonicalizePath(childDir);
|
|
531
|
+
// Resume: `.cleo/` is already in this directory and the registry still names
|
|
532
|
+
// an ancestor that no longer holds the project.
|
|
533
|
+
if (source === target) {
|
|
534
|
+
const oldRoot = await interruptedRerootSource(projectId, childDir);
|
|
535
|
+
if (!oldRoot) {
|
|
536
|
+
return engineError('E_SAME_PATH', `"${childDir}" is already the project root and no interrupted reroot was found`, {
|
|
537
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
538
|
+
fix: 'Pass a subdirectory: `cleo project reroot <childDir>`',
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
if (opts.dryRun) {
|
|
542
|
+
return engineSuccess({
|
|
543
|
+
dryRun: true,
|
|
544
|
+
kind: 'reroot',
|
|
545
|
+
projectId,
|
|
546
|
+
source: oldRoot,
|
|
547
|
+
target: childDir,
|
|
548
|
+
transfer: 'rename',
|
|
549
|
+
entries: [],
|
|
550
|
+
excluded: [],
|
|
551
|
+
writes: [join(oldRoot, '.cleo-moved.json')],
|
|
552
|
+
registry: {
|
|
553
|
+
action: 'rebind',
|
|
554
|
+
livePath: childDir,
|
|
555
|
+
demotedPath: oldRoot,
|
|
556
|
+
demotedState: 'missing',
|
|
557
|
+
nonce: 'carried',
|
|
558
|
+
},
|
|
559
|
+
checkpoint: 'none: resuming an interrupted reroot',
|
|
560
|
+
blockers: [],
|
|
561
|
+
deferredChecks: [],
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
try {
|
|
565
|
+
const done = await completeReroot(projectId, childDir, oldRoot);
|
|
566
|
+
if (!done.success)
|
|
567
|
+
return done;
|
|
568
|
+
return engineSuccess({
|
|
569
|
+
dryRun: false,
|
|
570
|
+
projectId,
|
|
571
|
+
oldRoot,
|
|
572
|
+
newRoot: childDir,
|
|
573
|
+
resumed: true,
|
|
574
|
+
checkpointId: '',
|
|
575
|
+
checkpointPath: '',
|
|
576
|
+
renamed: [],
|
|
577
|
+
projectIdFile: done.data.projectIdFile,
|
|
578
|
+
tombstone: done.data.tombstone,
|
|
579
|
+
reconcileStatus: done.data.status,
|
|
580
|
+
notes: rerootNotes(oldRoot, childDir),
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
catch (err) {
|
|
584
|
+
return engineError('E_IDENTITY_CONFLICT', err.message, {
|
|
585
|
+
exitCode: ExitCode.CONFIG_ERROR,
|
|
586
|
+
fix: 'Run `cleo doctor project-identity --resolve`, then `cleo project reroot .` again',
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (!isStrictlyInside(source, target)) {
|
|
591
|
+
return engineError('E_INVALID_TARGET', `childDir "${childDir}" is not inside the project at "${projectRoot}"`, {
|
|
592
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
593
|
+
fix: `To relocate the whole project, run \`cleo project move ${childDir}\``,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
const { entries, excluded, clashes } = await rerootEntries(projectRoot, childDir);
|
|
597
|
+
if (clashes.length > 0) {
|
|
598
|
+
return engineError('E_INVALID_TARGET', `childDir already holds ${clashes.join(', ')}: "${childDir}"`, {
|
|
599
|
+
exitCode: ExitCode.INVALID_INPUT,
|
|
600
|
+
fix: `Move ${clashes.map((c) => join(childDir, c)).join(', ')} aside first; reroot never merges or overwrites`,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
const tracked = readPortableProjectId(projectRoot);
|
|
604
|
+
if (tracked.status === 'invalid' ||
|
|
605
|
+
(tracked.status === 'valid' && tracked.projectId !== projectId)) {
|
|
606
|
+
return engineError('E_IDENTITY_CONFLICT', `.cleo/project-id does not agree with project-info.json at "${projectRoot}"`, {
|
|
607
|
+
exitCode: ExitCode.CONFIG_ERROR,
|
|
608
|
+
fix: 'Run `cleo doctor project-identity` and resolve it first',
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
const worktrees = await listBoundWorktrees(projectRoot, false);
|
|
612
|
+
// A child can be a mount point: then `.cleo/` cannot be renamed into it.
|
|
613
|
+
const crossDevice = !sameDevice(projectRoot, childDir);
|
|
614
|
+
const crossDeviceError = crossDeviceRefusal(projectRoot, childDir, `mv "${join(projectRoot, '.cleo')}" "${join(childDir, '.cleo')}" && cd "${childDir}" && cleo project reroot .`);
|
|
615
|
+
if (opts.dryRun) {
|
|
616
|
+
return engineSuccess({
|
|
617
|
+
dryRun: true,
|
|
618
|
+
kind: 'reroot',
|
|
619
|
+
projectId,
|
|
620
|
+
source: projectRoot,
|
|
621
|
+
target: childDir,
|
|
622
|
+
transfer: 'rename',
|
|
623
|
+
entries,
|
|
624
|
+
excluded,
|
|
625
|
+
writes: [
|
|
626
|
+
...(tracked.status === 'absent' ? [join(childDir, '.cleo', 'project-id')] : []),
|
|
627
|
+
join(projectRoot, '.cleo-moved.json'),
|
|
628
|
+
],
|
|
629
|
+
registry: {
|
|
630
|
+
action: 'rebind',
|
|
631
|
+
livePath: childDir,
|
|
632
|
+
demotedPath: projectRoot,
|
|
633
|
+
demotedState: 'missing',
|
|
634
|
+
nonce: 'carried',
|
|
635
|
+
},
|
|
636
|
+
checkpoint: await checkpointLocation(projectId),
|
|
637
|
+
blockers: [
|
|
638
|
+
...(crossDevice ? ['E_CROSS_DEVICE: the child is on another device'] : []),
|
|
639
|
+
...worktrees,
|
|
640
|
+
],
|
|
641
|
+
deferredChecks: ['no active session (reads the project database)'],
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
if (crossDevice)
|
|
645
|
+
return crossDeviceError;
|
|
646
|
+
const sessions = await activeSessionIds(projectRoot);
|
|
647
|
+
if (worktrees.length > 0 || sessions.length > 0) {
|
|
648
|
+
return blockedError('E_REROOT_BLOCKED', worktrees, sessions);
|
|
649
|
+
}
|
|
650
|
+
const checkpoint = await takeCheckpoint(projectRoot, projectId, 'reroot', childDir);
|
|
651
|
+
if (!checkpoint.success)
|
|
652
|
+
return checkpoint;
|
|
653
|
+
const { closeAllDatabases } = await import('./store/sqlite.js');
|
|
654
|
+
await closeAllDatabases();
|
|
655
|
+
try {
|
|
656
|
+
await renameEntries(projectRoot, childDir, entries);
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
if (err.code === 'EXDEV')
|
|
660
|
+
return crossDeviceError;
|
|
661
|
+
return engineError('E_MOVE_FAILED', `Failed to rename ${entries.join(', ')} into "${childDir}": ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Nothing was moved; check permissions and retry' });
|
|
662
|
+
}
|
|
663
|
+
let done;
|
|
664
|
+
try {
|
|
665
|
+
done = await completeReroot(projectId, childDir, projectRoot);
|
|
666
|
+
}
|
|
667
|
+
catch (err) {
|
|
668
|
+
// Identity or tombstone failed before the registry changed: undo the renames.
|
|
669
|
+
await renameBack(projectRoot, childDir, entries);
|
|
670
|
+
const { rm } = await import('node:fs/promises');
|
|
671
|
+
await rm(join(projectRoot, '.cleo-moved.json'), { force: true });
|
|
672
|
+
return engineError('E_REROOT_FAILED', `Reroot rolled back: ${err.message}`, {
|
|
673
|
+
exitCode: ExitCode.FILE_ERROR,
|
|
674
|
+
fix: 'Nothing changed. Run `cleo doctor project-identity`, then retry',
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
if (!done.success) {
|
|
678
|
+
return engineError(done.error.code, done.error.message, {
|
|
679
|
+
exitCode: done.error.exitCode,
|
|
680
|
+
details: done.error.details,
|
|
681
|
+
fix: `The files are already in ${childDir}; run \`cleo project reroot .\` there to finish`,
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
return engineSuccess({
|
|
685
|
+
dryRun: false,
|
|
686
|
+
projectId,
|
|
687
|
+
oldRoot: projectRoot,
|
|
688
|
+
newRoot: childDir,
|
|
689
|
+
resumed: false,
|
|
690
|
+
checkpointId: checkpoint.data.id,
|
|
691
|
+
checkpointPath: checkpoint.data.path,
|
|
692
|
+
renamed: entries,
|
|
693
|
+
projectIdFile: done.data.projectIdFile,
|
|
694
|
+
tombstone: done.data.tombstone,
|
|
695
|
+
reconcileStatus: done.data.status,
|
|
696
|
+
notes: rerootNotes(projectRoot, childDir),
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
/** Git bookkeeping a reroot leaves to the operator. */
|
|
700
|
+
function rerootNotes(oldRoot, newRoot) {
|
|
701
|
+
return [
|
|
702
|
+
`Commit .cleo/project-id in the repository at ${newRoot}`,
|
|
703
|
+
`The repository at ${oldRoot} now shows .cleo/ as deleted; do not restore it (commands there refuse with E_PROJECT_MOVED)`,
|
|
704
|
+
];
|
|
151
705
|
}
|
|
152
706
|
/**
|
|
153
707
|
* Rename a CLEO project (updates project-info.json name and hash).
|
|
@@ -191,13 +745,23 @@ export async function renameProject(newName, projectRoot) {
|
|
|
191
745
|
const oldName = (typeof info.name === 'string' ? info.name : '') ||
|
|
192
746
|
(typeof info.projectName === 'string' ? info.projectName : '') ||
|
|
193
747
|
basename(projectRoot);
|
|
194
|
-
// AC4: Update project-info.json — only name changes
|
|
195
|
-
|
|
748
|
+
// AC4: Update project-info.json — only name changes. T12557: projectHash is
|
|
749
|
+
// a write-once identity key (release ids, audit rows), so the stored value is
|
|
750
|
+
// kept byte-identical. projectRoot is a path fact and is never written back:
|
|
751
|
+
// a legacy value is dropped into the same `strippedFields` receipt that
|
|
752
|
+
// `cleo doctor project-identity --resolve` keeps.
|
|
753
|
+
const newProjectHash = typeof info.projectHash === 'string' && info.projectHash.length > 0
|
|
754
|
+
? info.projectHash
|
|
755
|
+
: computeStableProjectHash(projectRoot);
|
|
756
|
+
const now = new Date().toISOString();
|
|
757
|
+
const kept = info.projectRoot === undefined
|
|
758
|
+
? info
|
|
759
|
+
: withStrippedFieldsReceipt(info, [{ file: 'project-info.json', field: 'projectRoot', value: info.projectRoot }], now, true);
|
|
196
760
|
const newInfo = {
|
|
197
|
-
...
|
|
761
|
+
...kept,
|
|
198
762
|
name: newName.trim(),
|
|
199
763
|
projectHash: newProjectHash,
|
|
200
|
-
lastUpdated:
|
|
764
|
+
lastUpdated: now,
|
|
201
765
|
};
|
|
202
766
|
await writeProjectInfo(projectRoot, newInfo);
|
|
203
767
|
// AC1, AC3, AC5: Register self-alias in nexus projectIdAliases table
|