@cleocode/cleo 2026.2.5
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/LICENSE +107 -0
- package/README.md +1266 -0
- package/completions/bash-completion.sh +362 -0
- package/completions/zsh-completion.zsh +305 -0
- package/dist/cli/commands/add.d.ts +12 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +74 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +12 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +37 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/archive-stats.d.ts +26 -0
- package/dist/cli/commands/archive-stats.d.ts.map +1 -0
- package/dist/cli/commands/archive-stats.js +291 -0
- package/dist/cli/commands/archive-stats.js.map +1 -0
- package/dist/cli/commands/archive.d.ts +12 -0
- package/dist/cli/commands/archive.d.ts.map +1 -0
- package/dist/cli/commands/archive.js +43 -0
- package/dist/cli/commands/archive.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +7 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +122 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/blockers.d.ts +7 -0
- package/dist/cli/commands/blockers.d.ts.map +1 -0
- package/dist/cli/commands/blockers.js +107 -0
- package/dist/cli/commands/blockers.js.map +1 -0
- package/dist/cli/commands/checkpoint.d.ts +13 -0
- package/dist/cli/commands/checkpoint.d.ts.map +1 -0
- package/dist/cli/commands/checkpoint.js +185 -0
- package/dist/cli/commands/checkpoint.js.map +1 -0
- package/dist/cli/commands/claude-migrate.d.ts +13 -0
- package/dist/cli/commands/claude-migrate.d.ts.map +1 -0
- package/dist/cli/commands/claude-migrate.js +355 -0
- package/dist/cli/commands/claude-migrate.js.map +1 -0
- package/dist/cli/commands/commands.d.ts +13 -0
- package/dist/cli/commands/commands.d.ts.map +1 -0
- package/dist/cli/commands/commands.js +114 -0
- package/dist/cli/commands/commands.js.map +1 -0
- package/dist/cli/commands/complete.d.ts +12 -0
- package/dist/cli/commands/complete.d.ts.map +1 -0
- package/dist/cli/commands/complete.js +45 -0
- package/dist/cli/commands/complete.js.map +1 -0
- package/dist/cli/commands/compliance.d.ts +12 -0
- package/dist/cli/commands/compliance.d.ts.map +1 -0
- package/dist/cli/commands/compliance.js +152 -0
- package/dist/cli/commands/compliance.js.map +1 -0
- package/dist/cli/commands/config.d.ts +7 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +107 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/consensus.d.ts +12 -0
- package/dist/cli/commands/consensus.d.ts.map +1 -0
- package/dist/cli/commands/consensus.js +61 -0
- package/dist/cli/commands/consensus.js.map +1 -0
- package/dist/cli/commands/context.d.ts +12 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +76 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/contribution.d.ts +12 -0
- package/dist/cli/commands/contribution.d.ts.map +1 -0
- package/dist/cli/commands/contribution.js +57 -0
- package/dist/cli/commands/contribution.js.map +1 -0
- package/dist/cli/commands/current.d.ts +13 -0
- package/dist/cli/commands/current.d.ts.map +1 -0
- package/dist/cli/commands/current.js +35 -0
- package/dist/cli/commands/current.js.map +1 -0
- package/dist/cli/commands/dash.d.ts +12 -0
- package/dist/cli/commands/dash.d.ts.map +1 -0
- package/dist/cli/commands/dash.js +44 -0
- package/dist/cli/commands/dash.js.map +1 -0
- package/dist/cli/commands/decomposition.d.ts +12 -0
- package/dist/cli/commands/decomposition.d.ts.map +1 -0
- package/dist/cli/commands/decomposition.js +61 -0
- package/dist/cli/commands/decomposition.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +12 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +45 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/deps.d.ts +17 -0
- package/dist/cli/commands/deps.d.ts.map +1 -0
- package/dist/cli/commands/deps.js +139 -0
- package/dist/cli/commands/deps.js.map +1 -0
- package/dist/cli/commands/detect-drift.d.ts +8 -0
- package/dist/cli/commands/detect-drift.d.ts.map +1 -0
- package/dist/cli/commands/detect-drift.js +202 -0
- package/dist/cli/commands/detect-drift.js.map +1 -0
- package/dist/cli/commands/docs.d.ts +13 -0
- package/dist/cli/commands/docs.d.ts.map +1 -0
- package/dist/cli/commands/docs.js +167 -0
- package/dist/cli/commands/docs.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +7 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +215 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/env.d.ts +12 -0
- package/dist/cli/commands/env.d.ts.map +1 -0
- package/dist/cli/commands/env.js +167 -0
- package/dist/cli/commands/env.js.map +1 -0
- package/dist/cli/commands/exists.d.ts +7 -0
- package/dist/cli/commands/exists.d.ts.map +1 -0
- package/dist/cli/commands/exists.js +78 -0
- package/dist/cli/commands/exists.js.map +1 -0
- package/dist/cli/commands/export-tasks.d.ts +13 -0
- package/dist/cli/commands/export-tasks.d.ts.map +1 -0
- package/dist/cli/commands/export-tasks.js +214 -0
- package/dist/cli/commands/export-tasks.js.map +1 -0
- package/dist/cli/commands/export.d.ts +7 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +144 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/extract.d.ts +13 -0
- package/dist/cli/commands/extract.d.ts.map +1 -0
- package/dist/cli/commands/extract.js +208 -0
- package/dist/cli/commands/extract.js.map +1 -0
- package/dist/cli/commands/find.d.ts +14 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +62 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/focus.d.ts +19 -0
- package/dist/cli/commands/focus.d.ts.map +1 -0
- package/dist/cli/commands/focus.js +95 -0
- package/dist/cli/commands/focus.js.map +1 -0
- package/dist/cli/commands/generate-changelog.d.ts +14 -0
- package/dist/cli/commands/generate-changelog.d.ts.map +1 -0
- package/dist/cli/commands/generate-changelog.js +252 -0
- package/dist/cli/commands/generate-changelog.js.map +1 -0
- package/dist/cli/commands/history.d.ts +12 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +40 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/implementation.d.ts +12 -0
- package/dist/cli/commands/implementation.d.ts.map +1 -0
- package/dist/cli/commands/implementation.js +57 -0
- package/dist/cli/commands/implementation.js.map +1 -0
- package/dist/cli/commands/import-tasks.d.ts +13 -0
- package/dist/cli/commands/import-tasks.d.ts.map +1 -0
- package/dist/cli/commands/import-tasks.js +219 -0
- package/dist/cli/commands/import-tasks.js.map +1 -0
- package/dist/cli/commands/import.d.ts +7 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +162 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +34 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +88 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/inject.d.ts +12 -0
- package/dist/cli/commands/inject.d.ts.map +1 -0
- package/dist/cli/commands/inject.js +45 -0
- package/dist/cli/commands/inject.js.map +1 -0
- package/dist/cli/commands/issue.d.ts +14 -0
- package/dist/cli/commands/issue.d.ts.map +1 -0
- package/dist/cli/commands/issue.js +256 -0
- package/dist/cli/commands/issue.js.map +1 -0
- package/dist/cli/commands/labels.d.ts +12 -0
- package/dist/cli/commands/labels.d.ts.map +1 -0
- package/dist/cli/commands/labels.js +89 -0
- package/dist/cli/commands/labels.js.map +1 -0
- package/dist/cli/commands/lifecycle.d.ts +12 -0
- package/dist/cli/commands/lifecycle.d.ts.map +1 -0
- package/dist/cli/commands/lifecycle.js +108 -0
- package/dist/cli/commands/lifecycle.js.map +1 -0
- package/dist/cli/commands/list.d.ts +14 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +65 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/log.d.ts +12 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +43 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/mcp-install.d.ts +17 -0
- package/dist/cli/commands/mcp-install.d.ts.map +1 -0
- package/dist/cli/commands/mcp-install.js +125 -0
- package/dist/cli/commands/mcp-install.js.map +1 -0
- package/dist/cli/commands/migrate-storage.d.ts +19 -0
- package/dist/cli/commands/migrate-storage.d.ts.map +1 -0
- package/dist/cli/commands/migrate-storage.js +494 -0
- package/dist/cli/commands/migrate-storage.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +12 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +62 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/next.d.ts +7 -0
- package/dist/cli/commands/next.d.ts.map +1 -0
- package/dist/cli/commands/next.js +124 -0
- package/dist/cli/commands/next.js.map +1 -0
- package/dist/cli/commands/nexus.d.ts +19 -0
- package/dist/cli/commands/nexus.d.ts.map +1 -0
- package/dist/cli/commands/nexus.js +440 -0
- package/dist/cli/commands/nexus.js.map +1 -0
- package/dist/cli/commands/orchestrate.d.ts +12 -0
- package/dist/cli/commands/orchestrate.d.ts.map +1 -0
- package/dist/cli/commands/orchestrate.js +141 -0
- package/dist/cli/commands/orchestrate.js.map +1 -0
- package/dist/cli/commands/otel.d.ts +12 -0
- package/dist/cli/commands/otel.d.ts.map +1 -0
- package/dist/cli/commands/otel.js +130 -0
- package/dist/cli/commands/otel.js.map +1 -0
- package/dist/cli/commands/phase.d.ts +12 -0
- package/dist/cli/commands/phase.d.ts.map +1 -0
- package/dist/cli/commands/phase.js +161 -0
- package/dist/cli/commands/phase.js.map +1 -0
- package/dist/cli/commands/phases.d.ts +12 -0
- package/dist/cli/commands/phases.d.ts.map +1 -0
- package/dist/cli/commands/phases.js +67 -0
- package/dist/cli/commands/phases.js.map +1 -0
- package/dist/cli/commands/promote.d.ts +7 -0
- package/dist/cli/commands/promote.d.ts.map +1 -0
- package/dist/cli/commands/promote.js +64 -0
- package/dist/cli/commands/promote.js.map +1 -0
- package/dist/cli/commands/relates.d.ts +12 -0
- package/dist/cli/commands/relates.d.ts.map +1 -0
- package/dist/cli/commands/relates.js +91 -0
- package/dist/cli/commands/relates.js.map +1 -0
- package/dist/cli/commands/release.d.ts +12 -0
- package/dist/cli/commands/release.d.ts.map +1 -0
- package/dist/cli/commands/release.js +142 -0
- package/dist/cli/commands/release.js.map +1 -0
- package/dist/cli/commands/reopen.d.ts +7 -0
- package/dist/cli/commands/reopen.d.ts.map +1 -0
- package/dist/cli/commands/reopen.js +83 -0
- package/dist/cli/commands/reopen.js.map +1 -0
- package/dist/cli/commands/reorder.d.ts +7 -0
- package/dist/cli/commands/reorder.d.ts.map +1 -0
- package/dist/cli/commands/reorder.js +106 -0
- package/dist/cli/commands/reorder.js.map +1 -0
- package/dist/cli/commands/reparent.d.ts +10 -0
- package/dist/cli/commands/reparent.d.ts.map +1 -0
- package/dist/cli/commands/reparent.js +53 -0
- package/dist/cli/commands/reparent.js.map +1 -0
- package/dist/cli/commands/research.d.ts +12 -0
- package/dist/cli/commands/research.d.ts.map +1 -0
- package/dist/cli/commands/research.js +220 -0
- package/dist/cli/commands/research.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +7 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +202 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/roadmap.d.ts +12 -0
- package/dist/cli/commands/roadmap.d.ts.map +1 -0
- package/dist/cli/commands/roadmap.js +37 -0
- package/dist/cli/commands/roadmap.js.map +1 -0
- package/dist/cli/commands/safestop.d.ts +13 -0
- package/dist/cli/commands/safestop.d.ts.map +1 -0
- package/dist/cli/commands/safestop.js +217 -0
- package/dist/cli/commands/safestop.js.map +1 -0
- package/dist/cli/commands/self-update.d.ts +15 -0
- package/dist/cli/commands/self-update.d.ts.map +1 -0
- package/dist/cli/commands/self-update.js +195 -0
- package/dist/cli/commands/self-update.js.map +1 -0
- package/dist/cli/commands/sequence.d.ts +12 -0
- package/dist/cli/commands/sequence.d.ts.map +1 -0
- package/dist/cli/commands/sequence.js +67 -0
- package/dist/cli/commands/sequence.js.map +1 -0
- package/dist/cli/commands/session.d.ts +12 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +150 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/show.d.ts +13 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +35 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/skills.d.ts +13 -0
- package/dist/cli/commands/skills.d.ts.map +1 -0
- package/dist/cli/commands/skills.js +215 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/specification.d.ts +12 -0
- package/dist/cli/commands/specification.d.ts.map +1 -0
- package/dist/cli/commands/specification.js +61 -0
- package/dist/cli/commands/specification.js.map +1 -0
- package/dist/cli/commands/start.d.ts +13 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +35 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +12 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +37 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +13 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +35 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +13 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +129 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/testing.d.ts +13 -0
- package/dist/cli/commands/testing.d.ts.map +1 -0
- package/dist/cli/commands/testing.js +160 -0
- package/dist/cli/commands/testing.js.map +1 -0
- package/dist/cli/commands/unarchive.d.ts +7 -0
- package/dist/cli/commands/unarchive.d.ts.map +1 -0
- package/dist/cli/commands/unarchive.js +93 -0
- package/dist/cli/commands/unarchive.js.map +1 -0
- package/dist/cli/commands/uncancel.d.ts +7 -0
- package/dist/cli/commands/uncancel.d.ts.map +1 -0
- package/dist/cli/commands/uncancel.js +93 -0
- package/dist/cli/commands/uncancel.js.map +1 -0
- package/dist/cli/commands/update.d.ts +12 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +74 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +15 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +59 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +211 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +7 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +153 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/web.d.ts +13 -0
- package/dist/cli/commands/web.d.ts.map +1 -0
- package/dist/cli/commands/web.js +281 -0
- package/dist/cli/commands/web.js.map +1 -0
- package/dist/cli/format-context.d.ts +32 -0
- package/dist/cli/format-context.d.ts.map +1 -0
- package/dist/cli/format-context.js +50 -0
- package/dist/cli/format-context.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +34903 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/middleware/output-format.d.ts +30 -0
- package/dist/cli/middleware/output-format.d.ts.map +1 -0
- package/dist/cli/middleware/output-format.js +35 -0
- package/dist/cli/middleware/output-format.js.map +1 -0
- package/dist/cli/renderers/colors.d.ts +41 -0
- package/dist/cli/renderers/colors.d.ts.map +1 -0
- package/dist/cli/renderers/colors.js +120 -0
- package/dist/cli/renderers/colors.js.map +1 -0
- package/dist/cli/renderers/index.d.ts +47 -0
- package/dist/cli/renderers/index.d.ts.map +1 -0
- package/dist/cli/renderers/index.js +103 -0
- package/dist/cli/renderers/index.js.map +1 -0
- package/dist/cli/renderers/system.d.ts +24 -0
- package/dist/cli/renderers/system.d.ts.map +1 -0
- package/dist/cli/renderers/system.js +317 -0
- package/dist/cli/renderers/system.js.map +1 -0
- package/dist/cli/renderers/tasks.d.ts +28 -0
- package/dist/cli/renderers/tasks.d.ts.map +1 -0
- package/dist/cli/renderers/tasks.js +307 -0
- package/dist/cli/renderers/tasks.js.map +1 -0
- package/dist/core/caamp/adapter.d.ts +141 -0
- package/dist/core/caamp/adapter.d.ts.map +1 -0
- package/dist/core/caamp/adapter.js +437 -0
- package/dist/core/caamp/adapter.js.map +1 -0
- package/dist/core/caamp/index.d.ts +11 -0
- package/dist/core/caamp/index.d.ts.map +1 -0
- package/dist/core/caamp/index.js +21 -0
- package/dist/core/caamp/index.js.map +1 -0
- package/dist/core/compliance/index.d.ts +38 -0
- package/dist/core/compliance/index.d.ts.map +1 -0
- package/dist/core/compliance/index.js +229 -0
- package/dist/core/compliance/index.js.map +1 -0
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +179 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context/index.d.ts +20 -0
- package/dist/core/context/index.d.ts.map +1 -0
- package/dist/core/context/index.js +137 -0
- package/dist/core/context/index.js.map +1 -0
- package/dist/core/error-registry.d.ts +54 -0
- package/dist/core/error-registry.d.ts.map +1 -0
- package/dist/core/error-registry.js +109 -0
- package/dist/core/error-registry.js.map +1 -0
- package/dist/core/errors.d.ts +38 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +105 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/focus/index.d.ts +46 -0
- package/dist/core/focus/index.d.ts.map +1 -0
- package/dist/core/focus/index.js +118 -0
- package/dist/core/focus/index.js.map +1 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/init.d.ts +76 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +730 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/inject/index.d.ts +24 -0
- package/dist/core/inject/index.d.ts.map +1 -0
- package/dist/core/inject/index.js +84 -0
- package/dist/core/inject/index.js.map +1 -0
- package/dist/core/issue/index.d.ts +9 -0
- package/dist/core/issue/index.d.ts.map +1 -0
- package/dist/core/issue/index.js +8 -0
- package/dist/core/issue/index.js.map +1 -0
- package/dist/core/issue/template-parser.d.ts +45 -0
- package/dist/core/issue/template-parser.d.ts.map +1 -0
- package/dist/core/issue/template-parser.js +178 -0
- package/dist/core/issue/template-parser.js.map +1 -0
- package/dist/core/lifecycle/index.d.ts +71 -0
- package/dist/core/lifecycle/index.d.ts.map +1 -0
- package/dist/core/lifecycle/index.js +213 -0
- package/dist/core/lifecycle/index.js.map +1 -0
- package/dist/core/log/index.d.ts +15 -0
- package/dist/core/log/index.d.ts.map +1 -0
- package/dist/core/log/index.js +33 -0
- package/dist/core/log/index.js.map +1 -0
- package/dist/core/mcp/index.d.ts +37 -0
- package/dist/core/mcp/index.d.ts.map +1 -0
- package/dist/core/mcp/index.js +73 -0
- package/dist/core/mcp/index.js.map +1 -0
- package/dist/core/metrics/ab-test.d.ts +52 -0
- package/dist/core/metrics/ab-test.d.ts.map +1 -0
- package/dist/core/metrics/ab-test.js +261 -0
- package/dist/core/metrics/ab-test.js.map +1 -0
- package/dist/core/metrics/aggregation.d.ts +41 -0
- package/dist/core/metrics/aggregation.d.ts.map +1 -0
- package/dist/core/metrics/aggregation.js +353 -0
- package/dist/core/metrics/aggregation.js.map +1 -0
- package/dist/core/metrics/common.d.ts +30 -0
- package/dist/core/metrics/common.d.ts.map +1 -0
- package/dist/core/metrics/common.js +64 -0
- package/dist/core/metrics/common.js.map +1 -0
- package/dist/core/metrics/enums.d.ts +68 -0
- package/dist/core/metrics/enums.d.ts.map +1 -0
- package/dist/core/metrics/enums.js +78 -0
- package/dist/core/metrics/enums.js.map +1 -0
- package/dist/core/metrics/index.d.ts +17 -0
- package/dist/core/metrics/index.d.ts.map +1 -0
- package/dist/core/metrics/index.js +19 -0
- package/dist/core/metrics/index.js.map +1 -0
- package/dist/core/metrics/otel-integration.d.ts +49 -0
- package/dist/core/metrics/otel-integration.d.ts.map +1 -0
- package/dist/core/metrics/otel-integration.js +261 -0
- package/dist/core/metrics/otel-integration.js.map +1 -0
- package/dist/core/metrics/token-estimation.d.ts +70 -0
- package/dist/core/metrics/token-estimation.d.ts.map +1 -0
- package/dist/core/metrics/token-estimation.js +253 -0
- package/dist/core/metrics/token-estimation.js.map +1 -0
- package/dist/core/migration/checksum.d.ts +55 -0
- package/dist/core/migration/checksum.d.ts.map +1 -0
- package/dist/core/migration/checksum.js +90 -0
- package/dist/core/migration/checksum.js.map +1 -0
- package/dist/core/migration/index.d.ts +77 -0
- package/dist/core/migration/index.d.ts.map +1 -0
- package/dist/core/migration/index.js +278 -0
- package/dist/core/migration/index.js.map +1 -0
- package/dist/core/migration/logger.d.ts +161 -0
- package/dist/core/migration/logger.d.ts.map +1 -0
- package/dist/core/migration/logger.js +364 -0
- package/dist/core/migration/logger.js.map +1 -0
- package/dist/core/migration/preflight.d.ts +43 -0
- package/dist/core/migration/preflight.d.ts.map +1 -0
- package/dist/core/migration/preflight.js +164 -0
- package/dist/core/migration/preflight.js.map +1 -0
- package/dist/core/migration/state.d.ts +186 -0
- package/dist/core/migration/state.d.ts.map +1 -0
- package/dist/core/migration/state.js +419 -0
- package/dist/core/migration/state.js.map +1 -0
- package/dist/core/migration/validate.d.ts +57 -0
- package/dist/core/migration/validate.d.ts.map +1 -0
- package/dist/core/migration/validate.js +242 -0
- package/dist/core/migration/validate.js.map +1 -0
- package/dist/core/nexus/deps.d.ts +112 -0
- package/dist/core/nexus/deps.d.ts.map +1 -0
- package/dist/core/nexus/deps.js +394 -0
- package/dist/core/nexus/deps.js.map +1 -0
- package/dist/core/nexus/index.d.ts +14 -0
- package/dist/core/nexus/index.d.ts.map +1 -0
- package/dist/core/nexus/index.js +36 -0
- package/dist/core/nexus/index.js.map +1 -0
- package/dist/core/nexus/permissions.d.ts +75 -0
- package/dist/core/nexus/permissions.d.ts.map +1 -0
- package/dist/core/nexus/permissions.js +126 -0
- package/dist/core/nexus/permissions.js.map +1 -0
- package/dist/core/nexus/query.d.ts +55 -0
- package/dist/core/nexus/query.d.ts.map +1 -0
- package/dist/core/nexus/query.js +181 -0
- package/dist/core/nexus/query.js.map +1 -0
- package/dist/core/nexus/registry.d.ts +135 -0
- package/dist/core/nexus/registry.d.ts.map +1 -0
- package/dist/core/nexus/registry.js +296 -0
- package/dist/core/nexus/registry.js.map +1 -0
- package/dist/core/orchestration/index.d.ts +114 -0
- package/dist/core/orchestration/index.d.ts.map +1 -0
- package/dist/core/orchestration/index.js +295 -0
- package/dist/core/orchestration/index.js.map +1 -0
- package/dist/core/orchestration/protocol-validators.d.ts +94 -0
- package/dist/core/orchestration/protocol-validators.d.ts.map +1 -0
- package/dist/core/orchestration/protocol-validators.js +510 -0
- package/dist/core/orchestration/protocol-validators.js.map +1 -0
- package/dist/core/otel/index.d.ts +27 -0
- package/dist/core/otel/index.d.ts.map +1 -0
- package/dist/core/otel/index.js +126 -0
- package/dist/core/otel/index.js.map +1 -0
- package/dist/core/output.d.ts +64 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +134 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/pagination.d.ts +45 -0
- package/dist/core/pagination.d.ts.map +1 -0
- package/dist/core/pagination.js +61 -0
- package/dist/core/pagination.js.map +1 -0
- package/dist/core/paths.d.ts +122 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +269 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/phases/deps.d.ts +142 -0
- package/dist/core/phases/deps.d.ts.map +1 -0
- package/dist/core/phases/deps.js +390 -0
- package/dist/core/phases/deps.js.map +1 -0
- package/dist/core/phases/index.d.ts +123 -0
- package/dist/core/phases/index.d.ts.map +1 -0
- package/dist/core/phases/index.js +409 -0
- package/dist/core/phases/index.js.map +1 -0
- package/dist/core/platform.d.ts +55 -0
- package/dist/core/platform.d.ts.map +1 -0
- package/dist/core/platform.js +117 -0
- package/dist/core/platform.js.map +1 -0
- package/dist/core/release/artifacts.d.ts +71 -0
- package/dist/core/release/artifacts.d.ts.map +1 -0
- package/dist/core/release/artifacts.js +412 -0
- package/dist/core/release/artifacts.js.map +1 -0
- package/dist/core/release/ci.d.ts +35 -0
- package/dist/core/release/ci.d.ts.map +1 -0
- package/dist/core/release/ci.js +162 -0
- package/dist/core/release/ci.js.map +1 -0
- package/dist/core/release/guards.d.ts +47 -0
- package/dist/core/release/guards.d.ts.map +1 -0
- package/dist/core/release/guards.js +110 -0
- package/dist/core/release/guards.js.map +1 -0
- package/dist/core/release/index.d.ts +97 -0
- package/dist/core/release/index.d.ts.map +1 -0
- package/dist/core/release/index.js +459 -0
- package/dist/core/release/index.js.map +1 -0
- package/dist/core/release/provenance.d.ts +75 -0
- package/dist/core/release/provenance.d.ts.map +1 -0
- package/dist/core/release/provenance.js +213 -0
- package/dist/core/release/provenance.js.map +1 -0
- package/dist/core/release/release-config.d.ts +55 -0
- package/dist/core/release/release-config.d.ts.map +1 -0
- package/dist/core/release/release-config.js +105 -0
- package/dist/core/release/release-config.js.map +1 -0
- package/dist/core/release/version-bump.d.ts +51 -0
- package/dist/core/release/version-bump.d.ts.map +1 -0
- package/dist/core/release/version-bump.js +251 -0
- package/dist/core/release/version-bump.js.map +1 -0
- package/dist/core/research/index.d.ts +129 -0
- package/dist/core/research/index.d.ts.map +1 -0
- package/dist/core/research/index.js +251 -0
- package/dist/core/research/index.js.map +1 -0
- package/dist/core/roadmap/index.d.ts +13 -0
- package/dist/core/roadmap/index.d.ts.map +1 -0
- package/dist/core/roadmap/index.js +63 -0
- package/dist/core/roadmap/index.js.map +1 -0
- package/dist/core/schema.d.ts +20 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +75 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/sequence/index.d.ts +21 -0
- package/dist/core/sequence/index.d.ts.map +1 -0
- package/dist/core/sequence/index.js +108 -0
- package/dist/core/sequence/index.js.map +1 -0
- package/dist/core/sessions/context-alert.d.ts +48 -0
- package/dist/core/sessions/context-alert.d.ts.map +1 -0
- package/dist/core/sessions/context-alert.js +222 -0
- package/dist/core/sessions/context-alert.js.map +1 -0
- package/dist/core/sessions/context-monitor.d.ts +31 -0
- package/dist/core/sessions/context-monitor.d.ts.map +1 -0
- package/dist/core/sessions/context-monitor.js +83 -0
- package/dist/core/sessions/context-monitor.js.map +1 -0
- package/dist/core/sessions/hitl-warnings.d.ts +58 -0
- package/dist/core/sessions/hitl-warnings.d.ts.map +1 -0
- package/dist/core/sessions/hitl-warnings.js +253 -0
- package/dist/core/sessions/hitl-warnings.js.map +1 -0
- package/dist/core/sessions/index.d.ts +65 -0
- package/dist/core/sessions/index.d.ts.map +1 -0
- package/dist/core/sessions/index.js +244 -0
- package/dist/core/sessions/index.js.map +1 -0
- package/dist/core/sessions/session-enforcement.d.ts +50 -0
- package/dist/core/sessions/session-enforcement.d.ts.map +1 -0
- package/dist/core/sessions/session-enforcement.js +139 -0
- package/dist/core/sessions/session-enforcement.js.map +1 -0
- package/dist/core/sessions/session-migration.d.ts +31 -0
- package/dist/core/sessions/session-migration.d.ts.map +1 -0
- package/dist/core/sessions/session-migration.js +122 -0
- package/dist/core/sessions/session-migration.js.map +1 -0
- package/dist/core/sessions/statusline-setup.d.ts +24 -0
- package/dist/core/sessions/statusline-setup.d.ts.map +1 -0
- package/dist/core/sessions/statusline-setup.js +82 -0
- package/dist/core/sessions/statusline-setup.js.map +1 -0
- package/dist/core/skills/agents/config.d.ts +39 -0
- package/dist/core/skills/agents/config.d.ts.map +1 -0
- package/dist/core/skills/agents/config.js +94 -0
- package/dist/core/skills/agents/config.js.map +1 -0
- package/dist/core/skills/agents/install.d.ts +33 -0
- package/dist/core/skills/agents/install.d.ts.map +1 -0
- package/dist/core/skills/agents/install.js +105 -0
- package/dist/core/skills/agents/install.js.map +1 -0
- package/dist/core/skills/agents/registry.d.ts +56 -0
- package/dist/core/skills/agents/registry.d.ts.map +1 -0
- package/dist/core/skills/agents/registry.js +161 -0
- package/dist/core/skills/agents/registry.js.map +1 -0
- package/dist/core/skills/discovery.d.ts +102 -0
- package/dist/core/skills/discovery.d.ts.map +1 -0
- package/dist/core/skills/discovery.js +331 -0
- package/dist/core/skills/discovery.js.map +1 -0
- package/dist/core/skills/dispatch.d.ts +67 -0
- package/dist/core/skills/dispatch.d.ts.map +1 -0
- package/dist/core/skills/dispatch.js +327 -0
- package/dist/core/skills/dispatch.js.map +1 -0
- package/dist/core/skills/index.d.ts +39 -0
- package/dist/core/skills/index.d.ts.map +1 -0
- package/dist/core/skills/index.js +44 -0
- package/dist/core/skills/index.js.map +1 -0
- package/dist/core/skills/injection/subagent.d.ts +47 -0
- package/dist/core/skills/injection/subagent.d.ts.map +1 -0
- package/dist/core/skills/injection/subagent.js +143 -0
- package/dist/core/skills/injection/subagent.js.map +1 -0
- package/dist/core/skills/injection/token.d.ts +121 -0
- package/dist/core/skills/injection/token.d.ts.map +1 -0
- package/dist/core/skills/injection/token.js +255 -0
- package/dist/core/skills/injection/token.js.map +1 -0
- package/dist/core/skills/install.d.ts +42 -0
- package/dist/core/skills/install.d.ts.map +1 -0
- package/dist/core/skills/install.js +129 -0
- package/dist/core/skills/install.js.map +1 -0
- package/dist/core/skills/manifests/contribution.d.ts +74 -0
- package/dist/core/skills/manifests/contribution.d.ts.map +1 -0
- package/dist/core/skills/manifests/contribution.js +180 -0
- package/dist/core/skills/manifests/contribution.js.map +1 -0
- package/dist/core/skills/manifests/research.d.ts +73 -0
- package/dist/core/skills/manifests/research.d.ts.map +1 -0
- package/dist/core/skills/manifests/research.js +264 -0
- package/dist/core/skills/manifests/research.js.map +1 -0
- package/dist/core/skills/manifests/resolver.d.ts +40 -0
- package/dist/core/skills/manifests/resolver.d.ts.map +1 -0
- package/dist/core/skills/manifests/resolver.js +146 -0
- package/dist/core/skills/manifests/resolver.js.map +1 -0
- package/dist/core/skills/marketplace.d.ts +45 -0
- package/dist/core/skills/marketplace.d.ts.map +1 -0
- package/dist/core/skills/marketplace.js +90 -0
- package/dist/core/skills/marketplace.js.map +1 -0
- package/dist/core/skills/orchestrator/spawn.d.ts +66 -0
- package/dist/core/skills/orchestrator/spawn.d.ts.map +1 -0
- package/dist/core/skills/orchestrator/spawn.js +186 -0
- package/dist/core/skills/orchestrator/spawn.js.map +1 -0
- package/dist/core/skills/orchestrator/startup.d.ts +89 -0
- package/dist/core/skills/orchestrator/startup.d.ts.map +1 -0
- package/dist/core/skills/orchestrator/startup.js +434 -0
- package/dist/core/skills/orchestrator/startup.js.map +1 -0
- package/dist/core/skills/orchestrator/validator.d.ts +40 -0
- package/dist/core/skills/orchestrator/validator.d.ts.map +1 -0
- package/dist/core/skills/orchestrator/validator.js +297 -0
- package/dist/core/skills/orchestrator/validator.js.map +1 -0
- package/dist/core/skills/skill-paths.d.ts +79 -0
- package/dist/core/skills/skill-paths.d.ts.map +1 -0
- package/dist/core/skills/skill-paths.js +220 -0
- package/dist/core/skills/skill-paths.js.map +1 -0
- package/dist/core/skills/test-utility.d.ts +39 -0
- package/dist/core/skills/test-utility.d.ts.map +1 -0
- package/dist/core/skills/test-utility.js +55 -0
- package/dist/core/skills/test-utility.js.map +1 -0
- package/dist/core/skills/types.d.ts +290 -0
- package/dist/core/skills/types.d.ts.map +1 -0
- package/dist/core/skills/types.js +86 -0
- package/dist/core/skills/types.js.map +1 -0
- package/dist/core/skills/validation.d.ts +46 -0
- package/dist/core/skills/validation.d.ts.map +1 -0
- package/dist/core/skills/validation.js +176 -0
- package/dist/core/skills/validation.js.map +1 -0
- package/dist/core/skills/version.d.ts +87 -0
- package/dist/core/skills/version.d.ts.map +1 -0
- package/dist/core/skills/version.js +241 -0
- package/dist/core/skills/version.js.map +1 -0
- package/dist/core/stats/index.d.ts +30 -0
- package/dist/core/stats/index.d.ts.map +1 -0
- package/dist/core/stats/index.js +152 -0
- package/dist/core/stats/index.js.map +1 -0
- package/dist/core/task-work/index.d.ts +66 -0
- package/dist/core/task-work/index.d.ts.map +1 -0
- package/dist/core/task-work/index.js +148 -0
- package/dist/core/task-work/index.js.map +1 -0
- package/dist/core/tasks/add.d.ts +125 -0
- package/dist/core/tasks/add.d.ts.map +1 -0
- package/dist/core/tasks/add.js +489 -0
- package/dist/core/tasks/add.js.map +1 -0
- package/dist/core/tasks/analyze.d.ts +49 -0
- package/dist/core/tasks/analyze.d.ts.map +1 -0
- package/dist/core/tasks/analyze.js +94 -0
- package/dist/core/tasks/analyze.js.map +1 -0
- package/dist/core/tasks/archive.d.ts +31 -0
- package/dist/core/tasks/archive.d.ts.map +1 -0
- package/dist/core/tasks/archive.js +126 -0
- package/dist/core/tasks/archive.js.map +1 -0
- package/dist/core/tasks/cancel-ops.d.ts +42 -0
- package/dist/core/tasks/cancel-ops.d.ts.map +1 -0
- package/dist/core/tasks/cancel-ops.js +83 -0
- package/dist/core/tasks/cancel-ops.js.map +1 -0
- package/dist/core/tasks/complete.d.ts +25 -0
- package/dist/core/tasks/complete.d.ts.map +1 -0
- package/dist/core/tasks/complete.js +109 -0
- package/dist/core/tasks/complete.js.map +1 -0
- package/dist/core/tasks/crossref-extract.d.ts +39 -0
- package/dist/core/tasks/crossref-extract.d.ts.map +1 -0
- package/dist/core/tasks/crossref-extract.js +75 -0
- package/dist/core/tasks/crossref-extract.js.map +1 -0
- package/dist/core/tasks/delete-preview.d.ts +69 -0
- package/dist/core/tasks/delete-preview.d.ts.map +1 -0
- package/dist/core/tasks/delete-preview.js +192 -0
- package/dist/core/tasks/delete-preview.js.map +1 -0
- package/dist/core/tasks/delete.d.ts +24 -0
- package/dist/core/tasks/delete.d.ts.map +1 -0
- package/dist/core/tasks/delete.js +130 -0
- package/dist/core/tasks/delete.js.map +1 -0
- package/dist/core/tasks/deletion-strategy.d.ts +46 -0
- package/dist/core/tasks/deletion-strategy.d.ts.map +1 -0
- package/dist/core/tasks/deletion-strategy.js +200 -0
- package/dist/core/tasks/deletion-strategy.js.map +1 -0
- package/dist/core/tasks/dependency-check.d.ts +70 -0
- package/dist/core/tasks/dependency-check.d.ts.map +1 -0
- package/dist/core/tasks/dependency-check.js +226 -0
- package/dist/core/tasks/dependency-check.js.map +1 -0
- package/dist/core/tasks/find.d.ts +48 -0
- package/dist/core/tasks/find.d.ts.map +1 -0
- package/dist/core/tasks/find.js +155 -0
- package/dist/core/tasks/find.js.map +1 -0
- package/dist/core/tasks/graph-cache.d.ts +70 -0
- package/dist/core/tasks/graph-cache.d.ts.map +1 -0
- package/dist/core/tasks/graph-cache.js +127 -0
- package/dist/core/tasks/graph-cache.js.map +1 -0
- package/dist/core/tasks/graph-ops.d.ts +36 -0
- package/dist/core/tasks/graph-ops.d.ts.map +1 -0
- package/dist/core/tasks/graph-ops.js +173 -0
- package/dist/core/tasks/graph-ops.js.map +1 -0
- package/dist/core/tasks/graph-rag.d.ts +49 -0
- package/dist/core/tasks/graph-rag.d.ts.map +1 -0
- package/dist/core/tasks/graph-rag.js +253 -0
- package/dist/core/tasks/graph-rag.js.map +1 -0
- package/dist/core/tasks/hierarchy.d.ts +82 -0
- package/dist/core/tasks/hierarchy.d.ts.map +1 -0
- package/dist/core/tasks/hierarchy.js +188 -0
- package/dist/core/tasks/hierarchy.js.map +1 -0
- package/dist/core/tasks/index.d.ts +15 -0
- package/dist/core/tasks/index.d.ts.map +1 -0
- package/dist/core/tasks/index.js +15 -0
- package/dist/core/tasks/index.js.map +1 -0
- package/dist/core/tasks/labels.d.ts +19 -0
- package/dist/core/tasks/labels.d.ts.map +1 -0
- package/dist/core/tasks/labels.js +56 -0
- package/dist/core/tasks/labels.js.map +1 -0
- package/dist/core/tasks/list.d.ts +36 -0
- package/dist/core/tasks/list.d.ts.map +1 -0
- package/dist/core/tasks/list.js +72 -0
- package/dist/core/tasks/list.js.map +1 -0
- package/dist/core/tasks/phase-tracking.d.ts +61 -0
- package/dist/core/tasks/phase-tracking.d.ts.map +1 -0
- package/dist/core/tasks/phase-tracking.js +133 -0
- package/dist/core/tasks/phase-tracking.js.map +1 -0
- package/dist/core/tasks/relates.d.ts +18 -0
- package/dist/core/tasks/relates.d.ts.map +1 -0
- package/dist/core/tasks/relates.js +115 -0
- package/dist/core/tasks/relates.js.map +1 -0
- package/dist/core/tasks/show.d.ts +25 -0
- package/dist/core/tasks/show.d.ts.map +1 -0
- package/dist/core/tasks/show.js +79 -0
- package/dist/core/tasks/show.js.map +1 -0
- package/dist/core/tasks/size-weighting.d.ts +38 -0
- package/dist/core/tasks/size-weighting.d.ts.map +1 -0
- package/dist/core/tasks/size-weighting.js +86 -0
- package/dist/core/tasks/size-weighting.js.map +1 -0
- package/dist/core/tasks/staleness.d.ts +56 -0
- package/dist/core/tasks/staleness.d.ts.map +1 -0
- package/dist/core/tasks/staleness.js +91 -0
- package/dist/core/tasks/staleness.js.map +1 -0
- package/dist/core/tasks/todowrite-integration.d.ts +46 -0
- package/dist/core/tasks/todowrite-integration.d.ts.map +1 -0
- package/dist/core/tasks/todowrite-integration.js +172 -0
- package/dist/core/tasks/todowrite-integration.js.map +1 -0
- package/dist/core/tasks/update.d.ts +41 -0
- package/dist/core/tasks/update.d.ts.map +1 -0
- package/dist/core/tasks/update.js +178 -0
- package/dist/core/tasks/update.js.map +1 -0
- package/dist/core/ui/aliases.d.ts +43 -0
- package/dist/core/ui/aliases.d.ts.map +1 -0
- package/dist/core/ui/aliases.js +150 -0
- package/dist/core/ui/aliases.js.map +1 -0
- package/dist/core/ui/changelog.d.ts +58 -0
- package/dist/core/ui/changelog.d.ts.map +1 -0
- package/dist/core/ui/changelog.js +195 -0
- package/dist/core/ui/changelog.js.map +1 -0
- package/dist/core/ui/command-registry.d.ts +44 -0
- package/dist/core/ui/command-registry.d.ts.map +1 -0
- package/dist/core/ui/command-registry.js +156 -0
- package/dist/core/ui/command-registry.js.map +1 -0
- package/dist/core/ui/flags.d.ts +34 -0
- package/dist/core/ui/flags.d.ts.map +1 -0
- package/dist/core/ui/flags.js +94 -0
- package/dist/core/ui/flags.js.map +1 -0
- package/dist/core/ui/index.d.ts +18 -0
- package/dist/core/ui/index.d.ts.map +1 -0
- package/dist/core/ui/index.js +28 -0
- package/dist/core/ui/index.js.map +1 -0
- package/dist/core/ui/injection-legacy.d.ts +26 -0
- package/dist/core/ui/injection-legacy.d.ts.map +1 -0
- package/dist/core/ui/injection-legacy.js +42 -0
- package/dist/core/ui/injection-legacy.js.map +1 -0
- package/dist/core/ui/injection-registry.d.ts +56 -0
- package/dist/core/ui/injection-registry.d.ts.map +1 -0
- package/dist/core/ui/injection-registry.js +68 -0
- package/dist/core/ui/injection-registry.js.map +1 -0
- package/dist/core/ui/injection.d.ts +51 -0
- package/dist/core/ui/injection.d.ts.map +1 -0
- package/dist/core/ui/injection.js +125 -0
- package/dist/core/ui/injection.js.map +1 -0
- package/dist/core/ui/mcp-config.d.ts +40 -0
- package/dist/core/ui/mcp-config.d.ts.map +1 -0
- package/dist/core/ui/mcp-config.js +173 -0
- package/dist/core/ui/mcp-config.js.map +1 -0
- package/dist/core/ui/version-check.d.ts +31 -0
- package/dist/core/ui/version-check.d.ts.map +1 -0
- package/dist/core/ui/version-check.js +121 -0
- package/dist/core/ui/version-check.js.map +1 -0
- package/dist/core/upgrade.d.ts +59 -0
- package/dist/core/upgrade.d.ts.map +1 -0
- package/dist/core/upgrade.js +649 -0
- package/dist/core/upgrade.js.map +1 -0
- package/dist/core/validation/compliance.d.ts +94 -0
- package/dist/core/validation/compliance.d.ts.map +1 -0
- package/dist/core/validation/compliance.js +157 -0
- package/dist/core/validation/compliance.js.map +1 -0
- package/dist/core/validation/docs-sync.d.ts +66 -0
- package/dist/core/validation/docs-sync.d.ts.map +1 -0
- package/dist/core/validation/docs-sync.js +204 -0
- package/dist/core/validation/docs-sync.js.map +1 -0
- package/dist/core/validation/doctor/checks.d.ts +61 -0
- package/dist/core/validation/doctor/checks.d.ts.map +1 -0
- package/dist/core/validation/doctor/checks.js +457 -0
- package/dist/core/validation/doctor/checks.js.map +1 -0
- package/dist/core/validation/doctor/index.d.ts +9 -0
- package/dist/core/validation/doctor/index.d.ts.map +1 -0
- package/dist/core/validation/doctor/index.js +9 -0
- package/dist/core/validation/doctor/index.js.map +1 -0
- package/dist/core/validation/doctor/project-cache.d.ts +79 -0
- package/dist/core/validation/doctor/project-cache.d.ts.map +1 -0
- package/dist/core/validation/doctor/project-cache.js +164 -0
- package/dist/core/validation/doctor/project-cache.js.map +1 -0
- package/dist/core/validation/doctor/utils.d.ts +68 -0
- package/dist/core/validation/doctor/utils.d.ts.map +1 -0
- package/dist/core/validation/doctor/utils.js +162 -0
- package/dist/core/validation/doctor/utils.js.map +1 -0
- package/dist/core/validation/engine.d.ts +172 -0
- package/dist/core/validation/engine.d.ts.map +1 -0
- package/dist/core/validation/engine.js +791 -0
- package/dist/core/validation/engine.js.map +1 -0
- package/dist/core/validation/gap-check.d.ts +74 -0
- package/dist/core/validation/gap-check.d.ts.map +1 -0
- package/dist/core/validation/gap-check.js +175 -0
- package/dist/core/validation/gap-check.js.map +1 -0
- package/dist/core/validation/index.d.ts +17 -0
- package/dist/core/validation/index.d.ts.map +1 -0
- package/dist/core/validation/index.js +25 -0
- package/dist/core/validation/index.js.map +1 -0
- package/dist/core/validation/manifest.d.ts +81 -0
- package/dist/core/validation/manifest.d.ts.map +1 -0
- package/dist/core/validation/manifest.js +225 -0
- package/dist/core/validation/manifest.js.map +1 -0
- package/dist/core/validation/protocol-common.d.ts +77 -0
- package/dist/core/validation/protocol-common.d.ts.map +1 -0
- package/dist/core/validation/protocol-common.js +240 -0
- package/dist/core/validation/protocol-common.js.map +1 -0
- package/dist/core/validation/protocols/consensus.d.ts +28 -0
- package/dist/core/validation/protocols/consensus.d.ts.map +1 -0
- package/dist/core/validation/protocols/consensus.js +70 -0
- package/dist/core/validation/protocols/consensus.js.map +1 -0
- package/dist/core/validation/protocols/contribution.d.ts +26 -0
- package/dist/core/validation/protocols/contribution.d.ts.map +1 -0
- package/dist/core/validation/protocols/contribution.js +58 -0
- package/dist/core/validation/protocols/contribution.js.map +1 -0
- package/dist/core/validation/protocols/decomposition.d.ts +28 -0
- package/dist/core/validation/protocols/decomposition.d.ts.map +1 -0
- package/dist/core/validation/protocols/decomposition.js +58 -0
- package/dist/core/validation/protocols/decomposition.js.map +1 -0
- package/dist/core/validation/protocols/implementation.d.ts +26 -0
- package/dist/core/validation/protocols/implementation.d.ts.map +1 -0
- package/dist/core/validation/protocols/implementation.js +58 -0
- package/dist/core/validation/protocols/implementation.js.map +1 -0
- package/dist/core/validation/protocols/specification.d.ts +28 -0
- package/dist/core/validation/protocols/specification.d.ts.map +1 -0
- package/dist/core/validation/protocols/specification.js +83 -0
- package/dist/core/validation/protocols/specification.js.map +1 -0
- package/dist/core/validation/verification.d.ts +153 -0
- package/dist/core/validation/verification.d.ts.map +1 -0
- package/dist/core/validation/verification.js +311 -0
- package/dist/core/validation/verification.js.map +1 -0
- package/dist/dispatch/dispatcher.d.ts +23 -0
- package/dist/dispatch/dispatcher.d.ts.map +1 -0
- package/dist/dispatch/dispatcher.js +90 -0
- package/dist/dispatch/dispatcher.js.map +1 -0
- package/dist/dispatch/domains/_meta.d.ts +23 -0
- package/dist/dispatch/domains/_meta.d.ts.map +1 -0
- package/dist/dispatch/domains/_meta.js +25 -0
- package/dist/dispatch/domains/_meta.js.map +1 -0
- package/dist/dispatch/domains/admin.d.ts +29 -0
- package/dist/dispatch/domains/admin.d.ts.map +1 -0
- package/dist/dispatch/domains/admin.js +200 -0
- package/dist/dispatch/domains/admin.js.map +1 -0
- package/dist/dispatch/domains/check.d.ts +28 -0
- package/dist/dispatch/domains/check.d.ts.map +1 -0
- package/dist/dispatch/domains/check.js +170 -0
- package/dist/dispatch/domains/check.js.map +1 -0
- package/dist/dispatch/domains/index.d.ts +26 -0
- package/dist/dispatch/domains/index.d.ts.map +1 -0
- package/dist/dispatch/domains/index.js +36 -0
- package/dist/dispatch/domains/index.js.map +1 -0
- package/dist/dispatch/domains/memory.d.ts +27 -0
- package/dist/dispatch/domains/memory.d.ts.map +1 -0
- package/dist/dispatch/domains/memory.js +169 -0
- package/dist/dispatch/domains/memory.js.map +1 -0
- package/dist/dispatch/domains/nexus.d.ts +18 -0
- package/dist/dispatch/domains/nexus.d.ts.map +1 -0
- package/dist/dispatch/domains/nexus.js +34 -0
- package/dist/dispatch/domains/nexus.js.map +1 -0
- package/dist/dispatch/domains/orchestrate.d.ts +24 -0
- package/dist/dispatch/domains/orchestrate.d.ts.map +1 -0
- package/dist/dispatch/domains/orchestrate.js +199 -0
- package/dist/dispatch/domains/orchestrate.js.map +1 -0
- package/dist/dispatch/domains/pipeline.d.ts +31 -0
- package/dist/dispatch/domains/pipeline.d.ts.map +1 -0
- package/dist/dispatch/domains/pipeline.js +284 -0
- package/dist/dispatch/domains/pipeline.js.map +1 -0
- package/dist/dispatch/domains/session.d.ts +27 -0
- package/dist/dispatch/domains/session.d.ts.map +1 -0
- package/dist/dispatch/domains/session.js +180 -0
- package/dist/dispatch/domains/session.js.map +1 -0
- package/dist/dispatch/domains/tools.d.ts +39 -0
- package/dist/dispatch/domains/tools.d.ts.map +1 -0
- package/dist/dispatch/domains/tools.js +314 -0
- package/dist/dispatch/domains/tools.js.map +1 -0
- package/dist/dispatch/index.d.ts +20 -0
- package/dist/dispatch/index.d.ts.map +1 -0
- package/dist/dispatch/index.js +19 -0
- package/dist/dispatch/index.js.map +1 -0
- package/dist/dispatch/lib/meta.d.ts +24 -0
- package/dist/dispatch/lib/meta.d.ts.map +1 -0
- package/dist/dispatch/lib/meta.js +34 -0
- package/dist/dispatch/lib/meta.js.map +1 -0
- package/dist/dispatch/middleware/audit.d.ts +123 -0
- package/dist/dispatch/middleware/audit.d.ts.map +1 -0
- package/dist/dispatch/middleware/audit.js +345 -0
- package/dist/dispatch/middleware/audit.js.map +1 -0
- package/dist/dispatch/middleware/pipeline.d.ts +20 -0
- package/dist/dispatch/middleware/pipeline.d.ts.map +1 -0
- package/dist/dispatch/middleware/pipeline.js +47 -0
- package/dist/dispatch/middleware/pipeline.js.map +1 -0
- package/dist/dispatch/middleware/protocol-enforcement.d.ts +6 -0
- package/dist/dispatch/middleware/protocol-enforcement.d.ts.map +1 -0
- package/dist/dispatch/middleware/protocol-enforcement.js +12 -0
- package/dist/dispatch/middleware/protocol-enforcement.js.map +1 -0
- package/dist/dispatch/middleware/rate-limiter.d.ts +30 -0
- package/dist/dispatch/middleware/rate-limiter.d.ts.map +1 -0
- package/dist/dispatch/middleware/rate-limiter.js +101 -0
- package/dist/dispatch/middleware/rate-limiter.js.map +1 -0
- package/dist/dispatch/middleware/sanitizer.d.ts +10 -0
- package/dist/dispatch/middleware/sanitizer.d.ts.map +1 -0
- package/dist/dispatch/middleware/sanitizer.js +39 -0
- package/dist/dispatch/middleware/sanitizer.js.map +1 -0
- package/dist/dispatch/middleware/verification-gates.d.ts +3 -0
- package/dist/dispatch/middleware/verification-gates.d.ts.map +1 -0
- package/dist/dispatch/middleware/verification-gates.js +40 -0
- package/dist/dispatch/middleware/verification-gates.js.map +1 -0
- package/dist/dispatch/registry.d.ts +89 -0
- package/dist/dispatch/registry.d.ts.map +1 -0
- package/dist/dispatch/registry.js +1591 -0
- package/dist/dispatch/registry.js.map +1 -0
- package/dist/dispatch/types.d.ts +137 -0
- package/dist/dispatch/types.d.ts.map +1 -0
- package/dist/dispatch/types.js +24 -0
- package/dist/dispatch/types.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/domains/index.d.ts +19 -0
- package/dist/mcp/domains/index.d.ts.map +1 -0
- package/dist/mcp/domains/index.js +19 -0
- package/dist/mcp/domains/index.js.map +1 -0
- package/dist/mcp/domains/issues.d.ts +69 -0
- package/dist/mcp/domains/issues.d.ts.map +1 -0
- package/dist/mcp/domains/issues.js +260 -0
- package/dist/mcp/domains/issues.js.map +1 -0
- package/dist/mcp/domains/lifecycle.d.ts +154 -0
- package/dist/mcp/domains/lifecycle.d.ts.map +1 -0
- package/dist/mcp/domains/lifecycle.js +508 -0
- package/dist/mcp/domains/lifecycle.js.map +1 -0
- package/dist/mcp/domains/orchestrate.d.ts +140 -0
- package/dist/mcp/domains/orchestrate.d.ts.map +1 -0
- package/dist/mcp/domains/orchestrate.js +542 -0
- package/dist/mcp/domains/orchestrate.js.map +1 -0
- package/dist/mcp/domains/providers.d.ts +28 -0
- package/dist/mcp/domains/providers.d.ts.map +1 -0
- package/dist/mcp/domains/providers.js +108 -0
- package/dist/mcp/domains/providers.js.map +1 -0
- package/dist/mcp/domains/release.d.ts +121 -0
- package/dist/mcp/domains/release.d.ts.map +1 -0
- package/dist/mcp/domains/release.js +486 -0
- package/dist/mcp/domains/release.js.map +1 -0
- package/dist/mcp/domains/research.d.ts +158 -0
- package/dist/mcp/domains/research.d.ts.map +1 -0
- package/dist/mcp/domains/research.js +698 -0
- package/dist/mcp/domains/research.js.map +1 -0
- package/dist/mcp/domains/session.d.ts +136 -0
- package/dist/mcp/domains/session.d.ts.map +1 -0
- package/dist/mcp/domains/session.js +583 -0
- package/dist/mcp/domains/session.js.map +1 -0
- package/dist/mcp/domains/skills.d.ts +129 -0
- package/dist/mcp/domains/skills.d.ts.map +1 -0
- package/dist/mcp/domains/skills.js +691 -0
- package/dist/mcp/domains/skills.js.map +1 -0
- package/dist/mcp/domains/system.d.ts +166 -0
- package/dist/mcp/domains/system.d.ts.map +1 -0
- package/dist/mcp/domains/system.js +1000 -0
- package/dist/mcp/domains/system.js.map +1 -0
- package/dist/mcp/domains/tasks.d.ts +241 -0
- package/dist/mcp/domains/tasks.d.ts.map +1 -0
- package/dist/mcp/domains/tasks.js +1152 -0
- package/dist/mcp/domains/tasks.js.map +1 -0
- package/dist/mcp/domains/validate.d.ts +163 -0
- package/dist/mcp/domains/validate.d.ts.map +1 -0
- package/dist/mcp/domains/validate.js +787 -0
- package/dist/mcp/domains/validate.js.map +1 -0
- package/dist/mcp/engine/caamp-adapter.d.ts +12 -0
- package/dist/mcp/engine/caamp-adapter.d.ts.map +1 -0
- package/dist/mcp/engine/caamp-adapter.js +23 -0
- package/dist/mcp/engine/caamp-adapter.js.map +1 -0
- package/dist/mcp/engine/caamp-verify.d.ts +2 -0
- package/dist/mcp/engine/caamp-verify.d.ts.map +1 -0
- package/dist/mcp/engine/caamp-verify.js +15 -0
- package/dist/mcp/engine/caamp-verify.js.map +1 -0
- package/dist/mcp/engine/capability-matrix.d.ts +67 -0
- package/dist/mcp/engine/capability-matrix.d.ts.map +1 -0
- package/dist/mcp/engine/capability-matrix.js +243 -0
- package/dist/mcp/engine/capability-matrix.js.map +1 -0
- package/dist/mcp/engine/config-engine.d.ts +29 -0
- package/dist/mcp/engine/config-engine.d.ts.map +1 -0
- package/dist/mcp/engine/config-engine.js +110 -0
- package/dist/mcp/engine/config-engine.js.map +1 -0
- package/dist/mcp/engine/id-generator.d.ts +34 -0
- package/dist/mcp/engine/id-generator.d.ts.map +1 -0
- package/dist/mcp/engine/id-generator.js +91 -0
- package/dist/mcp/engine/id-generator.js.map +1 -0
- package/dist/mcp/engine/index.d.ts +25 -0
- package/dist/mcp/engine/index.d.ts.map +1 -0
- package/dist/mcp/engine/index.js +42 -0
- package/dist/mcp/engine/index.js.map +1 -0
- package/dist/mcp/engine/init-engine.d.ts +52 -0
- package/dist/mcp/engine/init-engine.d.ts.map +1 -0
- package/dist/mcp/engine/init-engine.js +222 -0
- package/dist/mcp/engine/init-engine.js.map +1 -0
- package/dist/mcp/engine/lifecycle-engine.d.ts +119 -0
- package/dist/mcp/engine/lifecycle-engine.d.ts.map +1 -0
- package/dist/mcp/engine/lifecycle-engine.js +564 -0
- package/dist/mcp/engine/lifecycle-engine.js.map +1 -0
- package/dist/mcp/engine/orchestrate-engine.d.ts +127 -0
- package/dist/mcp/engine/orchestrate-engine.d.ts.map +1 -0
- package/dist/mcp/engine/orchestrate-engine.js +1233 -0
- package/dist/mcp/engine/orchestrate-engine.js.map +1 -0
- package/dist/mcp/engine/release-engine.d.ts +71 -0
- package/dist/mcp/engine/release-engine.d.ts.map +1 -0
- package/dist/mcp/engine/release-engine.js +515 -0
- package/dist/mcp/engine/release-engine.js.map +1 -0
- package/dist/mcp/engine/research-engine.d.ts +182 -0
- package/dist/mcp/engine/research-engine.d.ts.map +1 -0
- package/dist/mcp/engine/research-engine.js +747 -0
- package/dist/mcp/engine/research-engine.js.map +1 -0
- package/dist/mcp/engine/schema-validator.d.ts +47 -0
- package/dist/mcp/engine/schema-validator.d.ts.map +1 -0
- package/dist/mcp/engine/schema-validator.js +219 -0
- package/dist/mcp/engine/schema-validator.js.map +1 -0
- package/dist/mcp/engine/session-engine.d.ts +340 -0
- package/dist/mcp/engine/session-engine.d.ts.map +1 -0
- package/dist/mcp/engine/session-engine.js +1355 -0
- package/dist/mcp/engine/session-engine.js.map +1 -0
- package/dist/mcp/engine/store.d.ts +86 -0
- package/dist/mcp/engine/store.d.ts.map +1 -0
- package/dist/mcp/engine/store.js +393 -0
- package/dist/mcp/engine/store.js.map +1 -0
- package/dist/mcp/engine/system-engine.d.ts +458 -0
- package/dist/mcp/engine/system-engine.d.ts.map +1 -0
- package/dist/mcp/engine/system-engine.js +1568 -0
- package/dist/mcp/engine/system-engine.js.map +1 -0
- package/dist/mcp/engine/task-engine.d.ts +501 -0
- package/dist/mcp/engine/task-engine.d.ts.map +1 -0
- package/dist/mcp/engine/task-engine.js +1840 -0
- package/dist/mcp/engine/task-engine.js.map +1 -0
- package/dist/mcp/engine/template-parser.d.ts +83 -0
- package/dist/mcp/engine/template-parser.d.ts.map +1 -0
- package/dist/mcp/engine/template-parser.js +255 -0
- package/dist/mcp/engine/template-parser.js.map +1 -0
- package/dist/mcp/engine/validate-engine.d.ts +120 -0
- package/dist/mcp/engine/validate-engine.d.ts.map +1 -0
- package/dist/mcp/engine/validate-engine.js +828 -0
- package/dist/mcp/engine/validate-engine.js.map +1 -0
- package/dist/mcp/engine/validation-rules.d.ts +85 -0
- package/dist/mcp/engine/validation-rules.d.ts.map +1 -0
- package/dist/mcp/engine/validation-rules.js +220 -0
- package/dist/mcp/engine/validation-rules.js.map +1 -0
- package/dist/mcp/gateways/mutate.d.ts +100 -0
- package/dist/mcp/gateways/mutate.d.ts.map +1 -0
- package/dist/mcp/gateways/mutate.js +1070 -0
- package/dist/mcp/gateways/mutate.js.map +1 -0
- package/dist/mcp/gateways/query.d.ts +91 -0
- package/dist/mcp/gateways/query.d.ts.map +1 -0
- package/dist/mcp/gateways/query.js +278 -0
- package/dist/mcp/gateways/query.js.map +1 -0
- package/dist/mcp/index.d.ts +20 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +20993 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/mcp/lib/audit.d.ts +118 -0
- package/dist/mcp/lib/audit.d.ts.map +1 -0
- package/dist/mcp/lib/audit.js +310 -0
- package/dist/mcp/lib/audit.js.map +1 -0
- package/dist/mcp/lib/background-jobs.d.ts +86 -0
- package/dist/mcp/lib/background-jobs.d.ts.map +1 -0
- package/dist/mcp/lib/background-jobs.js +183 -0
- package/dist/mcp/lib/background-jobs.js.map +1 -0
- package/dist/mcp/lib/budget.d.ts +35 -0
- package/dist/mcp/lib/budget.d.ts.map +1 -0
- package/dist/mcp/lib/budget.js +101 -0
- package/dist/mcp/lib/budget.js.map +1 -0
- package/dist/mcp/lib/cache.d.ts +78 -0
- package/dist/mcp/lib/cache.d.ts.map +1 -0
- package/dist/mcp/lib/cache.js +204 -0
- package/dist/mcp/lib/cache.js.map +1 -0
- package/dist/mcp/lib/command-builder.d.ts +52 -0
- package/dist/mcp/lib/command-builder.d.ts.map +1 -0
- package/dist/mcp/lib/command-builder.js +269 -0
- package/dist/mcp/lib/command-builder.js.map +1 -0
- package/dist/mcp/lib/config.d.ts +42 -0
- package/dist/mcp/lib/config.d.ts.map +1 -0
- package/dist/mcp/lib/config.js +248 -0
- package/dist/mcp/lib/config.js.map +1 -0
- package/dist/mcp/lib/defaults.d.ts +115 -0
- package/dist/mcp/lib/defaults.d.ts.map +1 -0
- package/dist/mcp/lib/defaults.js +61 -0
- package/dist/mcp/lib/defaults.js.map +1 -0
- package/dist/mcp/lib/error-handler.d.ts +101 -0
- package/dist/mcp/lib/error-handler.d.ts.map +1 -0
- package/dist/mcp/lib/error-handler.js +277 -0
- package/dist/mcp/lib/error-handler.js.map +1 -0
- package/dist/mcp/lib/executor.d.ts +122 -0
- package/dist/mcp/lib/executor.d.ts.map +1 -0
- package/dist/mcp/lib/executor.js +391 -0
- package/dist/mcp/lib/executor.js.map +1 -0
- package/dist/mcp/lib/exit-codes.d.ts +192 -0
- package/dist/mcp/lib/exit-codes.d.ts.map +1 -0
- package/dist/mcp/lib/exit-codes.js +1029 -0
- package/dist/mcp/lib/exit-codes.js.map +1 -0
- package/dist/mcp/lib/formatter.d.ts +196 -0
- package/dist/mcp/lib/formatter.d.ts.map +1 -0
- package/dist/mcp/lib/formatter.js +260 -0
- package/dist/mcp/lib/formatter.js.map +1 -0
- package/dist/mcp/lib/gate-validators.d.ts +104 -0
- package/dist/mcp/lib/gate-validators.d.ts.map +1 -0
- package/dist/mcp/lib/gate-validators.js +709 -0
- package/dist/mcp/lib/gate-validators.js.map +1 -0
- package/dist/mcp/lib/gateway-meta.d.ts +37 -0
- package/dist/mcp/lib/gateway-meta.d.ts.map +1 -0
- package/dist/mcp/lib/gateway-meta.js +50 -0
- package/dist/mcp/lib/gateway-meta.js.map +1 -0
- package/dist/mcp/lib/manifest-parser.d.ts +61 -0
- package/dist/mcp/lib/manifest-parser.d.ts.map +1 -0
- package/dist/mcp/lib/manifest-parser.js +338 -0
- package/dist/mcp/lib/manifest-parser.js.map +1 -0
- package/dist/mcp/lib/manifest.d.ts +177 -0
- package/dist/mcp/lib/manifest.d.ts.map +1 -0
- package/dist/mcp/lib/manifest.js +301 -0
- package/dist/mcp/lib/manifest.js.map +1 -0
- package/dist/mcp/lib/mode-detector.d.ts +71 -0
- package/dist/mcp/lib/mode-detector.d.ts.map +1 -0
- package/dist/mcp/lib/mode-detector.js +184 -0
- package/dist/mcp/lib/mode-detector.js.map +1 -0
- package/dist/mcp/lib/protocol-enforcement.d.ts +105 -0
- package/dist/mcp/lib/protocol-enforcement.d.ts.map +1 -0
- package/dist/mcp/lib/protocol-enforcement.js +331 -0
- package/dist/mcp/lib/protocol-enforcement.js.map +1 -0
- package/dist/mcp/lib/protocol-rules.d.ts +55 -0
- package/dist/mcp/lib/protocol-rules.d.ts.map +1 -0
- package/dist/mcp/lib/protocol-rules.js +760 -0
- package/dist/mcp/lib/protocol-rules.js.map +1 -0
- package/dist/mcp/lib/rate-limiter.d.ts +110 -0
- package/dist/mcp/lib/rate-limiter.d.ts.map +1 -0
- package/dist/mcp/lib/rate-limiter.js +208 -0
- package/dist/mcp/lib/rate-limiter.js.map +1 -0
- package/dist/mcp/lib/router.d.ts +136 -0
- package/dist/mcp/lib/router.d.ts.map +1 -0
- package/dist/mcp/lib/router.js +298 -0
- package/dist/mcp/lib/router.js.map +1 -0
- package/dist/mcp/lib/schema.d.ts +55 -0
- package/dist/mcp/lib/schema.d.ts.map +1 -0
- package/dist/mcp/lib/schema.js +70 -0
- package/dist/mcp/lib/schema.js.map +1 -0
- package/dist/mcp/lib/security.d.ts +158 -0
- package/dist/mcp/lib/security.d.ts.map +1 -0
- package/dist/mcp/lib/security.js +353 -0
- package/dist/mcp/lib/security.js.map +1 -0
- package/dist/mcp/lib/verification-gates.d.ts +287 -0
- package/dist/mcp/lib/verification-gates.d.ts.map +1 -0
- package/dist/mcp/lib/verification-gates.js +547 -0
- package/dist/mcp/lib/verification-gates.js.map +1 -0
- package/dist/mcp/types/domain.d.ts +29 -0
- package/dist/mcp/types/domain.d.ts.map +1 -0
- package/dist/mcp/types/domain.js +7 -0
- package/dist/mcp/types/domain.js.map +1 -0
- package/dist/mcp/types/error.d.ts +101 -0
- package/dist/mcp/types/error.d.ts.map +1 -0
- package/dist/mcp/types/error.js +148 -0
- package/dist/mcp/types/error.js.map +1 -0
- package/dist/mcp/types/gateway.d.ts +78 -0
- package/dist/mcp/types/gateway.d.ts.map +1 -0
- package/dist/mcp/types/gateway.js +7 -0
- package/dist/mcp/types/gateway.js.map +1 -0
- package/dist/mcp/types/index.d.ts +23 -0
- package/dist/mcp/types/index.d.ts.map +1 -0
- package/dist/mcp/types/index.js +11 -0
- package/dist/mcp/types/index.js.map +1 -0
- package/dist/mcp/types/operations/issues.d.ts +3 -0
- package/dist/mcp/types/operations/issues.d.ts.map +1 -0
- package/dist/mcp/types/operations/issues.js +3 -0
- package/dist/mcp/types/operations/issues.js.map +1 -0
- package/dist/mcp/types/operations/lifecycle.d.ts +3 -0
- package/dist/mcp/types/operations/lifecycle.d.ts.map +1 -0
- package/dist/mcp/types/operations/lifecycle.js +3 -0
- package/dist/mcp/types/operations/lifecycle.js.map +1 -0
- package/dist/mcp/types/operations/orchestrate.d.ts +3 -0
- package/dist/mcp/types/operations/orchestrate.d.ts.map +1 -0
- package/dist/mcp/types/operations/orchestrate.js +3 -0
- package/dist/mcp/types/operations/orchestrate.js.map +1 -0
- package/dist/mcp/types/operations/release.d.ts +3 -0
- package/dist/mcp/types/operations/release.d.ts.map +1 -0
- package/dist/mcp/types/operations/release.js +3 -0
- package/dist/mcp/types/operations/release.js.map +1 -0
- package/dist/mcp/types/operations/research.d.ts +3 -0
- package/dist/mcp/types/operations/research.d.ts.map +1 -0
- package/dist/mcp/types/operations/research.js +3 -0
- package/dist/mcp/types/operations/research.js.map +1 -0
- package/dist/mcp/types/operations/session.d.ts +3 -0
- package/dist/mcp/types/operations/session.d.ts.map +1 -0
- package/dist/mcp/types/operations/session.js +3 -0
- package/dist/mcp/types/operations/session.js.map +1 -0
- package/dist/mcp/types/operations/skills.d.ts +3 -0
- package/dist/mcp/types/operations/skills.d.ts.map +1 -0
- package/dist/mcp/types/operations/skills.js +3 -0
- package/dist/mcp/types/operations/skills.js.map +1 -0
- package/dist/mcp/types/operations/system.d.ts +3 -0
- package/dist/mcp/types/operations/system.d.ts.map +1 -0
- package/dist/mcp/types/operations/system.js +3 -0
- package/dist/mcp/types/operations/system.js.map +1 -0
- package/dist/mcp/types/operations/tasks.d.ts +3 -0
- package/dist/mcp/types/operations/tasks.d.ts.map +1 -0
- package/dist/mcp/types/operations/tasks.js +3 -0
- package/dist/mcp/types/operations/tasks.js.map +1 -0
- package/dist/mcp/types/operations/validate.d.ts +3 -0
- package/dist/mcp/types/operations/validate.d.ts.map +1 -0
- package/dist/mcp/types/operations/validate.js +3 -0
- package/dist/mcp/types/operations/validate.js.map +1 -0
- package/dist/scripts/migrate-todo-to-tasks.d.ts +46 -0
- package/dist/scripts/migrate-todo-to-tasks.d.ts.map +1 -0
- package/dist/scripts/migrate-todo-to-tasks.js +379 -0
- package/dist/scripts/migrate-todo-to-tasks.js.map +1 -0
- package/dist/store/atomic.d.ts +75 -0
- package/dist/store/atomic.d.ts.map +1 -0
- package/dist/store/atomic.js +167 -0
- package/dist/store/atomic.js.map +1 -0
- package/dist/store/backup.d.ts +21 -0
- package/dist/store/backup.d.ts.map +1 -0
- package/dist/store/backup.js +94 -0
- package/dist/store/backup.js.map +1 -0
- package/dist/store/cache.d.ts +67 -0
- package/dist/store/cache.d.ts.map +1 -0
- package/dist/store/cache.js +168 -0
- package/dist/store/cache.js.map +1 -0
- package/dist/store/data-accessor.d.ts +77 -0
- package/dist/store/data-accessor.d.ts.map +1 -0
- package/dist/store/data-accessor.js +149 -0
- package/dist/store/data-accessor.js.map +1 -0
- package/dist/store/data-safety-central.d.ts +103 -0
- package/dist/store/data-safety-central.d.ts.map +1 -0
- package/dist/store/data-safety-central.js +291 -0
- package/dist/store/data-safety-central.js.map +1 -0
- package/dist/store/data-safety.d.ts +93 -0
- package/dist/store/data-safety.d.ts.map +1 -0
- package/dist/store/data-safety.js +298 -0
- package/dist/store/data-safety.js.map +1 -0
- package/dist/store/export.d.ts +87 -0
- package/dist/store/export.d.ts.map +1 -0
- package/dist/store/export.js +153 -0
- package/dist/store/export.js.map +1 -0
- package/dist/store/git-checkpoint.d.ts +65 -0
- package/dist/store/git-checkpoint.d.ts.map +1 -0
- package/dist/store/git-checkpoint.js +304 -0
- package/dist/store/git-checkpoint.js.map +1 -0
- package/dist/store/import-logging.d.ts +58 -0
- package/dist/store/import-logging.d.ts.map +1 -0
- package/dist/store/import-logging.js +139 -0
- package/dist/store/import-logging.js.map +1 -0
- package/dist/store/import-remap.d.ts +50 -0
- package/dist/store/import-remap.d.ts.map +1 -0
- package/dist/store/import-remap.js +145 -0
- package/dist/store/import-remap.js.map +1 -0
- package/dist/store/import-sort.d.ts +35 -0
- package/dist/store/import-sort.d.ts.map +1 -0
- package/dist/store/import-sort.js +123 -0
- package/dist/store/import-sort.js.map +1 -0
- package/dist/store/index.d.ts +28 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +28 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/json-data-accessor.d.ts +16 -0
- package/dist/store/json-data-accessor.d.ts.map +1 -0
- package/dist/store/json-data-accessor.js +68 -0
- package/dist/store/json-data-accessor.js.map +1 -0
- package/dist/store/json-provider.d.ts +23 -0
- package/dist/store/json-provider.d.ts.map +1 -0
- package/dist/store/json-provider.js +263 -0
- package/dist/store/json-provider.js.map +1 -0
- package/dist/store/json.d.ts +57 -0
- package/dist/store/json.d.ts.map +1 -0
- package/dist/store/json.js +198 -0
- package/dist/store/json.js.map +1 -0
- package/dist/store/lock.d.ts +29 -0
- package/dist/store/lock.d.ts.map +1 -0
- package/dist/store/lock.js +70 -0
- package/dist/store/lock.js.map +1 -0
- package/dist/store/migration-sqlite.d.ts +68 -0
- package/dist/store/migration-sqlite.d.ts.map +1 -0
- package/dist/store/migration-sqlite.js +742 -0
- package/dist/store/migration-sqlite.js.map +1 -0
- package/dist/store/project-detect.d.ts +24 -0
- package/dist/store/project-detect.d.ts.map +1 -0
- package/dist/store/project-detect.js +93 -0
- package/dist/store/project-detect.js.map +1 -0
- package/dist/store/project-registry.d.ts +113 -0
- package/dist/store/project-registry.d.ts.map +1 -0
- package/dist/store/project-registry.js +194 -0
- package/dist/store/project-registry.js.map +1 -0
- package/dist/store/provider.d.ts +162 -0
- package/dist/store/provider.d.ts.map +1 -0
- package/dist/store/provider.js +319 -0
- package/dist/store/provider.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +99 -0
- package/dist/store/safety-data-accessor.d.ts.map +1 -0
- package/dist/store/safety-data-accessor.js +167 -0
- package/dist/store/safety-data-accessor.js.map +1 -0
- package/dist/store/schema.d.ts +1094 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +114 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/session-store.d.ts +42 -0
- package/dist/store/session-store.d.ts.map +1 -0
- package/dist/store/session-store.js +227 -0
- package/dist/store/session-store.js.map +1 -0
- package/dist/store/sqlite-data-accessor.d.ts +24 -0
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -0
- package/dist/store/sqlite-data-accessor.js +564 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -0
- package/dist/store/sqlite.d.ts +51 -0
- package/dist/store/sqlite.d.ts.map +1 -0
- package/dist/store/sqlite.js +235 -0
- package/dist/store/sqlite.js.map +1 -0
- package/dist/store/task-store.d.ts +70 -0
- package/dist/store/task-store.d.ts.map +1 -0
- package/dist/store/task-store.js +401 -0
- package/dist/store/task-store.js.map +1 -0
- package/dist/types/config.d.ts +59 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/exit-codes.d.ts +102 -0
- package/dist/types/exit-codes.d.ts.map +1 -0
- package/dist/types/exit-codes.js +150 -0
- package/dist/types/exit-codes.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lafs.d.ts +77 -0
- package/dist/types/lafs.d.ts.map +1 -0
- package/dist/types/lafs.js +28 -0
- package/dist/types/lafs.js.map +1 -0
- package/dist/types/operations/issues.d.ts +75 -0
- package/dist/types/operations/issues.d.ts.map +1 -0
- package/dist/types/operations/issues.js +10 -0
- package/dist/types/operations/issues.js.map +1 -0
- package/dist/types/operations/lifecycle.d.ts +140 -0
- package/dist/types/operations/lifecycle.d.ts.map +1 -0
- package/dist/types/operations/lifecycle.js +8 -0
- package/dist/types/operations/lifecycle.js.map +1 -0
- package/dist/types/operations/orchestrate.d.ts +187 -0
- package/dist/types/operations/orchestrate.d.ts.map +1 -0
- package/dist/types/operations/orchestrate.js +8 -0
- package/dist/types/operations/orchestrate.js.map +1 -0
- package/dist/types/operations/release.d.ts +97 -0
- package/dist/types/operations/release.d.ts.map +1 -0
- package/dist/types/operations/release.js +7 -0
- package/dist/types/operations/release.js.map +1 -0
- package/dist/types/operations/research.d.ts +122 -0
- package/dist/types/operations/research.d.ts.map +1 -0
- package/dist/types/operations/research.js +8 -0
- package/dist/types/operations/research.js.map +1 -0
- package/dist/types/operations/session.d.ts +93 -0
- package/dist/types/operations/session.d.ts.map +1 -0
- package/dist/types/operations/session.js +12 -0
- package/dist/types/operations/session.js.map +1 -0
- package/dist/types/operations/skills.d.ts +182 -0
- package/dist/types/operations/skills.d.ts.map +1 -0
- package/dist/types/operations/skills.js +10 -0
- package/dist/types/operations/skills.js.map +1 -0
- package/dist/types/operations/system.d.ts +147 -0
- package/dist/types/operations/system.d.ts.map +1 -0
- package/dist/types/operations/system.js +8 -0
- package/dist/types/operations/system.js.map +1 -0
- package/dist/types/operations/tasks.d.ts +219 -0
- package/dist/types/operations/tasks.d.ts.map +1 -0
- package/dist/types/operations/tasks.js +13 -0
- package/dist/types/operations/tasks.js.map +1 -0
- package/dist/types/operations/validate.d.ts +170 -0
- package/dist/types/operations/validate.d.ts.map +1 -0
- package/dist/types/operations/validate.js +8 -0
- package/dist/types/operations/validate.js.map +1 -0
- package/dist/types/session.d.ts +48 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +8 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/task.d.ts +160 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +7 -0
- package/dist/types/task.js.map +1 -0
- package/package.json +88 -0
- package/schemas/agent-configs.schema.json +120 -0
- package/schemas/agent-registry.json +243 -0
- package/schemas/agent-registry.schema.json +132 -0
- package/schemas/archive.schema.json +450 -0
- package/schemas/claudedocs-frontmatter.schema.json +162 -0
- package/schemas/commands-index.schema.json +158 -0
- package/schemas/config.schema.json +2552 -0
- package/schemas/context-state.schema.json +137 -0
- package/schemas/contribution.schema.json +722 -0
- package/schemas/critical-path.schema.json +246 -0
- package/schemas/deps-cache.schema.json +97 -0
- package/schemas/doctor-output.schema.json +283 -0
- package/schemas/error.schema.json +161 -0
- package/schemas/export-package.schema.json +375 -0
- package/schemas/global-config.schema.json +219 -0
- package/schemas/log.schema.json +250 -0
- package/schemas/metrics.schema.json +328 -0
- package/schemas/migrations.schema.json +150 -0
- package/schemas/nexus-registry.schema.json +90 -0
- package/schemas/output.schema.json +164 -0
- package/schemas/project-context.schema.json +164 -0
- package/schemas/project-info.schema.json +170 -0
- package/schemas/projects-registry.schema.json +107 -0
- package/schemas/rcsd-consensus-report.schema.json +491 -0
- package/schemas/rcsd-hitl-resolution.schema.json +216 -0
- package/schemas/rcsd-index.schema.json +384 -0
- package/schemas/rcsd-manifest.schema.json +264 -0
- package/schemas/rcsd-research-output.schema.json +564 -0
- package/schemas/rcsd-spec-frontmatter.schema.json +225 -0
- package/schemas/releases.schema.json +267 -0
- package/schemas/research-manifest.schema.json +257 -0
- package/schemas/sessions.schema.json +406 -0
- package/schemas/skills-manifest.schema.json +91 -0
- package/schemas/skillsmp.schema.json +208 -0
- package/schemas/spec-index.schema.json +196 -0
- package/schemas/todo.schema.json +994 -0
- package/server.json +57 -0
- package/skills/_shared/cleo-style-guide.md +84 -0
- package/skills/_shared/manifest-operations.md +810 -0
- package/skills/_shared/placeholders.json +433 -0
- package/skills/_shared/skill-chaining-patterns.md +240 -0
- package/skills/_shared/subagent-protocol-base.md +221 -0
- package/skills/_shared/task-system-integration.md +232 -0
- package/skills/_shared/testing-framework-config.md +110 -0
- package/skills/agentskills-integrate.md +104 -0
- package/skills/agentskills-specs.md +255 -0
- package/skills/agentskills-what-are-skills.md +75 -0
- package/skills/manifest.json +510 -0
- package/templates/AGENT-INJECTION.md +166 -0
- package/templates/CLEO-INJECTION.md +470 -0
- package/templates/CONTRIBUTION-INJECTION.md +19 -0
- package/templates/CONTRIBUTION-PROTOCOL.template.md +224 -0
- package/templates/README.md +110 -0
- package/templates/agent-registry.json +305 -0
- package/templates/agents/BASE-SUBAGENT-PROTOCOL.md +115 -0
- package/templates/agents/README.md +197 -0
- package/templates/agents/cleo-subagent.md +147 -0
- package/templates/archive.template.json +24 -0
- package/templates/backups/archive/.gitkeep +0 -0
- package/templates/backups/incremental/.gitkeep +0 -0
- package/templates/backups/migration/.gitkeep +0 -0
- package/templates/backups/safety/.gitkeep +0 -0
- package/templates/backups/snapshot/.gitkeep +0 -0
- package/templates/ci/circleci/config.yml +96 -0
- package/templates/ci/github-actions/release.yml +91 -0
- package/templates/ci/gitlab-ci/release.yml +61 -0
- package/templates/cleo-gitignore +62 -0
- package/templates/config.template.json +187 -0
- package/templates/global-config.template.json +56 -0
- package/templates/hooks/precompact-safestop.sh +89 -0
- package/templates/log.template.json +13 -0
- package/templates/migrations.template.json +8 -0
- package/templates/orchestrator-protocol/PLACEHOLDER-REGISTRY.md +150 -0
- package/templates/orchestrator-protocol/README.md +162 -0
- package/templates/sessions.template.json +20 -0
- package/templates/skillsmp.json.example +28 -0
- package/templates/skillsmp.json.example.md +214 -0
- package/templates/subagent-protocol/INJECT.md +32 -0
- package/templates/subagent-protocol/MANIFEST.jsonl +0 -0
- package/templates/subagent-protocol/README.md +76 -0
- package/templates/subagent-protocol/SUBAGENT_PROTOCOL.md +135 -0
- package/templates/subagent-protocol/install.sh +41 -0
- package/templates/todo.template.json +68 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/paths.ts", "../../src/core/migration/preflight.ts", "../../src/store/schema.ts", "../../src/types/exit-codes.ts", "../../src/core/errors.ts", "../../src/store/sqlite.ts", "../../src/store/atomic.ts", "../../src/store/backup.ts", "../../src/store/lock.ts", "../../src/store/json.ts", "../../src/store/git-checkpoint.ts", "../../src/core/sequence/index.ts", "../../src/store/data-safety.ts", "../../src/store/task-store.ts", "../../src/store/session-store.ts", "../../src/store/migration-sqlite.ts", "../../src/store/sqlite-data-accessor.ts", "../../src/store/json-data-accessor.ts", "../../src/core/mcp/index.ts", "../../src/core/nexus/registry.ts", "../../src/store/project-detect.ts", "../../src/mcp/index.ts", "../../src/mcp/lib/config.ts", "../../src/mcp/lib/rate-limiter.ts", "../../src/mcp/lib/defaults.ts", "../../src/dispatch/registry.ts", "../../src/dispatch/lib/meta.ts", "../../src/dispatch/middleware/pipeline.ts", "../../src/dispatch/dispatcher.ts", "../../src/dispatch/domains/_meta.ts", "../../src/dispatch/domains/tasks.ts", "../../src/mcp/engine/store.ts", "../../src/mcp/engine/schema-validator.ts", "../../src/mcp/engine/validation-rules.ts", "../../src/store/data-accessor.ts", "../../src/core/tasks/add.ts", "../../src/core/config.ts", "../../src/core/tasks/update.ts", "../../src/core/tasks/reparent.ts", "../../src/core/tasks/hierarchy.ts", "../../src/core/tasks/delete.ts", "../../src/core/tasks/archive.ts", "../../src/core/tasks/show.ts", "../../src/core/tasks/list.ts", "../../src/core/tasks/find.ts", "../../src/core/tasks/task-ops.ts", "../../src/mcp/engine/task-engine.ts", "../../src/core/sessions/index.ts", "../../src/core/sessions/session-show.ts", "../../src/core/sessions/session-suspend.ts", "../../src/core/sessions/session-history.ts", "../../src/core/sessions/session-stats.ts", "../../src/core/sessions/session-switch.ts", "../../src/core/sessions/session-drift.ts", "../../src/core/sessions/decisions.ts", "../../src/core/sessions/assumptions.ts", "../../src/core/lifecycle/resume.ts", "../../src/core/lifecycle/stages.ts", "../../src/core/task-work/index.ts", "../../src/mcp/engine/session-engine.ts", "../../src/mcp/engine/system-engine.ts", "../../src/core/stats/index.ts", "../../src/core/system/labels.ts", "../../src/core/system/archive-stats.ts", "../../src/core/system/inject-generate.ts", "../../src/core/system/health.ts", "../../src/core/roadmap/index.ts", "../../src/core/system/backup.ts", "../../src/core/system/migrate.ts", "../../src/core/system/cleanup.ts", "../../src/core/system/safestop.ts", "../../src/mcp/engine/config-engine.ts", "../../src/core/init.ts", "../../src/mcp/engine/init-engine.ts", "../../src/core/caamp/adapter.ts", "../../src/mcp/engine/template-parser.ts", "../../src/mcp/engine/lifecycle-engine.ts", "../../src/core/lifecycle/index.ts", "../../src/core/validation/validate-ops.ts", "../../src/core/tasks/dependency-check.ts", "../../src/mcp/engine/validate-engine.ts", "../../src/mcp/engine/orchestrate-engine.ts", "../../src/core/orchestration/index.ts", "../../src/core/phases/deps.ts", "../../src/core/orchestration/waves.ts", "../../src/core/orchestration/critical-path.ts", "../../src/core/orchestration/unblock.ts", "../../src/core/orchestration/parallel.ts", "../../src/core/orchestration/skill-ops.ts", "../../src/core/orchestration/validate-spawn.ts", "../../src/core/orchestration/bootstrap.ts", "../../src/mcp/engine/research-engine.ts", "../../src/core/research/index.ts", "../../src/core/release/release-manifest.ts", "../../src/mcp/engine/release-engine.ts", "../../src/mcp/engine/capability-matrix.ts", "../../src/dispatch/domains/session.ts", "../../src/dispatch/domains/check.ts", "../../src/dispatch/domains/admin.ts", "../../src/dispatch/domains/memory.ts", "../../src/dispatch/domains/orchestrate.ts", "../../src/dispatch/domains/pipeline.ts", "../../src/dispatch/domains/tools.ts", "../../src/dispatch/domains/nexus.ts", "../../src/dispatch/domains/index.ts", "../../src/mcp/lib/security.ts", "../../src/dispatch/middleware/sanitizer.ts", "../../src/dispatch/middleware/rate-limiter.ts", "../../src/mcp/lib/protocol-rules.ts", "../../src/mcp/lib/protocol-enforcement.ts", "../../src/mcp/lib/gate-validators.ts", "../../src/mcp/lib/verification-gates.ts", "../../src/dispatch/middleware/verification-gates.ts", "../../src/dispatch/middleware/protocol-enforcement.ts", "../../src/dispatch/middleware/audit.ts", "../../src/dispatch/adapters/mcp.ts", "../../src/mcp/lib/executor.ts", "../../src/mcp/lib/command-builder.ts", "../../src/mcp/types/error.ts", "../../src/mcp/gateways/query.ts", "../../src/mcp/lib/audit.ts", "../../src/mcp/gateways/mutate.ts", "../../src/mcp/lib/cache.ts", "../../src/mcp/lib/background-jobs.ts", "../../src/mcp/lib/mode-detector.ts", "../../src/mcp/lib/budget.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * XDG-compliant path resolution for CLEO V2.\n *\n * Environment variables:\n * CLEO_HOME - Global installation directory (default: ~/.cleo)\n * CLEO_DIR - Project data directory (default: .cleo)\n *\n * @epic T4454\n * @task T4458\n */\n\nimport { resolve, dirname, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { existsSync, readFileSync, renameSync } from 'node:fs';\n\n/**\n * Check if a CLEO project is initialized at the given root.\n * Checks for both tasks.json (canonical) and todo.json (legacy).\n */\nexport function isProjectInitialized(projectRoot?: string): boolean {\n const root = projectRoot ?? getProjectRoot();\n const cleoDir = join(root, '.cleo');\n return existsSync(cleoDir) && (existsSync(join(cleoDir, 'tasks.json')) || existsSync(join(cleoDir, 'todo.json')));\n}\n\n/**\n * Get the global CLEO home directory.\n * Respects CLEO_HOME env var, defaults to ~/.cleo.\n */\nexport function getCleoHome(): string {\n return process.env['CLEO_HOME'] ?? join(homedir(), '.cleo');\n}\n\n/**\n * Get the global CLEO templates directory.\n */\nexport function getCleoTemplatesDir(): string {\n return join(getCleoHome(), 'templates');\n}\n\n/**\n * Get the global CLEO schemas directory.\n */\nexport function getCleoSchemasDir(): string {\n return join(getCleoHome(), 'schemas');\n}\n\n/**\n * Get the global CLEO docs directory.\n */\nexport function getCleoDocsDir(): string {\n return join(getCleoHome(), 'docs');\n}\n\n/**\n * Get the project CLEO data directory (relative).\n * Respects CLEO_DIR env var, defaults to \".cleo\".\n */\nexport function getCleoDir(cwd?: string): string {\n if (cwd) {\n return getCleoDirAbsolute(cwd);\n }\n return process.env['CLEO_DIR'] ?? '.cleo';\n}\n\n/**\n * Get the absolute path to the project CLEO directory.\n */\nexport function getCleoDirAbsolute(cwd?: string): string {\n const cleoDir = getCleoDir();\n if (isAbsolutePath(cleoDir)) {\n return cleoDir;\n }\n return resolve(cwd ?? process.cwd(), cleoDir);\n}\n\n/**\n * Get the project root from the CLEO directory.\n * Respects CLEO_ROOT env var, then derives from CLEO_DIR.\n * If CLEO_DIR is \".cleo\", the project root is its parent.\n */\nexport function getProjectRoot(cwd?: string): string {\n if (!cwd && process.env['CLEO_ROOT']) {\n return process.env['CLEO_ROOT'];\n }\n const cleoDirAbs = getCleoDirAbsolute(cwd);\n if (cleoDirAbs.endsWith('/.cleo') || cleoDirAbs.endsWith('\\\\.cleo')) {\n return dirname(cleoDirAbs);\n }\n return cwd ?? process.cwd();\n}\n\n/**\n * Resolve a project-relative path to an absolute path.\n */\nexport function resolveProjectPath(relativePath: string, cwd?: string): string {\n if (isAbsolutePath(relativePath)) {\n return relativePath;\n }\n // Expand leading tilde\n if (relativePath.startsWith('~/') || relativePath === '~') {\n return resolve(homedir(), relativePath.slice(2));\n }\n return resolve(getProjectRoot(cwd), relativePath);\n}\n\n/**\n * Get the path to the project's tasks.json file.\n */\nexport function getTaskPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'tasks.json');\n}\n\n/**\n * Get the path to the project's todo.json file.\n * @deprecated Use getTaskPath() instead.\n */\nexport function getTodoPath(cwd?: string): string {\n return getTaskPath(cwd);\n}\n\n/**\n * Get the path to the project's config.json file.\n */\nexport function getConfigPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'config.json');\n}\n\n/**\n * Get the path to the project's sessions.json file.\n */\nexport function getSessionsPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'sessions.json');\n}\n\n/**\n * Get the path to the project's archive file.\n */\nexport function getArchivePath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'tasks-archive.json');\n}\n\n/**\n * Get the path to the project's log file.\n * Auto-migrates legacy todo-log.json to tasks-log.jsonl if needed.\n * @task T4644\n */\nexport function getLogPath(cwd?: string): string {\n const cleoDir = getCleoDirAbsolute(cwd);\n const newPath = join(cleoDir, 'tasks-log.jsonl');\n const legacyPath = join(cleoDir, 'todo-log.json');\n\n // Auto-migrate: rename legacy file if new file doesn't exist\n if (!existsSync(newPath) && existsSync(legacyPath)) {\n try {\n renameSync(legacyPath, newPath);\n } catch {\n // If rename fails (e.g. permissions), fall back to legacy path\n return legacyPath;\n }\n }\n\n return newPath;\n}\n\n/**\n * Get the backup directory for operational backups.\n */\nexport function getBackupDir(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'backups', 'operational');\n}\n\n/**\n * Get the global config file path.\n */\nexport function getGlobalConfigPath(): string {\n return join(getCleoHome(), 'config.json');\n}\n\n// ============================================================================\n// Agent Outputs\n// ============================================================================\n\nconst DEFAULT_AGENT_OUTPUTS_DIR = '.cleo/agent-outputs';\n\n/**\n * Get the agent outputs directory (relative path) from config or default.\n *\n * Config lookup priority:\n * 1. config.agentOutputs.directory\n * 2. config.research.outputDir (deprecated)\n * 3. config.directories.agentOutputs (deprecated)\n * 4. Default: '.cleo/agent-outputs'\n *\n * @task T4700\n */\nexport function getAgentOutputsDir(cwd?: string): string {\n const projectRoot = getProjectRoot(cwd);\n const configPath = join(projectRoot, '.cleo', 'config.json');\n\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'));\n\n // Priority 1: agentOutputs.directory (canonical)\n if (typeof config.agentOutputs === 'object' && config.agentOutputs?.directory) {\n return config.agentOutputs.directory;\n }\n // Also support agentOutputs as a plain string\n if (typeof config.agentOutputs === 'string' && config.agentOutputs) {\n return config.agentOutputs;\n }\n\n // Priority 2: research.outputDir (deprecated)\n if (config.research?.outputDir) {\n return config.research.outputDir;\n }\n\n // Priority 3: directories.agentOutputs (deprecated)\n if (config.directories?.agentOutputs) {\n return config.directories.agentOutputs;\n }\n } catch {\n // fallback to default\n }\n }\n\n return DEFAULT_AGENT_OUTPUTS_DIR;\n}\n\n/**\n * Get the absolute path to the agent outputs directory.\n * @task T4700\n */\nexport function getAgentOutputsAbsolute(cwd?: string): string {\n const dir = getAgentOutputsDir(cwd);\n if (isAbsolutePath(dir)) {\n return dir;\n }\n return resolve(getProjectRoot(cwd), dir);\n}\n\n/**\n * Get the absolute path to the MANIFEST.jsonl file.\n *\n * Checks config.agentOutputs.manifestFile for custom filename,\n * defaults to 'MANIFEST.jsonl'.\n *\n * @task T4700\n */\nexport function getManifestPath(cwd?: string): string {\n const outputDir = getAgentOutputsDir(cwd);\n const projectRoot = getProjectRoot(cwd);\n const configPath = join(projectRoot, '.cleo', 'config.json');\n\n let manifestFile = 'MANIFEST.jsonl';\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'));\n const customFile = config.agentOutputs?.manifestFile ?? config.research?.manifestFile;\n if (customFile) {\n manifestFile = customFile;\n }\n } catch {\n // fallback\n }\n }\n\n return resolve(projectRoot, outputDir, manifestFile);\n}\n\n/**\n * Get the absolute path to the MANIFEST.archive.jsonl file.\n * @task T4700\n */\nexport function getManifestArchivePath(cwd?: string): string {\n const outputDir = getAgentOutputsDir(cwd);\n const projectRoot = getProjectRoot(cwd);\n return resolve(projectRoot, outputDir, 'MANIFEST.archive.jsonl');\n}\n\n// ============================================================================\n// Path Utilities\n// ============================================================================\n\n/**\n * Check if a path is absolute (POSIX or Windows).\n */\nexport function isAbsolutePath(path: string): boolean {\n // POSIX absolute\n if (path.startsWith('/')) return true;\n // Windows drive letter (C:\\, D:/)\n if (/^[A-Za-z]:[\\\\/]/.test(path)) return true;\n // UNC path\n if (path.startsWith('\\\\\\\\')) return true;\n return false;\n}\n", "/**\n * Pre-flight migration checks.\n *\n * Detects when JSON data exists but hasn't been migrated to SQLite,\n * and provides actionable diagnostics for users upgrading to v2.\n *\n * Core module: CLI and MCP both call these functions.\n *\n * @task T4699\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getCleoDirAbsolute } from '../paths.js';\n\n/** Pre-flight check result. */\nexport interface PreflightResult {\n /** Whether a storage migration is needed. */\n migrationNeeded: boolean;\n /** Current detected storage engine. */\n currentEngine: 'json' | 'sqlite' | 'dual' | 'none';\n /** Human-readable summary of what was detected. */\n summary: string;\n /** Actionable fix command. */\n fix: string | null;\n /** Detailed diagnostics. */\n details: {\n todoJsonExists: boolean;\n todoJsonTaskCount: number;\n archiveJsonExists: boolean;\n archiveJsonTaskCount: number;\n sessionsJsonExists: boolean;\n sessionsJsonCount: number;\n tasksDbExists: boolean;\n tasksDbSize: number;\n configEngine: string | null;\n };\n}\n\n/**\n * Check whether JSON data needs to be migrated to SQLite.\n *\n * Returns a diagnostic result that callers can use to warn users.\n * This function is read-only and never modifies any files.\n *\n * @task T4699\n */\nexport function checkStorageMigration(cwd?: string): PreflightResult {\n const cleoDir = getCleoDirAbsolute(cwd);\n\n const details: PreflightResult['details'] = {\n todoJsonExists: false,\n todoJsonTaskCount: 0,\n archiveJsonExists: false,\n archiveJsonTaskCount: 0,\n sessionsJsonExists: false,\n sessionsJsonCount: 0,\n tasksDbExists: false,\n tasksDbSize: 0,\n configEngine: null,\n };\n\n // Check config.json for engine setting\n const configPath = join(cleoDir, 'config.json');\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'));\n details.configEngine = config?.storage?.engine ?? null;\n } catch {\n // Ignore parse errors\n }\n }\n\n // Check todo.json\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n details.todoJsonExists = true;\n try {\n const data = JSON.parse(readFileSync(todoPath, 'utf-8'));\n details.todoJsonTaskCount = (data.tasks ?? []).length;\n } catch {\n // Corrupted but exists\n }\n }\n\n // Check todo-archive.json\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (existsSync(archivePath)) {\n details.archiveJsonExists = true;\n try {\n const data = JSON.parse(readFileSync(archivePath, 'utf-8'));\n details.archiveJsonTaskCount = (data.tasks ?? data.archivedTasks ?? []).length;\n } catch {\n // Corrupted but exists\n }\n }\n\n // Check sessions.json\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n details.sessionsJsonExists = true;\n try {\n const data = JSON.parse(readFileSync(sessionsPath, 'utf-8'));\n details.sessionsJsonCount = (data.sessions ?? []).length;\n } catch {\n // Corrupted but exists\n }\n }\n\n // Check tasks.db\n const dbPath = join(cleoDir, 'tasks.db');\n if (existsSync(dbPath)) {\n details.tasksDbExists = true;\n try {\n details.tasksDbSize = statSync(dbPath).size;\n } catch {\n // Can't stat\n }\n }\n\n // Determine current engine\n let currentEngine: PreflightResult['currentEngine'] = 'none';\n if (details.configEngine === 'sqlite' || details.configEngine === 'dual') {\n currentEngine = details.configEngine as 'sqlite' | 'dual';\n } else if (details.configEngine === 'json') {\n currentEngine = 'json';\n } else if (details.tasksDbExists) {\n currentEngine = 'sqlite';\n } else if (details.todoJsonExists) {\n currentEngine = 'json';\n }\n\n // Determine if migration is needed\n const jsonHasData = details.todoJsonTaskCount > 0\n || details.archiveJsonTaskCount > 0\n || details.sessionsJsonCount > 0;\n\n // Migration is flagged for broken or upgrade states:\n //\n // Cases:\n // 1. Config says sqlite but tasks.db is missing (broken state)\n // 2. No config engine set, JSON data exists, no tasks.db (v1\u2192v2 upgrade)\n //\n // NOT flagged:\n // - Config says sqlite and tasks.db exists (normal post-migration state,\n // even if JSON files remain as backups)\n // - Config says json explicitly (user opted out of SQLite)\n\n let migrationNeeded = false;\n let summary = '';\n let fix: string | null = null;\n\n if (details.configEngine === 'sqlite' && !details.tasksDbExists && jsonHasData) {\n // Config says sqlite but DB is missing - broken state\n migrationNeeded = true;\n summary = `Config engine is 'sqlite' but tasks.db is missing. `\n + `${details.todoJsonTaskCount} active tasks and ${details.archiveJsonTaskCount} archived tasks found in JSON files.`;\n fix = 'cleo migrate-storage --to-sqlite --verify';\n } else if (details.configEngine === 'sqlite' && !details.tasksDbExists && !jsonHasData) {\n // Config says sqlite, no DB, no JSON data - fresh project with bad config\n migrationNeeded = false;\n summary = 'No data found. Run cleo init to set up a new project.';\n } else if (\n details.configEngine === null\n && jsonHasData\n && !details.tasksDbExists\n ) {\n // No explicit config, JSON data exists but no SQLite DB.\n // User is upgrading from JSON era \u2014 SQLite is now the default in CLEO V2.\n const totalTasks = details.todoJsonTaskCount + details.archiveJsonTaskCount;\n migrationNeeded = true;\n summary = `Found ${totalTasks} task(s) in JSON files but no SQLite database. `\n + `SQLite is the default storage engine in CLEO V2. `\n + `Run migration to upgrade, or set storage.engine to 'json' in .cleo/config.json to keep using JSON.`;\n fix = 'cleo migrate-storage --to-sqlite --verify';\n } else if (!jsonHasData && !details.tasksDbExists) {\n summary = 'No data found. Run cleo init to set up a new project.';\n } else {\n summary = currentEngine === 'sqlite'\n ? `SQLite storage active (${details.tasksDbSize} bytes).`\n : `JSON storage active (${details.todoJsonTaskCount} tasks).`;\n }\n\n return {\n migrationNeeded,\n currentEngine,\n summary,\n fix,\n details,\n };\n}\n", "/**\n * Drizzle ORM schema for CLEO tasks.db (SQLite via sql.js WASM).\n *\n * Core Tables: tasks, task_dependencies, task_relations, sessions, task_work_history\n * Lifecycle Tables: lifecycle_pipelines, lifecycle_stages, lifecycle_transitions,\n * lifecycle_gate_results, lifecycle_evidence\n * ADR Tables: architecture_decisions\n * Archive uses the same tasks table with status = 'archived' + archive metadata.\n *\n * @epic T4454\n * @task T4801 - Lifecycle schema design\n * @epic T4798 - Lifecycle persistence improvements\n * @ref T4804 - Gate recording stubs\n * @ref T4811 - ADR Registry\n */\n\nimport {\n sqliteTable,\n text,\n integer,\n index,\n primaryKey,\n} from 'drizzle-orm/sqlite-core';\nimport { sql } from 'drizzle-orm';\n\n// === TASKS TABLE ===\n\nexport const tasks = sqliteTable('tasks', {\n id: text('id').primaryKey(),\n title: text('title').notNull(),\n description: text('description'),\n status: text('status', {\n enum: ['pending', 'active', 'blocked', 'done', 'cancelled', 'archived'],\n }).notNull().default('pending'),\n priority: text('priority', {\n enum: ['critical', 'high', 'medium', 'low'],\n }).notNull().default('medium'),\n type: text('type', { enum: ['epic', 'task', 'subtask'] }),\n parentId: text('parent_id'),\n phase: text('phase'),\n size: text('size', { enum: ['small', 'medium', 'large'] }),\n position: integer('position'),\n positionVersion: integer('position_version').default(0),\n\n // JSON-serialized complex fields (avoids excessive normalization)\n labelsJson: text('labels_json').default('[]'),\n notesJson: text('notes_json').default('[]'),\n acceptanceJson: text('acceptance_json').default('[]'),\n filesJson: text('files_json').default('[]'),\n\n // Provenance\n origin: text('origin'),\n blockedBy: text('blocked_by'),\n epicLifecycle: text('epic_lifecycle'),\n noAutoComplete: integer('no_auto_complete', { mode: 'boolean' }),\n\n // Timestamps\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n updatedAt: text('updated_at'),\n completedAt: text('completed_at'),\n cancelledAt: text('cancelled_at'),\n cancellationReason: text('cancellation_reason'),\n\n // Archive metadata (populated when status = 'archived')\n archivedAt: text('archived_at'),\n archiveReason: text('archive_reason'),\n cycleTimeDays: integer('cycle_time_days'),\n\n // Verification (JSON-serialized)\n verificationJson: text('verification_json'),\n\n // Provenance tracking\n createdBy: text('created_by'),\n modifiedBy: text('modified_by'),\n sessionId: text('session_id'),\n}, (table) => [\n index('idx_tasks_status').on(table.status),\n index('idx_tasks_parent_id').on(table.parentId),\n index('idx_tasks_phase').on(table.phase),\n index('idx_tasks_type').on(table.type),\n index('idx_tasks_priority').on(table.priority),\n]);\n\n// === TASK DEPENDENCIES ===\n\nexport const taskDependencies = sqliteTable('task_dependencies', {\n taskId: text('task_id').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n dependsOn: text('depends_on').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n}, (table) => [\n primaryKey({ columns: [table.taskId, table.dependsOn] }),\n index('idx_deps_depends_on').on(table.dependsOn),\n]);\n\n// === TASK RELATIONS ===\n\nexport const taskRelations = sqliteTable('task_relations', {\n taskId: text('task_id').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n relatedTo: text('related_to').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n relationType: text('relation_type', {\n enum: ['related', 'blocks', 'duplicates'],\n }).notNull().default('related'),\n}, (table) => [\n primaryKey({ columns: [table.taskId, table.relatedTo] }),\n]);\n\n// === SESSIONS ===\n\nexport const sessions = sqliteTable('sessions', {\n id: text('id').primaryKey(),\n name: text('name').notNull(),\n status: text('status', {\n enum: ['active', 'ended', 'orphaned', 'suspended'],\n }).notNull().default('active'),\n scopeJson: text('scope_json').notNull().default('{}'),\n currentTask: text('current_task'),\n taskStartedAt: text('task_started_at'),\n agent: text('agent'),\n notesJson: text('notes_json').default('[]'),\n tasksCompletedJson: text('tasks_completed_json').default('[]'),\n tasksCreatedJson: text('tasks_created_json').default('[]'),\n startedAt: text('started_at').notNull().default(sql`(datetime('now'))`),\n endedAt: text('ended_at'),\n}, (table) => [\n index('idx_sessions_status').on(table.status),\n]);\n\n// === TASK WORK HISTORY ===\n\nexport const taskWorkHistory = sqliteTable('task_work_history', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n sessionId: text('session_id').notNull().references(() => sessions.id, { onDelete: 'cascade' }),\n taskId: text('task_id').notNull(),\n setAt: text('set_at').notNull().default(sql`(datetime('now'))`),\n clearedAt: text('cleared_at'),\n}, (table) => [\n index('idx_work_history_session').on(table.sessionId),\n]);\n\n// === SCHEMA METADATA ===\n\nexport const schemaMeta = sqliteTable('schema_meta', {\n key: text('key').primaryKey(),\n value: text('value').notNull(),\n});\n\n// === LIFECYCLE PIPELINES ===\n// Reference: T4801 - Lifecycle schema design, T4798 - Lifecycle persistence\n\nexport const lifecyclePipelines = sqliteTable('lifecycle_pipelines', {\n id: text('id').primaryKey(),\n taskId: text('task_id').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n name: text('name').notNull(),\n description: text('description'),\n status: text('status', {\n enum: ['active', 'completed', 'aborted'],\n }).notNull().default('active'),\n currentStageId: text('current_stage_id'),\n startedAt: text('started_at').notNull().default(sql`(datetime('now'))`),\n completedAt: text('completed_at'),\n abortedAt: text('aborted_at'),\n abortReason: text('abort_reason'),\n metadataJson: text('metadata_json').default('{}'),\n}, (table) => [\n index('idx_lifecycle_pipelines_task_id').on(table.taskId),\n index('idx_lifecycle_pipelines_status').on(table.status),\n]);\n\n// === LIFECYCLE STAGES ===\n// Tracks individual stages in the 9-stage RCSD pipeline\n// Stages: Research \u2192 Consensus \u2192 ADR \u2192 Spec \u2192 Decompose \u2192 Implement \u2192 Verify \u2192 Test \u2192 Release\n\nexport const lifecycleStages = sqliteTable('lifecycle_stages', {\n id: text('id').primaryKey(),\n pipelineId: text('pipeline_id').notNull().references(() => lifecyclePipelines.id, { onDelete: 'cascade' }),\n taskId: text('task_id').notNull().references(() => tasks.id, { onDelete: 'cascade' }),\n stageName: text('stage_name', {\n enum: ['research', 'consensus', 'adr', 'spec', 'decompose', 'implement', 'verify', 'test', 'release'],\n }).notNull(),\n sequence: integer('sequence').notNull(),\n status: text('status', {\n enum: ['pending', 'active', 'blocked', 'completed', 'skipped'],\n }).notNull().default('pending'),\n startedAt: text('started_at'),\n completedAt: text('completed_at'),\n blockedAt: text('blocked_at'),\n blockReason: text('block_reason'),\n skippedAt: text('skipped_at'),\n skipReason: text('skip_reason'),\n notesJson: text('notes_json').default('[]'),\n metadataJson: text('metadata_json').default('{}'),\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n updatedAt: text('updated_at'),\n}, (table) => [\n index('idx_lifecycle_stages_pipeline_id').on(table.pipelineId),\n index('idx_lifecycle_stages_task_id').on(table.taskId),\n index('idx_lifecycle_stages_status').on(table.status),\n index('idx_lifecycle_stages_sequence').on(table.sequence),\n]);\n\n// === LIFECYCLE TRANSITIONS ===\n// Defines allowed transitions between stages\n\nexport const lifecycleTransitions = sqliteTable('lifecycle_transitions', {\n id: text('id').primaryKey(),\n pipelineId: text('pipeline_id').notNull().references(() => lifecyclePipelines.id, { onDelete: 'cascade' }),\n fromStageId: text('from_stage_id').notNull().references(() => lifecycleStages.id, { onDelete: 'cascade' }),\n toStageId: text('to_stage_id').notNull().references(() => lifecycleStages.id, { onDelete: 'cascade' }),\n transitionType: text('transition_type', {\n enum: ['auto', 'manual', 'conditional'],\n }).notNull().default('manual'),\n conditionJson: text('condition_json').default('{}'),\n requiresGate: integer('requires_gate', { mode: 'boolean' }).default(true),\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n}, (table) => [\n index('idx_lifecycle_transitions_pipeline_id').on(table.pipelineId),\n index('idx_lifecycle_transitions_from_stage').on(table.fromStageId),\n index('idx_lifecycle_transitions_to_stage').on(table.toStageId),\n]);\n\n// === LIFECYCLE GATE RESULTS ===\n// Records gate check outcomes for lifecycle stages\n// Integrates with T4804 - SQLite Lifecycle Gate & Evidence Recording\n\nexport const lifecycleGateResults = sqliteTable('lifecycle_gate_results', {\n id: text('id').primaryKey(),\n stageId: text('stage_id').notNull().references(() => lifecycleStages.id, { onDelete: 'cascade' }),\n gateName: text('gate_name').notNull(),\n result: text('result', {\n enum: ['pass', 'fail', 'warn'],\n }).notNull(),\n checkedAt: text('checked_at').notNull().default(sql`(datetime('now'))`),\n checkedBy: text('checked_by').notNull(),\n details: text('details'),\n reason: text('reason'),\n metadataJson: text('metadata_json').default('{}'),\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n}, (table) => [\n index('idx_lifecycle_gate_results_stage_id').on(table.stageId),\n index('idx_lifecycle_gate_results_gate_name').on(table.gateName),\n index('idx_lifecycle_gate_results_result').on(table.result),\n index('idx_lifecycle_gate_results_checked_at').on(table.checkedAt),\n]);\n\n// === LIFECYCLE EVIDENCE ===\n// Links external artifacts to lifecycle stage completion\n// Integrates with T4804 - SQLite Lifecycle Gate & Evidence Recording\n\nexport const lifecycleEvidence = sqliteTable('lifecycle_evidence', {\n id: text('id').primaryKey(),\n stageId: text('stage_id').notNull().references(() => lifecycleStages.id, { onDelete: 'cascade' }),\n uri: text('uri').notNull(),\n type: text('type', {\n enum: ['file', 'url', 'manifest'],\n }).notNull(),\n recordedAt: text('recorded_at').notNull().default(sql`(datetime('now'))`),\n recordedBy: text('recorded_by'),\n description: text('description'),\n metadataJson: text('metadata_json').default('{}'),\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n}, (table) => [\n index('idx_lifecycle_evidence_stage_id').on(table.stageId),\n index('idx_lifecycle_evidence_type').on(table.type),\n index('idx_lifecycle_evidence_recorded_at').on(table.recordedAt),\n]);\n\n// === ARCHITECTURE DECISION RECORDS (ADR) ===\n// Reference: T4811 - ADR Registry requirement\n// Stores architecture decision records with full content, relations, and status tracking\n// Supports self-referential superseding chains and links to tasks and consensus manifests\n\nexport const architectureDecisions = sqliteTable('architecture_decisions', {\n id: text('id').primaryKey(),\n title: text('title').notNull(),\n status: text('status', {\n enum: ['proposed', 'accepted', 'superseded', 'deprecated'],\n }).notNull().default('proposed'),\n context: text('context'),\n decision: text('decision'),\n rationale: text('rationale'),\n consequences: text('consequences'),\n consequencesJson: text('consequences_json').default('{}'),\n downstreamImpactJson: text('downstream_impact_json').default('[]'),\n content: text('content'),\n supersedesId: text('supersedes_id'),\n supersededById: text('superseded_by_id'),\n consensusManifestId: text('consensus_manifest_id'),\n taskId: text('task_id').references(() => tasks.id, { onDelete: 'set null' }),\n tagsJson: text('tags_json').default('[]'),\n metadataJson: text('metadata_json').default('{}'),\n createdAt: text('created_at').notNull().default(sql`(datetime('now'))`),\n updatedAt: text('updated_at'),\n acceptedAt: text('accepted_at'),\n deprecatedAt: text('deprecated_at'),\n}, (table) => [\n index('idx_architecture_decisions_status').on(table.status),\n index('idx_architecture_decisions_task_id').on(table.taskId),\n index('idx_architecture_decisions_supersedes').on(table.supersedesId),\n index('idx_architecture_decisions_superseded_by').on(table.supersededById),\n]);\n\n// === TYPE EXPORTS ===\n\nexport type TaskRow = typeof tasks.$inferSelect;\nexport type NewTaskRow = typeof tasks.$inferInsert;\nexport type SessionRow = typeof sessions.$inferSelect;\nexport type NewSessionRow = typeof sessions.$inferInsert;\nexport type TaskDependencyRow = typeof taskDependencies.$inferSelect;\nexport type TaskRelationRow = typeof taskRelations.$inferSelect;\nexport type WorkHistoryRow = typeof taskWorkHistory.$inferSelect;\n\n// Lifecycle types\nexport type LifecyclePipelineRow = typeof lifecyclePipelines.$inferSelect;\nexport type NewLifecyclePipelineRow = typeof lifecyclePipelines.$inferInsert;\nexport type LifecycleStageRow = typeof lifecycleStages.$inferSelect;\nexport type NewLifecycleStageRow = typeof lifecycleStages.$inferInsert;\nexport type LifecycleTransitionRow = typeof lifecycleTransitions.$inferSelect;\nexport type NewLifecycleTransitionRow = typeof lifecycleTransitions.$inferInsert;\nexport type LifecycleGateResultRow = typeof lifecycleGateResults.$inferSelect;\nexport type NewLifecycleGateResultRow = typeof lifecycleGateResults.$inferInsert;\nexport type LifecycleEvidenceRow = typeof lifecycleEvidence.$inferSelect;\nexport type NewLifecycleEvidenceRow = typeof lifecycleEvidence.$inferInsert;\n\n// ADR types\nexport type ArchitectureDecisionRow = typeof architectureDecisions.$inferSelect;\nexport type NewArchitectureDecisionRow = typeof architectureDecisions.$inferInsert;\n", "/**\n * CLEO exit codes - all 72 codes from the Bash CLI.\n * Ranges: 0 = success, 1-99 = errors, 100+ = special (non-error) states.\n *\n * @epic T4454\n * @task T4456\n */\n\nexport enum ExitCode {\n // === SUCCESS (0) ===\n SUCCESS = 0,\n\n // === GENERAL ERRORS (1-9) ===\n GENERAL_ERROR = 1,\n INVALID_INPUT = 2,\n FILE_ERROR = 3,\n NOT_FOUND = 4,\n DEPENDENCY_ERROR = 5,\n VALIDATION_ERROR = 6,\n LOCK_TIMEOUT = 7,\n CONFIG_ERROR = 8,\n\n // === HIERARCHY ERRORS (10-19) ===\n PARENT_NOT_FOUND = 10,\n DEPTH_EXCEEDED = 11,\n SIBLING_LIMIT = 12,\n INVALID_PARENT_TYPE = 13,\n CIRCULAR_REFERENCE = 14,\n ORPHAN_DETECTED = 15,\n HAS_CHILDREN = 16,\n TASK_COMPLETED = 17,\n CASCADE_FAILED = 18,\n HAS_DEPENDENTS = 19,\n\n // === CONCURRENCY ERRORS (20-29) ===\n CHECKSUM_MISMATCH = 20,\n CONCURRENT_MODIFICATION = 21,\n ID_COLLISION = 22,\n\n // === SESSION ERRORS (30-39) ===\n SESSION_EXISTS = 30,\n SESSION_NOT_FOUND = 31,\n SCOPE_CONFLICT = 32,\n SCOPE_INVALID = 33,\n TASK_NOT_IN_SCOPE = 34,\n TASK_CLAIMED = 35,\n SESSION_REQUIRED = 36,\n SESSION_CLOSE_BLOCKED = 37,\n FOCUS_REQUIRED = 38,\n NOTES_REQUIRED = 39,\n\n // === VERIFICATION ERRORS (40-47) ===\n VERIFICATION_INIT_FAILED = 40,\n GATE_UPDATE_FAILED = 41,\n INVALID_GATE = 42,\n INVALID_AGENT = 43,\n MAX_ROUNDS_EXCEEDED = 44,\n GATE_DEPENDENCY = 45,\n VERIFICATION_LOCKED = 46,\n ROUND_MISMATCH = 47,\n\n // === CONTEXT SAFEGUARD (50-54) ===\n CONTEXT_WARNING = 50,\n CONTEXT_CAUTION = 51,\n CONTEXT_CRITICAL = 52,\n CONTEXT_EMERGENCY = 53,\n CONTEXT_STALE = 54,\n\n // === ORCHESTRATOR ERRORS (60-67) ===\n PROTOCOL_MISSING = 60,\n INVALID_RETURN_MESSAGE = 61,\n MANIFEST_ENTRY_MISSING = 62,\n SPAWN_VALIDATION_FAILED = 63,\n AUTONOMOUS_BOUNDARY = 64,\n HANDOFF_REQUIRED = 65,\n RESUME_FAILED = 66,\n CONCURRENT_SESSION = 67,\n\n // === NEXUS ERRORS (70-79) ===\n NEXUS_NOT_INITIALIZED = 70,\n NEXUS_PROJECT_NOT_FOUND = 71,\n NEXUS_PERMISSION_DENIED = 72,\n NEXUS_INVALID_SYNTAX = 73,\n NEXUS_SYNC_FAILED = 74,\n NEXUS_REGISTRY_CORRUPT = 75,\n NEXUS_PROJECT_EXISTS = 76,\n NEXUS_QUERY_FAILED = 77,\n NEXUS_GRAPH_ERROR = 78,\n NEXUS_RESERVED = 79,\n\n // === LIFECYCLE ENFORCEMENT (80-84) ===\n LIFECYCLE_GATE_FAILED = 80,\n AUDIT_MISSING = 81,\n CIRCULAR_VALIDATION = 82,\n LIFECYCLE_TRANSITION_INVALID = 83,\n PROVENANCE_REQUIRED = 84,\n\n // === ARTIFACT PUBLISH (85-89) ===\n ARTIFACT_TYPE_UNKNOWN = 85,\n ARTIFACT_VALIDATION_FAILED = 86,\n ARTIFACT_BUILD_FAILED = 87,\n ARTIFACT_PUBLISH_FAILED = 88,\n ARTIFACT_ROLLBACK_FAILED = 89,\n\n // === PROVENANCE (90-94) ===\n PROVENANCE_CONFIG_INVALID = 90,\n SIGNING_KEY_MISSING = 91,\n SIGNATURE_INVALID = 92,\n DIGEST_MISMATCH = 93,\n ATTESTATION_INVALID = 94,\n\n // === STORAGE INTEGRITY (95-96) ===\n /** Empty DB created but sequence counter shows tasks exist (stale worktree). */\n DB_INTEGRITY_ERROR = 95,\n /** JSON data needs SQLite migration before accessor can be used. */\n MIGRATION_REQUIRED = 96,\n\n // === SPECIAL CODES (100+) - NOT errors ===\n NO_DATA = 100,\n ALREADY_EXISTS = 101,\n NO_CHANGE = 102,\n TESTS_SKIPPED = 103,\n}\n\n/** Check if an exit code represents an error (1-99). */\nexport function isErrorCode(code: ExitCode): boolean {\n return code >= 1 && code < 100;\n}\n\n/** Check if an exit code represents success (0 or 100+). */\nexport function isSuccessCode(code: ExitCode): boolean {\n return code === 0 || code >= 100;\n}\n\n/** Check if an exit code indicates no change (idempotent operation). */\nexport function isNoChangeCode(code: ExitCode): boolean {\n return code === ExitCode.NO_CHANGE;\n}\n\n/** Check if an exit code is recoverable (retry may succeed). */\nexport function isRecoverableCode(code: ExitCode): boolean {\n const nonRecoverable = new Set<ExitCode>([\n ExitCode.FILE_ERROR,\n ExitCode.DEPENDENCY_ERROR,\n ExitCode.CIRCULAR_REFERENCE,\n ExitCode.CASCADE_FAILED,\n ExitCode.SESSION_CLOSE_BLOCKED,\n ExitCode.VERIFICATION_LOCKED,\n ExitCode.CONTEXT_WARNING,\n ExitCode.CONTEXT_CAUTION,\n ExitCode.CONTEXT_CRITICAL,\n ExitCode.CONTEXT_EMERGENCY,\n ExitCode.CONTEXT_STALE,\n ExitCode.AUTONOMOUS_BOUNDARY,\n ExitCode.HANDOFF_REQUIRED,\n ExitCode.NEXUS_PERMISSION_DENIED,\n ExitCode.NEXUS_REGISTRY_CORRUPT,\n ExitCode.CIRCULAR_VALIDATION,\n ExitCode.LIFECYCLE_TRANSITION_INVALID,\n ExitCode.ARTIFACT_TYPE_UNKNOWN,\n ExitCode.ARTIFACT_ROLLBACK_FAILED,\n ExitCode.DIGEST_MISMATCH,\n ]);\n\n if (!isErrorCode(code)) return false;\n return !nonRecoverable.has(code);\n}\n\n/** Human-readable name for an exit code. */\nexport function getExitCodeName(code: ExitCode): string {\n return ExitCode[code] ?? 'UNKNOWN';\n}\n", "/**\n * CLEO error types with exit code integration and LAFS error shape.\n *\n * @epic T4654\n * @task T4655\n */\n\nimport type { LAFSError, LAFSErrorCategory } from '@cleocode/lafs-protocol';\nimport { ExitCode, getExitCodeName, isRecoverableCode } from '../types/exit-codes.js';\n\n/**\n * Map numeric exit codes to LAFS error category.\n *\n * @task T4655\n */\nfunction exitCodeToCategory(code: ExitCode): LAFSErrorCategory {\n if (code >= 1 && code <= 9) {\n switch (code) {\n case ExitCode.NOT_FOUND: return 'NOT_FOUND';\n case ExitCode.VALIDATION_ERROR: return 'VALIDATION';\n case ExitCode.CONFIG_ERROR: return 'VALIDATION';\n case ExitCode.LOCK_TIMEOUT: return 'CONFLICT';\n default: return 'INTERNAL';\n }\n }\n if (code >= 10 && code <= 19) return 'VALIDATION'; // hierarchy\n if (code >= 20 && code <= 29) return 'CONFLICT'; // concurrency\n if (code >= 30 && code <= 39) return 'CONTRACT'; // session\n if (code >= 40 && code <= 47) return 'VALIDATION'; // verification\n if (code >= 50 && code <= 54) return 'CONTRACT'; // context safeguard\n if (code >= 60 && code <= 67) return 'CONTRACT'; // orchestrator\n if (code >= 70 && code <= 79) return 'INTERNAL'; // nexus\n if (code >= 80 && code <= 84) return 'CONTRACT'; // lifecycle\n if (code >= 85 && code <= 89) return 'VALIDATION'; // artifact\n if (code >= 90 && code <= 94) return 'VALIDATION'; // provenance\n return 'INTERNAL';\n}\n\n/**\n * Map numeric exit code to LAFS string error code (E_CATEGORY_DETAIL).\n *\n * @task T4655\n */\nfunction exitCodeToLafsCode(code: ExitCode): string {\n const name = getExitCodeName(code);\n const category = exitCodeToCategory(code);\n return `E_${category}_${name}`;\n}\n\n/**\n * Structured error class for CLEO operations.\n * Carries an exit code, human-readable message, and optional fix suggestions.\n * Produces LAFS-conformant error shapes via toLAFSError().\n */\nexport class CleoError extends Error {\n readonly code: ExitCode;\n readonly fix?: string;\n readonly alternatives?: Array<{ action: string; command: string }>;\n\n constructor(\n code: ExitCode,\n message: string,\n options?: {\n fix?: string;\n alternatives?: Array<{ action: string; command: string }>;\n cause?: unknown;\n },\n ) {\n super(message, { cause: options?.cause });\n this.name = 'CleoError';\n this.code = code;\n this.fix = options?.fix;\n this.alternatives = options?.alternatives;\n }\n\n /**\n * Produce a LAFS-conformant error object.\n *\n * @task T4655\n */\n toLAFSError(): LAFSError {\n return {\n code: exitCodeToLafsCode(this.code),\n message: this.message,\n category: exitCodeToCategory(this.code),\n retryable: isRecoverableCode(this.code),\n retryAfterMs: null,\n details: {\n exitCode: this.code,\n name: getExitCodeName(this.code),\n ...(this.fix && { fix: this.fix }),\n ...(this.alternatives && { alternatives: this.alternatives }),\n },\n };\n }\n\n /** Structured JSON representation for LAFS output (backward compatible). */\n toJSON(): Record<string, unknown> {\n return {\n success: false,\n error: {\n code: this.code,\n name: getExitCodeName(this.code),\n message: this.message,\n ...(this.fix && { fix: this.fix }),\n ...(this.alternatives && { alternatives: this.alternatives }),\n },\n };\n }\n}\n", "/**\n * SQLite store via drizzle-orm + sql.js (WASM).\n *\n * Zero native bindings, cross-platform. Database stored at .cleo/tasks.db.\n * Lazy initialization: WASM only loaded when first database operation occurs.\n * Journal mode (not WAL) since sql.js is in-memory WASM with explicit save.\n *\n * @epic T4454\n * @task W1-T1\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { eq } from 'drizzle-orm';\nimport { drizzle } from 'drizzle-orm/sql-js';\nimport type { SQLJsDatabase } from 'drizzle-orm/sql-js';\nimport initSqlJs, { type Database as SqlJsNativeDb } from 'sql.js';\nimport * as schema from './schema.js';\nimport { getCleoDirAbsolute } from '../core/paths.js';\nimport { CleoError } from '../core/errors.js';\nimport { ExitCode } from '../types/exit-codes.js';\n\n/** Database file name within .cleo/ directory. */\nconst DB_FILENAME = 'tasks.db';\n\n/** Schema version stored in schema_meta table. */\nconst SCHEMA_VERSION = '2.0.0';\n\n/** Singleton state for lazy initialization. */\nlet _db: SQLJsDatabase<typeof schema> | null = null;\nlet _nativeDb: SqlJsNativeDb | null = null;\nlet _dbPath: string | null = null;\n\n/**\n * Get the path to the SQLite database file.\n */\nexport function getDbPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), DB_FILENAME);\n}\n\n/**\n * Initialize the SQLite database (lazy, singleton).\n * Creates the database file and tables if they don't exist.\n * Returns the drizzle ORM instance.\n */\nexport async function getDb(cwd?: string): Promise<SQLJsDatabase<typeof schema>> {\n const requestedPath = getDbPath(cwd);\n\n // If singleton exists but points to different path, reset it\n if (_db && _dbPath !== requestedPath) {\n resetDbState();\n }\n\n if (_db) return _db;\n\n const dbPath = requestedPath;\n _dbPath = dbPath;\n\n // Initialize sql.js WASM\n const SQL = await initSqlJs();\n\n // Load existing database or create new\n let nativeDb: SqlJsNativeDb;\n let wasNewlyCreated = false;\n if (existsSync(dbPath)) {\n const buffer = readFileSync(dbPath);\n nativeDb = new SQL.Database(buffer);\n } else {\n mkdirSync(dirname(dbPath), { recursive: true });\n nativeDb = new SQL.Database();\n wasNewlyCreated = true;\n }\n\n _nativeDb = nativeDb;\n\n // Create drizzle ORM wrapper\n const db = drizzle(nativeDb, { schema });\n _db = db;\n\n // Ensure tables exist\n await createTablesIfNeeded(nativeDb);\n\n // Guard: newly-created empty DB must not contradict an existing sequence counter\n if (wasNewlyCreated) {\n await verifyNewDbIsExpected(nativeDb, cwd);\n }\n\n return db;\n}\n\n/**\n * Create all tables if they don't exist.\n * Uses raw SQL since drizzle-kit migrations aren't needed for initial setup.\n */\nasync function createTablesIfNeeded(nativeDb: SqlJsNativeDb): Promise<void> {\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS tasks (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'pending'\n CHECK(status IN ('pending','active','blocked','done','cancelled','archived')),\n priority TEXT NOT NULL DEFAULT 'medium'\n CHECK(priority IN ('critical','high','medium','low')),\n type TEXT CHECK(type IN ('epic','task','subtask')),\n parent_id TEXT REFERENCES tasks(id),\n phase TEXT,\n size TEXT CHECK(size IN ('small','medium','large')),\n position INTEGER,\n position_version INTEGER DEFAULT 0,\n labels_json TEXT DEFAULT '[]',\n notes_json TEXT DEFAULT '[]',\n acceptance_json TEXT DEFAULT '[]',\n files_json TEXT DEFAULT '[]',\n origin TEXT,\n blocked_by TEXT,\n epic_lifecycle TEXT,\n no_auto_complete INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT,\n completed_at TEXT,\n cancelled_at TEXT,\n cancellation_reason TEXT,\n archived_at TEXT,\n archive_reason TEXT,\n cycle_time_days INTEGER,\n verification_json TEXT,\n created_by TEXT,\n modified_by TEXT,\n session_id TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_dependencies (\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n depends_on TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n PRIMARY KEY (task_id, depends_on)\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_relations (\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n related_to TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n relation_type TEXT NOT NULL DEFAULT 'related'\n CHECK(relation_type IN ('related','blocks','duplicates')),\n PRIMARY KEY (task_id, related_to)\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'active'\n CHECK(status IN ('active','ended','orphaned','suspended')),\n scope_json TEXT NOT NULL DEFAULT '{}',\n current_task TEXT,\n task_started_at TEXT,\n agent TEXT,\n notes_json TEXT DEFAULT '[]',\n tasks_completed_json TEXT DEFAULT '[]',\n tasks_created_json TEXT DEFAULT '[]',\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n ended_at TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_work_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n task_id TEXT NOT NULL,\n set_at TEXT NOT NULL DEFAULT (datetime('now')),\n cleared_at TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n // Create lifecycle pipeline tables\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS lifecycle_pipelines (\n id TEXT PRIMARY KEY,\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'active'\n CHECK(status IN ('active','completed','aborted')),\n current_stage_id TEXT,\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT,\n aborted_at TEXT,\n abort_reason TEXT,\n metadata_json TEXT DEFAULT '{}'\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS lifecycle_stages (\n id TEXT PRIMARY KEY,\n pipeline_id TEXT NOT NULL REFERENCES lifecycle_pipelines(id) ON DELETE CASCADE,\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n stage_name TEXT NOT NULL\n CHECK(stage_name IN ('research','consensus','adr','spec','decompose','implement','verify','test','release')),\n sequence INTEGER NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending'\n CHECK(status IN ('pending','active','blocked','completed','skipped')),\n started_at TEXT,\n completed_at TEXT,\n blocked_at TEXT,\n block_reason TEXT,\n skipped_at TEXT,\n skip_reason TEXT,\n notes_json TEXT DEFAULT '[]',\n metadata_json TEXT DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS lifecycle_transitions (\n id TEXT PRIMARY KEY,\n pipeline_id TEXT NOT NULL REFERENCES lifecycle_pipelines(id) ON DELETE CASCADE,\n from_stage_id TEXT NOT NULL REFERENCES lifecycle_stages(id) ON DELETE CASCADE,\n to_stage_id TEXT NOT NULL REFERENCES lifecycle_stages(id) ON DELETE CASCADE,\n transition_type TEXT NOT NULL DEFAULT 'manual'\n CHECK(transition_type IN ('auto','manual','conditional')),\n condition_json TEXT DEFAULT '{}',\n requires_gate INTEGER DEFAULT 1,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS lifecycle_gate_results (\n id TEXT PRIMARY KEY,\n stage_id TEXT NOT NULL REFERENCES lifecycle_stages(id) ON DELETE CASCADE,\n gate_name TEXT NOT NULL,\n result TEXT NOT NULL\n CHECK(result IN ('pass','fail','warn')),\n checked_at TEXT NOT NULL DEFAULT (datetime('now')),\n checked_by TEXT NOT NULL,\n details TEXT,\n reason TEXT,\n metadata_json TEXT DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS lifecycle_evidence (\n id TEXT PRIMARY KEY,\n stage_id TEXT NOT NULL REFERENCES lifecycle_stages(id) ON DELETE CASCADE,\n uri TEXT NOT NULL,\n type TEXT NOT NULL\n CHECK(type IN ('file','url','manifest')),\n recorded_at TEXT NOT NULL DEFAULT (datetime('now')),\n recorded_by TEXT,\n description TEXT,\n metadata_json TEXT DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS architecture_decisions (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'proposed'\n CHECK(status IN ('proposed','accepted','superseded','deprecated')),\n context TEXT,\n decision TEXT,\n rationale TEXT,\n consequences TEXT,\n consequences_json TEXT DEFAULT '{}',\n downstream_impact_json TEXT DEFAULT '[]',\n content TEXT,\n supersedes_id TEXT,\n superseded_by_id TEXT,\n consensus_manifest_id TEXT,\n task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,\n tags_json TEXT DEFAULT '[]',\n metadata_json TEXT DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT,\n accepted_at TEXT,\n deprecated_at TEXT\n );\n `);\n\n // Create indexes (IF NOT EXISTS)\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_parent_id ON tasks(parent_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_phase ON tasks(phase);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_type ON tasks(type);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_deps_depends_on ON task_dependencies(depends_on);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_work_history_session ON task_work_history(session_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_pipelines_task_id ON lifecycle_pipelines(task_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_pipelines_status ON lifecycle_pipelines(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_stages_pipeline_id ON lifecycle_stages(pipeline_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_stages_task_id ON lifecycle_stages(task_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_stages_status ON lifecycle_stages(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_stages_sequence ON lifecycle_stages(sequence);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_transitions_pipeline_id ON lifecycle_transitions(pipeline_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_transitions_from_stage ON lifecycle_transitions(from_stage_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_transitions_to_stage ON lifecycle_transitions(to_stage_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_gate_results_stage_id ON lifecycle_gate_results(stage_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_gate_results_gate_name ON lifecycle_gate_results(gate_name);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_gate_results_result ON lifecycle_gate_results(result);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_gate_results_checked_at ON lifecycle_gate_results(checked_at);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_evidence_stage_id ON lifecycle_evidence(stage_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_evidence_type ON lifecycle_evidence(type);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_lifecycle_evidence_recorded_at ON lifecycle_evidence(recorded_at);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_architecture_decisions_status ON architecture_decisions(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_architecture_decisions_task_id ON architecture_decisions(task_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_architecture_decisions_supersedes ON architecture_decisions(supersedes_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_architecture_decisions_superseded_by ON architecture_decisions(superseded_by_id);');\n\n // Set schema version\n nativeDb.run(\n `INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schemaVersion', '${SCHEMA_VERSION}')`,\n );\n\n // Save to disk\n saveToFile();\n}\n\n/**\n * Verify that a newly-created empty database is expected given the sequence state.\n * Throws CleoError(DB_INTEGRITY_ERROR) if .sequence.json reports tasks exist but DB is empty.\n * Ignores non-CleoError failures to avoid blocking DB initialization.\n */\nasync function verifyNewDbIsExpected(nativeDb: SqlJsNativeDb, cwd?: string): Promise<void> {\n try {\n const sequencePath = join(getCleoDirAbsolute(cwd), '.sequence.json');\n if (!existsSync(sequencePath)) return; // New project, OK\n\n const raw = readFileSync(sequencePath, 'utf8');\n const seq = JSON.parse(raw) as { counter: number; lastId: string; checksum: string };\n const counter = seq?.counter ?? 0;\n\n if (counter === 0) return; // No tasks expected\n\n // nativeDb.exec() is the sql.js SQLite API (not child_process.exec)\n const result = nativeDb.exec('SELECT COUNT(*) FROM tasks');\n const taskCount = (result[0]?.values?.[0]?.[0] ?? 0) as number;\n\n if (taskCount === 0 && counter > 0) {\n throw new CleoError(\n ExitCode.DB_INTEGRITY_ERROR,\n `Empty database created but .sequence.json shows ${counter} tasks exist. You may be in a stale git worktree or missing a migration. Run: cleo migrate-storage --status`,\n );\n }\n } catch (err) {\n if (err instanceof CleoError) throw err;\n // Ignore other errors (parse failures, fs errors) \u2014 don't block DB init\n }\n}\n\n/**\n * Save the in-memory database to disk.\n * Must be called after any write operation since sql.js is in-memory.\n */\nexport function saveToFile(): void {\n if (!_nativeDb || !_dbPath) return;\n const data = _nativeDb.export();\n const buffer = Buffer.from(data);\n mkdirSync(dirname(_dbPath), { recursive: true });\n writeFileSync(_dbPath, buffer);\n}\n\n/**\n * Close the database connection and release resources.\n */\nexport function closeDb(): void {\n if (_nativeDb) {\n saveToFile();\n _nativeDb.close();\n _nativeDb = null;\n }\n _db = null;\n _dbPath = null;\n}\n\n/**\n * Reset database singleton state without saving.\n * Used during migrations when database file is deleted and recreated.\n * Safe to call multiple times.\n */\nexport function resetDbState(): void {\n if (_nativeDb) {\n try {\n _nativeDb.close();\n } catch {\n // Ignore close errors\n }\n _nativeDb = null;\n }\n _db = null;\n _dbPath = null;\n}\n\n/**\n * Get the schema version from the database.\n */\nexport async function getSchemaVersion(cwd?: string): Promise<string | null> {\n const db = await getDb(cwd);\n const result = db\n .select()\n .from(schema.schemaMeta)\n .where(eq(schema.schemaMeta.key, 'schemaVersion'))\n .all();\n\n return result[0]?.value ?? null;\n}\n\n/**\n * Check if the database file exists.\n */\nexport function dbExists(cwd?: string): boolean {\n return existsSync(getDbPath(cwd));\n}\n\n/**\n * Re-export schema for external use.\n */\nexport { schema };\nexport type { SQLJsDatabase };\n", "/**\n * Atomic file write operations using write-file-atomic.\n * Ensures writes are crash-safe: temp file -> validate -> rename.\n * @epic T4454\n * @task T4457\n * @task T4721 - Added atomic database operations\n */\n\nimport writeFileAtomic from 'write-file-atomic';\nimport { readFile, mkdir, rename, unlink } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { CleoError } from '../core/errors.js';\nimport { ExitCode } from '../types/exit-codes.js';\n\n/**\n * Write data to a file atomically.\n * Creates parent directories if they don't exist.\n * Uses write-file-atomic for crash-safe writes (temp file -> rename).\n */\nexport async function atomicWrite(\n filePath: string,\n data: string,\n options?: { mode?: number; encoding?: BufferEncoding },\n): Promise<void> {\n try {\n await mkdir(dirname(filePath), { recursive: true });\n await writeFileAtomic(filePath, data, {\n encoding: options?.encoding ?? 'utf8',\n mode: options?.mode,\n });\n } catch (err) {\n throw new CleoError(\n ExitCode.FILE_ERROR,\n `Atomic write failed: ${filePath}`,\n { cause: err },\n );\n }\n}\n\n/**\n * Read a file and return its contents.\n * Returns null if the file does not exist.\n */\nexport async function safeReadFile(filePath: string): Promise<string | null> {\n try {\n return await readFile(filePath, 'utf8');\n } catch (err: unknown) {\n if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw new CleoError(\n ExitCode.FILE_ERROR,\n `Failed to read: ${filePath}`,\n { cause: err },\n );\n }\n}\n\n/**\n * Write JSON data atomically with consistent formatting.\n */\nexport async function atomicWriteJson(\n filePath: string,\n data: unknown,\n options?: { indent?: number },\n): Promise<void> {\n const json = JSON.stringify(data, null, options?.indent ?? 2) + '\\n';\n await atomicWrite(filePath, json);\n}\n\n/**\n * Atomic database migration result.\n */\nexport interface AtomicMigrationResult {\n success: boolean;\n tempPath: string;\n backupPath?: string;\n error?: string;\n}\n\n/**\n * Perform atomic database migration using rename operations.\n *\n * Pattern:\n * 1. Write new database to temp file (tasks.db.new)\n * 2. Validate temp database integrity\n * 3. Rename existing tasks.db \u2192 tasks.db.backup\n * 4. Rename temp \u2192 tasks.db (atomic)\n * 5. Only delete backup on success\n *\n * @param dbPath - Path to the database file (e.g., tasks.db)\n * @param tempPath - Path to temporary database (e.g., tasks.db.new)\n * @param validateFn - Async function to validate the temp database\n * @returns Result with paths and success status\n */\nexport async function atomicDatabaseMigration(\n dbPath: string,\n tempPath: string,\n validateFn: (path: string) => Promise<boolean>,\n): Promise<AtomicMigrationResult> {\n const backupPath = `${dbPath}.backup`;\n\n try {\n // Step 1: Validate temp database exists\n if (!existsSync(tempPath)) {\n throw new Error(`Temp database not found: ${tempPath}`);\n }\n\n // Step 2: Validate the temp database integrity\n const isValid = await validateFn(tempPath);\n if (!isValid) {\n throw new Error(`Temp database validation failed: ${tempPath}`);\n }\n\n // Step 3: If existing database exists, rename to backup\n if (existsSync(dbPath)) {\n await rename(dbPath, backupPath);\n }\n\n // Step 4: Atomically rename temp to final (atomic on POSIX systems)\n await rename(tempPath, dbPath);\n\n return {\n success: true,\n tempPath,\n backupPath: existsSync(backupPath) ? backupPath : undefined,\n };\n } catch (err) {\n return {\n success: false,\n tempPath,\n backupPath: existsSync(backupPath) ? backupPath : undefined,\n error: String(err),\n };\n }\n}\n\n/**\n * Restore database from backup after failed migration.\n *\n * @param dbPath - Path to the database file\n * @param backupPath - Path to the backup file\n * @returns true if restore succeeded\n */\nexport async function restoreDatabaseFromBackup(\n dbPath: string,\n backupPath: string,\n): Promise<boolean> {\n try {\n if (!existsSync(backupPath)) {\n return false;\n }\n\n // If a partial database exists, remove it\n if (existsSync(dbPath)) {\n await unlink(dbPath);\n }\n\n // Restore from backup\n await rename(backupPath, dbPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Clean up migration artifacts after successful migration.\n *\n * @param backupPath - Path to backup file to delete\n * @returns true if cleanup succeeded\n */\nexport async function cleanupMigrationArtifacts(backupPath: string): Promise<boolean> {\n try {\n if (existsSync(backupPath)) {\n await unlink(backupPath);\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Validate SQLite database integrity by attempting to open it.\n *\n * @param dbPath - Path to database file\n * @returns true if database is valid\n */\nexport async function validateSqliteDatabase(dbPath: string): Promise<boolean> {\n try {\n const initSqlJs = (await import('sql.js')).default;\n const { readFileSync } = await import('node:fs');\n\n const SQL = await initSqlJs();\n const buffer = readFileSync(dbPath);\n const db = new SQL.Database(buffer);\n\n // Try to run a simple query to verify integrity\n db.run('PRAGMA integrity_check;');\n\n // Check for basic tables\n const result = db.exec(\"SELECT name FROM sqlite_master WHERE type='table' AND name='tasks';\");\n const hasTasksTable = result.length > 0 && result[0].values.length > 0;\n\n db.close();\n return hasTasksTable;\n } catch {\n return false;\n }\n}\n", "/**\n * Numbered backup system for CLEO data files.\n * Maintains a rotating window of recent backups for rollback protection.\n * @epic T4454\n * @task T4457\n */\n\nimport { copyFile, rename as fsRename, readdir, unlink, stat, mkdir } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { CleoError } from '../core/errors.js';\nimport { ExitCode } from '../types/exit-codes.js';\n\nconst DEFAULT_MAX_BACKUPS = 5;\n\n/**\n * Create a numbered backup of a file.\n * Rotates existing backups (file.1 -> file.2, etc.) and removes excess.\n */\nexport async function createBackup(\n filePath: string,\n backupDir: string,\n maxBackups: number = DEFAULT_MAX_BACKUPS,\n): Promise<string> {\n try {\n await mkdir(backupDir, { recursive: true });\n\n const fileName = basename(filePath);\n\n // Check if source file exists\n try {\n await stat(filePath);\n } catch {\n throw new CleoError(\n ExitCode.FILE_ERROR,\n `Cannot backup: source file not found: ${filePath}`,\n );\n }\n\n // Rotate existing backups (shift numbers up)\n for (let i = maxBackups; i >= 1; i--) {\n const current = join(backupDir, `${fileName}.${i}`);\n if (i === maxBackups) {\n // Remove oldest backup\n try {\n await unlink(current);\n } catch {\n // File may not exist\n }\n } else {\n const next = join(backupDir, `${fileName}.${i + 1}`);\n try {\n await stat(current);\n await fsRename(current, next);\n } catch {\n // File may not exist\n }\n }\n }\n\n // Create new backup as .1\n const backupPath = join(backupDir, `${fileName}.1`);\n await copyFile(filePath, backupPath);\n return backupPath;\n } catch (err) {\n if (err instanceof CleoError) throw err;\n throw new CleoError(\n ExitCode.FILE_ERROR,\n `Backup failed for: ${filePath}`,\n { cause: err },\n );\n }\n}\n\n/**\n * List existing backups for a file, sorted by number (newest first).\n */\nexport async function listBackups(\n fileName: string,\n backupDir: string,\n): Promise<string[]> {\n try {\n const entries = await readdir(backupDir);\n const prefix = `${fileName}.`;\n return entries\n .filter((e) => e.startsWith(prefix) && /^\\d+$/.test(e.slice(prefix.length)))\n .sort((a, b) => {\n const numA = parseInt(a.slice(prefix.length), 10);\n const numB = parseInt(b.slice(prefix.length), 10);\n return numA - numB;\n })\n .map((e) => join(backupDir, e));\n } catch {\n return [];\n }\n}\n\n/**\n * Restore a file from its most recent backup.\n * Returns the path of the backup that was restored.\n */\nexport async function restoreFromBackup(\n fileName: string,\n backupDir: string,\n targetPath: string,\n): Promise<string> {\n const backups = await listBackups(fileName, backupDir);\n if (backups.length === 0) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `No backups found for: ${fileName}`,\n );\n }\n const newest = backups[0]!;\n await copyFile(newest, targetPath);\n return newest;\n}\n", "/**\n * File locking using proper-lockfile.\n * Prevents concurrent modifications to CLEO data files.\n * @epic T4454\n * @task T4457\n */\n\nimport lockfile from 'proper-lockfile';\nimport { CleoError } from '../core/errors.js';\nimport { ExitCode } from '../types/exit-codes.js';\n\n/** Default lock options. */\nconst DEFAULT_LOCK_OPTIONS = {\n retries: {\n retries: 3,\n minTimeout: 100,\n maxTimeout: 1000,\n factor: 2,\n },\n stale: 10_000,\n realpath: false,\n};\n\n/** A release function returned by acquireLock. */\nexport type ReleaseFn = () => Promise<void>;\n\n/**\n * Acquire an exclusive lock on a file.\n * Returns a release function that must be called when done.\n */\nexport async function acquireLock(\n filePath: string,\n options?: { stale?: number; retries?: number },\n): Promise<ReleaseFn> {\n try {\n const release = await lockfile.lock(filePath, {\n ...DEFAULT_LOCK_OPTIONS,\n ...(options?.stale !== undefined && { stale: options.stale }),\n ...(options?.retries !== undefined && {\n retries: {\n ...DEFAULT_LOCK_OPTIONS.retries,\n retries: options.retries,\n },\n }),\n });\n return release;\n } catch (err) {\n throw new CleoError(\n ExitCode.LOCK_TIMEOUT,\n `Failed to acquire lock: ${filePath}`,\n {\n fix: `Another process may be writing to this file. Wait and retry.`,\n cause: err,\n },\n );\n }\n}\n\n/**\n * Check if a file is currently locked.\n */\nexport async function isLocked(filePath: string): Promise<boolean> {\n try {\n return await lockfile.check(filePath, { realpath: false });\n } catch {\n return false;\n }\n}\n\n/**\n * Execute a function while holding an exclusive lock on a file.\n * The lock is automatically released when the function completes (or throws).\n */\nexport async function withLock<T>(\n filePath: string,\n fn: () => Promise<T>,\n options?: { stale?: number; retries?: number },\n): Promise<T> {\n const release = await acquireLock(filePath, options);\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n", "/**\n * JSON read/write with schema validation, locking, and backup.\n * This is the primary data access layer for CLEO data files.\n * @epic T4454\n * @task T4457\n */\n\nimport { createHash } from 'node:crypto';\nimport { atomicWrite, atomicWriteJson, safeReadFile } from './atomic.js';\nimport { createBackup } from './backup.js';\nimport { withLock } from './lock.js';\nimport { CleoError } from '../core/errors.js';\nimport { ExitCode } from '../types/exit-codes.js';\n\n/**\n * Read and parse a JSON file.\n * Returns null if the file does not exist.\n */\nexport async function readJson<T = unknown>(filePath: string): Promise<T | null> {\n const content = await safeReadFile(filePath);\n if (content === null) return null;\n\n try {\n return JSON.parse(content) as T;\n } catch (err) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid JSON in: ${filePath}`,\n { cause: err },\n );\n }\n}\n\n/**\n * Read a JSON file, throwing if it doesn't exist.\n */\nexport async function readJsonRequired<T = unknown>(filePath: string): Promise<T> {\n const data = await readJson<T>(filePath);\n if (data === null) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Required file not found: ${filePath}`,\n );\n }\n return data;\n}\n\n/**\n * Compute a truncated SHA-256 checksum of a value.\n * Used for integrity verification (matches Bash CLI's 16-char hex format).\n */\nexport function computeChecksum(data: unknown): string {\n const json = JSON.stringify(data);\n const hash = createHash('sha256').update(json).digest('hex');\n return hash.substring(0, 16);\n}\n\n/** Options for saveJson. */\nexport interface SaveJsonOptions {\n /** Directory for backups. If omitted, no backup is created. */\n backupDir?: string;\n /** Maximum number of backups to retain. Default: 5. */\n maxBackups?: number;\n /** JSON indentation. Default: 2. */\n indent?: number;\n /** Validation function. Called before write; throw to abort. */\n validate?: (data: unknown) => void | Promise<void>;\n}\n\n/**\n * Save JSON data with optional locking, backup, and validation.\n * Follows the CLEO atomic write pattern:\n * 1. Acquire lock\n * 2. Validate data\n * 3. Create backup of existing file\n * 4. Atomic write (temp file -> rename)\n * 5. Release lock\n */\nexport async function saveJson(\n filePath: string,\n data: unknown,\n options?: SaveJsonOptions,\n): Promise<void> {\n await withLock(filePath, async () => {\n // Validate before write\n if (options?.validate) {\n try {\n await options.validate(data);\n } catch (err) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Validation failed before write: ${filePath}`,\n { cause: err },\n );\n }\n }\n\n // Create backup if configured\n if (options?.backupDir) {\n try {\n await createBackup(filePath, options.backupDir, options.maxBackups);\n } catch {\n // Backup failure is non-fatal for first write (file may not exist yet)\n }\n }\n\n // Atomic write\n await atomicWriteJson(filePath, data, { indent: options?.indent });\n });\n}\n\n/**\n * Append a line to a JSONL file atomically.\n * Used for manifest entries and audit logs.\n */\nexport async function appendJsonl(\n filePath: string,\n entry: unknown,\n): Promise<void> {\n const existing = await safeReadFile(filePath);\n const line = JSON.stringify(entry);\n const content = existing ? existing.trimEnd() + '\\n' + line + '\\n' : line + '\\n';\n await atomicWrite(filePath, content);\n}\n\n/**\n * Read log entries from a hybrid JSON/JSONL file.\n * Handles three formats:\n * 1. Pure JSON: `{ \"entries\": [...] }` (legacy bash format)\n * 2. Pure JSONL: one JSON object per line (new TS format)\n * 3. Hybrid: JSON object followed by JSONL lines (migration state)\n * Returns a flat array of all entries found.\n * @task T4622\n */\nexport async function readLogEntries(filePath: string): Promise<Record<string, unknown>[]> {\n const content = await safeReadFile(filePath);\n if (content === null) return [];\n\n const trimmed = content.trim();\n if (!trimmed) return [];\n\n // Fast path: try parsing as a single JSON object\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) return parsed as Record<string, unknown>[];\n if (parsed && typeof parsed === 'object' && Array.isArray(parsed.entries)) {\n return parsed.entries as Record<string, unknown>[];\n }\n // Single object, wrap in array\n return [parsed as Record<string, unknown>];\n } catch {\n // Not valid JSON - handle hybrid format\n }\n\n // Hybrid format: find where the initial JSON object ends, then parse JSONL after it\n const entries: Record<string, unknown>[] = [];\n\n if (trimmed.startsWith('{')) {\n // Find the matching closing brace for the initial JSON object\n let depth = 0;\n let inString = false;\n let escaped = false;\n let jsonEnd = -1;\n\n for (let i = 0; i < trimmed.length; i++) {\n const ch = trimmed[i]!;\n if (escaped) { escaped = false; continue; }\n if (ch === '\\\\' && inString) { escaped = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) { jsonEnd = i + 1; break; }\n }\n }\n\n if (jsonEnd > 0) {\n // Parse the initial JSON object\n try {\n const initialJson = JSON.parse(trimmed.substring(0, jsonEnd));\n if (initialJson && Array.isArray(initialJson.entries)) {\n entries.push(...(initialJson.entries as Record<string, unknown>[]));\n }\n } catch {\n // Corrupted initial JSON - skip it\n }\n\n // Parse remaining lines as JSONL\n const remainder = trimmed.substring(jsonEnd).trim();\n if (remainder) {\n for (const line of remainder.split('\\n')) {\n const l = line.trim();\n if (!l || !l.startsWith('{')) continue;\n try {\n entries.push(JSON.parse(l) as Record<string, unknown>);\n } catch {\n // Skip unparseable lines\n }\n }\n }\n }\n } else {\n // Pure JSONL (no initial JSON object)\n for (const line of trimmed.split('\\n')) {\n const l = line.trim();\n if (!l || !l.startsWith('{')) continue;\n try {\n entries.push(JSON.parse(l) as Record<string, unknown>);\n } catch {\n // Skip unparseable lines\n }\n }\n }\n\n return entries;\n}\n", "/**\n * Git checkpoint system for CLEO state files.\n * Ported from lib/data/git-checkpoint.sh\n *\n * Opt-in automatic git commits of .cleo/ state files at semantic\n * boundaries (save_json, session end) with debounce to prevent commit noise.\n * All git errors are suppressed - checkpointing is never fatal.\n *\n * @task T4552\n * @epic T4545\n */\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { join } from 'node:path';\nimport { getCleoDir, getConfigPath } from '../core/paths.js';\nimport { readJson } from './json.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * State files eligible for checkpointing (relative to .cleo/).\n * Includes both JSON and SQLite data files \u2014 `getChangedStateFiles()` skips\n * files that don't exist on disk, so listing both engines is safe.\n */\nconst STATE_FILES = [\n // Core data (JSON engine)\n 'todo.json',\n 'todo-archive.json',\n 'sessions.json',\n // Core data (SQLite engine)\n 'tasks.db',\n // Always-present files\n 'config.json',\n 'todo-log.jsonl',\n '.sequence.json',\n 'project-context.json',\n // Metrics\n 'metrics/COMPLIANCE.jsonl',\n 'metrics/SESSIONS.jsonl',\n 'metrics/TOKEN_USAGE.jsonl',\n 'metrics/BENCHMARK.jsonl',\n] as const;\n\n/** Debounce state file name (relative to .cleo/). */\nconst CHECKPOINT_STATE_FILE = '.git-checkpoint-state';\n\n/** Checkpoint configuration. */\nexport interface CheckpointConfig {\n enabled: boolean;\n debounceMinutes: number;\n messagePrefix: string;\n noVerify: boolean;\n}\n\n/** Checkpoint status information. */\nexport interface CheckpointStatus {\n config: CheckpointConfig;\n status: {\n isGitRepo: boolean;\n lastCheckpoint: string;\n lastCheckpointEpoch: number;\n pendingChanges: number;\n suppressed: boolean;\n };\n}\n\n/** Changed file with its status. */\nexport interface ChangedFile {\n path: string;\n status: 'modified' | 'untracked';\n}\n\n/**\n * Load checkpoint configuration from config.json.\n * @task T4552\n */\nexport async function loadCheckpointConfig(cwd?: string): Promise<CheckpointConfig> {\n try {\n const configPath = getConfigPath(cwd);\n const config = await readJson<Record<string, unknown>>(configPath);\n const gc = (config as Record<string, Record<string, unknown>> | null)?.gitCheckpoint;\n\n return {\n enabled: gc?.enabled !== false,\n debounceMinutes: typeof gc?.debounceMinutes === 'number' ? gc.debounceMinutes : 5,\n messagePrefix: typeof gc?.messagePrefix === 'string' ? gc.messagePrefix : 'chore(cleo):',\n noVerify: gc?.noVerify !== false,\n };\n } catch {\n return {\n enabled: true,\n debounceMinutes: 5,\n messagePrefix: 'chore(cleo):',\n noVerify: true,\n };\n }\n}\n\n/**\n * Run a git command, suppressing errors.\n * @task T4552\n */\nasync function gitCommand(args: string[], cwd?: string): Promise<{ stdout: string; success: boolean }> {\n try {\n const result = await execFileAsync('git', args, {\n cwd: cwd ?? process.cwd(),\n timeout: 10_000,\n });\n return { stdout: result.stdout.trim(), success: true };\n } catch {\n return { stdout: '', success: false };\n }\n}\n\n/**\n * Check if we're inside a git work tree.\n * @task T4552\n */\nasync function isGitRepo(cwd?: string): Promise<boolean> {\n const result = await gitCommand(['rev-parse', '--is-inside-work-tree'], cwd);\n return result.success && result.stdout === 'true';\n}\n\n/**\n * Check if a merge is in progress.\n * @task T4552\n */\nasync function isMergeInProgress(cwd?: string): Promise<boolean> {\n const result = await gitCommand(['rev-parse', '--git-dir'], cwd);\n if (!result.success) return false;\n return existsSync(join(result.stdout, 'MERGE_HEAD'));\n}\n\n/**\n * Check if HEAD is detached.\n * @task T4552\n */\nasync function isDetachedHead(cwd?: string): Promise<boolean> {\n const result = await gitCommand(['symbolic-ref', 'HEAD'], cwd);\n return !result.success;\n}\n\n/**\n * Check if a rebase is in progress.\n * @task T4552\n */\nasync function isRebaseInProgress(cwd?: string): Promise<boolean> {\n const result = await gitCommand(['rev-parse', '--git-dir'], cwd);\n if (!result.success) return false;\n return existsSync(join(result.stdout, 'rebase-merge')) ||\n existsSync(join(result.stdout, 'rebase-apply'));\n}\n\n/**\n * Record the current time as the last checkpoint time.\n * @task T4552\n */\nasync function recordCheckpointTime(cleoDir: string): Promise<void> {\n try {\n const stateFile = join(cleoDir, CHECKPOINT_STATE_FILE);\n await writeFile(stateFile, String(Math.floor(Date.now() / 1000)));\n } catch {\n // Non-fatal\n }\n}\n\n/**\n * Get the epoch time of the last checkpoint.\n * @task T4552\n */\nasync function getLastCheckpointTime(cleoDir: string): Promise<number> {\n try {\n const stateFile = join(cleoDir, CHECKPOINT_STATE_FILE);\n const content = await readFile(stateFile, 'utf-8');\n const epoch = parseInt(content.trim(), 10);\n return isNaN(epoch) ? 0 : epoch;\n } catch {\n return 0;\n }\n}\n\n/**\n * Get list of state files with pending changes.\n * @task T4552\n */\nasync function getChangedStateFiles(cleoDir: string, cwd?: string): Promise<ChangedFile[]> {\n const changed: ChangedFile[] = [];\n\n for (const stateFile of STATE_FILES) {\n const fullPath = join(cleoDir, stateFile);\n if (!existsSync(fullPath)) continue;\n\n // Check for staged or unstaged changes\n const diffResult = await gitCommand(['diff', '--quiet', '--', fullPath], cwd);\n const cachedResult = await gitCommand(['diff', '--cached', '--quiet', '--', fullPath], cwd);\n const untrackedResult = await gitCommand(\n ['ls-files', '--others', '--exclude-standard', '--', fullPath],\n cwd,\n );\n\n if (!diffResult.success || !cachedResult.success) {\n changed.push({ path: fullPath, status: 'modified' });\n } else if (untrackedResult.stdout.length > 0) {\n changed.push({ path: fullPath, status: 'untracked' });\n }\n }\n\n return changed;\n}\n\n/**\n * Check whether a checkpoint should be performed.\n * Evaluates: enabled, git repo, debounce elapsed, files changed.\n * @task T4552\n */\nexport async function shouldCheckpoint(\n options?: { force?: boolean; cwd?: string },\n): Promise<boolean> {\n const force = options?.force ?? false;\n const cwd = options?.cwd;\n\n // Suppression check (even force doesn't override explicit suppression)\n if (process.env['GIT_CHECKPOINT_SUPPRESS'] === 'true') {\n return false;\n }\n\n const config = await loadCheckpointConfig(cwd);\n\n if (!config.enabled) return false;\n if (!(await isGitRepo(cwd))) return false;\n if (await isMergeInProgress(cwd)) return false;\n if (await isDetachedHead(cwd)) return false;\n if (await isRebaseInProgress(cwd)) return false;\n\n const cleoDir = getCleoDir(cwd);\n if (!existsSync(cleoDir)) return false;\n\n // Check debounce (unless forced)\n if (!force) {\n const lastCheckpoint = await getLastCheckpointTime(cleoDir);\n const now = Math.floor(Date.now() / 1000);\n const elapsed = now - lastCheckpoint;\n const debounceSeconds = config.debounceMinutes * 60;\n\n if (elapsed < debounceSeconds) return false;\n }\n\n // Check if any state files have changes\n const changed = await getChangedStateFiles(cleoDir, cwd);\n return changed.length > 0;\n}\n\n/**\n * Stage .cleo/ state files and commit if conditions met.\n * Never fatal - all git errors are suppressed.\n * @task T4552\n */\nexport async function gitCheckpoint(\n trigger: 'auto' | 'session-end' | 'manual' = 'auto',\n context?: string,\n cwd?: string,\n): Promise<void> {\n // Suppression check\n if (process.env['GIT_CHECKPOINT_SUPPRESS'] === 'true') {\n return;\n }\n\n const force = trigger === 'manual';\n\n if (!(await shouldCheckpoint({ force, cwd }))) {\n return;\n }\n\n const config = await loadCheckpointConfig(cwd);\n const cleoDir = getCleoDir(cwd);\n const changed = await getChangedStateFiles(cleoDir, cwd);\n\n if (changed.length === 0) return;\n\n // Stage changed files\n let stagedCount = 0;\n for (const file of changed) {\n const result = await gitCommand(['add', file.path], cwd);\n if (result.success) stagedCount++;\n }\n\n if (stagedCount === 0) return;\n\n // Build commit message\n let commitMsg = `${config.messagePrefix} ${trigger} checkpoint`;\n if (context) {\n commitMsg = `${config.messagePrefix} ${trigger} checkpoint (${context})`;\n }\n\n // Build commit args\n const commitArgs = ['commit', '-m', commitMsg];\n if (config.noVerify) {\n commitArgs.push('--no-verify');\n }\n\n // Commit\n const commitResult = await gitCommand(commitArgs, cwd);\n\n if (!commitResult.success) {\n // If commit failed, unstage our changes\n for (const file of changed) {\n await gitCommand(['reset', 'HEAD', '--', file.path], cwd);\n }\n return;\n }\n\n // Record checkpoint time\n await recordCheckpointTime(cleoDir);\n}\n\n/**\n * Show checkpoint configuration and status.\n * @task T4552\n */\nexport async function gitCheckpointStatus(cwd?: string): Promise<CheckpointStatus> {\n const config = await loadCheckpointConfig(cwd);\n const cleoDir = getCleoDir(cwd);\n const lastCheckpoint = await getLastCheckpointTime(cleoDir);\n\n let lastCheckpointIso = 'never';\n if (lastCheckpoint !== 0) {\n lastCheckpointIso = new Date(lastCheckpoint * 1000).toISOString();\n }\n\n const isRepo = await isGitRepo(cwd);\n\n let pendingChanges = 0;\n if (isRepo) {\n const changed = await getChangedStateFiles(cleoDir, cwd);\n pendingChanges = changed.length;\n }\n\n const suppressed = process.env['GIT_CHECKPOINT_SUPPRESS'] === 'true';\n\n return {\n config,\n status: {\n isGitRepo: isRepo,\n lastCheckpoint: lastCheckpointIso,\n lastCheckpointEpoch: lastCheckpoint,\n pendingChanges,\n suppressed,\n },\n };\n}\n\n/**\n * Show what files would be committed (dry-run).\n * @task T4552\n */\nexport async function gitCheckpointDryRun(cwd?: string): Promise<ChangedFile[]> {\n const cleoDir = getCleoDir(cwd);\n const isRepo = await isGitRepo(cwd);\n\n if (!isRepo) return [];\n\n return getChangedStateFiles(cleoDir, cwd);\n}\n", "/**\n * Task ID sequence management core module.\n * @task T4538\n * @epic T4454\n */\n\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { readJson } from '../../store/json.js';\nimport { getTaskPath, getArchivePath } from '../paths.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { TaskFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nfunction getSequencePath(cwd?: string): string {\n return join(cwd ?? process.cwd(), '.cleo', '.sequence.json');\n}\n\ninterface SequenceState {\n counter: number;\n lastId: string;\n checksum: string;\n}\n\nfunction readSequence(cwd?: string): SequenceState | null {\n const path = getSequencePath(cwd);\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf-8'));\n}\n\nfunction getMaxIdFromTasks(tasks: Array<{ id: string }>): number {\n let max = 0;\n for (const t of tasks) {\n const match = t.id.match(/^T(\\d+)$/);\n if (match) {\n const num = parseInt(match[1]!, 10);\n if (num > max) max = num;\n }\n }\n return max;\n}\n\n/** Show current sequence state. */\nexport async function showSequence(cwd?: string): Promise<Record<string, unknown>> {\n const seq = readSequence(cwd);\n if (!seq) {\n throw new CleoError(ExitCode.NOT_FOUND, 'Sequence file not found');\n }\n return {\n counter: seq.counter,\n lastId: seq.lastId,\n checksum: seq.checksum,\n nextId: `T${seq.counter + 1}`,\n };\n}\n\n/** Check sequence integrity. */\nexport async function checkSequence(cwd?: string, accessor?: DataAccessor): Promise<Record<string, unknown>> {\n const seq = readSequence(cwd);\n if (!seq) {\n throw new CleoError(ExitCode.NOT_FOUND, 'Sequence file not found');\n }\n\n const todoData = accessor\n ? await accessor.loadTaskFile()\n : await readJson<TaskFile>(getTaskPath(cwd));\n const archiveData = accessor\n ? await accessor.loadArchive()\n : await readJson<{ archivedTasks: Array<{ id: string }> }>(getArchivePath(cwd));\n\n const allTasks = [\n ...(todoData?.tasks ?? []),\n ...(archiveData?.archivedTasks ?? []),\n ];\n\n const maxId = getMaxIdFromTasks(allTasks);\n const valid = seq.counter >= maxId;\n\n return {\n counter: seq.counter,\n maxIdInData: maxId,\n valid,\n ...(valid ? {} : {\n issue: `Counter (${seq.counter}) is behind max ID (T${maxId})`,\n fix: 'Run cleo sequence repair',\n }),\n };\n}\n\n/** Repair result with proper typing. */\nexport interface RepairResult {\n repaired: boolean;\n message: string;\n counter: number;\n oldCounter?: number;\n newCounter?: number;\n}\n\n/** Repair sequence if behind. */\nexport async function repairSequence(cwd?: string, accessor?: DataAccessor): Promise<RepairResult> {\n const seqPath = getSequencePath(cwd);\n const seq = readSequence(cwd);\n\n const todoData = accessor\n ? await accessor.loadTaskFile()\n : await readJson<TaskFile>(getTaskPath(cwd));\n const archiveData = accessor\n ? await accessor.loadArchive()\n : await readJson<{ archivedTasks: Array<{ id: string }> }>(getArchivePath(cwd));\n\n const allTasks = [\n ...(todoData?.tasks ?? []),\n ...(archiveData?.archivedTasks ?? []),\n ];\n\n const maxId = getMaxIdFromTasks(allTasks);\n const oldCounter = seq?.counter ?? 0;\n\n if (oldCounter >= maxId) {\n return { repaired: false, message: 'Sequence already valid', counter: oldCounter, oldCounter, newCounter: oldCounter };\n }\n\n const newCounter = maxId;\n const newSeq: SequenceState = {\n counter: newCounter,\n lastId: `T${newCounter}`,\n checksum: `repair-${Date.now()}`,\n };\n\n writeFileSync(seqPath, JSON.stringify(newSeq, null, 2));\n\n return {\n repaired: true,\n counter: newCounter,\n oldCounter,\n newCounter,\n message: `Sequence repaired: ${oldCounter} -> ${newCounter}`,\n };\n}\n", "/**\n * Data Safety Module - Critical protection layer for CLEO data operations.\n *\n * Implements:\n * - Write verification (verify data was actually persisted)\n * - Collision detection (prevent duplicate task IDs)\n * - Sequence validation (ensure sequence counter matches database)\n * - Auto-checkpoint integration (git commit after writes)\n *\n * @task T4739\n * @epic T4732\n */\n\nimport { eq } from 'drizzle-orm';\nimport { getDb } from './sqlite.js';\nimport * as schema from './schema.js';\nimport { gitCheckpoint } from './git-checkpoint.js';\nimport {\n checkSequence,\n repairSequence,\n} from '../core/sequence/index.js';\nimport type { Task } from '../types/task.js';\nimport type { Session } from '../types/session.js';\n\n/** Safety configuration options. */\nexport interface SafetyConfig {\n /** Enable write verification (default: true) */\n verifyWrites: boolean;\n /** Enable collision detection (default: true) */\n detectCollisions: boolean;\n /** Enable sequence validation (default: true) */\n validateSequence: boolean;\n /** Enable auto-checkpoint (default: true) */\n autoCheckpoint: boolean;\n /** Throw on safety violations (default: true) */\n strictMode: boolean;\n}\n\nconst DEFAULT_CONFIG: SafetyConfig = {\n verifyWrites: true,\n detectCollisions: true,\n validateSequence: true,\n autoCheckpoint: true,\n strictMode: true,\n};\n\n/** Safety violation error. */\nexport class SafetyError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'SafetyError';\n }\n}\n\n/**\n * Check if a task ID already exists (collision detection).\n * @throws SafetyError if task exists and strict mode is enabled\n */\nexport async function checkTaskExists(\n taskId: string,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<boolean> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.detectCollisions) return false;\n\n const db = await getDb(cwd);\n const existing = db\n .select()\n .from(schema.tasks)\n .where(eq(schema.tasks.id, taskId))\n .all();\n\n const exists = existing.length > 0;\n\n if (exists && cfg.strictMode) {\n throw new SafetyError(\n `Task ID collision detected: ${taskId} already exists`,\n 'COLLISION_DETECTED',\n { taskId, existingTask: existing[0] },\n );\n }\n\n return exists;\n}\n\n/**\n * Verify a task was actually written to the database.\n * @throws SafetyError if verification fails\n */\nexport async function verifyTaskWrite(\n taskId: string,\n expectedData?: Partial<Task>,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<boolean> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.verifyWrites) return true;\n\n const db = await getDb(cwd);\n const rows = db\n .select()\n .from(schema.tasks)\n .where(eq(schema.tasks.id, taskId))\n .all();\n\n if (rows.length === 0) {\n if (cfg.strictMode) {\n throw new SafetyError(\n `Write verification failed: Task ${taskId} not found after write`,\n 'WRITE_VERIFICATION_FAILED',\n { taskId },\n );\n }\n return false;\n }\n\n // Verify expected data if provided\n if (expectedData) {\n const row = rows[0]!;\n for (const [key, value] of Object.entries(expectedData)) {\n if (value !== undefined && row[key as keyof typeof row] !== value) {\n if (cfg.strictMode) {\n throw new SafetyError(\n `Write verification failed: Task ${taskId} field ${key} mismatch`,\n 'WRITE_VERIFICATION_MISMATCH',\n { taskId, field: key, expected: value, actual: row[key as keyof typeof row] },\n );\n }\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Validate and repair sequence if necessary.\n * @returns true if sequence was valid or successfully repaired\n */\nexport async function validateAndRepairSequence(\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<{ valid: boolean; repaired: boolean; oldCounter?: number; newCounter?: number }> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.validateSequence) return { valid: true, repaired: false };\n\n try {\n const check = await checkSequence(cwd);\n\n if (check.valid) {\n return { valid: true, repaired: false };\n }\n\n // Sequence is behind, repair it\n const repair = await repairSequence(cwd);\n\n if (repair.repaired) {\n console.warn(`[SAFETY] Sequence repaired: ${repair.oldCounter} -> ${repair.newCounter}`);\n return {\n valid: true,\n repaired: true,\n oldCounter: repair.oldCounter,\n newCounter: repair.newCounter,\n };\n }\n\n return { valid: false, repaired: false };\n } catch (err) {\n if (cfg.strictMode) {\n throw new SafetyError(\n `Sequence validation failed: ${String(err)}`,\n 'SEQUENCE_VALIDATION_FAILED',\n { error: String(err) },\n );\n }\n return { valid: false, repaired: false };\n }\n}\n\n/**\n * Trigger auto-checkpoint after successful write.\n */\nexport async function triggerCheckpoint(\n context: string,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<void> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.autoCheckpoint) return;\n\n try {\n await gitCheckpoint('auto', context, cwd);\n } catch (err) {\n // Checkpoint failures are non-fatal but should be logged\n console.warn(`[SAFETY] Checkpoint failed (non-fatal): ${String(err)}`);\n }\n}\n\n/**\n * Safely create a task with all safety mechanisms.\n * Wraps the actual createTask operation.\n */\nexport async function safeCreateTask(\n createFn: () => Promise<Task>,\n task: Task,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<Task> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n // 1. Validate sequence before creation\n if (cfg.validateSequence) {\n await validateAndRepairSequence(cwd, config);\n }\n\n // 2. Check for collisions\n if (cfg.detectCollisions) {\n await checkTaskExists(task.id, cwd, config);\n }\n\n // 3. Perform the actual creation\n const result = await createFn();\n\n // 4. Verify the write\n if (cfg.verifyWrites) {\n await verifyTaskWrite(task.id, { title: task.title }, cwd, config);\n }\n\n // 5. Trigger checkpoint\n if (cfg.autoCheckpoint) {\n await triggerCheckpoint(`created ${task.id}`, cwd, config);\n }\n\n return result;\n}\n\n/**\n * Safely update a task with all safety mechanisms.\n */\nexport async function safeUpdateTask(\n updateFn: () => Promise<Task | null>,\n taskId: string,\n updates: Partial<Task>,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<Task | null> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n // 1. Perform the actual update\n const result = await updateFn();\n\n if (!result) return null;\n\n // 2. Verify the write\n if (cfg.verifyWrites) {\n await verifyTaskWrite(taskId, updates, cwd, config);\n }\n\n // 3. Trigger checkpoint\n if (cfg.autoCheckpoint) {\n await triggerCheckpoint(`updated ${taskId}`, cwd, config);\n }\n\n return result;\n}\n\n/**\n * Safely delete a task with all safety mechanisms.\n */\nexport async function safeDeleteTask(\n deleteFn: () => Promise<boolean>,\n taskId: string,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<boolean> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n // 1. Perform the actual deletion\n const result = await deleteFn();\n\n if (!result) return false;\n\n // 2. Verify the deletion (task should NOT exist)\n if (cfg.verifyWrites) {\n const db = await getDb(cwd);\n const rows = db\n .select()\n .from(schema.tasks)\n .where(eq(schema.tasks.id, taskId))\n .all();\n\n if (rows.length > 0) {\n if (cfg.strictMode) {\n throw new SafetyError(\n `Delete verification failed: Task ${taskId} still exists after delete`,\n 'DELETE_VERIFICATION_FAILED',\n { taskId },\n );\n }\n }\n }\n\n // 3. Trigger checkpoint\n if (cfg.autoCheckpoint) {\n await triggerCheckpoint(`deleted ${taskId}`, cwd, config);\n }\n\n return result;\n}\n\n/**\n * Verify session write.\n */\nexport async function verifySessionWrite(\n sessionId: string,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<boolean> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n if (!cfg.verifyWrites) return true;\n\n const db = await getDb(cwd);\n const rows = db\n .select()\n .from(schema.sessions)\n .where(eq(schema.sessions.id, sessionId))\n .all();\n\n if (rows.length === 0) {\n if (cfg.strictMode) {\n throw new SafetyError(\n `Write verification failed: Session ${sessionId} not found after write`,\n 'SESSION_WRITE_VERIFICATION_FAILED',\n { sessionId },\n );\n }\n return false;\n }\n\n return true;\n}\n\n/**\n * Safely create a session with all safety mechanisms.\n */\nexport async function safeCreateSession(\n createFn: () => Promise<Session>,\n session: Session,\n cwd?: string,\n config: Partial<SafetyConfig> = {},\n): Promise<Session> {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n\n // 1. Perform the actual creation\n const result = await createFn();\n\n // 2. Verify the write\n if (cfg.verifyWrites) {\n await verifySessionWrite(session.id, cwd, config);\n }\n\n // 3. Trigger checkpoint\n if (cfg.autoCheckpoint) {\n await triggerCheckpoint(`session ${session.id} started`, cwd, config);\n }\n\n return result;\n}\n\n/**\n * Force a checkpoint before destructive operations.\n * Use this before migrations, bulk updates, etc.\n */\nexport async function forceCheckpointBeforeOperation(\n operation: string,\n cwd?: string,\n): Promise<void> {\n console.log(`[SAFETY] Forcing checkpoint before: ${operation}`);\n\n try {\n await gitCheckpoint('manual', `pre-${operation}`, cwd);\n } catch (err) {\n console.error(`[SAFETY] Failed to create pre-operation checkpoint: ${String(err)}`);\n // Don't throw - checkpoint failures shouldn't block operations\n }\n}\n\n/**\n * Run comprehensive data integrity check.\n * Reports all issues found.\n */\nexport async function runDataIntegrityCheck(cwd?: string): Promise<{\n passed: boolean;\n issues: string[];\n repairs: string[];\n}> {\n const issues: string[] = [];\n const repairs: string[] = [];\n\n // 1. Check sequence\n try {\n const seqCheck = await checkSequence(cwd);\n if (!seqCheck.valid) {\n issues.push(`Sequence invalid: counter ${seqCheck.counter} < max ID T${seqCheck.maxIdInData}`);\n\n // Auto-repair\n const repair = await repairSequence(cwd);\n if (repair.repaired) {\n repairs.push(`Sequence repaired: ${repair.oldCounter} -> ${repair.newCounter}`);\n } else {\n issues.push('Sequence repair failed');\n }\n }\n } catch (err) {\n issues.push(`Sequence check failed: ${String(err)}`);\n }\n\n // 2. Check for ghost entries (would need to compare todo-log with database)\n // This is a complex check that would require loading the entire log\n // For now, we skip this but document it as needed\n\n return {\n passed: issues.length === repairs.length,\n issues,\n repairs,\n };\n}\n", "/**\n * SQLite-backed task store operations.\n *\n * CRUD operations for tasks, dependencies, and relations backed by tasks.db.\n * Implements the same interface as the JSON store for StoreProvider compatibility.\n *\n * @epic T4454\n * @task W1-T3\n */\n\nimport { eq, and, sql, inArray, asc, isNull, ne } from 'drizzle-orm';\nimport { getDb, saveToFile } from './sqlite.js';\nimport * as schema from './schema.js';\nimport type { TaskRow, NewTaskRow } from './schema.js';\nimport type { Task, TaskStatus, TaskPriority, TaskType, TaskSize } from '../types/task.js';\nimport {\n safeCreateTask,\n safeUpdateTask,\n safeDeleteTask,\n verifyTaskWrite,\n triggerCheckpoint,\n type SafetyConfig,\n} from './data-safety.js';\n\n// === ROW <-> DOMAIN CONVERSION ===\n\n/** Convert a database row to a domain Task object. */\nfunction rowToTask(row: TaskRow): Task {\n return {\n id: row.id,\n title: row.title,\n status: row.status as TaskStatus,\n priority: row.priority as TaskPriority,\n type: row.type as TaskType | undefined,\n parentId: row.parentId,\n phase: row.phase ?? undefined,\n size: row.size as TaskSize | undefined,\n position: row.position,\n positionVersion: row.positionVersion ?? undefined,\n description: row.description ?? undefined,\n labels: parseJson<string[]>(row.labelsJson),\n notes: parseJson<string[]>(row.notesJson),\n acceptance: parseJson<string[]>(row.acceptanceJson),\n files: parseJson<string[]>(row.filesJson),\n depends: undefined, // Populated separately from task_dependencies\n origin: row.origin as Task['origin'],\n blockedBy: row.blockedBy ?? undefined,\n epicLifecycle: row.epicLifecycle as Task['epicLifecycle'],\n noAutoComplete: row.noAutoComplete ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n completedAt: row.completedAt ?? undefined,\n cancelledAt: row.cancelledAt ?? undefined,\n cancellationReason: row.cancellationReason ?? undefined,\n verification: row.verificationJson ? parseJson(row.verificationJson) : undefined,\n provenance: (row.createdBy || row.modifiedBy || row.sessionId) ? {\n createdBy: row.createdBy,\n modifiedBy: row.modifiedBy,\n sessionId: row.sessionId,\n } : undefined,\n };\n}\n\n/** Convert a domain Task to a database row for insert/update. */\nfunction taskToRow(task: Partial<Task> & { id: string }): NewTaskRow {\n return {\n id: task.id,\n title: task.title ?? '',\n description: task.description,\n status: task.status ?? 'pending',\n priority: task.priority ?? 'medium',\n type: task.type,\n parentId: task.parentId,\n phase: task.phase,\n size: task.size,\n position: task.position,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance ? JSON.stringify(task.acceptance) : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n origin: task.origin,\n blockedBy: task.blockedBy,\n epicLifecycle: task.epicLifecycle,\n noAutoComplete: task.noAutoComplete,\n createdAt: task.createdAt ?? new Date().toISOString(),\n updatedAt: task.updatedAt,\n completedAt: task.completedAt,\n cancelledAt: task.cancelledAt,\n cancellationReason: task.cancellationReason,\n verificationJson: task.verification ? JSON.stringify(task.verification) : undefined,\n createdBy: task.provenance?.createdBy,\n modifiedBy: task.provenance?.modifiedBy,\n sessionId: task.provenance?.sessionId,\n };\n}\n\nfunction parseJson<T>(jsonStr: string | null | undefined): T | undefined {\n if (!jsonStr) return undefined;\n try {\n const parsed = JSON.parse(jsonStr) as T;\n if (Array.isArray(parsed) && parsed.length === 0) return undefined;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n// === CRUD OPERATIONS ===\n\n/** Create a new task (with safety protections by default). */\nexport async function createTask(task: Task, cwd?: string, config?: Partial<SafetyConfig>): Promise<Task> {\n const rawCreate = async (): Promise<Task> => {\n const db = await getDb(cwd);\n const row = taskToRow(task);\n db.insert(schema.tasks).values(row).run();\n\n // Insert dependencies\n if (task.depends && task.depends.length > 0) {\n for (const depId of task.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId: task.id, dependsOn: depId })\n .run();\n }\n }\n\n saveToFile();\n return task;\n };\n\n return safeCreateTask(rawCreate, task, cwd, config);\n}\n\n/** Get a task by ID, including its dependencies. */\nexport async function getTask(taskId: string, cwd?: string): Promise<Task | null> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.tasks).where(eq(schema.tasks.id, taskId)).all();\n if (rows.length === 0) return null;\n\n const task = rowToTask(rows[0]!);\n\n // Load dependencies\n const deps = db.select().from(schema.taskDependencies)\n .where(eq(schema.taskDependencies.taskId, taskId)).all();\n if (deps.length > 0) {\n task.depends = deps.map(d => d.dependsOn);\n }\n\n return task;\n}\n\n/** Update an existing task (with safety protections by default). */\nexport async function updateTask(\n taskId: string,\n updates: Partial<Task>,\n cwd?: string,\n config?: Partial<SafetyConfig>,\n): Promise<Task | null> {\n const rawUpdate = async (): Promise<Task | null> => {\n const db = await getDb(cwd);\n const existing = await getTask(taskId, cwd);\n if (!existing) return null;\n\n // Build update object (only changed fields)\n const updateRow: Record<string, unknown> = {\n updatedAt: new Date().toISOString(),\n };\n\n if (updates.title !== undefined) updateRow.title = updates.title;\n if (updates.description !== undefined) updateRow.description = updates.description;\n if (updates.status !== undefined) updateRow.status = updates.status;\n if (updates.priority !== undefined) updateRow.priority = updates.priority;\n if (updates.type !== undefined) updateRow.type = updates.type;\n if (updates.parentId !== undefined) updateRow.parentId = updates.parentId;\n if (updates.phase !== undefined) updateRow.phase = updates.phase;\n if (updates.size !== undefined) updateRow.size = updates.size;\n if (updates.position !== undefined) updateRow.position = updates.position;\n if (updates.labels !== undefined) updateRow.labelsJson = JSON.stringify(updates.labels);\n if (updates.notes !== undefined) updateRow.notesJson = JSON.stringify(updates.notes);\n if (updates.acceptance !== undefined) updateRow.acceptanceJson = JSON.stringify(updates.acceptance);\n if (updates.files !== undefined) updateRow.filesJson = JSON.stringify(updates.files);\n if (updates.origin !== undefined) updateRow.origin = updates.origin;\n if (updates.blockedBy !== undefined) updateRow.blockedBy = updates.blockedBy;\n if (updates.epicLifecycle !== undefined) updateRow.epicLifecycle = updates.epicLifecycle;\n if (updates.completedAt !== undefined) updateRow.completedAt = updates.completedAt;\n if (updates.cancelledAt !== undefined) updateRow.cancelledAt = updates.cancelledAt;\n if (updates.cancellationReason !== undefined) updateRow.cancellationReason = updates.cancellationReason;\n if (updates.verification !== undefined) updateRow.verificationJson = JSON.stringify(updates.verification);\n\n db.update(schema.tasks).set(updateRow).where(eq(schema.tasks.id, taskId)).run();\n\n // Update dependencies if provided\n if (updates.depends !== undefined) {\n db.delete(schema.taskDependencies).where(eq(schema.taskDependencies.taskId, taskId)).run();\n for (const depId of updates.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId, dependsOn: depId })\n .run();\n }\n }\n\n saveToFile();\n return getTask(taskId, cwd);\n };\n\n return safeUpdateTask(rawUpdate, taskId, updates, cwd, config);\n}\n\n/** Delete a task by ID (with safety protections by default). */\nexport async function deleteTask(taskId: string, cwd?: string, config?: Partial<SafetyConfig>): Promise<boolean> {\n const rawDelete = async (): Promise<boolean> => {\n const db = await getDb(cwd);\n const existing = db.select({ id: schema.tasks.id }).from(schema.tasks)\n .where(eq(schema.tasks.id, taskId)).all();\n if (existing.length === 0) return false;\n\n db.delete(schema.tasks).where(eq(schema.tasks.id, taskId)).run();\n saveToFile();\n return true;\n };\n\n return safeDeleteTask(rawDelete, taskId, cwd, config);\n}\n\n/** List tasks with optional filters. */\nexport async function listTasks(\n filters?: {\n status?: TaskStatus;\n parentId?: string | null;\n type?: TaskType;\n phase?: string;\n limit?: number;\n },\n cwd?: string,\n): Promise<Task[]> {\n const db = await getDb(cwd);\n\n const conditions = [];\n // Exclude archived by default\n conditions.push(ne(schema.tasks.status, 'archived'));\n\n if (filters?.status) conditions.push(eq(schema.tasks.status, filters.status));\n if (filters?.parentId !== undefined) {\n if (filters.parentId === null) {\n conditions.push(isNull(schema.tasks.parentId));\n } else {\n conditions.push(eq(schema.tasks.parentId, filters.parentId));\n }\n }\n if (filters?.type) conditions.push(eq(schema.tasks.type, filters.type));\n if (filters?.phase) conditions.push(eq(schema.tasks.phase, filters.phase));\n\n let query = db.select().from(schema.tasks)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(asc(schema.tasks.position), asc(schema.tasks.createdAt));\n\n const rows = filters?.limit\n ? query.limit(filters.limit).all()\n : query.all();\n\n // Load dependencies for all tasks\n const tasks = rows.map(rowToTask);\n await loadDependencies(tasks, cwd);\n return tasks;\n}\n\n/** Find tasks by fuzzy text search. */\nexport async function findTasks(\n query: string,\n limit: number = 20,\n cwd?: string,\n): Promise<Task[]> {\n const db = await getDb(cwd);\n const pattern = `%${query}%`;\n\n const rows = db.select().from(schema.tasks)\n .where(\n and(\n ne(schema.tasks.status, 'archived'),\n sql`(${schema.tasks.id} LIKE ${pattern} OR ${schema.tasks.title} LIKE ${pattern} OR ${schema.tasks.description} LIKE ${pattern})`,\n ),\n )\n .limit(limit)\n .all();\n\n return rows.map(rowToTask);\n}\n\n/** Archive a task (sets status to 'archived' with metadata, with safety protections by default). */\nexport async function archiveTask(\n taskId: string,\n reason?: string,\n cwd?: string,\n config?: Partial<SafetyConfig>,\n): Promise<boolean> {\n const db = await getDb(cwd);\n const task = await getTask(taskId, cwd);\n if (!task) return false;\n\n const now = new Date().toISOString();\n const cycleTime = task.createdAt\n ? Math.floor((Date.now() - new Date(task.createdAt).getTime()) / (1000 * 60 * 60 * 24))\n : null;\n\n db.update(schema.tasks).set({\n status: 'archived',\n archivedAt: now,\n archiveReason: reason ?? 'completed',\n cycleTimeDays: cycleTime,\n updatedAt: now,\n }).where(eq(schema.tasks.id, taskId)).run();\n\n saveToFile();\n\n await verifyTaskWrite(taskId, undefined, cwd, config);\n await triggerCheckpoint('archived ' + taskId, cwd, config);\n\n return true;\n}\n\n// === DEPENDENCY & RELATION OPERATIONS ===\n\n/** Load dependencies for a list of tasks. */\nasync function loadDependencies(tasks: Task[], cwd?: string): Promise<void> {\n if (tasks.length === 0) return;\n const db = await getDb(cwd);\n const taskIds = tasks.map(t => t.id);\n\n const deps = db.select().from(schema.taskDependencies)\n .where(inArray(schema.taskDependencies.taskId, taskIds))\n .all();\n\n const depMap = new Map<string, string[]>();\n for (const dep of deps) {\n if (!depMap.has(dep.taskId)) depMap.set(dep.taskId, []);\n depMap.get(dep.taskId)!.push(dep.dependsOn);\n }\n\n for (const task of tasks) {\n const taskDeps = depMap.get(task.id);\n if (taskDeps && taskDeps.length > 0) {\n task.depends = taskDeps;\n }\n }\n}\n\n/** Add a dependency between tasks. */\nexport async function addDependency(taskId: string, dependsOn: string, cwd?: string): Promise<void> {\n const db = await getDb(cwd);\n db.insert(schema.taskDependencies)\n .values({ taskId, dependsOn })\n .onConflictDoNothing()\n .run();\n saveToFile();\n}\n\n/** Remove a dependency. */\nexport async function removeDependency(taskId: string, dependsOn: string, cwd?: string): Promise<void> {\n const db = await getDb(cwd);\n db.delete(schema.taskDependencies)\n .where(and(\n eq(schema.taskDependencies.taskId, taskId),\n eq(schema.taskDependencies.dependsOn, dependsOn),\n ))\n .run();\n saveToFile();\n}\n\n/** Add a relation between tasks. */\nexport async function addRelation(\n taskId: string,\n relatedTo: string,\n relationType: 'related' | 'blocks' | 'duplicates' = 'related',\n cwd?: string,\n): Promise<void> {\n const db = await getDb(cwd);\n db.insert(schema.taskRelations)\n .values({ taskId, relatedTo, relationType })\n .onConflictDoNothing()\n .run();\n saveToFile();\n}\n\n/** Get relations for a task. */\nexport async function getRelations(taskId: string, cwd?: string): Promise<Array<{ relatedTo: string; type: string }>> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.taskRelations)\n .where(eq(schema.taskRelations.taskId, taskId))\n .all();\n return rows.map(r => ({ relatedTo: r.relatedTo, type: r.relationType }));\n}\n\n// === GRAPH OPERATIONS ===\n\n/** Get the dependency chain (blockers) for a task using recursive CTE. */\nexport async function getBlockerChain(taskId: string, cwd?: string): Promise<string[]> {\n const db = await getDb(cwd);\n const result = db.all<{ id: string }>(sql`\n WITH RECURSIVE blocker_chain(id) AS (\n SELECT depends_on FROM task_dependencies WHERE task_id = ${taskId}\n UNION\n SELECT td.depends_on FROM task_dependencies td\n JOIN blocker_chain bc ON td.task_id = bc.id\n )\n SELECT id FROM blocker_chain\n `);\n return result.map(r => r.id);\n}\n\n/** Get children of a task (hierarchy). */\nexport async function getChildren(parentId: string, cwd?: string): Promise<Task[]> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.tasks)\n .where(eq(schema.tasks.parentId, parentId))\n .orderBy(asc(schema.tasks.position), asc(schema.tasks.createdAt))\n .all();\n return rows.map(rowToTask);\n}\n\n/** Build a tree from a root task using recursive CTE. */\nexport async function getSubtree(rootId: string, cwd?: string): Promise<Task[]> {\n const db = await getDb(cwd);\n const rows = db.all<TaskRow>(sql`\n WITH RECURSIVE subtree AS (\n SELECT * FROM tasks WHERE id = ${rootId}\n UNION ALL\n SELECT t.* FROM tasks t\n JOIN subtree s ON t.parent_id = s.id\n )\n SELECT * FROM subtree\n `);\n return rows.map(rowToTask);\n}\n\n/** Count tasks by status. */\nexport async function countByStatus(cwd?: string): Promise<Record<string, number>> {\n const db = await getDb(cwd);\n const rows = db.all<{ status: string; count: number }>(sql`\n SELECT status, COUNT(*) as count FROM tasks\n WHERE status != 'archived'\n GROUP BY status\n `);\n\n const result: Record<string, number> = {};\n for (const row of rows) {\n result[row.status] = row.count;\n }\n return result;\n}\n\n/** Get total task count (excluding archived). */\nexport async function countTasks(cwd?: string): Promise<number> {\n const db = await getDb(cwd);\n const result = db.all<{ count: number }>(sql`\n SELECT COUNT(*) as count FROM tasks WHERE status != 'archived'\n `);\n return result[0]?.count ?? 0;\n}\n\n/** Configuration for safe operations (re-exported for callers). */\nexport { type SafetyConfig } from './data-safety.js';\n", "/**\n * SQLite-backed session store operations.\n *\n * CRUD operations for sessions and task work tracking backed by tasks.db.\n *\n * @epic T4454\n * @task W1-T4\n */\n\nimport { eq, and, desc, isNull } from 'drizzle-orm';\nimport { getDb, saveToFile } from './sqlite.js';\nimport * as schema from './schema.js';\nimport type { SessionRow } from './schema.js';\nimport type { Session, SessionScope, SessionStatus } from '../types/session.js';\n\n// === ROW <-> DOMAIN CONVERSION ===\n\nfunction rowToSession(row: SessionRow): Session {\n const taskWork = {\n taskId: row.currentTask,\n setAt: row.taskStartedAt,\n };\n return {\n id: row.id,\n name: row.name,\n status: row.status as SessionStatus,\n scope: parseJson<SessionScope>(row.scopeJson) ?? { type: 'global' },\n taskWork,\n focus: taskWork,\n startedAt: row.startedAt,\n endedAt: row.endedAt,\n agent: row.agent,\n notes: parseJson<string[]>(row.notesJson),\n tasksCompleted: parseJson<string[]>(row.tasksCompletedJson),\n tasksCreated: parseJson<string[]>(row.tasksCreatedJson),\n };\n}\n\nfunction parseJson<T>(jsonStr: string | null | undefined): T | undefined {\n if (!jsonStr) return undefined;\n try {\n const parsed = JSON.parse(jsonStr) as T;\n if (Array.isArray(parsed) && parsed.length === 0) return undefined;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n// === CRUD OPERATIONS ===\n\n/** Create a new session. */\nexport async function createSession(session: Session, cwd?: string): Promise<Session> {\n const db = await getDb(cwd);\n const tw = session.taskWork ?? session.focus;\n db.insert(schema.sessions).values({\n id: session.id,\n name: session.name,\n status: session.status,\n scopeJson: JSON.stringify(session.scope),\n currentTask: tw?.taskId,\n taskStartedAt: tw?.setAt,\n agent: session.agent,\n notesJson: session.notes ? JSON.stringify(session.notes) : '[]',\n tasksCompletedJson: session.tasksCompleted ? JSON.stringify(session.tasksCompleted) : '[]',\n tasksCreatedJson: session.tasksCreated ? JSON.stringify(session.tasksCreated) : '[]',\n startedAt: session.startedAt,\n endedAt: session.endedAt,\n }).run();\n\n saveToFile();\n return session;\n}\n\n/** Get a session by ID. */\nexport async function getSession(sessionId: string, cwd?: string): Promise<Session | null> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.sessions)\n .where(eq(schema.sessions.id, sessionId))\n .all();\n\n if (rows.length === 0) return null;\n return rowToSession(rows[0]!);\n}\n\n/** Update a session. */\nexport async function updateSession(\n sessionId: string,\n updates: Partial<Session>,\n cwd?: string,\n): Promise<Session | null> {\n const db = await getDb(cwd);\n const existing = await getSession(sessionId, cwd);\n if (!existing) return null;\n\n const updateRow: Record<string, unknown> = {};\n\n if (updates.name !== undefined) updateRow.name = updates.name;\n if (updates.status !== undefined) updateRow.status = updates.status;\n if (updates.scope !== undefined) updateRow.scopeJson = JSON.stringify(updates.scope);\n if (updates.endedAt !== undefined) updateRow.endedAt = updates.endedAt;\n if (updates.agent !== undefined) updateRow.agent = updates.agent;\n if (updates.notes !== undefined) updateRow.notesJson = JSON.stringify(updates.notes);\n if (updates.tasksCompleted !== undefined) updateRow.tasksCompletedJson = JSON.stringify(updates.tasksCompleted);\n if (updates.tasksCreated !== undefined) updateRow.tasksCreatedJson = JSON.stringify(updates.tasksCreated);\n\n db.update(schema.sessions).set(updateRow).where(eq(schema.sessions.id, sessionId)).run();\n saveToFile();\n\n return getSession(sessionId, cwd);\n}\n\n/** List sessions with optional filters. */\nexport async function listSessions(\n filters?: {\n active?: boolean;\n limit?: number;\n },\n cwd?: string,\n): Promise<Session[]> {\n const db = await getDb(cwd);\n\n const conditions = [];\n if (filters?.active) {\n conditions.push(eq(schema.sessions.status, 'active'));\n }\n\n const query = db.select().from(schema.sessions)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(desc(schema.sessions.startedAt));\n\n const rows = filters?.limit ? query.limit(filters.limit).all() : query.all();\n return rows.map(rowToSession);\n}\n\n/** End a session. */\nexport async function endSession(\n sessionId: string,\n note?: string,\n cwd?: string,\n): Promise<Session | null> {\n const session = await getSession(sessionId, cwd);\n if (!session) return null;\n\n const updates: Partial<Session> = {\n status: 'ended',\n endedAt: new Date().toISOString(),\n };\n\n if (note) {\n const notes = session.notes ?? [];\n notes.push(note);\n updates.notes = notes;\n }\n\n return updateSession(sessionId, updates, cwd);\n}\n\n// === TASK WORK OPERATIONS ===\n\n/** Start working on a task within a session. */\nexport async function startTask(\n sessionId: string,\n taskId: string,\n cwd?: string,\n): Promise<void> {\n const db = await getDb(cwd);\n const now = new Date().toISOString();\n\n // Clear previous work history entry (set clearedAt)\n db.update(schema.taskWorkHistory)\n .set({ clearedAt: now })\n .where(and(\n eq(schema.taskWorkHistory.sessionId, sessionId),\n isNull(schema.taskWorkHistory.clearedAt),\n ))\n .run();\n\n // Record new task work in history\n db.insert(schema.taskWorkHistory)\n .values({ sessionId, taskId, setAt: now })\n .run();\n\n // Update session's current task\n db.update(schema.sessions)\n .set({ currentTask: taskId, taskStartedAt: now })\n .where(eq(schema.sessions.id, sessionId))\n .run();\n\n saveToFile();\n}\n\n/** Get current task for a session. */\nexport async function getCurrentTask(\n sessionId: string,\n cwd?: string,\n): Promise<{ taskId: string | null; since: string | null }> {\n const db = await getDb(cwd);\n const rows = db.select({\n currentTask: schema.sessions.currentTask,\n taskStartedAt: schema.sessions.taskStartedAt,\n }).from(schema.sessions)\n .where(eq(schema.sessions.id, sessionId))\n .all();\n\n if (rows.length === 0) return { taskId: null, since: null };\n return { taskId: rows[0]!.currentTask, since: rows[0]!.taskStartedAt };\n}\n\n/** Stop working on the current task for a session. */\nexport async function stopTask(sessionId: string, cwd?: string): Promise<void> {\n const db = await getDb(cwd);\n const now = new Date().toISOString();\n\n // Close current work history entry\n db.update(schema.taskWorkHistory)\n .set({ clearedAt: now })\n .where(and(\n eq(schema.taskWorkHistory.sessionId, sessionId),\n isNull(schema.taskWorkHistory.clearedAt),\n ))\n .run();\n\n // Clear session's current task\n db.update(schema.sessions)\n .set({ currentTask: null, taskStartedAt: null })\n .where(eq(schema.sessions.id, sessionId))\n .run();\n\n saveToFile();\n}\n\n/** Get work history for a session. */\nexport async function workHistory(\n sessionId: string,\n limit: number = 50,\n cwd?: string,\n): Promise<Array<{ taskId: string; setAt: string; clearedAt: string | null }>> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.taskWorkHistory)\n .where(eq(schema.taskWorkHistory.sessionId, sessionId))\n .orderBy(desc(schema.taskWorkHistory.setAt))\n .limit(limit)\n .all();\n\n return rows.map(r => ({\n taskId: r.taskId,\n setAt: r.setAt,\n clearedAt: r.clearedAt,\n }));\n}\n\n// === SESSION LIFECYCLE ===\n\n/** Garbage collect old sessions (mark ended sessions as orphaned after threshold). */\nexport async function gcSessions(\n maxAgeDays: number = 30,\n cwd?: string,\n): Promise<number> {\n const db = await getDb(cwd);\n const threshold = new Date();\n threshold.setDate(threshold.getDate() - maxAgeDays);\n\n // Count how many will be affected\n const before = db.select({ id: schema.sessions.id }).from(schema.sessions)\n .where(and(\n eq(schema.sessions.status, 'ended'),\n ))\n .all();\n\n const toUpdate = before;\n\n if (toUpdate.length > 0) {\n db.update(schema.sessions)\n .set({ status: 'orphaned' })\n .where(eq(schema.sessions.status, 'ended'))\n .run();\n saveToFile();\n }\n\n return toUpdate.length;\n}\n\n/** Get the currently active session (if any). */\nexport async function getActiveSession(cwd?: string): Promise<Session | null> {\n const db = await getDb(cwd);\n const rows = db.select().from(schema.sessions)\n .where(eq(schema.sessions.status, 'active'))\n .orderBy(desc(schema.sessions.startedAt))\n .limit(1)\n .all();\n\n if (rows.length === 0) return null;\n return rowToSession(rows[0]!);\n}\n\n// ---- Backward-compatible focus aliases (deprecated) ----\n\n/** @deprecated Use startTask() instead. */\nexport const setFocus = startTask;\n\n/** @deprecated Use getCurrentTask() instead. */\nexport const getFocus = getCurrentTask;\n\n/** @deprecated Use stopTask() instead. */\nexport const clearFocus = stopTask;\n\n/** @deprecated Use workHistory() instead. */\nexport const focusHistory = workHistory;\n", "/**\n * Data migration: JSON to SQLite.\n *\n * One-time migration of todo.json + todo-archive.json + sessions.json \u2192 tasks.db.\n * Validates row counts match after migration.\n * Keeps JSON files as read-only backup (does not delete).\n *\n * @epic T4454\n * @task W1-T5\n * @task T4721 - Added atomic migration support with custom db path\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\nimport { getCleoDirAbsolute } from '../core/paths.js';\nimport { getDb, saveToFile, dbExists } from './sqlite.js';\nimport * as schema from './schema.js';\nimport type { Task } from '../types/task.js';\nimport type { Session, SessionsFile } from '../types/session.js';\nimport initSqlJs from 'sql.js';\nimport { drizzle } from 'drizzle-orm/sql-js';\n\n/** Migration result. */\nexport interface MigrationResult {\n success: boolean;\n tasksImported: number;\n archivedImported: number;\n sessionsImported: number;\n errors: string[];\n warnings: string[];\n existingCounts?: {\n tasks: number;\n archived: number;\n sessions: number;\n };\n jsonCounts?: {\n tasks: number;\n archived: number;\n sessions: number;\n };\n}\n\n/** Options for migration. */\nexport interface MigrationOptions {\n force?: boolean;\n dryRun?: boolean;\n}\n\n/** Count records in JSON source files. */\nexport function countJsonRecords(cleoDir: string): {\n tasks: number;\n archived: number;\n sessions: number;\n} {\n let tasks = 0;\n let archived = 0;\n let sessions = 0;\n\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n try {\n const data = JSON.parse(readFileSync(todoPath, 'utf-8'));\n tasks = (data.tasks ?? []).length;\n } catch {\n // Corrupted file\n }\n }\n\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (existsSync(archivePath)) {\n try {\n const data = JSON.parse(readFileSync(archivePath, 'utf-8'));\n archived = (data.tasks ?? data.archivedTasks ?? []).length;\n } catch {\n // Corrupted file\n }\n }\n\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n try {\n const data = JSON.parse(readFileSync(sessionsPath, 'utf-8'));\n sessions = (data.sessions ?? []).length;\n } catch {\n // Corrupted file\n }\n }\n\n return { tasks, archived, sessions };\n}\n\n/**\n * Migrate JSON data to SQLite.\n * Reads todo.json, todo-archive.json, and sessions.json,\n * writes to tasks.db via drizzle-orm.\n */\n/**\n * Migrate JSON data to SQLite with atomic rename pattern.\n * Writes to a temporary database file first, then atomically renames.\n *\n * @param cwd - Optional working directory\n * @param tempDbPath - Optional temporary database path for atomic migration\n * @param logger - Optional migration logger for audit trail (@task T4727)\n * @returns Migration result\n */\nexport async function migrateJsonToSqliteAtomic(\n cwd?: string,\n tempDbPath?: string,\n logger?: import('../core/migration/logger.js').MigrationLogger,\n): Promise<MigrationResult> {\n const cleoDir = getCleoDirAbsolute(cwd);\n const result: MigrationResult = {\n success: false,\n tasksImported: 0,\n archivedImported: 0,\n sessionsImported: 0,\n errors: [],\n warnings: [],\n };\n\n // If no temp path provided, use standard migration\n if (!tempDbPath) {\n return migrateJsonToSqlite(cwd);\n }\n\n // Close any existing DB connection\n const { closeDb, resetDbState } = await import('./sqlite.js');\n closeDb();\n\n try {\n logger?.info('import', 'init', 'Initializing SQL.js for migration');\n\n // Initialize sql.js and create new database at temp path\n const SQL = await initSqlJs();\n const nativeDb = new SQL.Database();\n\n // Create tables\n logger?.info('import', 'create-tables', 'Creating database tables');\n await createMigrationTables(nativeDb);\n\n // Create drizzle wrapper\n const db = drizzle(nativeDb, { schema });\n\n // Run the actual migration\n logger?.info('import', 'data-import', 'Starting data import from JSON files');\n await runMigrationDataImport(db, cleoDir, result, logger);\n\n // Save to temp file\n logger?.info('import', 'save-temp', 'Saving to temporary database file', {\n tempPath: tempDbPath.replace(cleoDir, '.'),\n });\n mkdirSync(dirname(tempDbPath), { recursive: true });\n const data = nativeDb.export();\n const buffer = Buffer.from(data);\n writeFileSync(tempDbPath, buffer);\n\n // Get file size for logging\n const { statSync } = await import('node:fs');\n const fileStats = statSync(tempDbPath);\n logger?.info('import', 'temp-saved', 'Temporary database saved', {\n size: fileStats.size,\n path: tempDbPath.replace(cleoDir, '.'),\n });\n\n // Close the database\n nativeDb.close();\n resetDbState();\n\n result.success = result.errors.length === 0;\n logger?.info('import', 'complete', 'Migration import completed', {\n success: result.success,\n tasksImported: result.tasksImported,\n archivedImported: result.archivedImported,\n sessionsImported: result.sessionsImported,\n errors: result.errors.length,\n warnings: result.warnings.length,\n });\n return result;\n } catch (err) {\n const errorMsg = `Atomic migration failed: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'failed', errorMsg, {\n error: String(err),\n });\n resetDbState();\n return result;\n }\n}\n\n/**\n * Create tables for migration (standalone version without singleton state).\n */\nasync function createMigrationTables(nativeDb: import('sql.js').Database): Promise<void> {\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS tasks (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n description TEXT,\n status TEXT NOT NULL DEFAULT 'pending'\n CHECK(status IN ('pending','active','blocked','done','cancelled','archived')),\n priority TEXT NOT NULL DEFAULT 'medium'\n CHECK(priority IN ('critical','high','medium','low')),\n type TEXT CHECK(type IN ('epic','task','subtask')),\n parent_id TEXT REFERENCES tasks(id),\n phase TEXT,\n size TEXT CHECK(size IN ('small','medium','large')),\n position INTEGER,\n position_version INTEGER DEFAULT 0,\n labels_json TEXT DEFAULT '[]',\n notes_json TEXT DEFAULT '[]',\n acceptance_json TEXT DEFAULT '[]',\n files_json TEXT DEFAULT '[]',\n origin TEXT,\n blocked_by TEXT,\n epic_lifecycle TEXT,\n no_auto_complete INTEGER,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT,\n completed_at TEXT,\n cancelled_at TEXT,\n cancellation_reason TEXT,\n archived_at TEXT,\n archive_reason TEXT,\n cycle_time_days INTEGER,\n verification_json TEXT,\n created_by TEXT,\n modified_by TEXT,\n session_id TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_dependencies (\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n depends_on TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n PRIMARY KEY (task_id, depends_on)\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_relations (\n task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n related_to TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,\n relation_type TEXT NOT NULL DEFAULT 'related'\n CHECK(relation_type IN ('related','blocks','duplicates')),\n PRIMARY KEY (task_id, related_to)\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'active'\n CHECK(status IN ('active','ended','orphaned','suspended')),\n scope_json TEXT NOT NULL DEFAULT '{}',\n current_task TEXT,\n task_started_at TEXT,\n agent TEXT,\n notes_json TEXT DEFAULT '[]',\n tasks_completed_json TEXT DEFAULT '[]',\n tasks_created_json TEXT DEFAULT '[]',\n started_at TEXT NOT NULL DEFAULT (datetime('now')),\n ended_at TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS task_work_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n task_id TEXT NOT NULL,\n set_at TEXT NOT NULL DEFAULT (datetime('now')),\n cleared_at TEXT\n );\n `);\n\n nativeDb.run(`\n CREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n // Create indexes\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_parent_id ON tasks(parent_id);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_phase ON tasks(phase);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_type ON tasks(type);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_deps_depends_on ON task_dependencies(depends_on);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);');\n nativeDb.run('CREATE INDEX IF NOT EXISTS idx_work_history_session ON task_work_history(session_id);');\n\n // Set schema version\n nativeDb.run(\n `INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schemaVersion', '1.0.0')`,\n );\n}\n\n/**\n * Run the actual data import for migration.\n */\nasync function runMigrationDataImport(\n db: import('drizzle-orm/sql-js').SQLJsDatabase<typeof schema>,\n cleoDir: string,\n result: MigrationResult,\n logger?: import('../core/migration/logger.js').MigrationLogger,\n): Promise<void> {\n // === MIGRATE TASKS from todo.json ===\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n try {\n logger?.info('import', 'read-todo', 'Reading todo.json', {\n path: todoPath.replace(cleoDir, '.'),\n });\n\n const todoData = JSON.parse(readFileSync(todoPath, 'utf-8'));\n const tasks: Task[] = todoData.tasks ?? [];\n const totalTasks = tasks.length;\n\n logger?.info('import', 'tasks-start', `Starting import of ${totalTasks} tasks`, {\n totalTasks,\n });\n\n for (let i = 0; i < tasks.length; i++) {\n const task = tasks[i];\n try {\n db.insert(schema.tasks).values({\n id: task.id,\n title: task.title,\n description: task.description,\n status: task.status,\n priority: task.priority ?? 'medium',\n type: task.type,\n parentId: task.parentId,\n phase: task.phase,\n size: task.size,\n position: task.position,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance ? JSON.stringify(task.acceptance) : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n origin: task.origin,\n blockedBy: task.blockedBy,\n epicLifecycle: task.epicLifecycle,\n noAutoComplete: task.noAutoComplete,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n completedAt: task.completedAt,\n cancelledAt: task.cancelledAt,\n cancellationReason: task.cancellationReason,\n verificationJson: task.verification ? JSON.stringify(task.verification) : undefined,\n createdBy: task.provenance?.createdBy,\n modifiedBy: task.provenance?.modifiedBy,\n sessionId: task.provenance?.sessionId,\n }).onConflictDoNothing().run();\n\n // Insert dependencies\n if (task.depends) {\n for (const depId of task.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId: task.id, dependsOn: depId })\n .onConflictDoNothing()\n .run();\n }\n }\n\n result.tasksImported++;\n\n // Log progress every 100 tasks\n if ((i + 1) % 100 === 0 || i === tasks.length - 1) {\n logger?.logImportProgress('import', 'tasks', result.tasksImported, totalTasks);\n }\n } catch (err) {\n const errorMsg = `Failed to import task ${task.id}: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'task-import', errorMsg, {\n taskId: task.id,\n error: String(err),\n });\n }\n }\n\n logger?.info('import', 'tasks-complete', `Completed importing ${result.tasksImported} tasks`, {\n imported: result.tasksImported,\n failed: result.errors.length,\n });\n } catch (err) {\n const errorMsg = `Failed to parse todo.json: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'parse-todo', errorMsg);\n }\n } else {\n result.warnings.push('todo.json not found, skipping task import');\n logger?.warn('import', 'todo-missing', 'todo.json not found, skipping task import');\n }\n\n // === MIGRATE ARCHIVED TASKS from todo-archive.json ===\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (existsSync(archivePath)) {\n try {\n logger?.info('import', 'read-archive', 'Reading todo-archive.json', {\n path: archivePath.replace(cleoDir, '.'),\n });\n\n const archiveData = JSON.parse(readFileSync(archivePath, 'utf-8'));\n const archivedTasks: (Task & { archivedAt?: string; archiveReason?: string; cycleTimeDays?: number })[] =\n archiveData.tasks ?? archiveData.archivedTasks ?? [];\n const totalArchived = archivedTasks.length;\n\n logger?.info('import', 'archive-start', `Starting import of ${totalArchived} archived tasks`, {\n totalArchived,\n });\n\n for (let i = 0; i < archivedTasks.length; i++) {\n const task = archivedTasks[i];\n try {\n db.insert(schema.tasks).values({\n id: task.id,\n title: task.title,\n description: task.description,\n status: 'archived',\n priority: task.priority ?? 'medium',\n type: task.type,\n parentId: task.parentId,\n phase: task.phase,\n size: task.size,\n position: task.position,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance ? JSON.stringify(task.acceptance) : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n completedAt: task.completedAt,\n archivedAt: task.archivedAt ?? task.completedAt ?? new Date().toISOString(),\n archiveReason: task.archiveReason ?? 'migrated',\n cycleTimeDays: task.cycleTimeDays,\n }).onConflictDoNothing().run();\n\n result.archivedImported++;\n\n // Log progress every 50 archived tasks\n if ((i + 1) % 50 === 0 || i === archivedTasks.length - 1) {\n logger?.logImportProgress('import', 'archived', result.archivedImported, totalArchived);\n }\n } catch (err) {\n const errorMsg = `Failed to import archived task ${task.id}: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'archived-import', errorMsg, {\n taskId: task.id,\n error: String(err),\n });\n }\n }\n\n logger?.info('import', 'archive-complete', `Completed importing ${result.archivedImported} archived tasks`, {\n imported: result.archivedImported,\n });\n } catch (err) {\n const errorMsg = `Failed to parse todo-archive.json: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'parse-archive', errorMsg);\n }\n }\n\n // === MIGRATE SESSIONS from sessions.json ===\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n try {\n logger?.info('import', 'read-sessions', 'Reading sessions.json', {\n path: sessionsPath.replace(cleoDir, '.'),\n });\n\n const sessionsData = JSON.parse(readFileSync(sessionsPath, 'utf-8')) as SessionsFile;\n const sessions: Session[] = sessionsData.sessions ?? [];\n const totalSessions = sessions.length;\n\n logger?.info('import', 'sessions-start', `Starting import of ${totalSessions} sessions`, {\n totalSessions,\n });\n\n for (let i = 0; i < sessions.length; i++) {\n const session = sessions[i];\n try {\n // Normalize status: map legacy 'archived' to 'ended' for SQLite CHECK constraint\n const validStatuses = ['active', 'ended', 'orphaned', 'suspended'];\n const normalizedStatus = validStatuses.includes(session.status)\n ? session.status\n : 'ended';\n // Provide default name for sessions with null/undefined names\n const normalizedName = session.name || `session-${session.id}`;\n\n db.insert(schema.sessions).values({\n id: session.id,\n name: normalizedName,\n status: normalizedStatus,\n scopeJson: JSON.stringify(session.scope),\n currentTask: session.taskWork?.taskId ?? session.focus?.taskId,\n taskStartedAt: session.taskWork?.setAt ?? session.focus?.setAt,\n agent: session.agent,\n notesJson: session.notes ? JSON.stringify(session.notes) : '[]',\n tasksCompletedJson: session.tasksCompleted ? JSON.stringify(session.tasksCompleted) : '[]',\n tasksCreatedJson: session.tasksCreated ? JSON.stringify(session.tasksCreated) : '[]',\n startedAt: session.startedAt,\n endedAt: session.endedAt,\n }).onConflictDoNothing().run();\n\n result.sessionsImported++;\n\n // Log progress every 10 sessions\n if ((i + 1) % 10 === 0 || i === sessions.length - 1) {\n logger?.logImportProgress('import', 'sessions', result.sessionsImported, totalSessions);\n }\n } catch (err) {\n const errorMsg = `Failed to import session ${session.id}: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'session-import', errorMsg, {\n sessionId: session.id,\n error: String(err),\n });\n }\n }\n\n logger?.info('import', 'sessions-complete', `Completed importing ${result.sessionsImported} sessions`, {\n imported: result.sessionsImported,\n });\n } catch (err) {\n const errorMsg = `Failed to parse sessions.json: ${String(err)}`;\n result.errors.push(errorMsg);\n logger?.error('import', 'parse-sessions', errorMsg);\n }\n } else {\n logger?.warn('import', 'sessions-missing', 'sessions.json not found, skipping session import');\n }\n}\n\nexport async function migrateJsonToSqlite(\n cwd?: string,\n options?: MigrationOptions,\n): Promise<MigrationResult> {\n const cleoDir = getCleoDirAbsolute(cwd);\n const result: MigrationResult = {\n success: false,\n tasksImported: 0,\n archivedImported: 0,\n sessionsImported: 0,\n errors: [],\n warnings: [],\n };\n\n // Count JSON source records\n const jsonCounts = countJsonRecords(cleoDir);\n result.jsonCounts = jsonCounts;\n\n // Check if database already exists for idempotency\n if (dbExists(cwd)) {\n const { ne, eq, count } = await import('drizzle-orm');\n const db = await getDb(cwd);\n\n // Count existing rows in SQLite\n const tasksResult = db\n .select({ count: count() })\n .from(schema.tasks)\n .where(ne(schema.tasks.status, 'archived'))\n .get();\n const archivedResult = db\n .select({ count: count() })\n .from(schema.tasks)\n .where(eq(schema.tasks.status, 'archived'))\n .get();\n const sessionsResult = db\n .select({ count: count() })\n .from(schema.sessions)\n .get();\n\n const existingCounts = {\n tasks: tasksResult?.count ?? 0,\n archived: archivedResult?.count ?? 0,\n sessions: sessionsResult?.count ?? 0,\n };\n result.existingCounts = existingCounts;\n\n // Handle dry-run mode: show diff without making changes\n if (options?.dryRun) {\n const countsMatch =\n existingCounts.tasks === jsonCounts.tasks &&\n existingCounts.archived === jsonCounts.archived &&\n existingCounts.sessions === jsonCounts.sessions;\n\n if (countsMatch) {\n result.warnings.push(\n 'Dry-run: Database already contains migrated data. No changes needed.',\n );\n } else {\n const diffs: string[] = [];\n if (existingCounts.tasks !== jsonCounts.tasks) {\n diffs.push(\n `tasks: DB=${existingCounts.tasks}, JSON=${jsonCounts.tasks}`,\n );\n }\n if (existingCounts.archived !== jsonCounts.archived) {\n diffs.push(\n `archived: DB=${existingCounts.archived}, JSON=${jsonCounts.archived}`,\n );\n }\n if (existingCounts.sessions !== jsonCounts.sessions) {\n diffs.push(\n `sessions: DB=${existingCounts.sessions}, JSON=${jsonCounts.sessions}`,\n );\n }\n result.warnings.push(\n `Dry-run: Data mismatch detected - ${diffs.join('; ')}. Would import ${jsonCounts.tasks - existingCounts.tasks} tasks, ${jsonCounts.archived - existingCounts.archived} archived, ${jsonCounts.sessions - existingCounts.sessions} sessions.`,\n );\n }\n\n result.success = true;\n return result;\n }\n\n // Check if migration is already complete (unless force is specified)\n if (!options?.force) {\n const countsMatch =\n existingCounts.tasks === jsonCounts.tasks &&\n existingCounts.archived === jsonCounts.archived &&\n existingCounts.sessions === jsonCounts.sessions;\n\n if (countsMatch) {\n result.warnings.push(\n 'Database already contains migrated data. Use --force to re-import.',\n );\n result.success = true;\n return result;\n }\n\n // Counts differ - report mismatch\n result.warnings.push(\n `Data mismatch detected: DB has ${existingCounts.tasks} tasks, ${existingCounts.archived} archived, ${existingCounts.sessions} sessions; JSON has ${jsonCounts.tasks} tasks, ${jsonCounts.archived} archived, ${jsonCounts.sessions} sessions. Use --force to re-import.`,\n );\n result.success = true;\n return result;\n }\n\n // Force mode: continue with migration\n result.warnings.push(\n 'Force mode: Re-importing data despite existing database.',\n );\n }\n\n // Handle dry-run mode when DB doesn't exist\n if (options?.dryRun) {\n result.warnings.push(\n `Dry-run: Would import ${jsonCounts.tasks} tasks, ${jsonCounts.archived} archived tasks, ${jsonCounts.sessions} sessions.`,\n );\n result.success = true;\n return result;\n }\n\n const db = await getDb(cwd);\n\n // === MIGRATE TASKS from todo.json ===\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n try {\n const todoData = JSON.parse(readFileSync(todoPath, 'utf-8'));\n const tasks: Task[] = todoData.tasks ?? [];\n\n for (const task of tasks) {\n try {\n db.insert(schema.tasks)\n .values({\n id: task.id,\n title: task.title,\n description: task.description,\n status: task.status,\n priority: task.priority ?? 'medium',\n type: task.type,\n parentId: task.parentId,\n phase: task.phase,\n size: task.size,\n position: task.position,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance\n ? JSON.stringify(task.acceptance)\n : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n origin: task.origin,\n blockedBy: task.blockedBy,\n epicLifecycle: task.epicLifecycle,\n noAutoComplete: task.noAutoComplete,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n completedAt: task.completedAt,\n cancelledAt: task.cancelledAt,\n cancellationReason: task.cancellationReason,\n verificationJson: task.verification\n ? JSON.stringify(task.verification)\n : undefined,\n createdBy: task.provenance?.createdBy,\n modifiedBy: task.provenance?.modifiedBy,\n sessionId: task.provenance?.sessionId,\n })\n .onConflictDoNothing()\n .run();\n\n // Insert dependencies\n if (task.depends) {\n for (const depId of task.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId: task.id, dependsOn: depId })\n .onConflictDoNothing()\n .run();\n }\n }\n\n result.tasksImported++;\n } catch (err) {\n result.errors.push(`Failed to import task ${task.id}: ${String(err)}`);\n }\n }\n } catch (err) {\n result.errors.push(`Failed to parse todo.json: ${String(err)}`);\n }\n } else {\n result.warnings.push('todo.json not found, skipping task import');\n }\n\n // === MIGRATE ARCHIVED TASKS from todo-archive.json ===\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (existsSync(archivePath)) {\n try {\n const archiveData = JSON.parse(readFileSync(archivePath, 'utf-8'));\n const archivedTasks: (Task & {\n archivedAt?: string;\n archiveReason?: string;\n cycleTimeDays?: number;\n })[] = archiveData.tasks ?? archiveData.archivedTasks ?? [];\n\n for (const task of archivedTasks) {\n try {\n db.insert(schema.tasks)\n .values({\n id: task.id,\n title: task.title,\n description: task.description,\n status: 'archived',\n priority: task.priority ?? 'medium',\n type: task.type,\n parentId: task.parentId,\n phase: task.phase,\n size: task.size,\n position: task.position,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance\n ? JSON.stringify(task.acceptance)\n : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n completedAt: task.completedAt,\n archivedAt:\n task.archivedAt ??\n task.completedAt ??\n new Date().toISOString(),\n archiveReason: task.archiveReason ?? 'migrated',\n cycleTimeDays: task.cycleTimeDays,\n })\n .onConflictDoNothing()\n .run();\n\n result.archivedImported++;\n } catch (err) {\n result.errors.push(\n `Failed to import archived task ${task.id}: ${String(err)}`,\n );\n }\n }\n } catch (err) {\n result.errors.push(`Failed to parse todo-archive.json: ${String(err)}`);\n }\n }\n\n // === MIGRATE SESSIONS from sessions.json ===\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n try {\n const sessionsData = JSON.parse(\n readFileSync(sessionsPath, 'utf-8'),\n ) as SessionsFile;\n const sessions: Session[] = sessionsData.sessions ?? [];\n\n for (const session of sessions) {\n try {\n // Normalize status: map legacy 'archived' to 'ended' for SQLite CHECK constraint\n // @task T4658 @epic T4654\n const validStatuses = ['active', 'ended', 'orphaned', 'suspended'];\n const normalizedStatus = validStatuses.includes(session.status)\n ? session.status\n : 'ended'; // 'archived' and any other legacy statuses -> 'ended'\n // Provide default name for sessions with null/undefined names\n const normalizedName = session.name || `session-${session.id}`;\n\n db.insert(schema.sessions)\n .values({\n id: session.id,\n name: normalizedName,\n status: normalizedStatus,\n scopeJson: JSON.stringify(session.scope),\n currentTask: session.taskWork?.taskId ?? session.focus?.taskId,\n taskStartedAt: session.taskWork?.setAt ?? session.focus?.setAt,\n agent: session.agent,\n notesJson: session.notes\n ? JSON.stringify(session.notes)\n : '[]',\n tasksCompletedJson: session.tasksCompleted\n ? JSON.stringify(session.tasksCompleted)\n : '[]',\n tasksCreatedJson: session.tasksCreated\n ? JSON.stringify(session.tasksCreated)\n : '[]',\n startedAt: session.startedAt,\n endedAt: session.endedAt,\n })\n .onConflictDoNothing()\n .run();\n\n result.sessionsImported++;\n } catch (err) {\n result.errors.push(\n `Failed to import session ${session.id}: ${String(err)}`,\n );\n }\n }\n } catch (err) {\n result.errors.push(`Failed to parse sessions.json: ${String(err)}`);\n }\n }\n\n // Save database to disk\n saveToFile();\n\n result.success = result.errors.length === 0;\n return result;\n}\n\n/**\n * Export SQLite data back to JSON format (for inspection or emergency recovery).\n */\nexport async function exportToJson(cwd?: string): Promise<{\n tasks: Task[];\n archived: Task[];\n sessions: Session[];\n}> {\n const { listTasks } = await import('./task-store.js');\n const { listSessions } = await import('./session-store.js');\n const { eq } = await import('drizzle-orm');\n\n const tasks = await listTasks(undefined, cwd);\n\n // Get archived tasks separately\n const db = await getDb(cwd);\n const archivedRows = db.select().from(schema.tasks)\n .where(eq(schema.tasks.status, 'archived'))\n .all();\n\n // Convert rows to Task format\n const archived: Task[] = archivedRows.map(row => ({\n id: row.id,\n title: row.title,\n status: 'done' as const,\n priority: (row.priority ?? 'medium') as Task['priority'],\n createdAt: row.createdAt,\n description: row.description ?? undefined,\n updatedAt: row.updatedAt,\n completedAt: row.completedAt ?? undefined,\n }));\n\n const sessions = await listSessions(undefined, cwd);\n\n return { tasks, archived, sessions };\n}\n", "/**\n * SQLite-based implementation of the DataAccessor interface.\n *\n * Materializes TodoFile/ArchiveFile/SessionsFile from SQLite tables,\n * allowing core modules to continue using whole-file data structures\n * while storage is backed by the relational database.\n *\n * Uses existing sqlite.ts engine (sql.js / drizzle-orm) and\n * task-store.ts / session-store.ts for row-level operations.\n *\n * @epic T4454\n */\n\nimport { eq, ne } from 'drizzle-orm';\nimport type { DataAccessor, ArchiveFile, SessionsFile } from './data-accessor.js';\nimport type { TaskFile, Task, ProjectMeta, FocusState as TaskWorkState, FileMeta } from '../types/task.js';\nimport type { Session } from '../types/session.js';\nimport { getDb, saveToFile, closeDb } from './sqlite.js';\nimport * as schema from './schema.js';\nimport { appendJsonl, saveJson, computeChecksum } from './json.js';\nimport { getTaskPath, getLogPath, getBackupDir } from '../core/paths.js';\n\n// ---- Schema meta helpers ----\n\n/** Read a JSON blob from the schema_meta table by key. */\nasync function getMetaValue<T>(cwd: string | undefined, key: string): Promise<T | null> {\n const db = await getDb(cwd);\n const rows = db\n .select()\n .from(schema.schemaMeta)\n .where(eq(schema.schemaMeta.key, key))\n .all();\n if (rows.length === 0 || !rows[0]) return null;\n try {\n return JSON.parse(rows[0].value) as T;\n } catch {\n return null;\n }\n}\n\n/** Write a JSON blob to the schema_meta table by key. */\nasync function setMetaValue(cwd: string | undefined, key: string, value: unknown): Promise<void> {\n const db = await getDb(cwd);\n const json = JSON.stringify(value);\n db.insert(schema.schemaMeta)\n .values({ key, value: json })\n .onConflictDoUpdate({\n target: schema.schemaMeta.key,\n set: { value: json },\n })\n .run();\n}\n\n// ---- Row <-> Domain conversion ----\n\n/** Convert a database TaskRow to a domain Task. */\nfunction rowToTask(row: schema.TaskRow): Task {\n return {\n id: row.id,\n title: row.title,\n status: row.status as Task['status'],\n priority: row.priority as Task['priority'],\n type: (row.type as Task['type']) ?? undefined,\n parentId: row.parentId ?? undefined,\n phase: row.phase ?? undefined,\n size: (row.size as Task['size']) ?? undefined,\n position: row.position ?? undefined,\n positionVersion: row.positionVersion ?? undefined,\n description: row.description ?? undefined,\n labels: safeParseJsonArray(row.labelsJson),\n notes: safeParseJsonArray(row.notesJson),\n acceptance: safeParseJsonArray(row.acceptanceJson),\n files: safeParseJsonArray(row.filesJson),\n depends: undefined, // Populated separately from task_dependencies\n origin: (row.origin as Task['origin']) ?? undefined,\n blockedBy: row.blockedBy ?? undefined,\n epicLifecycle: (row.epicLifecycle as Task['epicLifecycle']) ?? undefined,\n noAutoComplete: row.noAutoComplete ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt ?? undefined,\n completedAt: row.completedAt ?? undefined,\n cancelledAt: row.cancelledAt ?? undefined,\n cancellationReason: row.cancellationReason ?? undefined,\n verification: row.verificationJson ? safeParseJson(row.verificationJson) : undefined,\n provenance:\n row.createdBy || row.modifiedBy || row.sessionId\n ? {\n createdBy: row.createdBy ?? null,\n modifiedBy: row.modifiedBy ?? null,\n sessionId: row.sessionId ?? null,\n }\n : undefined,\n };\n}\n\n/** Convert a domain Task to a database row for insert/upsert. */\nfunction taskToRow(task: Task): schema.NewTaskRow {\n return {\n id: task.id,\n title: task.title,\n description: task.description ?? null,\n status: task.status,\n priority: task.priority,\n type: task.type ?? null,\n parentId: task.parentId ?? null,\n phase: task.phase ?? null,\n size: task.size ?? null,\n position: task.position ?? null,\n positionVersion: task.positionVersion ?? 0,\n labelsJson: task.labels ? JSON.stringify(task.labels) : '[]',\n notesJson: task.notes ? JSON.stringify(task.notes) : '[]',\n acceptanceJson: task.acceptance ? JSON.stringify(task.acceptance) : '[]',\n filesJson: task.files ? JSON.stringify(task.files) : '[]',\n origin: task.origin ?? null,\n blockedBy: task.blockedBy ?? null,\n epicLifecycle: task.epicLifecycle ?? null,\n noAutoComplete: task.noAutoComplete ?? null,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt ?? null,\n completedAt: task.completedAt ?? null,\n cancelledAt: task.cancelledAt ?? null,\n cancellationReason: task.cancellationReason ?? null,\n verificationJson: task.verification ? JSON.stringify(task.verification) : null,\n createdBy: task.provenance?.createdBy ?? null,\n modifiedBy: task.provenance?.modifiedBy ?? null,\n sessionId: task.provenance?.sessionId ?? null,\n };\n}\n\n/** Convert a domain Task to a row suitable for archived tasks. */\nfunction archivedTaskToRow(task: Task): schema.NewTaskRow {\n const row = taskToRow(task);\n // Ensure archived status and metadata\n row.status = 'archived';\n if (!(row as Record<string, unknown>)['archivedAt']) {\n (row as Record<string, unknown>)['archivedAt'] = task.completedAt ?? new Date().toISOString();\n }\n return row;\n}\n\n/** Convert a SessionRow to a domain Session. */\nfunction rowToSession(row: schema.SessionRow): Session {\n return {\n id: row.id,\n name: row.name,\n status: row.status as Session['status'],\n scope: safeParseJson(row.scopeJson) ?? { type: 'global' as const },\n taskWork: {\n taskId: row.currentTask ?? null,\n setAt: row.taskStartedAt ?? null,\n },\n startedAt: row.startedAt,\n endedAt: row.endedAt ?? undefined,\n agent: row.agent ?? undefined,\n notes: safeParseJsonArray(row.notesJson),\n tasksCompleted: safeParseJsonArray(row.tasksCompletedJson),\n tasksCreated: safeParseJsonArray(row.tasksCreatedJson),\n };\n}\n\n// ---- JSON parse helpers ----\n\nfunction safeParseJson<T>(str: string | null | undefined): T | undefined {\n if (!str) return undefined;\n try {\n return JSON.parse(str) as T;\n } catch {\n return undefined;\n }\n}\n\nfunction safeParseJsonArray<T = string>(str: string | null | undefined): T[] | undefined {\n if (!str) return undefined;\n try {\n const arr = JSON.parse(str);\n if (Array.isArray(arr) && arr.length === 0) return undefined;\n return arr as T[];\n } catch {\n return undefined;\n }\n}\n\n// ---- Default structures ----\n\nconst DEFAULT_PROJECT_META: ProjectMeta = {\n name: 'project',\n currentPhase: null,\n phases: {},\n phaseHistory: [],\n releases: [],\n};\n\nconst DEFAULT_FILE_META: FileMeta = {\n schemaVersion: '2.10.0',\n checksum: '',\n configVersion: '1.0.0',\n};\n\nconst DEFAULT_WORK_STATE: TaskWorkState = {\n currentTask: null,\n currentPhase: null,\n blockedUntil: null,\n sessionNote: null,\n sessionNotes: [],\n nextAction: null,\n primarySession: null,\n};\n\n// ---- Accessor factory ----\n\n/**\n * Create a SQLite-backed DataAccessor.\n *\n * Opens (or creates) the SQLite database at `.cleo/tasks.db` and returns\n * a DataAccessor that materializes/dematerializes whole-file structures\n * from the relational tables.\n *\n * @param cwd - Working directory for path resolution (defaults to process.cwd())\n */\nexport async function createSqliteDataAccessor(cwd?: string): Promise<DataAccessor> {\n // Eagerly initialize the database to ensure tables exist\n await getDb(cwd);\n\n const accessor: DataAccessor = {\n engine: 'sqlite' as const,\n\n // ---- loadTaskFile ----\n\n async loadTaskFile(): Promise<TaskFile> {\n const db = await getDb(cwd);\n\n // 1. Query all non-archived tasks\n const taskRows = db\n .select()\n .from(schema.tasks)\n .where(ne(schema.tasks.status, 'archived'))\n .all();\n\n const tasks: Task[] = taskRows.map(rowToTask);\n\n // 2. Load dependencies for all tasks (batch query)\n if (tasks.length > 0) {\n const taskIds = tasks.map((t) => t.id);\n const allDeps = db.select().from(schema.taskDependencies).all();\n\n // Build lookup: taskId -> [dependsOn]\n const depMap = new Map<string, string[]>();\n for (const dep of allDeps) {\n if (taskIds.includes(dep.taskId)) {\n let arr = depMap.get(dep.taskId);\n if (!arr) {\n arr = [];\n depMap.set(dep.taskId, arr);\n }\n arr.push(dep.dependsOn);\n }\n }\n\n for (const task of tasks) {\n const deps = depMap.get(task.id);\n if (deps && deps.length > 0) {\n task.depends = deps;\n }\n }\n }\n\n // 3. Load project metadata from schema_meta\n const projectMeta =\n (await getMetaValue<ProjectMeta>(cwd, 'project_meta')) ?? DEFAULT_PROJECT_META;\n\n // 4. Load work state from schema_meta\n const workState =\n (await getMetaValue<TaskWorkState>(cwd, 'focus_state')) ?? DEFAULT_WORK_STATE;\n\n // 5. Load labels from schema_meta\n const labels =\n (await getMetaValue<Record<string, string[]>>(cwd, 'labels')) ?? undefined;\n\n // 6. Load file meta from schema_meta\n const storedMeta = await getMetaValue<FileMeta>(cwd, 'file_meta');\n\n // 7. Compute checksum over task data\n const checksum = computeChecksum(tasks);\n\n const fileMeta: FileMeta = {\n ...(storedMeta ?? DEFAULT_FILE_META),\n checksum,\n };\n\n // 8. Build and return the TaskFile\n const taskFile: TaskFile = {\n version: storedMeta?.schemaVersion ?? DEFAULT_FILE_META.schemaVersion,\n project: projectMeta,\n lastUpdated: new Date().toISOString(),\n _meta: fileMeta,\n focus: workState,\n tasks,\n };\n\n if (labels) {\n taskFile.labels = labels;\n }\n\n return taskFile;\n },\n\n // ---- saveTaskFile ----\n\n async saveTaskFile(data: TaskFile): Promise<void> {\n const db = await getDb(cwd);\n\n // 1. Determine which task IDs are in the incoming data\n const incomingIds = new Set(data.tasks.map((t) => t.id));\n\n // 2. Get existing non-archived task IDs from DB\n const existingRows = db\n .select({ id: schema.tasks.id })\n .from(schema.tasks)\n .where(ne(schema.tasks.status, 'archived'))\n .all();\n const existingIds = new Set(existingRows.map((r) => r.id));\n\n // 3. Delete tasks that are in DB but NOT in incoming data (non-archived only)\n for (const eid of existingIds) {\n if (!incomingIds.has(eid)) {\n db.delete(schema.taskDependencies)\n .where(eq(schema.taskDependencies.taskId, eid))\n .run();\n db.delete(schema.tasks).where(eq(schema.tasks.id, eid)).run();\n }\n }\n\n // 4. Upsert all tasks from data.tasks\n for (const task of data.tasks) {\n const row = taskToRow(task);\n db.insert(schema.tasks)\n .values(row)\n .onConflictDoUpdate({\n target: schema.tasks.id,\n set: {\n title: row.title,\n description: row.description,\n status: row.status,\n priority: row.priority,\n type: row.type,\n parentId: row.parentId,\n phase: row.phase,\n size: row.size,\n position: row.position,\n positionVersion: row.positionVersion,\n labelsJson: row.labelsJson,\n notesJson: row.notesJson,\n acceptanceJson: row.acceptanceJson,\n filesJson: row.filesJson,\n origin: row.origin,\n blockedBy: row.blockedBy,\n epicLifecycle: row.epicLifecycle,\n noAutoComplete: row.noAutoComplete,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n completedAt: row.completedAt,\n cancelledAt: row.cancelledAt,\n cancellationReason: row.cancellationReason,\n verificationJson: row.verificationJson,\n createdBy: row.createdBy,\n modifiedBy: row.modifiedBy,\n sessionId: row.sessionId,\n },\n })\n .run();\n\n // Update dependencies: delete old, insert new\n db.delete(schema.taskDependencies)\n .where(eq(schema.taskDependencies.taskId, task.id))\n .run();\n\n if (task.depends && task.depends.length > 0) {\n for (const depId of task.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId: task.id, dependsOn: depId })\n .onConflictDoNothing()\n .run();\n }\n }\n }\n\n // 5. Store project metadata, focus state, labels, and file meta in schema_meta\n await setMetaValue(cwd, 'project_meta', data.project);\n if (data.focus) {\n await setMetaValue(cwd, 'focus_state', data.focus);\n }\n if (data.labels) {\n await setMetaValue(cwd, 'labels', data.labels);\n }\n await setMetaValue(cwd, 'file_meta', {\n ...data._meta,\n checksum: computeChecksum(data.tasks),\n });\n\n // 6. Persist to disk\n saveToFile();\n\n // 7. Also persist the tasks.json for backward compatibility\n try {\n await saveJson(getTaskPath(cwd), data, { backupDir: getBackupDir(cwd) });\n } catch {\n // Non-fatal: SQLite is the source of truth in sqlite mode\n }\n },\n\n // ---- loadArchive ----\n\n async loadArchive(): Promise<ArchiveFile | null> {\n const db = await getDb(cwd);\n\n // Query tasks where status = 'archived'\n const archivedRows = db\n .select()\n .from(schema.tasks)\n .where(eq(schema.tasks.status, 'archived'))\n .all();\n\n if (archivedRows.length === 0) return null;\n\n const archivedTasks: Task[] = archivedRows.map((row) => {\n const task = rowToTask(row);\n // Restore the original terminal status for the archive representation\n // but keep the archived metadata accessible\n return {\n ...task,\n // In archive files, tasks retain their pre-archive status if available,\n // but since we store as 'archived' in DB, use the archived info\n archivedAt: row.archivedAt ?? undefined,\n archiveReason: row.archiveReason ?? undefined,\n cycleTimeDays: row.cycleTimeDays ?? undefined,\n } as Task & { archivedAt?: string; archiveReason?: string; cycleTimeDays?: number };\n });\n\n // Load dependencies for archived tasks\n if (archivedTasks.length > 0) {\n const taskIds = archivedTasks.map((t) => t.id);\n const allDeps = db.select().from(schema.taskDependencies).all();\n\n const depMap = new Map<string, string[]>();\n for (const dep of allDeps) {\n if (taskIds.includes(dep.taskId)) {\n let arr = depMap.get(dep.taskId);\n if (!arr) {\n arr = [];\n depMap.set(dep.taskId, arr);\n }\n arr.push(dep.dependsOn);\n }\n }\n\n for (const task of archivedTasks) {\n const deps = depMap.get(task.id);\n if (deps && deps.length > 0) {\n task.depends = deps;\n }\n }\n }\n\n return {\n archivedTasks,\n version: '1.0.0',\n };\n },\n\n // ---- saveArchive ----\n\n async saveArchive(data: ArchiveFile): Promise<void> {\n const db = await getDb(cwd);\n\n for (const task of data.archivedTasks) {\n const row = archivedTaskToRow(task);\n\n // Extract archive-specific fields if they exist on the task object\n const taskAny = task as Task & {\n archivedAt?: string;\n archiveReason?: string;\n cycleTimeDays?: number;\n };\n\n db.insert(schema.tasks)\n .values({\n ...row,\n archivedAt: taskAny.archivedAt ?? row.completedAt ?? new Date().toISOString(),\n archiveReason: taskAny.archiveReason ?? 'completed',\n cycleTimeDays: taskAny.cycleTimeDays ?? null,\n })\n .onConflictDoUpdate({\n target: schema.tasks.id,\n set: {\n status: 'archived',\n title: row.title,\n description: row.description,\n priority: row.priority,\n type: row.type,\n parentId: row.parentId,\n phase: row.phase,\n size: row.size,\n labelsJson: row.labelsJson,\n notesJson: row.notesJson,\n acceptanceJson: row.acceptanceJson,\n filesJson: row.filesJson,\n origin: row.origin,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n completedAt: row.completedAt,\n cancelledAt: row.cancelledAt,\n cancellationReason: row.cancellationReason,\n verificationJson: row.verificationJson,\n createdBy: row.createdBy,\n modifiedBy: row.modifiedBy,\n sessionId: row.sessionId,\n archivedAt:\n taskAny.archivedAt ?? row.completedAt ?? new Date().toISOString(),\n archiveReason: taskAny.archiveReason ?? 'completed',\n cycleTimeDays: taskAny.cycleTimeDays ?? null,\n },\n })\n .run();\n\n // Upsert dependencies for archived tasks too\n db.delete(schema.taskDependencies)\n .where(eq(schema.taskDependencies.taskId, task.id))\n .run();\n\n if (task.depends && task.depends.length > 0) {\n for (const depId of task.depends) {\n db.insert(schema.taskDependencies)\n .values({ taskId: task.id, dependsOn: depId })\n .onConflictDoNothing()\n .run();\n }\n }\n }\n\n saveToFile();\n },\n\n // ---- loadSessions ----\n\n async loadSessions(): Promise<SessionsFile> {\n const db = await getDb(cwd);\n\n const sessionRows = db.select().from(schema.sessions).all();\n const sessions: Session[] = sessionRows.map(rowToSession);\n\n return {\n sessions,\n version: '1.0.0',\n _meta: { schemaVersion: '1.0.0', lastUpdated: new Date().toISOString() },\n };\n },\n\n // ---- saveSessions ----\n\n async saveSessions(data: SessionsFile): Promise<void> {\n const db = await getDb(cwd);\n\n // Get existing session IDs\n const existingRows = db.select({ id: schema.sessions.id }).from(schema.sessions).all();\n const existingIds = new Set(existingRows.map((r) => r.id));\n const incomingIds = new Set(data.sessions.map((s) => s.id));\n\n // Delete sessions that are no longer in the data\n for (const eid of existingIds) {\n if (!incomingIds.has(eid)) {\n db.delete(schema.sessions).where(eq(schema.sessions.id, eid)).run();\n }\n }\n\n // Upsert all sessions\n for (const session of data.sessions) {\n db.insert(schema.sessions)\n .values({\n id: session.id,\n name: session.name,\n status: session.status,\n scopeJson: JSON.stringify(session.scope ?? { type: 'global' }),\n currentTask: session.taskWork?.taskId ?? null,\n taskStartedAt: session.taskWork?.setAt ?? null,\n agent: session.agent ?? null,\n notesJson: session.notes ? JSON.stringify(session.notes) : '[]',\n tasksCompletedJson: session.tasksCompleted\n ? JSON.stringify(session.tasksCompleted)\n : '[]',\n tasksCreatedJson: session.tasksCreated\n ? JSON.stringify(session.tasksCreated)\n : '[]',\n startedAt: session.startedAt,\n endedAt: session.endedAt ?? null,\n })\n .onConflictDoUpdate({\n target: schema.sessions.id,\n set: {\n name: session.name,\n status: session.status,\n scopeJson: JSON.stringify(session.scope ?? { type: 'global' }),\n currentTask: session.taskWork?.taskId ?? null,\n taskStartedAt: session.taskWork?.setAt ?? null,\n agent: session.agent ?? null,\n notesJson: session.notes ? JSON.stringify(session.notes) : '[]',\n tasksCompletedJson: session.tasksCompleted\n ? JSON.stringify(session.tasksCompleted)\n : '[]',\n tasksCreatedJson: session.tasksCreated\n ? JSON.stringify(session.tasksCreated)\n : '[]',\n startedAt: session.startedAt,\n endedAt: session.endedAt ?? null,\n },\n })\n .run();\n }\n\n saveToFile();\n },\n\n // ---- appendLog ----\n\n async appendLog(entry: Record<string, unknown>): Promise<void> {\n // Logs stay as JSONL files, not in SQLite\n await appendJsonl(getLogPath(cwd), entry);\n },\n\n // ---- close ----\n\n async close(): Promise<void> {\n closeDb();\n },\n\n // Deprecated aliases\n async loadTodoFile(): Promise<TaskFile> {\n return accessor.loadTaskFile();\n },\n\n async saveTodoFile(data: TaskFile): Promise<void> {\n return accessor.saveTaskFile(data);\n },\n };\n\n return accessor;\n}\n", "/**\n * JSON file-based implementation of the DataAccessor interface.\n *\n * Delegates to readJson/readJsonRequired/saveJson/appendJsonl for all I/O,\n * and uses path helpers from ../core/paths.js for file location resolution.\n *\n * @epic T4454\n */\n\nimport type { TaskFile } from '../types/task.js';\nimport type { DataAccessor, ArchiveFile, SessionsFile } from './data-accessor.js';\nimport { readJson, readJsonRequired, saveJson, appendJsonl } from './json.js';\nimport {\n getTaskPath,\n getArchivePath,\n getSessionsPath,\n getLogPath,\n getBackupDir,\n} from '../core/paths.js';\n\n/**\n * Create a JSON file-backed DataAccessor.\n *\n * @param cwd - Working directory for path resolution (defaults to process.cwd())\n */\nexport async function createJsonDataAccessor(cwd?: string): Promise<DataAccessor> {\n const accessor: DataAccessor = {\n engine: 'json' as const,\n\n async loadTaskFile(): Promise<TaskFile> {\n return readJsonRequired<TaskFile>(getTaskPath(cwd));\n },\n\n async saveTaskFile(data: TaskFile): Promise<void> {\n await saveJson(getTaskPath(cwd), data, { backupDir: getBackupDir(cwd) });\n },\n\n // Deprecated aliases\n async loadTodoFile(): Promise<TaskFile> {\n return accessor.loadTaskFile();\n },\n\n async saveTodoFile(data: TaskFile): Promise<void> {\n return accessor.saveTaskFile(data);\n },\n\n async loadArchive(): Promise<ArchiveFile | null> {\n return readJson<ArchiveFile>(getArchivePath(cwd));\n },\n\n async saveArchive(data: ArchiveFile): Promise<void> {\n await saveJson(getArchivePath(cwd), data, { backupDir: getBackupDir(cwd) });\n },\n\n async loadSessions(): Promise<SessionsFile> {\n const data = await readJson<SessionsFile>(getSessionsPath(cwd));\n if (data) {\n // Ensure _meta exists even on old sessions files\n if (!data._meta) {\n data._meta = { schemaVersion: '1.0.0', lastUpdated: new Date().toISOString() };\n }\n if (!data.version) {\n data.version = '1.0.0';\n }\n return data;\n }\n return {\n sessions: [],\n version: '1.0.0',\n _meta: { schemaVersion: '1.0.0', lastUpdated: new Date().toISOString() },\n };\n },\n\n async saveSessions(data: SessionsFile): Promise<void> {\n await saveJson(getSessionsPath(cwd), data, { backupDir: getBackupDir(cwd) });\n },\n\n async appendLog(entry: Record<string, unknown>): Promise<void> {\n await appendJsonl(getLogPath(cwd), entry);\n },\n\n async close(): Promise<void> {\n // No-op: JSON files don't hold open resources.\n },\n };\n\n return accessor;\n}\n", "/**\n * MCP environment detection - CLEO-specific runtime mode resolution.\n *\n * Detects dev-ts vs prod-npm mode by reading ~/.cleo/VERSION.\n * This is the only CLEO-specific concern here \u2014 all provider detection,\n * config writing, and MCP server installation is delegated to @cleocode/caamp.\n *\n * @task T4676\n * @epic T4663\n */\n\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\n\n/** Resolved environment mode for MCP server config. */\nexport interface McpEnvMode {\n mode: 'dev-ts' | 'prod-npm' | 'unknown';\n /** Absolute path to the source directory (dev-ts mode only). */\n source: string | null;\n}\n\n/**\n * Detect the current CLEO environment mode by reading ~/.cleo/VERSION.\n *\n * The VERSION file format:\n * Line 1: version number\n * Lines 2+: key=value pairs (mode, source, etc.)\n *\n * @task T4584\n */\nexport function detectEnvMode(): McpEnvMode {\n const versionPath = join(\n process.env['CLEO_HOME'] ?? join(homedir(), '.cleo'),\n 'VERSION',\n );\n\n let content: string;\n try {\n content = readFileSync(versionPath, 'utf-8');\n } catch {\n return { mode: 'unknown', source: null };\n }\n\n const kvPairs: Record<string, string> = {};\n const lines = content.trim().split('\\n');\n for (let i = 1; i < lines.length; i++) {\n const eqIdx = lines[i].indexOf('=');\n if (eqIdx > 0) {\n kvPairs[lines[i].slice(0, eqIdx).trim()] = lines[i].slice(eqIdx + 1).trim();\n }\n }\n\n const rawMode = kvPairs['mode'] ?? 'unknown';\n const mode = rawMode === 'dev-ts' ? 'dev-ts'\n : rawMode === 'prod-npm' ? 'prod-npm'\n : 'unknown';\n\n return {\n mode,\n source: mode === 'dev-ts' ? (kvPairs['source'] ?? null) : null,\n };\n}\n\n/**\n * Check if cleo-mcp binary is available in PATH.\n * Returns false on any error (treats missing as not found).\n */\nfunction isCleomcpInPath(): boolean {\n try {\n execSync('which cleo-mcp', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate the MCP server entry for the cleo server based on env mode.\n *\n * Returns a config object compatible with CAAMP's McpServerConfig:\n * - dev-ts: { command: 'node', args: ['<source>/dist/mcp/index.js'] }\n * - prod-npm: { command: 'cleo-mcp', args: [] }\n * - fallback: { command: 'npx', args: ['-y', '@cleocode/cleo', '--mcp-server'] }\n *\n * @task T4584\n */\nexport function generateMcpServerEntry(env: McpEnvMode): Record<string, unknown> {\n if (env.mode === 'dev-ts' && env.source) {\n return {\n command: 'node',\n args: [join(env.source, 'dist', 'mcp', 'index.js')],\n env: {},\n };\n }\n\n // prod-npm or unknown: prefer globally installed binary, fall back to npx\n if (isCleomcpInPath()) {\n return {\n command: 'cleo-mcp',\n args: [],\n env: {},\n };\n }\n\n // npx fallback: works for npm install -g via npx or direct npx usage\n return {\n command: 'npx',\n args: ['-y', '@cleocode/cleo', '--mcp-server'],\n env: {},\n };\n}\n", "/**\n * NEXUS project registry - cross-project registration and management.\n *\n * Manages the global project registry at ~/.cleo/projects-registry.json.\n * Supports registering, unregistering, listing, and syncing projects\n * for cross-project task coordination.\n *\n * @task T4574\n * @epic T4540\n */\n\nimport { createHash } from 'node:crypto';\nimport { join } from 'node:path';\nimport { mkdir, access, readFile } from 'node:fs/promises';\nimport { z } from 'zod';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport { getCleoHome } from '../paths.js';\nimport { readJson, saveJson } from '../../store/json.js';\n\n// \u2500\u2500 Schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const NexusPermissionLevelSchema = z.enum(['read', 'write', 'execute']);\nexport type NexusPermissionLevel = z.infer<typeof NexusPermissionLevelSchema>;\n\nexport const NexusHealthStatusSchema = z.enum(['unknown', 'healthy', 'degraded', 'unreachable']);\nexport type NexusHealthStatus = z.infer<typeof NexusHealthStatusSchema>;\n\nexport const NexusProjectSchema = z.object({\n hash: z.string().regex(/^[a-f0-9]{12}$/),\n path: z.string().min(1),\n name: z.string().min(1).max(64),\n registeredAt: z.string(),\n lastSeen: z.string(),\n healthStatus: NexusHealthStatusSchema.default('unknown'),\n healthLastCheck: z.string().nullable().default(null),\n permissions: NexusPermissionLevelSchema.default('read'),\n lastSync: z.string(),\n taskCount: z.number().int().min(0).default(0),\n labels: z.array(z.string()).default([]),\n});\nexport type NexusProject = z.infer<typeof NexusProjectSchema>;\n\nexport const NexusRegistryFileSchema = z.object({\n $schema: z.string().optional(),\n schemaVersion: z.string().default('1.0.0'),\n lastUpdated: z.string(),\n projects: z.record(z.string(), NexusProjectSchema),\n});\nexport type NexusRegistryFile = z.infer<typeof NexusRegistryFileSchema>;\n\n// \u2500\u2500 Path helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Get path to the NEXUS home directory (cache, etc.). */\nexport function getNexusHome(): string {\n return process.env['NEXUS_HOME'] ?? join(getCleoHome(), 'nexus');\n}\n\n/** Get path to the NEXUS cache directory. */\nexport function getNexusCacheDir(): string {\n return process.env['NEXUS_CACHE_DIR'] ?? join(getNexusHome(), 'cache');\n}\n\n/** Get path to the unified projects registry file. */\nexport function getRegistryPath(): string {\n return process.env['NEXUS_REGISTRY_FILE'] ?? join(getCleoHome(), 'projects-registry.json');\n}\n\n// \u2500\u2500 Hash \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Generate a 12-character hex hash from a project path.\n * Matches Bash CLI's generate_project_hash() behavior.\n */\nexport function generateProjectHash(projectPath: string): string {\n const hash = createHash('sha256').update(projectPath).digest('hex');\n return hash.substring(0, 12);\n}\n\n// \u2500\u2500 Registry operations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Read the global registry file.\n * Returns null if the file does not exist.\n */\nexport async function readRegistry(): Promise<NexusRegistryFile | null> {\n const data = await readJson<NexusRegistryFile>(getRegistryPath());\n if (!data) return null;\n return NexusRegistryFileSchema.parse(data);\n}\n\n/**\n * Read the global registry file, throwing if it does not exist.\n */\nexport async function readRegistryRequired(): Promise<NexusRegistryFile> {\n const registry = await readRegistry();\n if (!registry) {\n throw new CleoError(\n ExitCode.NEXUS_NOT_INITIALIZED,\n 'Nexus registry not initialized. Run: cleo nexus init',\n { fix: 'cleo nexus init' },\n );\n }\n return registry;\n}\n\n/**\n * Initialize the NEXUS directory structure and registry file.\n * Idempotent -- safe to call multiple times.\n */\nexport async function nexusInit(): Promise<void> {\n const nexusHome = getNexusHome();\n const cacheDir = getNexusCacheDir();\n const registryPath = getRegistryPath();\n\n // Create directories\n await mkdir(nexusHome, { recursive: true });\n await mkdir(cacheDir, { recursive: true });\n\n // Create empty registry if it doesn't exist\n const existing = await readJson(registryPath);\n if (!existing) {\n const now = new Date().toISOString();\n const registry: NexusRegistryFile = {\n $schema: './schemas/projects-registry.schema.json',\n schemaVersion: '1.0.0',\n lastUpdated: now,\n projects: {},\n };\n await saveJson(registryPath, registry);\n }\n}\n\n/** Check if a path contains a CLEO project (has .cleo/todo.json). */\nasync function isCleoProject(projectPath: string): Promise<boolean> {\n try {\n await access(join(projectPath, '.cleo', 'todo.json'));\n return true;\n } catch {\n return false;\n }\n}\n\n/** Read task metadata from a project's todo.json. */\nasync function readProjectMeta(projectPath: string): Promise<{ taskCount: number; labels: string[] }> {\n try {\n const todoPath = join(projectPath, '.cleo', 'todo.json');\n const raw = await readFile(todoPath, 'utf-8');\n const data = JSON.parse(raw) as { tasks: Array<{ labels?: string[] }> };\n const tasks = data.tasks ?? [];\n const allLabels = tasks.flatMap(t => t.labels ?? []);\n const uniqueLabels = [...new Set(allLabels)].sort();\n return { taskCount: tasks.length, labels: uniqueLabels };\n } catch {\n return { taskCount: 0, labels: [] };\n }\n}\n\n/**\n * Register a project in the global registry.\n * @returns The project hash.\n */\nexport async function nexusRegister(\n projectPath: string,\n name?: string,\n permissions: NexusPermissionLevel = 'read',\n): Promise<string> {\n if (!projectPath) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Project path required');\n }\n\n // Validate project has .cleo/todo.json\n if (!(await isCleoProject(projectPath))) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Path missing .cleo/todo.json: ${projectPath}`,\n { fix: `cd ${projectPath} && cleo init` },\n );\n }\n\n const projectName = name || projectPath.split('/').pop() || 'unnamed';\n const projectHash = generateProjectHash(projectPath);\n\n // Ensure registry exists\n await nexusInit();\n const registry = await readRegistryRequired();\n\n // Check if already registered\n const existing = registry.projects[projectHash];\n if (existing?.permissions) {\n throw new CleoError(\n ExitCode.NEXUS_PROJECT_EXISTS,\n `Project already registered with hash: ${projectHash}`,\n );\n }\n\n // Check for name conflicts (new entries only)\n if (!existing) {\n const nameConflict = Object.values(registry.projects).find(p => p.name === projectName);\n if (nameConflict) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Project name '${projectName}' already exists in registry`,\n );\n }\n }\n\n // Read project metadata\n const meta = await readProjectMeta(projectPath);\n const now = new Date().toISOString();\n\n if (existing) {\n // Merge nexus fields into existing entry\n existing.permissions = permissions;\n existing.lastSync = now;\n existing.taskCount = meta.taskCount;\n existing.labels = meta.labels;\n existing.lastSeen = now;\n } else {\n // Create new entry\n registry.projects[projectHash] = {\n hash: projectHash,\n path: projectPath,\n name: projectName,\n registeredAt: now,\n lastSeen: now,\n healthStatus: 'unknown',\n healthLastCheck: null,\n permissions,\n lastSync: now,\n taskCount: meta.taskCount,\n labels: meta.labels,\n };\n }\n\n registry.lastUpdated = now;\n await saveJson(getRegistryPath(), registry);\n return projectHash;\n}\n\n/**\n * Unregister a project from the global registry.\n */\nexport async function nexusUnregister(nameOrHash: string): Promise<void> {\n if (!nameOrHash) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Project name or hash required');\n }\n\n const registry = await readRegistryRequired();\n const hash = resolveProjectHash(registry, nameOrHash);\n\n if (!hash || !registry.projects[hash]) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Project not found in registry: ${nameOrHash}`,\n );\n }\n\n delete registry.projects[hash];\n registry.lastUpdated = new Date().toISOString();\n await saveJson(getRegistryPath(), registry);\n}\n\n/**\n * List all registered projects.\n */\nexport async function nexusList(): Promise<NexusProject[]> {\n const registry = await readRegistry();\n if (!registry) return [];\n return Object.values(registry.projects);\n}\n\n/**\n * Get a project by name or hash.\n * Returns null if not found.\n */\nexport async function nexusGetProject(nameOrHash: string): Promise<NexusProject | null> {\n const registry = await readRegistry();\n if (!registry) return null;\n\n // Try hash first\n if (/^[a-f0-9]{12}$/.test(nameOrHash)) {\n return registry.projects[nameOrHash] ?? null;\n }\n\n // Try name\n return Object.values(registry.projects).find(p => p.name === nameOrHash) ?? null;\n}\n\n/**\n * Check if a project exists in the registry.\n */\nexport async function nexusProjectExists(nameOrHash: string): Promise<boolean> {\n const project = await nexusGetProject(nameOrHash);\n return project !== null;\n}\n\n/**\n * Sync project metadata (task count, labels) for a registered project.\n */\nexport async function nexusSync(nameOrHash: string): Promise<void> {\n if (!nameOrHash) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Project name or hash required');\n }\n\n const registry = await readRegistryRequired();\n const hash = resolveProjectHash(registry, nameOrHash);\n\n if (!hash || !registry.projects[hash]) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Project not found in registry: ${nameOrHash}`,\n );\n }\n\n const project = registry.projects[hash];\n const meta = await readProjectMeta(project.path);\n const now = new Date().toISOString();\n\n project.taskCount = meta.taskCount;\n project.labels = meta.labels;\n project.lastSync = now;\n registry.lastUpdated = now;\n\n await saveJson(getRegistryPath(), registry);\n}\n\n/**\n * Sync all registered projects.\n * @returns Counts of synced and failed projects.\n */\nexport async function nexusSyncAll(): Promise<{ synced: number; failed: number }> {\n const registry = await readRegistryRequired();\n let synced = 0;\n let failed = 0;\n\n for (const project of Object.values(registry.projects)) {\n try {\n const meta = await readProjectMeta(project.path);\n project.taskCount = meta.taskCount;\n project.labels = meta.labels;\n project.lastSync = new Date().toISOString();\n synced++;\n } catch {\n failed++;\n }\n }\n\n registry.lastUpdated = new Date().toISOString();\n await saveJson(getRegistryPath(), registry);\n return { synced, failed };\n}\n\n// \u2500\u2500 Internal helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Resolve a name-or-hash to a registry key (hash). */\nfunction resolveProjectHash(registry: NexusRegistryFile, nameOrHash: string): string | null {\n // Direct hash match\n if (/^[a-f0-9]{12}$/.test(nameOrHash) && registry.projects[nameOrHash]) {\n return nameOrHash;\n }\n\n // Name lookup\n const entry = Object.entries(registry.projects).find(([, p]) => p.name === nameOrHash);\n return entry ? entry[0] : null;\n}\n", "/**\n * Project type detection and configuration.\n * Ported from lib/data/project-detect.sh and lib/data/project-registry.sh\n *\n * @epic T4454\n * @task T4530\n */\n\nimport { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Detected project type. */\nexport type ProjectType =\n | 'node'\n | 'python'\n | 'rust'\n | 'go'\n | 'ruby'\n | 'java'\n | 'dotnet'\n | 'bash'\n | 'unknown';\n\n/** Test framework. */\nexport type TestFramework =\n | 'jest'\n | 'vitest'\n | 'mocha'\n | 'pytest'\n | 'bats'\n | 'cargo-test'\n | 'go-test'\n | 'rspec'\n | 'junit'\n | 'unknown';\n\n/** Project detection result. */\nexport interface ProjectInfo {\n type: ProjectType;\n testFramework: TestFramework;\n hasTypeScript: boolean;\n packageManager?: 'npm' | 'yarn' | 'pnpm' | 'bun';\n monorepo: boolean;\n}\n\n/**\n * Detect project type from directory contents.\n */\nexport function detectProjectType(projectDir: string): ProjectInfo {\n const exists = (f: string) => existsSync(join(projectDir, f));\n\n const info: ProjectInfo = {\n type: 'unknown',\n testFramework: 'unknown',\n hasTypeScript: false,\n monorepo: false,\n };\n\n // Node.js\n if (exists('package.json')) {\n info.type = 'node';\n info.hasTypeScript = exists('tsconfig.json');\n\n if (exists('yarn.lock')) info.packageManager = 'yarn';\n else if (exists('pnpm-lock.yaml')) info.packageManager = 'pnpm';\n else if (exists('bun.lockb')) info.packageManager = 'bun';\n else info.packageManager = 'npm';\n\n // Monorepo detection\n if (exists('lerna.json') || exists('pnpm-workspace.yaml') || exists('packages')) {\n info.monorepo = true;\n }\n\n // Test framework\n if (exists('vitest.config.ts') || exists('vitest.config.js')) info.testFramework = 'vitest';\n else if (exists('jest.config.ts') || exists('jest.config.js')) info.testFramework = 'jest';\n else if (exists('.mocharc.yml') || exists('.mocharc.json')) info.testFramework = 'mocha';\n }\n // Python\n else if (exists('pyproject.toml') || exists('setup.py') || exists('requirements.txt')) {\n info.type = 'python';\n info.testFramework = 'pytest';\n }\n // Rust\n else if (exists('Cargo.toml')) {\n info.type = 'rust';\n info.testFramework = 'cargo-test';\n }\n // Go\n else if (exists('go.mod')) {\n info.type = 'go';\n info.testFramework = 'go-test';\n }\n // Ruby\n else if (exists('Gemfile')) {\n info.type = 'ruby';\n info.testFramework = 'rspec';\n }\n // Java\n else if (exists('pom.xml') || exists('build.gradle') || exists('build.gradle.kts')) {\n info.type = 'java';\n info.testFramework = 'junit';\n }\n // .NET (glob: existsSync doesn't support wildcards, check directory)\n else if (hasFileWithExtension(projectDir, '.csproj') || hasFileWithExtension(projectDir, '.sln')) {\n info.type = 'dotnet';\n }\n // Bash/Shell\n else if (exists('tests') && exists('install.sh')) {\n info.type = 'bash';\n if (exists('tests/unit') || exists('tests/integration')) {\n info.testFramework = 'bats';\n }\n }\n\n return info;\n}\n\n/** Check if a directory contains any file with the given extension. */\nfunction hasFileWithExtension(dir: string, ext: string): boolean {\n try {\n const entries = readdirSync(dir);\n return entries.some(e => e.endsWith(ext));\n } catch {\n return false;\n }\n}\n", "/**\n * CLEO MCP Server Entry Point\n *\n * Exposes CLEO's 65 CLI commands and 280+ library functions through\n * two gateway tools using CQRS pattern:\n * - cleo_query: 48 read operations (never modifies state)\n * - cleo_mutate: 48 write operations (validated, logged, atomic)\n *\n * Wires together:\n * 1. Configuration loader\n * 2. CLI executor wrapper\n * 3. Domain router\n * 4. Gateway tools (query + mutate)\n * 5. MCP SDK server with stdio transport\n *\n * @task T2926\n * @see MCP-SERVER-SPECIFICATION.md for complete API documentation\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { loadConfig} from './lib/config.js';\nimport { DomainRouter, DomainRequest } from './lib/router.js';\nimport { initMcpDispatcher, handleMcpToolCall, getMcpDispatcher } from '../dispatch/adapters/mcp.js';\nimport { createExecutor } from './lib/executor.js';\nimport { registerQueryTool } from './gateways/query.js';\nimport { registerMutateTool } from './gateways/mutate.js';\nimport { QueryCache } from './lib/cache.js';\nimport { BackgroundJobManager } from './lib/background-jobs.js';\nimport { detectExecutionMode, type ResolvedMode } from './lib/mode-detector.js';\nimport { generateCapabilityReport } from './engine/capability-matrix.js';\nimport { enforceBudget } from './lib/budget.js';\n\n/**\n * Server state for cleanup\n */\ninterface ServerState {\n dispatcher: any;\n server: Server;\n cache: QueryCache;\n jobManager: BackgroundJobManager;\n}\n\nlet serverState: ServerState | null = null;\n\n\n/**\n * Initialize and start MCP server\n */\nasync function main(): Promise<void> {\n try {\n // Load configuration\n console.error('[CLEO MCP] Loading configuration...');\n const config = loadConfig();\n\n // Detect execution mode\n console.error('[CLEO MCP] Detecting execution mode...');\n const modeDetection = detectExecutionMode();\n const executionMode: ResolvedMode = modeDetection.mode;\n console.error(`[CLEO MCP] Execution mode: ${executionMode} (${modeDetection.reason})`);\n\n if (executionMode === 'native') {\n const report = generateCapabilityReport();\n console.error(`[CLEO MCP] Native mode: ${report.native} native + ${report.hybrid} hybrid operations available`);\n console.error(`[CLEO MCP] CLI-only operations (${report.cli}) will return E_CLI_REQUIRED`);\n }\n\n // Log startup info (to stderr, not stdout which is used by MCP)\n console.error('[CLEO MCP] Starting server...');\n console.error(`[CLEO MCP] CLI path: ${config.cliPath}`);\n console.error(`[CLEO MCP] Timeout: ${config.timeout}ms`);\n console.error(`[CLEO MCP] Log level: ${config.logLevel}`);\n console.error(`[CLEO MCP] Metrics: ${config.enableMetrics ? 'enabled' : 'disabled'}`);\n console.error(`[CLEO MCP] Max retries: ${config.maxRetries}`);\n\n // Create CLI executor\n console.error('[CLEO MCP] Creating CLI executor...');\n const executor = createExecutor(config.cliPath, config.timeout, config.maxRetries);\n\n // Test CLI connection (non-fatal in native/auto mode)\n console.error('[CLEO MCP] Testing CLI connection...');\n const connected = await executor.testConnection();\n if (!connected) {\n if (executionMode === 'cli' && modeDetection.configuredMode === 'cli') {\n // CLI mode was forced but CLI isn't available\n throw new Error(`Failed to connect to CLEO CLI at ${config.cliPath}`);\n }\n // In native/auto mode, CLI unavailability is expected\n console.error('[CLEO MCP] CLI not available - running in native TypeScript mode');\n executor.setAvailable(false);\n } else {\n console.error('[CLEO MCP] CLI connection successful');\n executor.setAvailable(true);\n }\n\n // Get CLI version (only if connected)\n if (connected) {\n const cliVersion = await executor.getVersion();\n console.error(`[CLEO MCP] CLI version: ${cliVersion}`);\n }\n\n // Initialize MCP dispatcher pipeline\n console.error('[CLEO MCP] Initializing MCP dispatcher...');\n const dispatcher = initMcpDispatcher({ rateLimiting: config.rateLimiting });\n console.error('[CLEO MCP] Dispatcher initialized');\n console.error(`[CLEO MCP] Rate limiting: ${config.rateLimiting.enabled ? 'enabled' : 'disabled'}`);\n\n // Initialize background job manager\n const jobManager = new BackgroundJobManager({ maxJobs: 10, retentionMs: 3600000 });\n console.error('[CLEO MCP] Background job manager initialized (max: 10, retention: 1h)');\n\n // Wire job manager into system handler\n const systemHandler = (dispatcher as any).handlers.get('system');\n if (systemHandler && typeof systemHandler.setJobManager === 'function') {\n systemHandler.setJobManager(jobManager);\n console.error('[CLEO MCP] Background job manager wired to system handler');\n }\n\n // Initialize query cache\n const cache = new QueryCache(config.queryCacheTtl, config.queryCache);\n console.error(`[CLEO MCP] Query cache: ${config.queryCache ? 'enabled' : 'disabled'} (TTL: ${config.queryCacheTtl}ms)`);\n\n // Create MCP server\n const server = new Server(\n {\n name: 'cleo-server',\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // Register tools (ListTools handler)\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n registerQueryTool(),\n registerMutateTool(),\n ],\n };\n });\n\n // Handle tool calls (CallTool handler)\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n console.error(`[CLEO MCP] Tool call: ${name}`);\n if (config.logLevel === 'debug') {\n console.error(`[CLEO MCP] Arguments:`, JSON.stringify(args, null, 2));\n }\n\n try {\n // Validate gateway name\n if (name !== 'cleo_query' && name !== 'cleo_mutate') {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n _meta: {\n gateway: name,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n },\n success: false,\n error: {\n code: 'E_INVALID_GATEWAY',\n exitCode: 2,\n message: `Unknown gateway: ${name}. Use 'cleo_query' or 'cleo_mutate'.`,\n },\n }),\n },\n ],\n };\n }\n\n // Validate required parameters\n if (!args?.domain || !args?.operation) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n _meta: {\n gateway: name,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n },\n success: false,\n error: {\n code: 'E_INVALID_INPUT',\n exitCode: 2,\n message: 'Missing required parameters: domain and operation',\n },\n }),\n },\n ],\n };\n }\n\n // Build domain request\n const domainRequest: DomainRequest = {\n gateway: name as 'cleo_query' | 'cleo_mutate',\n domain: args.domain as string,\n operation: args.operation as string,\n params: args.params as Record<string, unknown> | undefined,\n };\n\n // Check cache bypass flag\n const bypassCache = !!(args.params as Record<string, unknown> | undefined)?.bypassCache;\n\n // For query operations, check cache first\n if (name === 'cleo_query' && !bypassCache) {\n const domain = args.domain as string;\n const operation = args.operation as string;\n const params = args.params as Record<string, unknown> | undefined;\n const cached = cache.get(domain, operation, params);\n if (cached !== undefined) {\n if (config.logLevel === 'debug') {\n console.error(`[CLEO MCP] Cache hit: ${domain}.${operation}`);\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(cached, null, 2),\n },\n ],\n };\n }\n }\n\n // Route to domain handler via central dispatchers+let result = await handleMcpToolCall(name, args.domain as string, args.operation as string, args.params as Record<string, unknown> | undefined);\n\n if (config.logLevel === 'debug') {\n console.error(`[CLEO MCP] Result:`, JSON.stringify(result, null, 2));\n }\n\n // Apply LAFS token budget enforcement (@task T4701)\n const tokenBudget = (args.params as Record<string, unknown> | undefined)?.tokenBudget as number | undefined;\n if (tokenBudget) {\n const { response: enforced, enforcement } = enforceBudget(\n result as unknown as Record<string, unknown>,\n tokenBudget,\n );\n result = enforced as unknown as typeof result;\n if (config.logLevel === 'debug') {\n console.error(`[CLEO MCP] Budget enforcement: ${enforcement.estimatedTokens}/${tokenBudget} tokens (${enforcement.truncated ? 'truncated' : 'ok'})`);\n }\n }\n\n // Cache successful query results\n if (name === 'cleo_query' && result.success && !bypassCache) {\n cache.set(\n args.domain as string,\n args.operation as string,\n args.params as Record<string, unknown> | undefined,\n result\n );\n }\n\n // Invalidate domain cache on mutate operations\n if (name === 'cleo_mutate') {\n const invalidated = cache.invalidateDomain(args.domain as string);\n if (invalidated > 0 && config.logLevel === 'debug') {\n console.error(`[CLEO MCP] Cache invalidated ${invalidated} entries for domain: ${args.domain}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (error) {\n console.error(`[CLEO MCP] Error:`, error);\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n _meta: {\n gateway: name,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n },\n success: false,\n error: {\n code: 'E_INTERNAL_ERROR',\n message: errorMessage,\n },\n },\n null,\n 2\n ),\n },\n ],\n isError: true,\n };\n }\n });\n\n // Store server state for cleanup\n serverState = {\n dispatcher,\n server,\n cache,\n jobManager,\n };\n\n // Create transport and connect\n console.error('[CLEO MCP] Connecting to stdio transport...');\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n console.error('[CLEO MCP] Server started successfully');\n console.error('[CLEO MCP] Ready for requests');\n } catch (error) {\n console.error('[CLEO MCP] Failed to start server:', error);\n process.exit(1);\n }\n}\n\n/**\n * Graceful shutdown handler\n */\nasync function shutdown(signal: string): Promise<void> {\n console.error(`[CLEO MCP] Received ${signal}, shutting down...`);\n\n if (serverState) {\n try {\n // Destroy background job manager\n serverState.jobManager.destroy();\n // Destroy cache\n serverState.cache.destroy();\n // Close server\n await serverState.server.close();\n console.error('[CLEO MCP] Server closed');\n } catch (error) {\n console.error('[CLEO MCP] Error during shutdown:', error);\n }\n }\n\n process.exit(0);\n}\n\n/**\n * Error handler for uncaught exceptions\n */\nfunction handleUncaughtError(error: Error, type: string): void {\n console.error(`[CLEO MCP] ${type}:`, error);\n\n // Attempt graceful shutdown\n if (serverState) {\n shutdown('ERROR').catch(() => {\n process.exit(1);\n });\n } else {\n process.exit(1);\n }\n}\n\n// Register signal handlers for graceful shutdown\nprocess.on('SIGINT', () => shutdown('SIGINT'));\nprocess.on('SIGTERM', () => shutdown('SIGTERM'));\n\n// Register error handlers\nprocess.on('uncaughtException', (error) =>\n handleUncaughtError(error, 'Uncaught Exception')\n);\nprocess.on('unhandledRejection', (reason) =>\n handleUncaughtError(\n reason instanceof Error ? reason : new Error(String(reason)),\n 'Unhandled Rejection'\n )\n);\n\n// Start server\nmain().catch((error) => {\n console.error('[CLEO MCP] Fatal error:', error);\n process.exit(1);\n});\n", "/**\n * Configuration loader for CLEO MCP Server\n *\n * Loads configuration from:\n * 1. Environment variables (CLEO_MCP_*)\n * 2. Config file (.cleo/config.json)\n * 3. Defaults (fallback values)\n *\n * @task T2928\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport {\n MCPConfig,\n DEFAULT_CONFIG,\n DEFAULT_LIFECYCLE_ENFORCEMENT,\n DEFAULT_PROTOCOL_VALIDATION,\n DEFAULT_RATE_LIMITING,\n ENV_PREFIX,\n CONFIG_SCHEMA,\n} from './defaults.js';\n\n/**\n * Configuration validation error\n */\nexport class ConfigValidationError extends Error {\n constructor(\n public field: string,\n public value: unknown,\n public constraint: string\n ) {\n super(`Invalid config field '${field}': ${constraint} (got ${value})`);\n this.name = 'ConfigValidationError';\n }\n}\n\n/**\n * Load configuration value from environment variable\n */\nfunction loadFromEnv(key: string): string | undefined {\n const envKey = `${ENV_PREFIX}${key.toUpperCase()}`;\n return process.env[envKey];\n}\n\n/**\n * Parse environment variable to appropriate type\n */\nfunction parseEnvValue(key: string, value: string): unknown {\n const schema = CONFIG_SCHEMA[key as keyof typeof CONFIG_SCHEMA];\n\n if (schema.type === 'boolean') {\n return value.toLowerCase() === 'true' || value === '1';\n }\n\n if (schema.type === 'number') {\n const num = parseInt(value, 10);\n if (isNaN(num)) {\n throw new ConfigValidationError(key, value, 'must be a number');\n }\n return num;\n }\n\n return value;\n}\n\n/**\n * Load configuration from .cleo/config.json file\n */\nfunction loadFromFile(projectRoot?: string): Partial<MCPConfig> {\n const root = projectRoot || process.cwd();\n const configPath = join(root, '.cleo', 'config.json');\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content);\n\n // Extract MCP-specific config if nested\n const result: Partial<MCPConfig> = {};\n\n if (config.mcp) {\n if (config.mcp.cliPath !== undefined) result.cliPath = config.mcp.cliPath;\n if (config.mcp.timeout !== undefined) result.timeout = config.mcp.timeout;\n if (config.mcp.logLevel !== undefined) result.logLevel = config.mcp.logLevel;\n if (config.mcp.enableMetrics !== undefined) result.enableMetrics = config.mcp.enableMetrics;\n if (config.mcp.maxRetries !== undefined) result.maxRetries = config.mcp.maxRetries;\n if (config.mcp.features?.queryCache !== undefined) result.queryCache = config.mcp.features.queryCache;\n if (config.mcp.features?.queryCacheTtl !== undefined) result.queryCacheTtl = config.mcp.features.queryCacheTtl;\n if (config.mcp.features?.auditLog !== undefined) result.auditLog = config.mcp.features.auditLog;\n if (config.mcp.features?.strictValidation !== undefined) result.strictValidation = config.mcp.features.strictValidation;\n }\n\n // Extract lifecycle enforcement config (Section 12.2)\n if (config.lifecycleEnforcement) {\n result.lifecycleEnforcement = {\n ...DEFAULT_LIFECYCLE_ENFORCEMENT,\n ...config.lifecycleEnforcement,\n };\n }\n\n // Extract protocol validation config (Section 12.3)\n if (config.protocolValidation) {\n result.protocolValidation = {\n ...DEFAULT_PROTOCOL_VALIDATION,\n ...config.protocolValidation,\n };\n }\n\n // Extract rate limiting config (Section 13.3)\n if (config.rateLimiting || config.mcp?.rateLimiting) {\n const rlConfig = config.rateLimiting || config.mcp?.rateLimiting;\n result.rateLimiting = {\n ...DEFAULT_RATE_LIMITING,\n ...rlConfig,\n query: { ...DEFAULT_RATE_LIMITING.query, ...rlConfig?.query },\n mutate: { ...DEFAULT_RATE_LIMITING.mutate, ...rlConfig?.mutate },\n spawn: { ...DEFAULT_RATE_LIMITING.spawn, ...rlConfig?.spawn },\n };\n }\n\n // If no mcp block, check for flat config keys\n if (!config.mcp) {\n return config;\n }\n\n return result;\n } catch (error) {\n // Log error but don't fail - fall back to defaults\n console.error(`Warning: Failed to load config file: ${error}`);\n return {};\n }\n}\n\n/**\n * Validate configuration field\n */\nfunction validateField(key: string, value: unknown): void {\n const schema = CONFIG_SCHEMA[key as keyof typeof CONFIG_SCHEMA];\n\n if (!schema) {\n return; // Unknown fields are ignored\n }\n\n // Type check\n const actualType = typeof value;\n if (actualType !== schema.type) {\n throw new ConfigValidationError(\n key,\n value,\n `must be of type ${schema.type}`\n );\n }\n\n // Enum check\n if ('enum' in schema && schema.enum && !schema.enum.includes(value as never)) {\n throw new ConfigValidationError(\n key,\n value,\n `must be one of: ${schema.enum.join(', ')}`\n );\n }\n\n // Range check for numbers\n if (schema.type === 'number') {\n const numValue = value as number;\n if ('min' in schema && numValue < schema.min) {\n throw new ConfigValidationError(\n key,\n value,\n `must be >= ${schema.min}`\n );\n }\n if ('max' in schema && numValue > schema.max) {\n throw new ConfigValidationError(\n key,\n value,\n `must be <= ${schema.max}`\n );\n }\n }\n}\n\n/**\n * Validate complete configuration\n */\nexport function validateConfig(config: MCPConfig): void {\n for (const [key, value] of Object.entries(config)) {\n validateField(key, value);\n }\n\n // Required field check\n for (const [key, schema] of Object.entries(CONFIG_SCHEMA)) {\n if ('required' in schema && schema.required) {\n if (config[key as keyof MCPConfig] === undefined) {\n throw new ConfigValidationError(key, undefined, 'is required');\n }\n }\n }\n}\n\n/**\n * Load configuration from all sources\n *\n * Priority order:\n * 1. Environment variables (CLEO_MCP_*)\n * 2. Config file (.cleo/config.json)\n * 3. Defaults\n */\nexport function loadConfig(projectRoot?: string): MCPConfig {\n // Start with defaults (deep copy nested objects)\n const config: MCPConfig = {\n ...DEFAULT_CONFIG,\n lifecycleEnforcement: { ...DEFAULT_LIFECYCLE_ENFORCEMENT },\n protocolValidation: { ...DEFAULT_PROTOCOL_VALIDATION },\n rateLimiting: {\n ...DEFAULT_RATE_LIMITING,\n query: { ...DEFAULT_RATE_LIMITING.query },\n mutate: { ...DEFAULT_RATE_LIMITING.mutate },\n spawn: { ...DEFAULT_RATE_LIMITING.spawn },\n },\n };\n\n // Load from file (overrides defaults)\n const fileConfig = loadFromFile(projectRoot);\n // Merge nested objects carefully\n if (fileConfig.lifecycleEnforcement) {\n config.lifecycleEnforcement = {\n ...config.lifecycleEnforcement,\n ...fileConfig.lifecycleEnforcement,\n };\n delete (fileConfig as any).lifecycleEnforcement;\n }\n if (fileConfig.protocolValidation) {\n config.protocolValidation = {\n ...config.protocolValidation,\n ...fileConfig.protocolValidation,\n };\n delete (fileConfig as any).protocolValidation;\n }\n if (fileConfig.rateLimiting) {\n config.rateLimiting = {\n ...config.rateLimiting,\n ...fileConfig.rateLimiting,\n query: { ...config.rateLimiting.query, ...fileConfig.rateLimiting.query },\n mutate: { ...config.rateLimiting.mutate, ...fileConfig.rateLimiting.mutate },\n spawn: { ...config.rateLimiting.spawn, ...fileConfig.rateLimiting.spawn },\n };\n delete (fileConfig as any).rateLimiting;\n }\n Object.assign(config, fileConfig);\n\n // Load from environment (overrides file and defaults)\n for (const key of Object.keys(DEFAULT_CONFIG) as Array<keyof MCPConfig>) {\n const envValue = loadFromEnv(key);\n if (envValue !== undefined) {\n config[key] = parseEnvValue(key, envValue) as never;\n }\n }\n\n // Validate final configuration\n validateConfig(config);\n\n return config;\n}\n\n/**\n * Global configuration singleton\n * Loaded once at module initialization\n */\nlet globalConfig: MCPConfig | null = null;\n\n/**\n * Get global configuration (singleton)\n */\nexport function getConfig(): MCPConfig {\n if (globalConfig === null) {\n globalConfig = loadConfig();\n }\n return globalConfig;\n}\n\n/**\n * Reset global configuration (for testing)\n */\nexport function resetConfig(): void {\n globalConfig = null;\n}\n", "/**\n * Rate Limiter for CLEO MCP Server\n *\n * Implements sliding window rate limiting per MCP-SERVER-SPECIFICATION Section 13.3:\n * - Query operations: 100/minute (default)\n * - Mutate operations: 30/minute (default)\n * - Spawn operations: 10/minute (default)\n *\n * Uses a sliding window algorithm with per-category tracking.\n * Limits are configurable via MCPConfig.rateLimiting.\n *\n * @task T2916\n */\n\n/**\n * Rate limit configuration for a single category\n */\nexport interface RateLimitConfig {\n /** Maximum requests allowed in the window */\n maxRequests: number;\n /** Time window in milliseconds */\n windowMs: number;\n}\n\n/**\n * Complete rate limiting configuration\n */\nexport interface RateLimitingConfig {\n /** Enable/disable rate limiting globally */\n enabled: boolean;\n /** Limits for query gateway operations */\n query: RateLimitConfig;\n /** Limits for mutate gateway operations */\n mutate: RateLimitConfig;\n /** Limits for spawn operations (orchestrate.spawn) */\n spawn: RateLimitConfig;\n}\n\n/**\n * Default rate limiting configuration per Section 13.3\n */\nexport const DEFAULT_RATE_LIMITING: RateLimitingConfig = {\n enabled: true,\n query: { maxRequests: 100, windowMs: 60_000 },\n mutate: { maxRequests: 30, windowMs: 60_000 },\n spawn: { maxRequests: 10, windowMs: 60_000 },\n};\n\n/**\n * Rate limit check result\n */\nexport interface RateLimitResult {\n /** Whether the request is allowed */\n allowed: boolean;\n /** Requests remaining in the current window */\n remaining: number;\n /** Maximum requests allowed in the window */\n limit: number;\n /** Milliseconds until the window resets */\n resetMs: number;\n /** The category that was checked */\n category: string;\n}\n\n/**\n * Internal bucket tracking timestamps of requests in the sliding window\n */\ninterface SlidingWindowBucket {\n timestamps: number[];\n}\n\n/**\n * Sliding window rate limiter\n *\n * Tracks request timestamps per category and rejects requests\n * that exceed the configured limit within the time window.\n */\nexport class RateLimiter {\n private buckets: Map<string, SlidingWindowBucket> = new Map();\n private config: RateLimitingConfig;\n\n constructor(config?: Partial<RateLimitingConfig>) {\n this.config = {\n ...DEFAULT_RATE_LIMITING,\n ...config,\n query: { ...DEFAULT_RATE_LIMITING.query, ...config?.query },\n mutate: { ...DEFAULT_RATE_LIMITING.mutate, ...config?.mutate },\n spawn: { ...DEFAULT_RATE_LIMITING.spawn, ...config?.spawn },\n };\n }\n\n /**\n * Check if a request is allowed and record it if so.\n *\n * @param gateway - The gateway type ('cleo_query' or 'cleo_mutate')\n * @param domain - The domain being accessed\n * @param operation - The operation being performed\n * @returns Rate limit check result with remaining quota\n */\n check(gateway: string, domain: string, operation: string): RateLimitResult {\n if (!this.config.enabled) {\n return {\n allowed: true,\n remaining: Infinity,\n limit: Infinity,\n resetMs: 0,\n category: 'disabled',\n };\n }\n\n // Determine the rate limit category\n const category = this.resolveCategory(gateway, domain, operation);\n const limitConfig = this.getLimitConfig(category);\n\n const now = Date.now();\n const windowStart = now - limitConfig.windowMs;\n\n // Get or create bucket\n const bucket = this.getOrCreateBucket(category);\n\n // Prune expired timestamps\n bucket.timestamps = bucket.timestamps.filter((ts) => ts > windowStart);\n\n // Check limit\n if (bucket.timestamps.length >= limitConfig.maxRequests) {\n // Find earliest timestamp to compute reset time\n const earliestInWindow = bucket.timestamps[0];\n const resetMs = earliestInWindow + limitConfig.windowMs - now;\n\n return {\n allowed: false,\n remaining: 0,\n limit: limitConfig.maxRequests,\n resetMs: Math.max(0, resetMs),\n category,\n };\n }\n\n // Record this request\n bucket.timestamps.push(now);\n\n const remaining = limitConfig.maxRequests - bucket.timestamps.length;\n\n return {\n allowed: true,\n remaining,\n limit: limitConfig.maxRequests,\n resetMs: bucket.timestamps.length > 0\n ? bucket.timestamps[0] + limitConfig.windowMs - now\n : limitConfig.windowMs,\n category,\n };\n }\n\n /**\n * Get current rate limit status without recording a request.\n */\n peek(gateway: string, domain: string, operation: string): RateLimitResult {\n if (!this.config.enabled) {\n return {\n allowed: true,\n remaining: Infinity,\n limit: Infinity,\n resetMs: 0,\n category: 'disabled',\n };\n }\n\n const category = this.resolveCategory(gateway, domain, operation);\n const limitConfig = this.getLimitConfig(category);\n const now = Date.now();\n const windowStart = now - limitConfig.windowMs;\n\n const bucket = this.buckets.get(category);\n if (!bucket) {\n return {\n allowed: true,\n remaining: limitConfig.maxRequests,\n limit: limitConfig.maxRequests,\n resetMs: limitConfig.windowMs,\n category,\n };\n }\n\n const activeTimestamps = bucket.timestamps.filter((ts) => ts > windowStart);\n const remaining = limitConfig.maxRequests - activeTimestamps.length;\n\n return {\n allowed: remaining > 0,\n remaining: Math.max(0, remaining),\n limit: limitConfig.maxRequests,\n resetMs: activeTimestamps.length > 0\n ? activeTimestamps[0] + limitConfig.windowMs - now\n : limitConfig.windowMs,\n category,\n };\n }\n\n /**\n * Reset all rate limit buckets (for testing)\n */\n reset(): void {\n this.buckets.clear();\n }\n\n /**\n * Reset a specific category bucket (for testing)\n */\n resetCategory(category: string): void {\n this.buckets.delete(category);\n }\n\n /**\n * Update configuration at runtime\n */\n updateConfig(config: Partial<RateLimitingConfig>): void {\n if (config.enabled !== undefined) this.config.enabled = config.enabled;\n if (config.query) this.config.query = { ...this.config.query, ...config.query };\n if (config.mutate) this.config.mutate = { ...this.config.mutate, ...config.mutate };\n if (config.spawn) this.config.spawn = { ...this.config.spawn, ...config.spawn };\n }\n\n /**\n * Get current configuration (for diagnostics)\n */\n getConfig(): Readonly<RateLimitingConfig> {\n return { ...this.config };\n }\n\n /**\n * Resolve the rate limit category for a given request.\n *\n * Spawn operations get their own stricter limit.\n * Everything else is categorized by gateway type.\n */\n private resolveCategory(gateway: string, domain: string, operation: string): string {\n // Spawn operations have their own limit\n if (domain === 'orchestrate' && operation === 'spawn') {\n return 'spawn';\n }\n\n // Map gateway to category\n if (gateway === 'cleo_query') {\n return 'query';\n }\n\n return 'mutate';\n }\n\n /**\n * Get the limit configuration for a category\n */\n private getLimitConfig(category: string): RateLimitConfig {\n switch (category) {\n case 'query':\n return this.config.query;\n case 'mutate':\n return this.config.mutate;\n case 'spawn':\n return this.config.spawn;\n default:\n return this.config.mutate;\n }\n }\n\n /**\n * Get or create a sliding window bucket for a category\n */\n private getOrCreateBucket(category: string): SlidingWindowBucket {\n let bucket = this.buckets.get(category);\n if (!bucket) {\n bucket = { timestamps: [] };\n this.buckets.set(category, bucket);\n }\n return bucket;\n }\n}\n", "/**\n * Default configuration values for CLEO MCP Server\n *\n * @task T2928\n * @task T3145\n * @task T2916 - Rate limiting configuration (Section 13.3)\n */\n\nimport type { RateLimitingConfig } from './rate-limiter.js';\nexport type { RateLimitingConfig } from './rate-limiter.js';\nimport { DEFAULT_RATE_LIMITING } from './rate-limiter.js';\nexport { DEFAULT_RATE_LIMITING } from './rate-limiter.js';\n\n/**\n * Lifecycle enforcement configuration (Section 12.2)\n */\nexport interface LifecycleEnforcementConfig {\n /** Enforcement mode: strict blocks, advisory warns, off skips */\n mode: 'strict' | 'advisory' | 'off';\n /** Stages that may be skipped without failing gates */\n allowSkip: string[];\n /** Emergency bypass flag - disables all gate checks */\n emergencyBypass: boolean;\n}\n\n/**\n * Protocol validation configuration (Section 12.3)\n */\nexport interface ProtocolValidationConfig {\n /** Enable strict protocol validation */\n strictMode: boolean;\n /** Block operations on protocol violations */\n blockOnViolation: boolean;\n /** Log protocol violations to audit trail */\n logViolations: boolean;\n}\n\nexport interface MCPConfig {\n /** Path to CLEO CLI binary (default: 'cleo') */\n cliPath: string;\n\n /** Operation timeout in milliseconds (default: 30000) */\n timeout: number;\n\n /** Logging verbosity level (default: 'info') */\n logLevel: 'debug' | 'info' | 'warn' | 'error';\n\n /** Enable token tracking metrics (default: false) */\n enableMetrics: boolean;\n\n /** Retry count for failed operations (default: 3) */\n maxRetries: number;\n\n /** Enable query cache (default: true) */\n queryCache: boolean;\n\n /** Query cache TTL in milliseconds (default: 30000) */\n queryCacheTtl: number;\n\n /** Enable audit logging (default: true) */\n auditLog: boolean;\n\n /** Strict validation mode (default: true) */\n strictValidation: boolean;\n\n /** Lifecycle enforcement configuration (Section 12.2) */\n lifecycleEnforcement: LifecycleEnforcementConfig;\n\n /** Protocol validation configuration (Section 12.3) */\n protocolValidation: ProtocolValidationConfig;\n\n /** Rate limiting configuration (Section 13.3) */\n rateLimiting: RateLimitingConfig;\n}\n\n/**\n * Default lifecycle enforcement configuration\n */\nexport const DEFAULT_LIFECYCLE_ENFORCEMENT: LifecycleEnforcementConfig = {\n mode: 'strict',\n allowSkip: ['consensus'],\n emergencyBypass: false,\n};\n\n/**\n * Default protocol validation configuration\n */\nexport const DEFAULT_PROTOCOL_VALIDATION: ProtocolValidationConfig = {\n strictMode: true,\n blockOnViolation: true,\n logViolations: true,\n};\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: MCPConfig = {\n cliPath: 'cleo',\n timeout: 30000, // 30 seconds\n logLevel: 'info',\n enableMetrics: false,\n maxRetries: 3,\n queryCache: true,\n queryCacheTtl: 30000, // 30 seconds\n auditLog: true,\n strictValidation: true,\n lifecycleEnforcement: { ...DEFAULT_LIFECYCLE_ENFORCEMENT },\n protocolValidation: { ...DEFAULT_PROTOCOL_VALIDATION },\n rateLimiting: { ...DEFAULT_RATE_LIMITING },\n};\n\n/**\n * Environment variable prefix for CLEO configuration\n */\nexport const ENV_PREFIX = 'CLEO_MCP_';\n\n/**\n * Configuration schema for validation\n */\nexport const CONFIG_SCHEMA = {\n cliPath: { type: 'string', required: true },\n timeout: { type: 'number', min: 1000, max: 300000 },\n logLevel: { type: 'string', enum: ['debug', 'info', 'warn', 'error'] },\n enableMetrics: { type: 'boolean' },\n maxRetries: { type: 'number', min: 0, max: 10 },\n queryCache: { type: 'boolean' },\n queryCacheTtl: { type: 'number', min: 0, max: 600000 },\n auditLog: { type: 'boolean' },\n strictValidation: { type: 'boolean' },\n} as const;\n", "/**\n * Unified CQRS Dispatch Layer -- Operation Registry\n *\n * Single source of truth for all 147 operations mapped to 9 canonical domains.\n * Canonical domains only -- no legacy alias support.\n *\n * @epic T4820\n * @task T4814\n */\n\nimport { Gateway, Tier, CanonicalDomain } from './types.js';\n\n/** Definition of a single dispatchable operation. */\nexport interface OperationDef {\n /** The CQRS gateway ('query' or 'mutate'). */\n gateway: Gateway;\n /** The canonical domain this operation belongs to. */\n domain: CanonicalDomain;\n /** The specific operation name (e.g. 'show', 'skill.list'). */\n operation: string;\n /** Brief description of what the operation does. */\n description: string;\n /** Agent progressive-disclosure tier (0=basic, 1=memory/check, 2=full). */\n tier: Tier;\n /** Whether the operation is safe to retry. */\n idempotent: boolean;\n /** Whether this operation requires an active session. */\n sessionRequired: boolean;\n /** List of parameter keys that MUST be present in the request. */\n requiredParams: string[];\n}\n\n/**\n * Resolution output for a dispatch request.\n */\nexport interface Resolution {\n /** The canonical domain. */\n domain: CanonicalDomain;\n /** The operation name. */\n operation: string;\n /** The definition of the matched operation. */\n def: OperationDef;\n}\n\n/**\n * The single source of truth for all operations in CLEO.\n */\nexport const OPERATIONS: OperationDef[] = [\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'show',\n description: 'tasks.show (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'list',\n description: 'tasks.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'find',\n description: 'tasks.find (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'exists',\n description: 'tasks.exists (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'tree',\n description: 'tasks.tree (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'blockers',\n description: 'tasks.blockers (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'depends',\n description: 'tasks.depends (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'analyze',\n description: 'tasks.analyze (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'next',\n description: 'tasks.next (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'relates',\n description: 'tasks.relates (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'complexity.estimate',\n description: 'tasks.complexity.estimate (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tasks',\n operation: 'current',\n description: 'tasks.current (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'status',\n description: 'session.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'list',\n description: 'session.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'show',\n description: 'session.show (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'history',\n description: 'session.history (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'decision.log',\n description: 'session.decision.log (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'session',\n operation: 'context.drift',\n description: 'session.context.drift (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'status',\n description: 'orchestrate.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'next',\n description: 'orchestrate.next (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'ready',\n description: 'orchestrate.ready (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'analyze',\n description: 'orchestrate.analyze (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'context',\n description: 'orchestrate.context (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'waves',\n description: 'orchestrate.waves (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'skill.list',\n description: 'orchestrate.skill.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'bootstrap',\n description: 'orchestrate.bootstrap (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'unblock.opportunities',\n description: 'orchestrate.unblock.opportunities (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'orchestrate',\n operation: 'critical.path',\n description: 'orchestrate.critical.path (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'show',\n description: 'memory.show (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'list',\n description: 'memory.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'find',\n description: 'memory.find (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'pending',\n description: 'memory.pending (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'stats',\n description: 'memory.stats (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'manifest.read',\n description: 'memory.manifest.read (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'contradictions',\n description: 'memory.contradictions (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'memory',\n operation: 'superseded',\n description: 'memory.superseded (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'pipeline',\n operation: 'stage.validate',\n description: 'pipeline.stage.validate (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'pipeline',\n operation: 'stage.status',\n description: 'pipeline.stage.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'pipeline',\n operation: 'stage.history',\n description: 'pipeline.stage.history (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'pipeline',\n operation: 'stage.gates',\n description: 'pipeline.stage.gates (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'pipeline',\n operation: 'stage.prerequisites',\n description: 'pipeline.stage.prerequisites (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'schema',\n description: 'check.schema (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'protocol',\n description: 'check.protocol (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'task',\n description: 'check.task (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'manifest',\n description: 'check.manifest (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'output',\n description: 'check.output (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'compliance.summary',\n description: 'check.compliance.summary (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'compliance.violations',\n description: 'check.compliance.violations (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'test.status',\n description: 'check.test.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'test.coverage',\n description: 'check.test.coverage (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'check',\n operation: 'coherence.check',\n description: 'check.coherence.check (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'version',\n description: 'admin.version (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'health',\n description: 'admin.health (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'config.get',\n description: 'admin.config.get (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'stats',\n description: 'admin.stats (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'context',\n description: 'admin.context (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'job.status',\n description: 'admin.job.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'job.list',\n description: 'admin.job.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'dash',\n description: 'admin.dash (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'roadmap',\n description: 'admin.roadmap (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'labels',\n description: 'admin.labels (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'compliance',\n description: 'admin.compliance (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'log',\n description: 'admin.log (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'archive.stats',\n description: 'admin.archive.stats (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'admin',\n operation: 'sequence',\n description: 'admin.sequence (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'issue.diagnostics',\n description: 'tools.issue.diagnostics (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'issue.templates',\n description: 'List available issue templates',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'issue.validate.labels',\n description: 'Validate issue labels against configured label set',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: ['labels'],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.list',\n description: 'tools.skill.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.show',\n description: 'tools.skill.show (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.find',\n description: 'tools.skill.find (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.dispatch',\n description: 'tools.skill.dispatch (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.verify',\n description: 'tools.skill.verify (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.dependencies',\n description: 'tools.skill.dependencies (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.catalog.protocols',\n description: 'List CAAMP protocol definitions',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.catalog.profiles',\n description: 'List CAAMP dispatch profiles',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.catalog.resources',\n description: 'List CAAMP shared resources',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'skill.catalog.info',\n description: 'Get CAAMP catalog metadata',\n tier: 2,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'provider.list',\n description: 'tools.provider.list (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'provider.detect',\n description: 'tools.provider.detect (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'query',\n domain: 'tools',\n operation: 'provider.inject.status',\n description: 'tools.provider.inject.status (query)',\n tier: 0,\n idempotent: true,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'add',\n description: 'tasks.add (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'update',\n description: 'tasks.update (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'complete',\n description: 'tasks.complete (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'delete',\n description: 'tasks.delete (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'archive',\n description: 'tasks.archive (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'restore',\n description: 'tasks.restore (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'reparent',\n description: 'tasks.reparent (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'promote',\n description: 'tasks.promote (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'reorder',\n description: 'tasks.reorder (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'reopen',\n description: 'tasks.reopen (mutate) \u2014 alias for tasks.restore',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'relates.add',\n description: 'tasks.relates.add (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'uncancel',\n description: 'tasks.uncancel (mutate) \u2014 alias for tasks.restore',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'start',\n description: 'tasks.start (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tasks',\n operation: 'stop',\n description: 'tasks.stop (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'start',\n description: 'session.start (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'end',\n description: 'session.end (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'resume',\n description: 'session.resume (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'suspend',\n description: 'session.suspend (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'gc',\n description: 'session.gc (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'record.decision',\n description: 'session.record.decision (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'session',\n operation: 'record.assumption',\n description: 'session.record.assumption (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'orchestrate',\n operation: 'start',\n description: 'orchestrate.start (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'orchestrate',\n operation: 'spawn',\n description: 'orchestrate.spawn (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'orchestrate',\n operation: 'validate',\n description: 'orchestrate.validate (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'orchestrate',\n operation: 'parallel.start',\n description: 'orchestrate.parallel.start (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'orchestrate',\n operation: 'parallel.end',\n description: 'orchestrate.parallel.end (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'memory',\n operation: 'inject',\n description: 'memory.inject (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'memory',\n operation: 'link',\n description: 'memory.link (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'memory',\n operation: 'manifest.append',\n description: 'memory.manifest.append (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'memory',\n operation: 'manifest.archive',\n description: 'memory.manifest.archive (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'stage.record',\n description: 'pipeline.stage.record (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'stage.skip',\n description: 'pipeline.stage.skip (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'stage.reset',\n description: 'pipeline.stage.reset (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'stage.gate.pass',\n description: 'pipeline.stage.gate.pass (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'stage.gate.fail',\n description: 'pipeline.stage.gate.fail (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'check',\n operation: 'compliance.record',\n description: 'check.compliance.record (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'check',\n operation: 'test.run',\n description: 'check.test.run (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.prepare',\n description: 'pipeline.release.prepare (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.changelog',\n description: 'pipeline.release.changelog (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.commit',\n description: 'pipeline.release.commit (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.tag',\n description: 'pipeline.release.tag (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.push',\n description: 'pipeline.release.push (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.gates.run',\n description: 'pipeline.release.gates.run (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'pipeline',\n operation: 'release.rollback',\n description: 'pipeline.release.rollback (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'init',\n description: 'admin.init (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'config.set',\n description: 'admin.config.set (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'backup',\n description: 'admin.backup (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'restore',\n description: 'admin.restore (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'migrate',\n description: 'admin.migrate (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'sync',\n description: 'admin.sync (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'cleanup',\n description: 'admin.cleanup (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'job.cancel',\n description: 'admin.job.cancel (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'safestop',\n description: 'admin.safestop (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'uncancel',\n description: 'admin.uncancel (mutate) \u2014 alias for admin.restore',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'admin',\n operation: 'inject.generate',\n description: 'admin.inject.generate (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'issue.add.bug',\n description: 'tools.issue.add.bug (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'issue.add.feature',\n description: 'tools.issue.add.feature (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'issue.add.help',\n description: 'tools.issue.add.help (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'issue.generate.config',\n description: 'Generate issue template configuration file',\n tier: 2,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.install',\n description: 'tools.skill.install (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.uninstall',\n description: 'tools.skill.uninstall (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.enable',\n description: 'tools.skill.enable (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.disable',\n description: 'tools.skill.disable (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.configure',\n description: 'tools.skill.configure (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'skill.refresh',\n description: 'tools.skill.refresh (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n {\n gateway: 'mutate',\n domain: 'tools',\n operation: 'provider.inject',\n description: 'tools.provider.inject (mutate)',\n tier: 0,\n idempotent: false,\n sessionRequired: false,\n requiredParams: [],\n },\n];\n\n// ---------------------------------------------------------------------------\n// Lookup & Validation\n// ---------------------------------------------------------------------------\n\n/**\n * Resolves a domain + operation to its registered definition.\n */\nexport function resolve(gateway: Gateway, domain: string, operation: string): Resolution | undefined {\n const def = OPERATIONS.find(\n o => o.gateway === gateway && o.domain === domain && o.operation === operation,\n );\n\n if (!def) return undefined;\n\n return { domain: def.domain, operation: def.operation, def };\n}\n\n/**\n * Validates that all required parameters are present in the request.\n * Returns an array of missing parameter keys.\n */\nexport function validateRequiredParams(def: OperationDef, params?: Record<string, unknown>): string[] {\n if (!def.requiredParams || def.requiredParams.length === 0) return [];\n const provided = params || {};\n return def.requiredParams.filter(key => provided[key] === undefined || provided[key] === null || provided[key] === '');\n}\n\n/** Get all operations for a specific canonical domain. */\nexport function getByDomain(domain: CanonicalDomain): OperationDef[] {\n return OPERATIONS.filter(o => o.domain === domain);\n}\n\n/** Get all operations for a specific gateway. */\nexport function getByGateway(gateway: Gateway): OperationDef[] {\n return OPERATIONS.filter(o => o.gateway === gateway);\n}\n\n/** Get all operations available at or below a specific tier. */\nexport function getByTier(tier: Tier): OperationDef[] {\n return OPERATIONS.filter(o => o.tier <= tier);\n}\n\n/** Get a list of canonical domains that actually have operations registered. */\nexport function getActiveDomains(): CanonicalDomain[] {\n const active = new Set(OPERATIONS.map(o => o.domain));\n return Array.from(active);\n}\n\n/**\n * Returns summary counts of operations for module validation.\n */\nexport function getCounts(): { query: number; mutate: number; total: number } {\n return {\n query: OPERATIONS.filter(o => o.gateway === 'query').length,\n mutate: OPERATIONS.filter(o => o.gateway === 'mutate').length,\n total: OPERATIONS.length,\n };\n}\n\n// Module load validation\nconst counts = getCounts();\nif (counts.query !== 81 || counts.mutate !== 66) {\n console.warn(`[Registry] Expected 81 query & 66 mutate ops, got ${counts.query} query & ${counts.mutate} mutate.`);\n}\n", "/**\n * Dispatch-local metadata factory.\n *\n * Replaces the import of createGatewayMeta from MCP lib.\n * Generates LAFS-conformant metadata for dispatch responses.\n *\n * @task T4772\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { DispatchResponse, Source } from '../types.js';\n\n/**\n * Create metadata for a dispatch response.\n *\n * @param gateway - Gateway name (e.g., 'query', 'mutate')\n * @param domain - Domain name (e.g., 'tasks', 'session')\n * @param operation - Operation name (e.g., 'show', 'list')\n * @param startTime - Timestamp from Date.now() at start of request\n * @param source - Where the request originated ('cli' or 'mcp')\n * @param requestId - Optional pre-generated request ID\n * @returns Metadata conforming to DispatchResponse['_meta']\n *\n * @task T4772\n */\nexport function createDispatchMeta(\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n source: Source = 'mcp',\n requestId?: string,\n): DispatchResponse['_meta'] {\n return {\n gateway: gateway as DispatchResponse['_meta']['gateway'],\n domain,\n operation,\n timestamp: new Date().toISOString(),\n duration_ms: Date.now() - startTime,\n source,\n requestId: requestId ?? randomUUID(),\n };\n}\n", "/**\n * Unified CQRS Dispatch Layer -- Middleware Pipeline\n *\n * Provides compose() to chain multiple Middleware functions together\n * into a single executable pipeline.\n *\n * @epic T4820\n * @task T4815\n */\n\nimport { DispatchRequest, DispatchResponse, Middleware, DispatchNext } from '../types.js';\n\n/**\n * Composes an array of Middleware functions into a single Middleware function.\n * Execution flows through the array from first to last, and returns bubble\n * back up from last to first.\n *\n * @param middlewares Array of middleware functions to chain\n * @returns A single composed Middleware function\n */\nexport function compose(middlewares: Middleware[]): Middleware {\n if (middlewares.length === 0) {\n return async (_req: DispatchRequest, next: DispatchNext) => next();\n }\n\n return async (request: DispatchRequest, next: DispatchNext): Promise<DispatchResponse> => {\n let index = -1;\n\n async function dispatch(i: number): Promise<DispatchResponse> {\n if (i <= index) {\n throw new Error('next() called multiple times in middleware');\n }\n index = i;\n\n let fn: Middleware | undefined = middlewares[i];\n if (i === middlewares.length) {\n // We've reached the end of the middleware chain; call the final handler\n fn = async (_req, nxt) => nxt();\n }\n\n if (!fn) {\n return next();\n }\n\n return fn(request, async () => {\n if (i === middlewares.length) {\n return next();\n }\n return dispatch(i + 1);\n });\n }\n\n return dispatch(0);\n };\n}\n", "/**\n * Central Dispatcher -- Routes requests through middleware to domain handlers.\n *\n * The dispatcher is the single entry point for both CLI and MCP adapters.\n * It resolves operations, validates parameters, runs the middleware pipeline,\n * and delegates to the appropriate domain handler.\n *\n * Flow: DispatchRequest \u2192 resolve \u2192 param validation \u2192 middleware \u2192 handler\n *\n * @epic T4820\n */\n\nimport type { DispatchRequest, DispatchResponse, DomainHandler, Middleware } from './types.js';\nimport { resolve, validateRequiredParams } from './registry.js';\nimport { createDispatchMeta } from './lib/meta.js';\nimport { compose } from './middleware/pipeline.js';\n\nexport interface DispatcherConfig {\n handlers: Map<string, DomainHandler>;\n middlewares?: Middleware[];\n}\n\nexport class Dispatcher {\n private handlers: Map<string, DomainHandler>;\n private pipeline: Middleware;\n\n constructor(config: DispatcherConfig) {\n this.handlers = config.handlers;\n this.pipeline = config.middlewares?.length\n ? compose(config.middlewares)\n : (_req, next) => next();\n }\n\n async dispatch(request: DispatchRequest): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n // 1. Resolve operation from registry\n const resolved = resolve(request.gateway, request.domain, request.operation);\n if (!resolved) {\n return {\n _meta: createDispatchMeta(\n request.gateway, request.domain, request.operation,\n startTime, request.source, request.requestId,\n ),\n success: false,\n error: {\n code: 'E_INVALID_OPERATION',\n message: `Unknown operation: ${request.gateway}:${request.domain}.${request.operation}`,\n },\n };\n }\n\n // 2. Validate required params\n const missing = validateRequiredParams(resolved.def, request.params);\n if (missing.length > 0) {\n return {\n _meta: createDispatchMeta(\n request.gateway, resolved.domain, resolved.operation,\n startTime, request.source, request.requestId,\n ),\n success: false,\n error: {\n code: 'E_MISSING_PARAMS',\n message: `Missing required parameters: ${missing.join(', ')}`,\n details: { missing },\n },\n };\n }\n\n // 3. Look up domain handler\n const handler = this.handlers.get(resolved.domain);\n if (!handler) {\n return {\n _meta: createDispatchMeta(\n request.gateway, resolved.domain, resolved.operation,\n startTime, request.source, request.requestId,\n ),\n success: false,\n error: {\n code: 'E_NO_HANDLER',\n message: `No handler for domain: ${resolved.domain}`,\n },\n };\n }\n\n // 4. Run middleware pipeline with terminal handler\n const terminal = async (): Promise<DispatchResponse> => {\n if (request.gateway === 'query') {\n return handler.query(resolved.operation, request.params);\n } else {\n return handler.mutate(resolved.operation, request.params);\n }\n };\n\n const response = await this.pipeline(request, terminal);\n\n // 5. Stamp timing and tracing metadata\n response._meta.duration_ms = Date.now() - startTime;\n response._meta.requestId = request.requestId;\n response._meta.source = request.source;\n\n return response;\n }\n}\n", "/**\n * Convenience wrapper for dispatch metadata creation.\n *\n * Domain handlers call dispatchMeta() to build DispatchResponse['_meta']\n * without importing the factory directly.\n *\n * @task T4772\n */\n\nimport { createDispatchMeta } from '../lib/meta.js';\nimport type { DispatchResponse, Source } from '../types.js';\n\n/**\n * Build metadata for a dispatch domain response.\n *\n * @param gateway - Gateway name (e.g., 'query', 'mutate')\n * @param domain - Domain name (e.g., 'tasks', 'session')\n * @param operation - Operation name (e.g., 'show', 'list')\n * @param startTime - Timestamp from Date.now() at start of request\n * @param source - Where the request originated ('cli' or 'mcp')\n * @returns Metadata conforming to DispatchResponse['_meta']\n *\n * @task T4772\n */\nexport function dispatchMeta(\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n source: Source = 'mcp',\n): DispatchResponse['_meta'] {\n return createDispatchMeta(gateway, domain, operation, startTime, source);\n}\n", "/**\n * Tasks Domain Handler (Dispatch Layer)\n *\n * Handles all task CRUD and non-CRUD operations: show, list, find, exists,\n * tree, blockers, depends, analyze, next, relates, complexity.estimate,\n * current, add, update, complete, delete, archive, restore, reparent,\n * promote, reorder, reopen, relates.add, uncancel, start, stop.\n *\n * Query operations delegate to task-engine; start/stop/current delegate\n * to session-engine (which hosts task-work functions).\n *\n * @epic T4820\n * @task T4818\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n taskShow,\n taskList,\n taskFind,\n taskExists,\n taskCreate,\n taskUpdate,\n taskComplete,\n taskDelete,\n taskArchive,\n taskNext,\n taskBlockers,\n taskTree,\n taskRelates,\n taskRelatesAdd,\n taskAnalyze,\n taskRestore,\n taskReorder,\n taskReparent,\n taskPromote,\n taskReopen,\n taskComplexityEstimate,\n taskDepends,\n taskCurrentGet,\n taskStart,\n taskStop,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// TasksHandler\n// ---------------------------------------------------------------------------\n\nexport class TasksHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'show': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskShow(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'list': {\n const result = await taskList(this.projectRoot, params as { parent?: string; status?: string; limit?: number });\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'find': {\n const query = params?.query as string;\n const limit = params?.limit as number | undefined;\n const result = await taskFind(this.projectRoot, query ?? '', limit);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'exists': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskExists(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'tree': {\n const taskId = params?.taskId as string | undefined;\n const result = await taskTree(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'blockers': {\n const result = await taskBlockers(this.projectRoot, params as { analyze?: boolean });\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'depends': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const direction = params?.direction as 'upstream' | 'downstream' | 'both' | undefined;\n const result = await taskDepends(this.projectRoot, taskId, direction);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'analyze': {\n const taskId = params?.taskId as string | undefined;\n const result = await taskAnalyze(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'next': {\n const result = await taskNext(this.projectRoot, params as { count?: number; explain?: boolean });\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'relates': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskRelates(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'complexity.estimate': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskComplexityEstimate(this.projectRoot, { taskId });\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n case 'current': {\n const result = await taskCurrentGet(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'tasks', operation, startTime);\n }\n\n default:\n return this.unsupported('query', 'tasks', operation, startTime);\n }\n } catch (error) {\n return this.handleError('query', 'tasks', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Mutate\n // -----------------------------------------------------------------------\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'add': {\n const title = params?.title as string;\n if (!title) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'title is required', startTime);\n }\n const result = await taskCreate(this.projectRoot, {\n title,\n description: params?.description as string ?? title,\n parent: params?.parent as string | undefined,\n depends: params?.depends as string[] | undefined,\n priority: params?.priority as string | undefined,\n labels: params?.labels as string[] | undefined,\n type: params?.type as string | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'update': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskUpdate(this.projectRoot, taskId, {\n title: params?.title as string | undefined,\n description: params?.description as string | undefined,\n status: params?.status as string | undefined,\n priority: params?.priority as string | undefined,\n notes: params?.notes as string | undefined,\n labels: params?.labels as string[] | undefined,\n addLabels: params?.addLabels as string[] | undefined,\n removeLabels: params?.removeLabels as string[] | undefined,\n depends: params?.depends as string[] | undefined,\n addDepends: params?.addDepends as string[] | undefined,\n removeDepends: params?.removeDepends as string[] | undefined,\n acceptance: params?.acceptance as string[] | undefined,\n parent: params?.parent as string | null | undefined,\n type: params?.type as string | undefined,\n size: params?.size as string | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'complete': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskComplete(this.projectRoot, taskId, params?.notes as string | undefined);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'delete': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskDelete(this.projectRoot, taskId, params?.force as boolean | undefined);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'archive': {\n const result = await taskArchive(\n this.projectRoot,\n params?.taskId as string | undefined,\n params?.before as string | undefined,\n );\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'restore': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskRestore(this.projectRoot, taskId, {\n cascade: params?.cascade as boolean | undefined,\n notes: params?.notes as string | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'reparent': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskReparent(\n this.projectRoot,\n taskId,\n (params?.newParentId as string | null) ?? null,\n );\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'promote': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskPromote(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'reorder': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const position = params?.position as number;\n if (position === undefined || position === null) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'position is required', startTime);\n }\n const result = await taskReorder(this.projectRoot, taskId, position);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'reopen': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskReopen(this.projectRoot, taskId, {\n status: params?.status as string | undefined,\n reason: params?.reason as string | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'relates.add': {\n const taskId = params?.taskId as string;\n const relatedId = params?.relatedId as string;\n const type = params?.type as string;\n if (!taskId || !relatedId || !type) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId, relatedId, and type are required', startTime);\n }\n const result = await taskRelatesAdd(\n this.projectRoot,\n taskId,\n relatedId,\n type,\n params?.reason as string | undefined,\n );\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'uncancel': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskRestore(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'start': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', 'tasks', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await taskStart(this.projectRoot, taskId);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n case 'stop': {\n const result = await taskStop(this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'tasks', operation, startTime);\n }\n\n default:\n return this.unsupported('mutate', 'tasks', operation, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', 'tasks', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Supported operations\n // -----------------------------------------------------------------------\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n 'show', 'list', 'find', 'exists', 'tree', 'blockers',\n 'depends', 'analyze', 'next', 'relates', 'complexity.estimate', 'current',\n ],\n mutate: [\n 'add', 'update', 'complete', 'delete', 'archive', 'restore',\n 'reparent', 'promote', 'reorder', 'reopen', 'relates.add',\n 'uncancel', 'start', 'stop',\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown; exitCode?: number } },\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: result.success,\n ...(result.success ? { data: result.data } : {}),\n ...(result.error ? { error: { code: result.error.code, message: result.error.message, exitCode: result.error.exitCode, details: result.error.details as Record<string, unknown> | undefined } } : {}),\n };\n }\n\n private unsupported(gateway: string, domain: string, operation: string, startTime: number): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INVALID_OPERATION', message: `Unknown ${domain} ${gateway}: ${operation}` },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(gateway: string, domain: string, operation: string, error: unknown, startTime: number): DispatchResponse {\n const message = error instanceof Error ? error.message : String(error);\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INTERNAL', message },\n };\n }\n}\n", "/**\n * JSON File Store\n *\n * Handles reading and writing CLEO JSON files with:\n * - Atomic writes (temp file -> validate -> backup -> rename)\n * - Cross-process file locking (proper-lockfile)\n * - Numbered backup rotation matching Tier 1 bash behavior\n * - Lock ordering to prevent deadlocks (todo.json before archive)\n */\n\nimport { readFileSync, writeFileSync, renameSync, mkdirSync, existsSync, readdirSync, unlinkSync} from 'fs';\nimport { join, dirname, basename } from 'path';\nimport { randomBytes } from 'crypto';\nimport * as lockfile from 'proper-lockfile';\n\n/**\n * Default lock options matching bash flock behavior\n */\nconst LOCK_OPTIONS: lockfile.LockOptions = {\n retries: {\n retries: 5,\n factor: 2,\n minTimeout: 100,\n maxTimeout: 5000,\n },\n stale: 30000, // 30s stale lock timeout\n};\n\n/**\n * Maximum number of operational backups to keep (Tier 1)\n */\nconst MAX_BACKUPS = 10;\n\n/**\n * Lock ordering to prevent deadlocks.\n * Always acquire locks in this order.\n */\nconst LOCK_ORDER: Record<string, number> = {\n 'todo.json': 1,\n 'sessions.json': 2,\n 'todo-archive.json': 3,\n 'todo-log.jsonl': 4,\n 'config.json': 5,\n};\n\nfunction getLockPriority(filePath: string): number {\n const name = basename(filePath);\n return LOCK_ORDER[name] ?? 99;\n}\n\n/**\n * Read a JSON file, returning parsed content or null if not found.\n *\n * @deprecated For task/session/archive data, use getStore() from '../../store/index.js'\n * instead. This function should only be used for config, template, and metadata reads\n * that are not domain data. See T4657 for the migration plan.\n * @task T4657\n * @epic T4654\n */\nexport function readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Read log entries from a hybrid JSON/JSONL file (synchronous).\n * Handles legacy JSON `{ \"entries\": [...] }`, pure JSONL, and\n * hybrid format (JSON object followed by JSONL lines).\n * @task T4622\n */\nexport function readLogFileEntries(filePath: string): Record<string, unknown>[] {\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8').trim();\n } catch (error: unknown) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n if (!content) return [];\n\n // Fast path: try as single JSON\n try {\n const parsed = JSON.parse(content);\n if (Array.isArray(parsed)) return parsed;\n if (parsed && typeof parsed === 'object' && Array.isArray(parsed.entries)) {\n return parsed.entries;\n }\n return [parsed];\n } catch {\n // Hybrid format\n }\n\n const entries: Record<string, unknown>[] = [];\n\n if (content.startsWith('{')) {\n let depth = 0;\n let inString = false;\n let escaped = false;\n let jsonEnd = -1;\n for (let i = 0; i < content.length; i++) {\n const ch = content[i]!;\n if (escaped) { escaped = false; continue; }\n if (ch === '\\\\' && inString) { escaped = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === '{') depth++;\n else if (ch === '}') { depth--; if (depth === 0) { jsonEnd = i + 1; break; } }\n }\n if (jsonEnd > 0) {\n try {\n const initial = JSON.parse(content.substring(0, jsonEnd));\n if (initial && Array.isArray(initial.entries)) entries.push(...initial.entries);\n } catch { /* skip corrupted initial JSON */ }\n const remainder = content.substring(jsonEnd).trim();\n if (remainder) {\n for (const line of remainder.split('\\n')) {\n const l = line.trim();\n if (!l || !l.startsWith('{')) continue;\n try { entries.push(JSON.parse(l)); } catch { /* skip */ }\n }\n }\n }\n } else {\n for (const line of content.split('\\n')) {\n const l = line.trim();\n if (!l || !l.startsWith('{')) continue;\n try { entries.push(JSON.parse(l)); } catch { /* skip */ }\n }\n }\n\n return entries;\n}\n\n/**\n * Write a JSON file atomically with backup rotation.\n *\n * Pattern: write temp -> backup original -> rename temp to target\n *\n * @deprecated For task/session/archive data, use getStore() from '../../store/index.js'\n * instead. This function should only be used for config, template, and metadata writes\n * that are not domain data. See T4657 for the migration plan.\n * @task T4657\n * @epic T4654\n * @param filePath - Target file path\n * @param data - Data to serialize as JSON\n * @param indent - JSON indentation (default: 2 spaces)\n */\nexport function writeJsonFileAtomic<T>(\n filePath: string,\n data: T,\n indent: number = 2\n): void {\n const dir = dirname(filePath);\n const tempPath = join(dir, `.${basename(filePath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Serialize\n const content = JSON.stringify(data, null, indent) + '\\n';\n\n // Write to temp file\n writeFileSync(tempPath, content, 'utf-8');\n\n try {\n // Create backup of existing file (Tier 1 operational backup)\n if (existsSync(filePath)) {\n rotateBackup(filePath);\n }\n\n // Atomic rename\n renameSync(tempPath, filePath);\n } catch (error) {\n // Clean up temp file on failure\n try {\n unlinkSync(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n}\n\n/**\n * Read and write a JSON file with exclusive locking.\n *\n * Acquires a cross-process lock, reads current state, applies the\n * transform function, validates, and writes back atomically.\n *\n * @param filePath - File to lock and modify\n * @param transform - Function that receives current data and returns new data\n * @returns The transformed data\n */\nexport async function withLock<T>(\n filePath: string,\n transform: (current: T | null) => T\n): Promise<T> {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Ensure file exists for locking (proper-lockfile needs the file to exist)\n if (!existsSync(filePath)) {\n writeFileSync(filePath, '', 'utf-8');\n }\n\n let release: (() => Promise<void>) | undefined;\n\n try {\n release = await lockfile.lock(filePath, LOCK_OPTIONS);\n\n const current = readJsonFile<T>(filePath);\n const updated = transform(current);\n writeJsonFileAtomic(filePath, updated);\n return updated;\n } finally {\n if (release) {\n await release();\n }\n }\n}\n\n/**\n * Acquire a file lock and execute an operation.\n * Unlike withLock, this doesn't read/write the file - caller manages I/O.\n * The return type R is independent of the file content type.\n */\nexport async function withFileLock<R>(\n filePath: string,\n operation: () => R | Promise<R>\n): Promise<R> {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n if (!existsSync(filePath)) {\n writeFileSync(filePath, '', 'utf-8');\n }\n\n let release: (() => Promise<void>) | undefined;\n\n try {\n release = await lockfile.lock(filePath, LOCK_OPTIONS);\n return await operation();\n } finally {\n if (release) {\n await release();\n }\n }\n}\n\n/**\n * Acquire locks on multiple files in correct order.\n * Used for operations that need to modify multiple files atomically\n * (e.g., moving a task from todo.json to archive).\n *\n * @param filePaths - Files to lock\n * @param operation - Function to execute while locks are held\n */\nexport async function withMultiLock<T>(\n filePaths: string[],\n operation: () => T | Promise<T>\n): Promise<T> {\n // Sort by lock priority to prevent deadlocks\n const sorted = [...filePaths].sort(\n (a, b) => getLockPriority(a) - getLockPriority(b)\n );\n\n const releases: Array<() => Promise<void>> = [];\n\n try {\n // Acquire locks in order\n for (const fp of sorted) {\n if (!existsSync(dirname(fp))) {\n mkdirSync(dirname(fp), { recursive: true });\n }\n if (!existsSync(fp)) {\n writeFileSync(fp, '', 'utf-8');\n }\n const release = await lockfile.lock(fp, LOCK_OPTIONS);\n releases.push(release);\n }\n\n return await operation();\n } finally {\n // Release in reverse order\n for (const release of releases.reverse()) {\n try {\n await release();\n } catch {\n // Ignore release errors\n }\n }\n }\n}\n\n/**\n * Create a numbered backup of a file (Tier 1 operational backup).\n *\n * Maintains up to MAX_BACKUPS copies:\n * .backups/todo.json.1 (newest)\n * .backups/todo.json.2\n * ...\n * .backups/todo.json.10 (oldest, deleted when new backup arrives)\n */\nfunction rotateBackup(filePath: string): void {\n const dir = dirname(filePath);\n const name = basename(filePath);\n const backupDir = join(dir, '.backups');\n\n if (!existsSync(backupDir)) {\n mkdirSync(backupDir, { recursive: true });\n }\n\n // Rotate existing backups (shift numbers up)\n for (let i = MAX_BACKUPS; i >= 1; i--) {\n const current = join(backupDir, `${name}.${i}`);\n if (i === MAX_BACKUPS) {\n // Delete oldest\n try {\n unlinkSync(current);\n } catch {\n // May not exist\n }\n } else {\n // Shift to next number\n const next = join(backupDir, `${name}.${i + 1}`);\n try {\n if (existsSync(current)) {\n renameSync(current, next);\n }\n } catch {\n // Ignore rename errors\n }\n }\n }\n\n // Copy current file to .1\n try {\n const content = readFileSync(filePath, 'utf-8');\n writeFileSync(join(backupDir, `${name}.1`), content, 'utf-8');\n } catch {\n // Non-fatal - backup failure shouldn't block write\n }\n}\n\n/**\n * Check if a CLEO project directory exists at the given path\n */\nexport function isProjectInitialized(projectRoot: string): boolean {\n const cleoDir = join(projectRoot, '.cleo');\n return existsSync(cleoDir) && existsSync(join(cleoDir, 'todo.json'));\n}\n\n/**\n * Resolve the project root directory.\n * Checks CLEO_ROOT env, then falls back to cwd.\n * @deprecated Use getProjectRoot() from '../../core/paths.js' instead.\n */\nexport function resolveProjectRoot(): string {\n return process.env.CLEO_ROOT || process.cwd();\n}\n\n/**\n * Get the path to a CLEO data file\n */\nexport function getDataPath(projectRoot: string, filename: string): string {\n return join(projectRoot, '.cleo', filename);\n}\n\n/**\n * List backup files for a given data file\n */\nexport function listBackups(filePath: string): string[] {\n const dir = dirname(filePath);\n const name = basename(filePath);\n const backupDir = join(dir, '.backups');\n\n if (!existsSync(backupDir)) {\n return [];\n }\n\n try {\n return readdirSync(backupDir)\n .filter((f) => f.startsWith(`${name}.`) && /\\.\\d+$/.test(f))\n .sort((a, b) => {\n const numA = parseInt(a.split('.').pop()!, 10);\n const numB = parseInt(b.split('.').pop()!, 10);\n return numA - numB;\n })\n .map((f) => join(backupDir, f));\n } catch {\n return [];\n }\n}\n", "/**\n * Schema Validator\n *\n * Validates CLEO JSON data against JSON Schema using Ajv.\n * Reuses existing schemas from the schemas/ directory.\n */\n\nimport AjvModule from 'ajv';\nimport addFormatsModule from 'ajv-formats';\nimport type { ValidateFunction, ErrorObject } from 'ajv';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\n\n// Handle ESM/CJS interop for Ajv and ajv-formats\nconst Ajv = (AjvModule as any).default || AjvModule;\nconst addFormats = (addFormatsModule as any).default || addFormatsModule;\n\n/**\n * Validation result\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Individual validation error\n */\nexport interface ValidationError {\n path: string;\n message: string;\n keyword: string;\n params: Record<string, unknown>;\n}\n\n/**\n * Schema types that can be validated\n */\nexport type SchemaType = 'todo' | 'config' | 'archive' | 'log' | 'sessions';\n\n/**\n * Schema cache to avoid re-reading/re-compiling\n */\nconst schemaCache = new Map<string, ValidateFunction>();\n\n/**\n * Create an Ajv instance configured for CLEO schemas\n */\nfunction createAjv(): InstanceType<typeof Ajv> {\n const ajv = new Ajv({\n allErrors: true,\n strict: false,\n validateFormats: true,\n });\n addFormats(ajv);\n return ajv;\n}\n\n/**\n * Shared Ajv instance\n */\nlet ajvInstance: InstanceType<typeof Ajv> | null = null;\n\nfunction getAjv(): InstanceType<typeof Ajv> {\n if (!ajvInstance) {\n ajvInstance = createAjv();\n }\n return ajvInstance;\n}\n\n/**\n * Resolve path to a schema file.\n * Looks in multiple locations: project schemas/, dist-relative schemas/\n */\nfunction resolveSchemaPath(schemaType: SchemaType): string | null {\n const filename = `${schemaType}.schema.json`;\n\n // Check project root schemas/ and dist-relative locations\n const projectRoot = process.env.CLEO_ROOT || process.cwd();\n const paths = [\n join(projectRoot, 'schemas', filename),\n join(__dirname, '..', '..', '..', 'schemas', filename), // relative from dist/mcp/engine/\n join(__dirname, '..', '..', 'schemas', filename), // relative from dist/mcp/\n ];\n\n for (const p of paths) {\n if (existsSync(p)) {\n return p;\n }\n }\n\n return null;\n}\n\n/**\n * Load and compile a schema, with caching\n */\nfunction getValidator(schemaType: SchemaType): ValidateFunction | null {\n const cached = schemaCache.get(schemaType);\n if (cached) {\n return cached;\n }\n\n const schemaPath = resolveSchemaPath(schemaType);\n if (!schemaPath) {\n return null;\n }\n\n try {\n const schemaContent = readFileSync(schemaPath, 'utf-8');\n const schema = JSON.parse(schemaContent);\n const ajv = getAjv();\n const validate = ajv.compile(schema);\n schemaCache.set(schemaType, validate);\n return validate;\n } catch {\n return null;\n }\n}\n\n/**\n * Validate data against a CLEO schema\n *\n * @param schemaType - Which schema to validate against\n * @param data - The data to validate\n * @returns Validation result with errors if invalid\n */\nexport function validateSchema(\n schemaType: SchemaType,\n data: unknown\n): ValidationResult {\n const validate = getValidator(schemaType);\n\n if (!validate) {\n return {\n valid: false,\n errors: [{\n path: '',\n message: `Schema '${schemaType}' not found. Ensure schemas/ directory is accessible.`,\n keyword: 'schema-not-found',\n params: { schemaType },\n }],\n };\n }\n\n const valid = validate(data);\n\n if (valid) {\n return { valid: true, errors: [] };\n }\n\n const errors: ValidationError[] = (validate.errors || []).map(\n (err: ErrorObject) => ({\n path: err.instancePath || '/',\n message: err.message || 'Validation failed',\n keyword: err.keyword,\n params: err.params as Record<string, unknown>,\n })\n );\n\n return { valid: false, errors };\n}\n\n/**\n * Validate a single task object against the task definition in todo.schema.json.\n * This extracts the task definition from the full schema for targeted validation.\n *\n * @param task - Task object to validate\n * @returns Validation result\n */\nexport function validateTask(task: unknown): ValidationResult {\n if (!task || typeof task !== 'object') {\n return {\n valid: false,\n errors: [{\n path: '',\n message: 'Task must be a non-null object',\n keyword: 'type',\n params: { type: 'object' },\n }],\n };\n }\n\n const taskObj = task as Record<string, unknown>;\n\n // Validate required fields exist\n const requiredFields = ['id', 'title', 'status', 'priority', 'createdAt'];\n const errors: ValidationError[] = [];\n\n for (const field of requiredFields) {\n if (taskObj[field] === undefined || taskObj[field] === null) {\n errors.push({\n path: `/${field}`,\n message: `Required field '${field}' is missing`,\n keyword: 'required',\n params: { missingProperty: field },\n });\n }\n }\n\n // Validate ID format\n if (typeof taskObj.id === 'string' && !/^T\\d{3,}$/.test(taskObj.id)) {\n errors.push({\n path: '/id',\n message: 'Task ID must match pattern T followed by 3+ digits (e.g., T001)',\n keyword: 'pattern',\n params: { pattern: '^T\\\\d{3,}$' },\n });\n }\n\n // Validate status enum\n const validStatuses = ['pending', 'active', 'blocked', 'done', 'cancelled'];\n if (taskObj.status && !validStatuses.includes(taskObj.status as string)) {\n errors.push({\n path: '/status',\n message: `Status must be one of: ${validStatuses.join(', ')}`,\n keyword: 'enum',\n params: { allowedValues: validStatuses },\n });\n }\n\n // Validate priority enum\n const validPriorities = ['critical', 'high', 'medium', 'low'];\n if (taskObj.priority && !validPriorities.includes(taskObj.priority as string)) {\n errors.push({\n path: '/priority',\n message: `Priority must be one of: ${validPriorities.join(', ')}`,\n keyword: 'enum',\n params: { allowedValues: validPriorities },\n });\n }\n\n // Validate title length\n if (typeof taskObj.title === 'string') {\n if (taskObj.title.length === 0) {\n errors.push({\n path: '/title',\n message: 'Title cannot be empty',\n keyword: 'minLength',\n params: { limit: 1 },\n });\n }\n if (taskObj.title.length > 120) {\n errors.push({\n path: '/title',\n message: 'Title cannot exceed 120 characters',\n keyword: 'maxLength',\n params: { limit: 120 },\n });\n }\n }\n\n // Validate description length\n if (typeof taskObj.description === 'string' && taskObj.description.length > 2000) {\n errors.push({\n path: '/description',\n message: 'Description cannot exceed 2000 characters',\n keyword: 'maxLength',\n params: { limit: 2000 },\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Clear the schema cache (useful for testing)\n */\nexport function clearSchemaCache(): void {\n schemaCache.clear();\n ajvInstance = null;\n}\n", "/**\n * Anti-Hallucination Validation Rules\n *\n * Implements CLEO's anti-hallucination requirements:\n * - Title and description both required and different\n * - No future timestamps\n * - No duplicate task descriptions\n * - Unique IDs across todo.json AND todo-archive.json\n * - Valid status transitions\n * - Hierarchy constraints (max depth 3, max 7 siblings)\n */\n\n/**\n * Validation error from anti-hallucination checks\n */\nexport interface RuleViolation {\n rule: string;\n field: string;\n message: string;\n severity: 'error' | 'warning';\n}\n\n/**\n * Task-like object for validation (doesn't need full Task type)\n */\ninterface TaskLike {\n id?: string;\n title?: string;\n description?: string;\n status?: string;\n createdAt?: string;\n updatedAt?: string;\n completedAt?: string;\n cancelledAt?: string;\n parentId?: string | null;\n type?: string;\n}\n\n/**\n * Validate that title and description are both present and different.\n * This is a critical anti-hallucination check.\n */\nexport function validateTitleDescription(\n title?: string,\n description?: string\n): RuleViolation[] {\n const violations: RuleViolation[] = [];\n\n if (!title || title.trim().length === 0) {\n violations.push({\n rule: 'title-required',\n field: 'title',\n message: 'Title is required and cannot be empty',\n severity: 'error',\n });\n }\n\n if (!description || description.trim().length === 0) {\n violations.push({\n rule: 'description-required',\n field: 'description',\n message: 'Description is required and cannot be empty',\n severity: 'error',\n });\n }\n\n if (\n title &&\n description &&\n title.trim().toLowerCase() === description.trim().toLowerCase()\n ) {\n violations.push({\n rule: 'title-description-different',\n field: 'description',\n message: 'Title and description must be different',\n severity: 'error',\n });\n }\n\n return violations;\n}\n\n/**\n * Validate that timestamps are not in the future\n */\nexport function validateTimestamps(task: TaskLike): RuleViolation[] {\n const violations: RuleViolation[] = [];\n const now = new Date();\n // Allow 5 minutes of clock skew\n const threshold = new Date(now.getTime() + 5 * 60 * 1000);\n\n const timestampFields: Array<[string, string | undefined]> = [\n ['createdAt', task.createdAt],\n ['updatedAt', task.updatedAt],\n ['completedAt', task.completedAt],\n ['cancelledAt', task.cancelledAt],\n ];\n\n for (const [field, value] of timestampFields) {\n if (value) {\n const date = new Date(value);\n if (isNaN(date.getTime())) {\n violations.push({\n rule: 'valid-timestamp',\n field,\n message: `Invalid timestamp format: ${value}`,\n severity: 'error',\n });\n } else if (date > threshold) {\n violations.push({\n rule: 'no-future-timestamps',\n field,\n message: `Timestamp ${value} is in the future`,\n severity: 'error',\n });\n }\n }\n }\n\n return violations;\n}\n\n/**\n * Validate ID uniqueness across all tasks (todo + archive)\n */\nexport function validateIdUniqueness(\n taskId: string,\n existingIds: Set<string>\n): RuleViolation[] {\n if (existingIds.has(taskId)) {\n return [{\n rule: 'unique-id',\n field: 'id',\n message: `Task ID '${taskId}' already exists`,\n severity: 'error',\n }];\n }\n return [];\n}\n\n/**\n * Validate no duplicate task descriptions\n */\nexport function validateNoDuplicateDescription(\n description: string,\n existingDescriptions: string[],\n _excludeTaskId?: string\n): RuleViolation[] {\n const normalizedNew = description.trim().toLowerCase();\n\n for (const existing of existingDescriptions) {\n if (existing.trim().toLowerCase() === normalizedNew) {\n return [{\n rule: 'no-duplicate-description',\n field: 'description',\n message: 'A task with this exact description already exists',\n severity: 'warning',\n }];\n }\n }\n\n return [];\n}\n\n/**\n * Validate hierarchy constraints.\n * Accepts optional limits to override defaults (from config).\n */\nexport function validateHierarchy(\n parentId: string | null | undefined,\n tasks: Array<{ id: string; parentId?: string | null; type?: string }>,\n _taskType?: string,\n limits?: { maxDepth?: number; maxSiblings?: number }\n): RuleViolation[] {\n const violations: RuleViolation[] = [];\n\n if (!parentId) {\n return violations;\n }\n\n const maxDepth = limits?.maxDepth ?? 3;\n const maxSiblings = limits?.maxSiblings ?? 7;\n\n // Find parent\n const parent = tasks.find((t) => t.id === parentId);\n if (!parent) {\n violations.push({\n rule: 'parent-exists',\n field: 'parentId',\n message: `Parent task '${parentId}' not found`,\n severity: 'error',\n });\n return violations;\n }\n\n // Check depth (default max 3: epic -> task -> subtask)\n let depth = 1;\n let current = parent;\n while (current.parentId) {\n depth++;\n const nextParent = tasks.find((t) => t.id === current.parentId);\n if (!nextParent) break;\n current = nextParent;\n }\n\n if (depth > maxDepth - 1) {\n violations.push({\n rule: 'max-depth',\n field: 'parentId',\n message: `Maximum hierarchy depth of ${maxDepth} exceeded (epic -> task -> subtask)`,\n severity: 'error',\n });\n }\n\n // Check sibling count\n const siblingCount = tasks.filter((t) => t.parentId === parentId).length;\n if (siblingCount >= maxSiblings) {\n violations.push({\n rule: 'max-siblings',\n field: 'parentId',\n message: `Parent '${parentId}' already has ${siblingCount} children (max ${maxSiblings})`,\n severity: 'error',\n });\n }\n\n return violations;\n}\n\n/**\n * Validate status transition\n */\nexport function validateStatusTransition(\n currentStatus: string,\n newStatus: string\n): RuleViolation[] {\n const validTransitions: Record<string, string[]> = {\n pending: ['active', 'blocked', 'done', 'cancelled'],\n active: ['pending', 'blocked', 'done', 'cancelled'],\n blocked: ['pending', 'active', 'done', 'cancelled'],\n done: ['pending', 'active'], // restore (alias: reopen)\n cancelled: ['pending'], // restore (alias: uncancel)\n };\n\n const allowed = validTransitions[currentStatus];\n if (!allowed) {\n return [{\n rule: 'valid-status-transition',\n field: 'status',\n message: `Unknown current status: '${currentStatus}'`,\n severity: 'error',\n }];\n }\n\n if (!allowed.includes(newStatus)) {\n return [{\n rule: 'valid-status-transition',\n field: 'status',\n message: `Cannot transition from '${currentStatus}' to '${newStatus}'. Valid: ${allowed.join(', ')}`,\n severity: 'error',\n }];\n }\n\n return [];\n}\n\n/**\n * Run all validation rules on a task being created\n */\nexport function validateNewTask(\n task: TaskLike,\n existingIds: Set<string>,\n existingDescriptions: string[],\n existingTasks: Array<{ id: string; parentId?: string | null; type?: string }>,\n limits?: { maxDepth?: number; maxSiblings?: number }\n): RuleViolation[] {\n const violations: RuleViolation[] = [];\n\n violations.push(...validateTitleDescription(task.title, task.description));\n violations.push(...validateTimestamps(task));\n\n if (task.id) {\n violations.push(...validateIdUniqueness(task.id, existingIds));\n }\n\n if (task.description) {\n violations.push(\n ...validateNoDuplicateDescription(task.description, existingDescriptions)\n );\n }\n\n if (task.parentId) {\n violations.push(\n ...validateHierarchy(task.parentId, existingTasks, task.type, limits)\n );\n }\n\n return violations;\n}\n\n/**\n * Check if violations contain any errors (not just warnings)\n */\nexport function hasErrors(violations: RuleViolation[]): boolean {\n return violations.some((v) => v.severity === 'error');\n}\n", "/**\n * DataAccessor: File-level storage abstraction for core modules.\n *\n * Core modules operate on whole-file data structures (TaskFile, ArchiveFile, SessionsFile).\n * The DataAccessor abstracts WHERE that data is stored (JSON files vs SQLite)\n * while preserving the read-modify-write pattern that core business logic relies on.\n *\n * This is the DRY/SOLID injection point: core modules accept a DataAccessor parameter\n * instead of calling readJson/saveJson directly.\n *\n * Two implementations:\n * - JsonDataAccessor: reads/writes .cleo/*.json files (current behavior)\n * - SqliteDataAccessor: materializes/dematerializes from SQLite tables\n *\n * @epic T4454\n */\n\nimport type { TaskFile } from '../types/task.js';\nimport type { Session } from '../types/session.js';\n\n/** Archive file structure. */\nexport interface ArchiveFile {\n archivedTasks: Array<import('../types/task.js').Task>;\n version?: string;\n}\n\n/** Sessions file structure. Must match types/session.ts SessionsFile. */\nexport interface SessionsFile {\n sessions: Session[];\n version: string;\n _meta: {\n schemaVersion: string;\n lastUpdated: string;\n };\n}\n\n/**\n * DataAccessor interface.\n *\n * Core modules call these methods instead of readJson/saveJson.\n * Each method maps directly to the file-level operations that\n * core modules already perform.\n */\nexport interface DataAccessor {\n /** The storage engine backing this accessor. */\n readonly engine: 'json' | 'sqlite' | 'dual';\n\n // ---- Task data (tasks.json equivalent) ----\n\n /** Load the full TaskFile (tasks + project meta + work state). */\n loadTaskFile(): Promise<TaskFile>;\n\n /** Save the full TaskFile atomically. Creates backup before write. */\n saveTaskFile(data: TaskFile): Promise<void>;\n\n /** @deprecated Use loadTaskFile() instead. */\n loadTodoFile(): Promise<TaskFile>;\n\n /** @deprecated Use saveTaskFile() instead. */\n saveTodoFile(data: TaskFile): Promise<void>;\n\n // ---- Archive data (todo-archive.json equivalent) ----\n\n /** Load the archive file. Returns null if archive doesn't exist. */\n loadArchive(): Promise<ArchiveFile | null>;\n\n /** Save the archive file atomically. Creates backup before write. */\n saveArchive(data: ArchiveFile): Promise<void>;\n\n // ---- Session data (sessions.json equivalent) ----\n\n /** Load the sessions file. Returns empty sessions array if file doesn't exist. */\n loadSessions(): Promise<SessionsFile>;\n\n /** Save the sessions file atomically. */\n saveSessions(data: SessionsFile): Promise<void>;\n\n // ---- Audit log (todo-log.jsonl equivalent) ----\n\n /** Append an entry to the audit log. */\n appendLog(entry: Record<string, unknown>): Promise<void>;\n\n // ---- Lifecycle ----\n\n /** Release any resources (close DB connections, etc.). */\n close(): Promise<void>;\n}\n\n/**\n * Create a DataAccessor for the given working directory.\n * Auto-detects engine from .cleo/config.json (storage.engine field).\n *\n * ALL accessors returned are safety-enabled by default via SafetyDataAccessor wrapper.\n * Use CLEO_DISABLE_SAFETY=true to bypass (emergency only).\n *\n * @param engine - Force a specific engine, or undefined for auto-detect\n * @param cwd - Working directory (defaults to process.cwd())\n */\nexport async function createDataAccessor(\n engine?: 'json' | 'sqlite' | 'dual',\n cwd?: string,\n): Promise<DataAccessor> {\n const resolvedEngine = engine ?? (await detectEngine(cwd));\n\n // Auto-migrate JSON\u2192SQLite when migration is needed (P2-B)\n if (resolvedEngine === 'sqlite' || resolvedEngine === 'dual') {\n const { checkStorageMigration } = await import('../core/migration/preflight.js');\n const preflight = checkStorageMigration(cwd);\n if (preflight.migrationNeeded) {\n const { migrateJsonToSqlite } = await import('./migration-sqlite.js');\n const result = await migrateJsonToSqlite(cwd, { force: false });\n if (result.success) {\n await archiveV1Files(cwd);\n } else {\n const errDetails = result.errors.join('; ') || 'unknown error';\n process.stderr.write(\n `CLEO auto-migration failed: ${errDetails}\\n`\n + `Run manually: cleo migrate-storage --to-sqlite --confirm\\n`,\n );\n const { CleoError } = await import('../core/errors.js');\n const { ExitCode } = await import('../types/exit-codes.js');\n throw new CleoError(\n ExitCode.MIGRATION_REQUIRED,\n `CLEO data migration required. Run: cleo migrate-storage --to-sqlite --confirm`,\n );\n }\n }\n }\n\n // Create the inner accessor based on engine\n let inner: DataAccessor;\n switch (resolvedEngine) {\n case 'sqlite': {\n const { createSqliteDataAccessor } = await import('./sqlite-data-accessor.js');\n inner = await createSqliteDataAccessor(cwd);\n break;\n }\n case 'dual': {\n // Dual mode: write to both, read from SQLite with JSON fallback\n const { createJsonDataAccessor } = await import('./json-data-accessor.js');\n const { createSqliteDataAccessor } = await import('./sqlite-data-accessor.js');\n inner = createDualDataAccessor(\n await createJsonDataAccessor(cwd),\n await createSqliteDataAccessor(cwd),\n );\n break;\n }\n case 'json':\n default: {\n const { createJsonDataAccessor } = await import('./json-data-accessor.js');\n inner = await createJsonDataAccessor(cwd);\n break;\n }\n }\n\n // Safety is now built into task-store.ts record-level operations (T4745 phase 2).\n // No wrapper needed \u2014 the inner accessor is returned directly.\n return inner;\n}\n\n/** Convenience: get a DataAccessor with auto-detected engine. */\nexport async function getAccessor(cwd?: string): Promise<DataAccessor> {\n return createDataAccessor(undefined, cwd);\n}\n\n// ---- Internal helpers ----\n\nasync function detectEngine(cwd?: string): Promise<'json' | 'sqlite' | 'dual'> {\n try {\n const { existsSync, readFileSync } = await import('node:fs');\n const { getCleoDirAbsolute } = await import('../core/paths.js');\n const cleoDir = getCleoDirAbsolute(cwd);\n const configPath = (await import('node:path')).join(cleoDir, 'config.json');\n\n if (existsSync(configPath)) {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'));\n const engine = config?.storage?.engine;\n if (engine === 'sqlite' || engine === 'dual' || engine === 'json') {\n return engine;\n }\n }\n\n const { join } = await import('node:path');\n\n // Auto-detect: if tasks.db exists, use sqlite\n if (existsSync(join(cleoDir, 'tasks.db'))) return 'sqlite';\n\n // Backward compat: if todo.json or tasks.json exists (but no tasks.db), keep json\n if (existsSync(join(cleoDir, 'todo.json'))) return 'json';\n if (existsSync(join(cleoDir, 'tasks.json'))) return 'json';\n } catch {\n // Fall through to default\n }\n // Default: sqlite (ADR-006 canonical storage for new projects)\n return 'sqlite';\n}\n\n/**\n * Archive v1 JSON files after successful SQLite migration.\n * Moves todo.json, todo-archive.json, sessions.json, todo-log.jsonl,\n * tasks-log.jsonl, and audit-log-*.json to .cleo/archive/.\n * Idempotent: safe to call multiple times.\n */\nasync function archiveV1Files(cwd?: string): Promise<void> {\n const { mkdirSync, renameSync, existsSync, readdirSync } = await import('node:fs');\n const { join } = await import('node:path');\n const { getCleoDirAbsolute } = await import('../core/paths.js');\n const cleoDir = getCleoDirAbsolute(cwd);\n const v1ArchiveDir = join(cleoDir, 'archive', 'v1-json');\n const auditArchiveDir = join(cleoDir, 'archive', 'audit-logs');\n\n const v1Files = [\n 'todo.json',\n 'todo-archive.json',\n 'sessions.json',\n 'todo-log.jsonl',\n 'tasks-log.jsonl',\n ];\n\n for (const f of v1Files) {\n const src = join(cleoDir, f);\n if (existsSync(src)) {\n mkdirSync(v1ArchiveDir, { recursive: true });\n renameSync(src, join(v1ArchiveDir, f));\n }\n }\n\n // Archive audit-log-*.json files\n try {\n const entries = readdirSync(cleoDir);\n for (const entry of entries) {\n if (entry.startsWith('audit-log-') && entry.endsWith('.json')) {\n mkdirSync(auditArchiveDir, { recursive: true });\n renameSync(join(cleoDir, entry), join(auditArchiveDir, entry));\n }\n }\n } catch {\n // Non-fatal: audit log archival failure should not block migration\n }\n}\n\n/**\n * Dual-write DataAccessor.\n * Writes to both JSON and SQLite. Reads from SQLite, falls back to JSON.\n */\nfunction createDualDataAccessor(json: DataAccessor, sqlite: DataAccessor): DataAccessor {\n return {\n engine: 'dual' as const,\n\n async loadTaskFile() {\n try {\n return await sqlite.loadTaskFile();\n } catch {\n return await json.loadTaskFile();\n }\n },\n\n async saveTaskFile(data) {\n await Promise.allSettled([\n json.saveTaskFile(data),\n sqlite.saveTaskFile(data),\n ]);\n },\n\n // Deprecated aliases\n async loadTodoFile() {\n return this.loadTaskFile();\n },\n\n async saveTodoFile(data: TaskFile) {\n return this.saveTaskFile(data);\n },\n\n async loadArchive() {\n try {\n return await sqlite.loadArchive();\n } catch {\n return await json.loadArchive();\n }\n },\n\n async saveArchive(data) {\n await Promise.allSettled([\n json.saveArchive(data),\n sqlite.saveArchive(data),\n ]);\n },\n\n async loadSessions() {\n try {\n return await sqlite.loadSessions();\n } catch {\n return await json.loadSessions();\n }\n },\n\n async saveSessions(data) {\n await Promise.allSettled([\n json.saveSessions(data),\n sqlite.saveSessions(data),\n ]);\n },\n\n async appendLog(entry) {\n // Logs always go to JSONL file (append-only, both backends)\n await json.appendLog(entry);\n },\n\n async close() {\n await Promise.allSettled([json.close(), sqlite.close()]);\n },\n };\n}\n", "/**\n * Task creation logic.\n * @task T4460\n * @epic T4454\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { readJsonRequired, appendJsonl } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TaskStatus, TaskPriority, TaskType, TaskSize, TaskFile } from '../../types/task.js';\nimport { getTaskPath, getArchivePath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\nimport { loadConfig } from '../config.js';\nimport {\n createTask as storeCreateTask,\n updateTask as storeUpdateTask,\n} from '../../store/task-store.js';\n\n/** Options for creating a task. */\nexport interface AddTaskOptions {\n title: string;\n status?: TaskStatus;\n priority?: TaskPriority;\n type?: TaskType;\n parentId?: string | null;\n size?: TaskSize;\n phase?: string;\n description?: string;\n labels?: string[];\n files?: string[];\n acceptance?: string[];\n depends?: string[];\n notes?: string;\n position?: number;\n addPhase?: boolean;\n dryRun?: boolean;\n}\n\n/** Result of adding a task. */\nexport interface AddTaskResult {\n task: Task;\n duplicate?: boolean;\n dryRun?: boolean;\n}\n\n/**\n * Validate a task title.\n * @task T4460\n */\nexport function validateTitle(title: string): void {\n if (!title || title.trim().length === 0) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Task title is required');\n }\n if (title.length > 200) {\n throw new CleoError(ExitCode.VALIDATION_ERROR, 'Task title must be 200 characters or less');\n }\n}\n\n/**\n * Validate task status.\n * @task T4460\n */\nexport function validateStatus(status: string): asserts status is TaskStatus {\n const valid: TaskStatus[] = ['pending', 'active', 'blocked', 'done', 'cancelled'];\n if (!valid.includes(status as TaskStatus)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid status: ${status} (must be ${valid.join('|')})`,\n );\n }\n}\n\n/**\n * Mapping from numeric priority (1-9) to string priority names.\n * 1-2 = critical, 3-4 = high, 5-6 = medium, 7-9 = low.\n * @task T4572\n */\nconst NUMERIC_PRIORITY_MAP: Record<number, TaskPriority> = {\n 1: 'critical',\n 2: 'critical',\n 3: 'high',\n 4: 'high',\n 5: 'medium',\n 6: 'medium',\n 7: 'low',\n 8: 'low',\n 9: 'low',\n};\n\n/** Valid string priority values. */\nexport const VALID_PRIORITIES: readonly TaskPriority[] = ['critical', 'high', 'medium', 'low'] as const;\n\n/**\n * Normalize priority to canonical string format.\n * Accepts both string names (\"critical\",\"high\",\"medium\",\"low\") and numeric (1-9).\n * Returns the canonical string format per todo.schema.json.\n * @task T4572\n */\nexport function normalizePriority(priority: string | number): TaskPriority {\n // Handle numeric input\n if (typeof priority === 'number') {\n const mapped = NUMERIC_PRIORITY_MAP[priority];\n if (!mapped) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid numeric priority: ${priority} (must be 1-9)`,\n );\n }\n return mapped;\n }\n\n // Handle string input - check for numeric string first\n const asNumber = Number(priority);\n if (!Number.isNaN(asNumber) && Number.isInteger(asNumber) && asNumber >= 1 && asNumber <= 9) {\n return NUMERIC_PRIORITY_MAP[asNumber]!;\n }\n\n // Canonical string validation\n const lower = priority.toLowerCase().trim();\n if (VALID_PRIORITIES.includes(lower as TaskPriority)) {\n return lower as TaskPriority;\n }\n\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid priority: ${priority} (must be ${VALID_PRIORITIES.join('|')} or numeric 1-9)`,\n );\n}\n\n/**\n * Validate task priority.\n * @task T4460\n * @task T4572\n */\nexport function validatePriority(priority: string): asserts priority is TaskPriority {\n normalizePriority(priority);\n}\n\n/**\n * Validate task type.\n * @task T4460\n */\nexport function validateTaskType(type: string): asserts type is TaskType {\n const valid: TaskType[] = ['epic', 'task', 'subtask'];\n if (!valid.includes(type as TaskType)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid task type: ${type} (must be ${valid.join('|')})`,\n );\n }\n}\n\n/**\n * Validate task size.\n * @task T4460\n */\nexport function validateSize(size: string): asserts size is TaskSize {\n const valid: TaskSize[] = ['small', 'medium', 'large'];\n if (!valid.includes(size as TaskSize)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid size: ${size} (must be ${valid.join('|')})`,\n );\n }\n}\n\n/**\n * Validate label format.\n * @task T4460\n */\nexport function validateLabels(labels: string[]): void {\n for (const label of labels) {\n const trimmed = label.trim();\n if (!/^[a-z][a-z0-9.-]*$/.test(trimmed)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid label format: '${trimmed}' (must be lowercase alphanumeric with hyphens/periods)`,\n );\n }\n }\n}\n\n/**\n * Validate phase slug format.\n * @task T4460\n */\nexport function validatePhaseFormat(phase: string): void {\n if (!/^[a-z][a-z0-9-]*$/.test(phase)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid phase format: ${phase} (must be lowercase alphanumeric with hyphens)`,\n );\n }\n}\n\n/**\n * Validate dependency IDs exist.\n * @task T4460\n */\nexport function validateDepends(depends: string[], tasks: Task[]): void {\n const existingIds = new Set(tasks.map(t => t.id));\n for (const depId of depends) {\n const trimmed = depId.trim();\n if (!/^T\\d{3,}$/.test(trimmed)) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid dependency ID format: '${trimmed}' (must be T### format)`,\n );\n }\n if (!existingIds.has(trimmed)) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Dependency task not found: ${trimmed}`,\n );\n }\n }\n}\n\n/**\n * Generate the next task ID by scanning existing tasks and archive.\n * @task T4460\n */\nexport function generateTaskId(tasks: Task[], archivedTasks?: Array<{ id: string }>): string {\n let maxId = 0;\n const allTasks = [...tasks, ...(archivedTasks ?? [])];\n for (const task of allTasks) {\n const match = task.id.match(/^T(\\d+)$/);\n if (match) {\n const num = parseInt(match[1]!, 10);\n if (num > maxId) maxId = num;\n }\n }\n return `T${String(maxId + 1).padStart(3, '0')}`;\n}\n\n/**\n * Validate parent hierarchy constraints.\n * @task T4460\n */\nexport function validateParent(\n parentId: string,\n tasks: Task[],\n maxDepth: number = 3,\n maxSiblings: number = 7,\n): void {\n // Check parent exists\n const parent = tasks.find(t => t.id === parentId);\n if (!parent) {\n throw new CleoError(\n ExitCode.PARENT_NOT_FOUND,\n `Parent task not found: ${parentId}`,\n { fix: `Use 'cleo show ${parentId}' to check or create as standalone task` },\n );\n }\n\n // Check parent type allows children\n if (parent.type === 'subtask') {\n throw new CleoError(\n ExitCode.INVALID_PARENT_TYPE,\n `Cannot add child to ${parentId}: subtasks cannot have children`,\n { fix: `Create as standalone task or add to parent's parent instead` },\n );\n }\n\n // Check depth\n const depth = getTaskDepth(parentId, tasks);\n if (depth >= maxDepth) {\n throw new CleoError(\n ExitCode.DEPTH_EXCEEDED,\n `Cannot add child to ${parentId}: max hierarchy depth (${maxDepth}) would be exceeded`,\n );\n }\n\n // Check sibling count\n if (maxSiblings > 0) {\n const siblingCount = tasks.filter(t => t.parentId === parentId).length;\n if (siblingCount >= maxSiblings) {\n throw new CleoError(\n ExitCode.SIBLING_LIMIT,\n `Cannot add child to ${parentId}: max siblings (${maxSiblings}) exceeded`,\n { fix: `Create as standalone task or increase hierarchy.maxSiblings in config` },\n );\n }\n }\n}\n\n/**\n * Get the depth of a task in the hierarchy.\n * @task T4460\n */\nexport function getTaskDepth(taskId: string, tasks: Task[]): number {\n let depth = 0;\n let currentId: string | null | undefined = taskId;\n const visited = new Set<string>();\n\n while (currentId) {\n if (visited.has(currentId)) break; // circular reference guard\n visited.add(currentId);\n const task = tasks.find(t => t.id === currentId);\n if (!task?.parentId) break;\n depth++;\n currentId = task.parentId;\n }\n return depth;\n}\n\n/**\n * Infer task type from parent context.\n * @task T4460\n */\nexport function inferTaskType(parentId: string | null | undefined, tasks: Task[]): TaskType {\n if (!parentId) return 'task';\n const parent = tasks.find(t => t.id === parentId);\n if (!parent) return 'task';\n if (parent.type === 'epic') return 'task';\n return 'subtask';\n}\n\n/**\n * Get the next position for a task within a parent scope.\n * @task T4460\n */\nexport function getNextPosition(parentId: string | null | undefined, tasks: Task[]): number {\n const siblings = tasks.filter(t =>\n parentId ? t.parentId === parentId : (!t.parentId || t.parentId === null),\n );\n let maxPos = 0;\n for (const s of siblings) {\n if (s.position !== undefined && s.position !== null && s.position > maxPos) {\n maxPos = s.position;\n }\n }\n return maxPos + 1;\n}\n\n/**\n * Log an operation to the audit log.\n * @task T4460\n */\nexport async function logOperation(\n logPath: string,\n operation: string,\n taskId: string,\n details: Record<string, unknown>,\n accessor?: import('../../store/data-accessor.js').DataAccessor,\n): Promise<void> {\n const logId = `log-${Math.floor(Date.now() / 1000)}-${randomBytes(3).toString('hex')}`;\n const entry = {\n id: logId,\n timestamp: new Date().toISOString(),\n action: operation,\n taskId,\n actor: 'system',\n details,\n before: null,\n after: details,\n };\n\n try {\n if (accessor) {\n await accessor.appendLog(entry);\n } else {\n await appendJsonl(logPath, entry);\n }\n } catch {\n // Log failure is non-fatal\n }\n}\n\n/**\n * Check for recent duplicate task.\n * @task T4460\n */\nexport function findRecentDuplicate(\n title: string,\n phase: string | undefined,\n tasks: Task[],\n windowSeconds: number = 60,\n): Task | null {\n const now = Date.now();\n const cutoff = now - windowSeconds * 1000;\n\n for (const task of tasks) {\n if (task.title !== title) continue;\n if (phase) {\n if (task.phase !== phase) continue;\n } else {\n if (task.phase && task.phase !== '') continue;\n }\n const created = new Date(task.createdAt).getTime();\n if (created > cutoff) return task;\n }\n return null;\n}\n\n/**\n * Add a new task to the todo file.\n * @task T4460\n */\nexport async function addTask(options: AddTaskOptions, cwd?: string, accessor?: DataAccessor): Promise<AddTaskResult> {\n const todoPath = getTaskPath(cwd);\n const archivePath = getArchivePath(cwd);\n\n // Validate title\n validateTitle(options.title);\n\n // Read current data\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(todoPath);\n\n // Read archive for ID generation\n let archivedTasks: Array<{ id: string }> = [];\n try {\n if (accessor) {\n const archive = await accessor.loadArchive();\n if (archive?.archivedTasks) {\n archivedTasks = archive.archivedTasks;\n }\n } else {\n const { readJson } = await import('../../store/json.js');\n const archive = await readJson<{ archivedTasks: Array<{ id: string }> }>(archivePath);\n if (archive?.archivedTasks) {\n archivedTasks = archive.archivedTasks;\n }\n }\n } catch {\n // Archive may not exist\n }\n\n // Resolve defaults\n const status = options.status ?? 'pending';\n const priority = normalizePriority(options.priority ?? 'medium');\n const size = options.size ?? 'medium';\n let taskType = options.type;\n const parentId = options.parentId ?? null;\n\n // Validate inputs\n validateStatus(status);\n // priority is already normalized above\n validateSize(size);\n if (options.labels?.length) validateLabels(options.labels);\n if (options.depends?.length) validateDepends(options.depends, data.tasks);\n\n // Phase validation\n let phase = options.phase;\n if (phase) {\n validatePhaseFormat(phase);\n // Check if phase exists in project\n const phases = data.project?.phases ?? {};\n if (!phases[phase]) {\n if (!options.addPhase) {\n const validPhases = Object.keys(phases).join(', ');\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Phase '${phase}' not found. Valid phases: ${validPhases || 'none'}. Use --add-phase to create new.`,\n );\n }\n // Create phase\n const order = Object.keys(phases).length + 1;\n const name = phase.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n if (!data.project) {\n (data as unknown as Record<string, unknown>).project = { name: '', phases: {} };\n }\n if (!data.project.phases) data.project.phases = {};\n data.project.phases[phase] = { order, name, status: 'pending' as const };\n }\n } else {\n // Inherit from project.currentPhase\n if (data.project?.currentPhase) {\n phase = data.project.currentPhase;\n }\n }\n\n // Parent hierarchy validation\n if (parentId) {\n if (!/^T\\d{3,}$/.test(parentId)) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Invalid parent ID format: ${parentId}`);\n }\n // Read hierarchy limits from config\n const config = await loadConfig(cwd);\n const maxDepth = (config as any).hierarchy?.maxDepth ?? 3;\n const maxSiblings = (config as any).hierarchy?.maxSiblings ?? 7;\n validateParent(parentId, data.tasks, maxDepth, maxSiblings);\n\n // Validate type constraints\n if (taskType === 'epic') {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n 'Epic tasks cannot have a parent - they must be root-level',\n { fix: \"Remove --parent flag or change --type to task|subtask\" },\n );\n }\n }\n\n if (taskType === 'subtask' && !parentId) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n 'Subtask tasks require a parent - specify with --parent',\n { fix: \"Add --parent T### flag or change --type to task|epic\" },\n );\n }\n\n if (taskType) {\n validateTaskType(taskType);\n } else {\n taskType = inferTaskType(parentId, data.tasks);\n }\n\n // Duplicate detection\n const duplicate = findRecentDuplicate(options.title, phase, data.tasks);\n if (duplicate) {\n return { task: duplicate, duplicate: true };\n }\n\n // Generate ID\n const taskId = generateTaskId(data.tasks, archivedTasks);\n\n // ID uniqueness check\n if (data.tasks.some(t => t.id === taskId)) {\n throw new CleoError(ExitCode.ID_COLLISION, `Generated ID ${taskId} already exists`);\n }\n\n const now = new Date().toISOString();\n const position = options.position ?? getNextPosition(parentId, data.tasks);\n\n // Build task object\n const task: Task = {\n id: taskId,\n title: options.title,\n status,\n priority,\n type: taskType,\n parentId: parentId || null,\n position,\n positionVersion: 0,\n size,\n createdAt: now,\n updatedAt: now,\n };\n\n // Add optional fields\n if (phase) task.phase = phase;\n if (options.description) task.description = options.description;\n if (options.labels?.length) task.labels = options.labels.map(l => l.trim());\n if (options.files?.length) task.files = options.files.map(f => f.trim());\n if (options.acceptance?.length) task.acceptance = options.acceptance.map(a => a.trim());\n if (options.depends?.length) task.depends = options.depends.map(d => d.trim());\n if (options.notes) {\n const timestampedNote = `${new Date().toISOString().replace('T', ' ').replace(/\\.\\d+Z$/, ' UTC')}: ${options.notes}`;\n task.notes = [timestampedNote];\n }\n if (status === 'blocked' && options.description) {\n task.blockedBy = options.description;\n }\n if (status === 'done') {\n task.completedAt = now;\n }\n\n // Dry run\n if (options.dryRun) {\n return { task, dryRun: true };\n }\n\n // Position shuffling if explicit position was given\n if (options.position !== undefined) {\n for (const t of data.tasks) {\n const isInScope = parentId\n ? t.parentId === parentId\n : (!t.parentId || t.parentId === null);\n if (isInScope && t.position !== undefined && t.position !== null && t.position >= options.position) {\n await storeUpdateTask(t.id, {\n position: t.position + 1,\n positionVersion: (t.positionVersion ?? 0) + 1,\n }, cwd);\n }\n }\n }\n\n // Create task via task-store (handles safety, checkpoint)\n await storeCreateTask(task, cwd);\n\n return { task };\n}\n", "/**\n * Configuration engine for CLEO V2.\n *\n * Resolution priority: CLI flags > Environment vars > Project config > Global config > Defaults\n *\n * @epic T4454\n * @task T4458\n */\n\nimport type { CleoConfig, ConfigSource, ResolvedValue } from '../types/config.js';\nimport { readJson, saveJson } from '../store/json.js';\nimport { getConfigPath, getGlobalConfigPath } from './paths.js';\nimport { existsSync } from 'node:fs';\nimport { writeFile, mkdir } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\n/** Default configuration values. */\nconst DEFAULTS: CleoConfig = {\n version: '2.10.0',\n output: {\n defaultFormat: 'json',\n showColor: true,\n showUnicode: true,\n showProgressBars: true,\n dateFormat: 'relative',\n },\n backup: {\n maxOperationalBackups: 10,\n maxSafetyBackups: 5,\n compressionEnabled: false,\n },\n hierarchy: {\n maxDepth: 3,\n maxSiblings: 7,\n cascadeDelete: false,\n },\n session: {\n autoStart: false,\n requireNotes: false,\n multiSession: false,\n },\n lifecycle: {\n mode: 'strict',\n },\n};\n\n/** Environment variable to config path mapping. */\nconst ENV_MAP: Record<string, string> = {\n 'CLEO_FORMAT': 'output.defaultFormat',\n 'CLEO_OUTPUT_DEFAULT_FORMAT': 'output.defaultFormat',\n 'CLEO_OUTPUT_SHOW_COLOR': 'output.showColor',\n 'CLEO_OUTPUT_SHOW_UNICODE': 'output.showUnicode',\n 'CLEO_OUTPUT_SHOW_PROGRESS_BARS': 'output.showProgressBars',\n 'CLEO_OUTPUT_DATE_FORMAT': 'output.dateFormat',\n 'CLEO_HIERARCHY_MAX_DEPTH': 'hierarchy.maxDepth',\n 'CLEO_HIERARCHY_MAX_SIBLINGS': 'hierarchy.maxSiblings',\n 'CLEO_SESSION_AUTO_START': 'session.autoStart',\n 'CLEO_SESSION_REQUIRE_NOTES': 'session.requireNotes',\n 'CLEO_LIFECYCLE_MODE': 'lifecycle.mode',\n};\n\n/**\n * Get a value at a dotted path from an object.\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\n/**\n * Set a value at a dotted path in an object (mutates).\n */\nfunction setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n if (current[part] === undefined || typeof current[part] !== 'object') {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]!] = value;\n}\n\n/**\n * Deep merge two objects. Source values override target values.\n * Arrays are replaced (not merged).\n */\nfunction deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown> {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = result[key];\n if (\n sourceVal !== null &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n );\n } else {\n result[key] = sourceVal;\n }\n }\n return result;\n}\n\n/**\n * Parse an environment variable value to the appropriate type.\n */\nfunction parseEnvValue(value: string): unknown {\n if (value === 'true') return true;\n if (value === 'false') return false;\n const num = Number(value);\n if (!isNaN(num) && value.trim() !== '') return num;\n return value;\n}\n\n/**\n * Load and merge configuration from all sources.\n * Priority: defaults < global config < project config < environment vars\n */\nexport async function loadConfig(cwd?: string): Promise<CleoConfig> {\n // Start with defaults\n let merged: Record<string, unknown> = JSON.parse(JSON.stringify(DEFAULTS));\n\n // Layer 1: Global config\n const globalConfig = await readJson<Record<string, unknown>>(getGlobalConfigPath());\n if (globalConfig) {\n merged = deepMerge(merged, globalConfig);\n }\n\n // Layer 2: Project config\n const projectConfig = await readJson<Record<string, unknown>>(getConfigPath(cwd));\n if (projectConfig) {\n merged = deepMerge(merged, projectConfig);\n }\n\n // Layer 3: Environment variables\n for (const [envKey, configPath] of Object.entries(ENV_MAP)) {\n const envValue = process.env[envKey];\n if (envValue !== undefined) {\n setNestedValue(merged, configPath, parseEnvValue(envValue));\n }\n }\n\n return merged as unknown as CleoConfig;\n}\n\n/**\n * Get a single config value with source tracking.\n * Returns the value and which source it came from.\n */\nexport async function getConfigValue<T>(\n path: string,\n cwd?: string,\n): Promise<ResolvedValue<T>> {\n // Check environment variables first\n for (const [envKey, configPath] of Object.entries(ENV_MAP)) {\n if (configPath === path && process.env[envKey] !== undefined) {\n return {\n value: parseEnvValue(process.env[envKey]!) as T,\n source: 'env' as ConfigSource,\n };\n }\n }\n\n // Check project config\n const projectConfig = await readJson<Record<string, unknown>>(getConfigPath(cwd));\n if (projectConfig) {\n const val = getNestedValue(projectConfig, path);\n if (val !== undefined) {\n return { value: val as T, source: 'project' as ConfigSource };\n }\n }\n\n // Check global config\n const globalConfig = await readJson<Record<string, unknown>>(getGlobalConfigPath());\n if (globalConfig) {\n const val = getNestedValue(globalConfig, path);\n if (val !== undefined) {\n return { value: val as T, source: 'global' as ConfigSource };\n }\n }\n\n // Fall back to defaults\n const defaultVal = getNestedValue(DEFAULTS as unknown as Record<string, unknown>, path);\n return { value: defaultVal as T, source: 'default' as ConfigSource };\n}\n\n/**\n * Get a raw config value from the project config file only (no cascade).\n * Returns undefined if the key is not found.\n * Used by the engine layer for simple key lookups without source tracking.\n * @task T4789\n */\nexport async function getRawConfigValue(\n key: string,\n cwd?: string,\n): Promise<unknown> {\n const configPath = getConfigPath(cwd);\n const config = await readJson<Record<string, unknown>>(configPath);\n if (!config) return undefined;\n\n if (!key) return config;\n\n return getNestedValue(config, key);\n}\n\n/**\n * Get the full raw project config (no cascade).\n * Returns null if no config file exists.\n * @task T4789\n */\nexport async function getRawConfig(\n cwd?: string,\n): Promise<Record<string, unknown> | null> {\n return readJson<Record<string, unknown>>(getConfigPath(cwd));\n}\n\n/**\n * Parse a string value into its appropriate JS type.\n * Handles booleans, null, integers, floats, and JSON.\n * @task T4789\n */\nexport function parseConfigValue(value: unknown): unknown {\n if (typeof value !== 'string') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (/^-?\\d+$/.test(value)) return parseInt(value, 10);\n if (/^-?\\d+\\.\\d+$/.test(value)) return parseFloat(value);\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\n/**\n * Set a config value in the project or global config file (dot-notation supported).\n * Creates intermediate objects as needed. Parses string values into\n * appropriate types (boolean, number, null, JSON).\n * @task T4789\n * @task T4795\n */\nexport async function setConfigValue(\n key: string,\n value: unknown,\n cwd?: string,\n opts?: { global?: boolean },\n): Promise<{ key: string; value: unknown; scope: 'project' | 'global' }> {\n const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);\n\n // Ensure file exists\n if (!existsSync(configPath)) {\n const dir = dirname(configPath);\n await mkdir(dir, { recursive: true });\n await writeFile(configPath, '{}', 'utf-8');\n }\n\n const config = (await readJson<Record<string, unknown>>(configPath)) ?? {};\n\n const parsedValue = parseConfigValue(value);\n\n setNestedValue(config, key, parsedValue);\n\n await saveJson(configPath, config);\n\n return { key, value: parsedValue, scope: opts?.global ? 'global' : 'project' };\n}\n", "/**\n * Task update logic.\n * @task T4461\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TaskStatus, TaskPriority, TaskType, TaskSize, TaskFile } from '../../types/task.js';\nimport { getTaskPath } from '../paths.js';\nimport {\n validateStatus,\n normalizePriority,\n validateTaskType,\n validateSize,\n validateLabels,\n validateTitle,\n} from './add.js';\nimport { reparentTask } from './reparent.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\nimport { updateTask as storeUpdateTask } from '../../store/task-store.js';\n\n/** Options for updating a task. */\nexport interface UpdateTaskOptions {\n taskId: string;\n title?: string;\n status?: TaskStatus;\n priority?: TaskPriority;\n type?: TaskType;\n size?: TaskSize;\n phase?: string;\n description?: string;\n labels?: string[];\n addLabels?: string[];\n removeLabels?: string[];\n depends?: string[];\n addDepends?: string[];\n removeDepends?: string[];\n notes?: string;\n acceptance?: string[];\n files?: string[];\n blockedBy?: string;\n parentId?: string | null;\n noAutoComplete?: boolean;\n}\n\n/** Result of updating a task. */\nexport interface UpdateTaskResult {\n task: Task;\n changes: string[];\n}\n\n/**\n * Update a task's fields.\n * @task T4461\n */\nexport async function updateTask(options: UpdateTaskOptions, cwd?: string, accessor?: DataAccessor): Promise<UpdateTaskResult> {\n const todoPath = getTaskPath(cwd);\n\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(todoPath);\n\n const taskIdx = data.tasks.findIndex(t => t.id === options.taskId);\n if (taskIdx === -1) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Task not found: ${options.taskId}`,\n { fix: `Use 'cleo find \"${options.taskId}\"' to search` },\n );\n }\n\n const task = data.tasks[taskIdx]!;\n const changes: string[] = [];\n const now = new Date().toISOString();\n\n // Update fields\n if (options.title !== undefined) {\n validateTitle(options.title);\n task.title = options.title;\n changes.push('title');\n }\n\n if (options.status !== undefined) {\n validateStatus(options.status);\n const oldStatus = task.status;\n task.status = options.status;\n changes.push('status');\n if (options.status === 'done' && oldStatus !== 'done') {\n task.completedAt = now;\n }\n if (options.status === 'cancelled' && oldStatus !== 'cancelled') {\n task.cancelledAt = now;\n }\n }\n\n if (options.priority !== undefined) {\n const normalizedPriority = normalizePriority(options.priority);\n task.priority = normalizedPriority;\n changes.push('priority');\n }\n\n if (options.type !== undefined) {\n validateTaskType(options.type);\n task.type = options.type;\n changes.push('type');\n }\n\n if (options.size !== undefined) {\n validateSize(options.size);\n task.size = options.size;\n changes.push('size');\n }\n\n if (options.phase !== undefined) {\n task.phase = options.phase;\n changes.push('phase');\n }\n\n if (options.description !== undefined) {\n task.description = options.description;\n changes.push('description');\n }\n\n if (options.labels !== undefined) {\n if (options.labels.length) validateLabels(options.labels);\n task.labels = options.labels;\n changes.push('labels');\n }\n\n if (options.addLabels?.length) {\n validateLabels(options.addLabels);\n const existing = new Set(task.labels ?? []);\n for (const l of options.addLabels) existing.add(l.trim());\n task.labels = [...existing];\n changes.push('labels');\n }\n\n if (options.removeLabels?.length) {\n const toRemove = new Set(options.removeLabels.map(l => l.trim()));\n task.labels = (task.labels ?? []).filter(l => !toRemove.has(l));\n changes.push('labels');\n }\n\n if (options.depends !== undefined) {\n task.depends = options.depends;\n changes.push('depends');\n }\n\n if (options.addDepends?.length) {\n const existing = new Set(task.depends ?? []);\n for (const d of options.addDepends) existing.add(d.trim());\n task.depends = [...existing];\n changes.push('depends');\n }\n\n if (options.removeDepends?.length) {\n const toRemove = new Set(options.removeDepends.map(d => d.trim()));\n task.depends = (task.depends ?? []).filter(d => !toRemove.has(d));\n changes.push('depends');\n }\n\n if (options.notes !== undefined) {\n const timestampedNote = `${new Date().toISOString().replace('T', ' ').replace(/\\.\\d+Z$/, ' UTC')}: ${options.notes}`;\n if (!task.notes) task.notes = [];\n task.notes.push(timestampedNote);\n changes.push('notes');\n }\n\n if (options.acceptance !== undefined) {\n task.acceptance = options.acceptance;\n changes.push('acceptance');\n }\n\n if (options.files !== undefined) {\n task.files = options.files;\n changes.push('files');\n }\n\n if (options.blockedBy !== undefined) {\n task.blockedBy = options.blockedBy;\n changes.push('blockedBy');\n }\n\n if (options.noAutoComplete !== undefined) {\n task.noAutoComplete = options.noAutoComplete;\n changes.push('noAutoComplete');\n }\n\n // Handle parentId change (reparent)\n // Supports: parentId=\"T001\" to set parent, parentId=null or parentId=\"\" to promote to root\n if (options.parentId !== undefined) {\n const newParentId = options.parentId || null; // normalize \"\" to null\n const currentParentId = task.parentId ?? null;\n\n if (newParentId !== currentParentId) {\n const result = await reparentTask(data, {\n taskId: options.taskId,\n newParentId,\n });\n // reparentTask mutates the task in-place and updates data._meta/lastUpdated\n // so we just need to track the change\n changes.push('parentId');\n if (result.newType !== (options.type ?? task.type)) {\n changes.push('type');\n }\n }\n }\n\n if (changes.length === 0) {\n throw new CleoError(ExitCode.NO_CHANGE, 'No changes specified');\n }\n\n // Build the updates object for task-store (only changed fields)\n const storeUpdates: Partial<Task> = {};\n if (changes.includes('title')) storeUpdates.title = task.title;\n if (changes.includes('status')) {\n storeUpdates.status = task.status;\n if (task.completedAt) storeUpdates.completedAt = task.completedAt;\n if (task.cancelledAt) storeUpdates.cancelledAt = task.cancelledAt;\n }\n if (changes.includes('priority')) storeUpdates.priority = task.priority;\n if (changes.includes('type')) storeUpdates.type = task.type;\n if (changes.includes('size')) storeUpdates.size = task.size;\n if (changes.includes('phase')) storeUpdates.phase = task.phase;\n if (changes.includes('description')) storeUpdates.description = task.description;\n if (changes.includes('labels')) storeUpdates.labels = task.labels;\n if (changes.includes('depends')) storeUpdates.depends = task.depends;\n if (changes.includes('notes')) storeUpdates.notes = task.notes;\n if (changes.includes('acceptance')) storeUpdates.acceptance = task.acceptance;\n if (changes.includes('files')) storeUpdates.files = task.files;\n if (changes.includes('blockedBy')) storeUpdates.blockedBy = task.blockedBy;\n if (changes.includes('noAutoComplete')) storeUpdates.noAutoComplete = task.noAutoComplete;\n if (changes.includes('parentId')) storeUpdates.parentId = task.parentId;\n\n // Write via task-store (handles safety, checkpoint)\n await storeUpdateTask(options.taskId, storeUpdates, cwd);\n\n task.updatedAt = now;\n return { task, changes };\n}\n", "/**\n * Canonical reparent logic \u2014 move a task to a different parent in the hierarchy.\n * Both CLI (reparent command) and core (updateTask) delegate here.\n *\n * This module operates on an in-memory TaskFile. The caller is responsible\n * for loading and saving the data (via DataAccessor or direct JSON I/O).\n *\n * @task T4807\n * @epic T4454\n */\n\nimport type { TaskFile } from '../../types/task.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport {\n validateHierarchy,\n wouldCreateCircle,\n getDepth,\n} from './hierarchy.js';\n\n/** Options for reparenting a task. */\nexport interface ReparentOptions {\n taskId: string;\n /** New parent ID, or null to promote to root. */\n newParentId: string | null;\n}\n\n/** @deprecated Use ReparentOptions */\nexport type ReparentTaskOptions = ReparentOptions;\n\n/** Result of a reparent operation. */\nexport interface ReparentResult {\n oldParent: string | null;\n newParent: string | null;\n newType: string;\n}\n\n/** @deprecated Use ReparentResult */\nexport type ReparentTaskResult = ReparentResult;\n\n/**\n * Reparent a task within a TaskFile.\n *\n * Mutates the task in-place within `data.tasks`. Updates `parentId`, `type`,\n * and `updatedAt` on the target task, and `lastUpdated` on the TaskFile.\n *\n * @param data The loaded TaskFile (mutated in place)\n * @param opts Reparent options (taskId, newParentId)\n * @returns Result with old/new parent and new type\n */\nexport async function reparentTask(\n data: TaskFile,\n opts: ReparentOptions,\n): Promise<ReparentResult> {\n const { taskId, newParentId } = opts;\n\n const task = data.tasks.find((t) => t.id === taskId);\n if (!task) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Task not found: ${taskId}`,\n { fix: `Use 'cleo find \"${taskId}\"' to search` },\n );\n }\n\n const oldParent = task.parentId ?? null;\n const effectiveNewParent = newParentId || null;\n\n // Promote to root\n if (!effectiveNewParent) {\n task.parentId = null;\n if (task.type === 'subtask') {\n task.type = 'task';\n }\n task.updatedAt = new Date().toISOString();\n data.lastUpdated = new Date().toISOString();\n\n return {\n oldParent,\n newParent: null,\n newType: task.type ?? 'task',\n };\n }\n\n // Validate target parent exists and hierarchy constraints (depth + sibling limits)\n const validation = validateHierarchy(effectiveNewParent, data.tasks);\n if (!validation.valid) {\n const code = validation.error?.code === 'E_PARENT_NOT_FOUND'\n ? ExitCode.PARENT_NOT_FOUND\n : validation.error?.code === 'E_DEPTH_EXCEEDED'\n ? ExitCode.DEPTH_EXCEEDED\n : validation.error?.code === 'E_SIBLING_LIMIT'\n ? ExitCode.SIBLING_LIMIT\n : ExitCode.INVALID_INPUT;\n\n throw new CleoError(\n code,\n validation.error?.message ?? `Cannot reparent under ${effectiveNewParent}`,\n { fix: `Check hierarchy constraints with 'cleo show ${effectiveNewParent}'` },\n );\n }\n\n const newParentTask = data.tasks.find((t) => t.id === effectiveNewParent);\n\n // Cannot parent under a subtask\n if (newParentTask?.type === 'subtask') {\n throw new CleoError(\n ExitCode.INVALID_PARENT_TYPE,\n `Cannot parent under subtask '${effectiveNewParent}'`,\n { fix: `Choose a task or epic as the parent instead` },\n );\n }\n\n // Check circular reference\n if (wouldCreateCircle(taskId, effectiveNewParent, data.tasks)) {\n throw new CleoError(\n ExitCode.CIRCULAR_REFERENCE,\n `Moving '${taskId}' under '${effectiveNewParent}' would create a circular reference`,\n { fix: `The target parent is a descendant of the task being moved` },\n );\n }\n\n // Apply the reparent\n task.parentId = effectiveNewParent;\n\n // Update type based on new depth in the hierarchy\n const newDepth = getDepth(taskId, data.tasks);\n if (newDepth === 1) {\n task.type = 'task';\n } else if (newDepth >= 2) {\n task.type = 'subtask';\n }\n\n task.updatedAt = new Date().toISOString();\n data.lastUpdated = new Date().toISOString();\n\n return {\n oldParent,\n newParent: effectiveNewParent,\n newType: task.type ?? 'task',\n };\n}\n", "/**\n * Task hierarchy operations - parent/child tree traversal and validation.\n * Ported from lib/tasks/hierarchy.sh\n *\n * @epic T4454\n * @task T4529\n */\n\nimport type { Task } from '../../types/task.js';\n\n/** Maximum nesting depth (epic -> task -> subtask). */\nconst MAX_DEPTH = 3;\n\n/** Maximum siblings per parent. */\nconst MAX_SIBLINGS = 7;\n\n/**\n * Get direct children of a task.\n */\nexport function getChildren(taskId: string, tasks: Task[]): Task[] {\n return tasks.filter((t) => t.parentId === taskId);\n}\n\n/**\n * Get direct child IDs.\n */\nexport function getChildIds(taskId: string, tasks: Task[]): string[] {\n return getChildren(taskId, tasks).map((t) => t.id);\n}\n\n/**\n * Get all descendants of a task (recursive).\n */\nexport function getDescendants(taskId: string, tasks: Task[]): Task[] {\n const result: Task[] = [];\n const queue = [taskId];\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const children = getChildren(current, tasks);\n for (const child of children) {\n result.push(child);\n queue.push(child.id);\n }\n }\n\n return result;\n}\n\n/**\n * Get all descendant IDs (flat list).\n */\nexport function getDescendantIds(taskId: string, tasks: Task[]): string[] {\n return getDescendants(taskId, tasks).map((t) => t.id);\n}\n\n/**\n * Get the parent chain (ancestors) from a task up to the root.\n * Returns ordered from immediate parent to root.\n */\nexport function getParentChain(taskId: string, tasks: Task[]): Task[] {\n const chain: Task[] = [];\n const taskMap = new Map(tasks.map((t) => [t.id, t]));\n let current = taskMap.get(taskId);\n const visited = new Set<string>();\n\n while (current?.parentId) {\n if (visited.has(current.parentId)) break; // circular reference guard\n visited.add(current.parentId);\n const parent = taskMap.get(current.parentId);\n if (!parent) break;\n chain.push(parent);\n current = parent;\n }\n\n return chain;\n}\n\n/**\n * Get the parent chain as IDs.\n */\nexport function getParentChainIds(taskId: string, tasks: Task[]): string[] {\n return getParentChain(taskId, tasks).map((t) => t.id);\n}\n\n/**\n * Calculate depth of a task in the hierarchy (0-based).\n * Root tasks have depth 0, their children depth 1, etc.\n */\nexport function getDepth(taskId: string, tasks: Task[]): number {\n return getParentChain(taskId, tasks).length;\n}\n\n/**\n * Get the root ancestor of a task.\n */\nexport function getRootAncestor(taskId: string, tasks: Task[]): Task | null {\n const chain = getParentChain(taskId, tasks);\n return chain.length > 0 ? chain[chain.length - 1] : null;\n}\n\n/**\n * Check if a task is an ancestor of another.\n */\nexport function isAncestorOf(\n ancestorId: string,\n descendantId: string,\n tasks: Task[],\n): boolean {\n const chain = getParentChainIds(descendantId, tasks);\n return chain.includes(ancestorId);\n}\n\n/**\n * Check if a task is a descendant of another.\n */\nexport function isDescendantOf(\n descendantId: string,\n ancestorId: string,\n tasks: Task[],\n): boolean {\n return isAncestorOf(ancestorId, descendantId, tasks);\n}\n\n/**\n * Get sibling tasks (same parent).\n */\nexport function getSiblings(taskId: string, tasks: Task[]): Task[] {\n const task = tasks.find((t) => t.id === taskId);\n if (!task) return [];\n\n if (task.parentId) {\n return tasks.filter((t) => t.parentId === task.parentId && t.id !== taskId);\n }\n // Root-level siblings: tasks with no parent, excluding self\n return tasks.filter((t) => !t.parentId && t.id !== taskId);\n}\n\n/**\n * Validate that adding a child to a parent would not violate constraints.\n */\nexport interface HierarchyValidation {\n valid: boolean;\n error?: {\n code: string;\n message: string;\n };\n}\n\nexport function validateHierarchy(\n parentId: string | null,\n tasks: Task[],\n): HierarchyValidation {\n if (!parentId) {\n return { valid: true };\n }\n\n const parent = tasks.find((t) => t.id === parentId);\n if (!parent) {\n return {\n valid: false,\n error: { code: 'E_PARENT_NOT_FOUND', message: `Parent task ${parentId} not found` },\n };\n }\n\n // Check depth\n const parentDepth = getDepth(parentId, tasks);\n if (parentDepth + 1 >= MAX_DEPTH) {\n return {\n valid: false,\n error: {\n code: 'E_DEPTH_EXCEEDED',\n message: `Maximum nesting depth ${MAX_DEPTH} would be exceeded`,\n },\n };\n }\n\n // Check sibling limit\n const existingChildren = getChildren(parentId, tasks);\n if (existingChildren.length >= MAX_SIBLINGS) {\n return {\n valid: false,\n error: {\n code: 'E_SIBLING_LIMIT',\n message: `Parent ${parentId} already has ${MAX_SIBLINGS} children (max)`,\n },\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Detect circular reference if parentId were set.\n */\nexport function wouldCreateCircle(\n taskId: string,\n newParentId: string,\n tasks: Task[],\n): boolean {\n if (taskId === newParentId) return true;\n const descendants = getDescendantIds(taskId, tasks);\n return descendants.includes(newParentId);\n}\n\n/**\n * Build a tree structure from flat task list.\n */\nexport interface TaskTreeNode {\n task: Task;\n children: TaskTreeNode[];\n}\n\nexport function buildTree(tasks: Task[]): TaskTreeNode[] {\n const childrenMap = new Map<string | null, Task[]>();\n\n for (const task of tasks) {\n const parentKey = task.parentId ?? null;\n if (!childrenMap.has(parentKey)) {\n childrenMap.set(parentKey, []);\n }\n childrenMap.get(parentKey)!.push(task);\n }\n\n function buildNode(task: Task): TaskTreeNode {\n const children = (childrenMap.get(task.id) ?? []).map(buildNode);\n return { task, children };\n }\n\n const roots = childrenMap.get(null) ?? [];\n return roots.map(buildNode);\n}\n\n/**\n * Flatten a tree back to a list (depth-first).\n */\nexport function flattenTree(nodes: TaskTreeNode[]): Task[] {\n const result: Task[] = [];\n for (const node of nodes) {\n result.push(node.task);\n result.push(...flattenTree(node.children));\n }\n return result;\n}\n", "/**\n * Task deletion (soft delete to archive).\n * @task T4461\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TaskFile } from '../../types/task.js';\nimport { getTaskPath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\nimport {\n archiveTask as storeArchiveTask,\n updateTask as storeUpdateTask,\n} from '../../store/task-store.js';\n\n/** Options for deleting a task. */\nexport interface DeleteTaskOptions {\n taskId: string;\n force?: boolean;\n cascade?: boolean;\n}\n\n/** Result of deleting a task. */\nexport interface DeleteTaskResult {\n deletedTask: Task;\n cascadeDeleted?: string[];\n}\n\n/**\n * Delete a task (soft delete - moves to archive).\n * @task T4461\n */\nexport async function deleteTask(options: DeleteTaskOptions, cwd?: string, accessor?: DataAccessor): Promise<DeleteTaskResult> {\n const todoPath = getTaskPath(cwd);\n\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(todoPath);\n\n const taskIdx = data.tasks.findIndex(t => t.id === options.taskId);\n if (taskIdx === -1) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Task not found: ${options.taskId}`,\n { fix: `Use 'cleo find \"${options.taskId}\"' to search` },\n );\n }\n\n const task = data.tasks[taskIdx]!;\n const cascadeDeleted: string[] = [];\n\n // Check for children\n const children = data.tasks.filter(t => t.parentId === options.taskId);\n if (children.length > 0) {\n if (!options.cascade && !options.force) {\n throw new CleoError(\n ExitCode.HAS_CHILDREN,\n `Task ${options.taskId} has ${children.length} children. Use --cascade to delete children or --force to orphan them.`,\n {\n alternatives: [\n { action: 'Delete with children', command: `cleo delete ${options.taskId} --cascade` },\n { action: 'Force delete (orphan children)', command: `cleo delete ${options.taskId} --force` },\n ],\n },\n );\n }\n\n if (options.cascade) {\n // Recursively find all descendants\n const toDelete = new Set<string>([options.taskId]);\n const findDescendants = (parentId: string) => {\n for (const t of data.tasks) {\n if (t.parentId === parentId && !toDelete.has(t.id)) {\n toDelete.add(t.id);\n cascadeDeleted.push(t.id);\n findDescendants(t.id);\n }\n }\n };\n findDescendants(options.taskId);\n } else if (options.force) {\n // Orphan children by clearing their parentId via task-store\n for (const child of children) {\n await storeUpdateTask(child.id, { parentId: null, type: 'task' }, cwd);\n }\n }\n }\n\n // Check for dependents (other tasks depending on this one)\n if (!options.force) {\n const dependents = data.tasks.filter(t =>\n t.depends?.includes(options.taskId) && t.id !== options.taskId,\n );\n if (dependents.length > 0) {\n throw new CleoError(\n ExitCode.HAS_DEPENDENTS,\n `Task ${options.taskId} is a dependency of: ${dependents.map(d => d.id).join(', ')}`,\n { fix: `Use --force to delete anyway or remove the dependency first` },\n );\n }\n }\n\n // Archive the task and cascade-deleted tasks via task-store\n // (archiveTask sets status='archived' in SQLite with safety)\n const idsToArchive = [options.taskId, ...cascadeDeleted];\n for (const id of idsToArchive) {\n await storeArchiveTask(id, 'deleted', cwd);\n }\n\n // Clean up dependency references in remaining tasks\n const idsToDelete = new Set(idsToArchive);\n for (const t of data.tasks) {\n if (idsToDelete.has(t.id)) continue;\n if (t.depends?.some(d => idsToDelete.has(d))) {\n const cleaned = t.depends.filter(d => !idsToDelete.has(d));\n await storeUpdateTask(t.id, { depends: cleaned.length > 0 ? cleaned : [] }, cwd);\n }\n }\n\n return {\n deletedTask: task,\n ...(cascadeDeleted.length > 0 && { cascadeDeleted }),\n };\n}\n", "/**\n * Batch archive completed tasks.\n * @task T4461\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport type { Task, TaskFile } from '../../types/task.js';\nimport { getTaskPath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\nimport { archiveTask as storeArchiveTask } from '../../store/task-store.js';\n\n/** Options for archiving tasks. */\nexport interface ArchiveTasksOptions {\n /** Only archive tasks completed before this date (ISO string). */\n before?: string;\n /** Specific task IDs to archive. */\n taskIds?: string[];\n /** Archive cancelled tasks too. Default: true. */\n includeCancelled?: boolean;\n /** Dry run mode. */\n dryRun?: boolean;\n}\n\n/** Result of archiving tasks. */\nexport interface ArchiveTasksResult {\n archived: string[];\n skipped: string[];\n total: number;\n dryRun?: boolean;\n}\n\n/**\n * Archive completed (and optionally cancelled) tasks.\n * Moves them from todo.json to todo-archive.json.\n * @task T4461\n */\nexport async function archiveTasks(options: ArchiveTasksOptions = {}, cwd?: string, accessor?: DataAccessor): Promise<ArchiveTasksResult> {\n const todoPath = getTaskPath(cwd);\n\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(todoPath);\n const includeCancelled = options.includeCancelled ?? true;\n\n // Determine which tasks to archive\n let candidates: Task[];\n\n if (options.taskIds?.length) {\n candidates = data.tasks.filter(t => options.taskIds!.includes(t.id));\n } else {\n candidates = data.tasks.filter(t => {\n if (t.status === 'done') return true;\n if (includeCancelled && t.status === 'cancelled') return true;\n return false;\n });\n }\n\n // Apply date filter\n if (options.before) {\n const beforeDate = new Date(options.before).getTime();\n candidates = candidates.filter(t => {\n const completedAt = t.completedAt ?? t.cancelledAt ?? t.updatedAt;\n if (!completedAt) return false;\n return new Date(completedAt).getTime() < beforeDate;\n });\n }\n\n // Check for tasks that can't be archived\n const archived: string[] = [];\n const skipped: string[] = [];\n\n for (const task of candidates) {\n // Skip tasks that aren't done/cancelled\n if (task.status !== 'done' && task.status !== 'cancelled') {\n skipped.push(task.id);\n continue;\n }\n\n // Skip epics that have non-archived children\n if (task.type === 'epic') {\n const activeChildren = data.tasks.filter(\n t => t.parentId === task.id && t.status !== 'done' && t.status !== 'cancelled',\n );\n if (activeChildren.length > 0) {\n skipped.push(task.id);\n continue;\n }\n }\n\n archived.push(task.id);\n }\n\n if (options.dryRun) {\n return {\n archived,\n skipped,\n total: data.tasks.length,\n dryRun: true,\n };\n }\n\n if (archived.length === 0) {\n return { archived: [], skipped, total: data.tasks.length };\n }\n\n // Archive each task via task-store (sets status='archived' in SQLite with safety)\n for (const id of archived) {\n await storeArchiveTask(id, 'completed', cwd);\n }\n\n return { archived, skipped, total: data.tasks.length };\n}\n", "/**\n * Show full task details by ID.\n * @task T4460\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TaskFile } from '../../types/task.js';\nimport { getTaskPath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Enriched task with hierarchy info. */\nexport interface TaskDetail extends Task {\n children?: string[];\n dependencyStatus?: Array<{ id: string; status: string; title: string }>;\n hierarchyPath?: string[];\n isArchived?: boolean;\n}\n\n/**\n * Get a task by ID with enriched details.\n * Checks active tasks first, then archive if not found.\n * @task T4460\n */\nexport async function showTask(taskId: string, cwd?: string, accessor?: DataAccessor): Promise<TaskDetail> {\n if (!taskId) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Task ID is required');\n }\n\n const taskPath = getTaskPath(cwd);\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(taskPath);\n\n // First, try to find in active tasks\n let task = data.tasks.find(t => t.id === taskId);\n let isArchived = false;\n\n // If not found in active tasks, check the archive\n if (!task && accessor) {\n const archive = await accessor.loadArchive();\n if (archive) {\n task = archive.archivedTasks.find(t => t.id === taskId);\n if (task) {\n isArchived = true;\n }\n }\n }\n\n if (!task) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Task not found: ${taskId}`,\n {\n fix: `Use 'cleo find \"${taskId}\"' to search for similar IDs`,\n alternatives: [\n { action: 'Search for task', command: `cleo find \"${taskId}\"` },\n { action: 'List all tasks', command: 'cleo list' },\n ],\n },\n );\n }\n\n const detail: TaskDetail = { ...task, isArchived };\n\n // Add children (only check active tasks, archived tasks don't have active children)\n if (!isArchived) {\n const children = data.tasks.filter(t => t.parentId === taskId);\n if (children.length > 0) {\n detail.children = children.map(c => c.id);\n }\n\n // Add dependency status\n if (task.depends?.length) {\n detail.dependencyStatus = task.depends.map(depId => {\n const dep = data.tasks.find(t => t.id === depId);\n return {\n id: depId,\n status: dep?.status ?? 'unknown',\n title: dep?.title ?? 'Unknown task',\n };\n });\n }\n\n // Build hierarchy path\n const path: string[] = [taskId];\n let currentId: string | null | undefined = task.parentId;\n const visited = new Set<string>();\n while (currentId && !visited.has(currentId)) {\n visited.add(currentId);\n path.unshift(currentId);\n const parent = data.tasks.find(t => t.id === currentId);\n currentId = parent?.parentId;\n }\n if (path.length > 1) {\n detail.hierarchyPath = path;\n }\n }\n\n return detail;\n}\n", "/**\n * Task listing with filters.\n * @task T4460\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport type { Task, TaskStatus, TaskPriority, TaskType, TodoFile } from '../../types/task.js';\nimport { getTodoPath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Filter options for listing tasks. */\nexport interface ListTasksOptions {\n status?: TaskStatus;\n priority?: TaskPriority;\n type?: TaskType;\n parentId?: string;\n phase?: string;\n label?: string;\n children?: boolean;\n limit?: number;\n offset?: number;\n}\n\n/** Result of listing tasks. */\nexport interface ListTasksResult {\n tasks: Task[];\n total: number;\n filtered: number;\n pagination?: {\n limit: number;\n offset: number;\n hasMore: boolean;\n };\n}\n\n/**\n * List tasks with optional filtering and pagination.\n * @task T4460\n */\nexport async function listTasks(options: ListTasksOptions = {}, cwd?: string, accessor?: DataAccessor): Promise<ListTasksResult> {\n const todoPath = getTodoPath(cwd);\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(todoPath);\n\n let filtered = data.tasks;\n\n // Apply filters\n if (options.status) {\n filtered = filtered.filter(t => t.status === options.status);\n }\n\n if (options.priority) {\n filtered = filtered.filter(t => t.priority === options.priority);\n }\n\n if (options.type) {\n filtered = filtered.filter(t => t.type === options.type);\n }\n\n if (options.parentId) {\n if (options.children) {\n // Show direct children of the parent\n filtered = filtered.filter(t => t.parentId === options.parentId);\n } else {\n filtered = filtered.filter(t => t.parentId === options.parentId);\n }\n }\n\n if (options.phase) {\n filtered = filtered.filter(t => t.phase === options.phase);\n }\n\n if (options.label) {\n filtered = filtered.filter(t => t.labels?.includes(options.label!));\n }\n\n const total = data.tasks.length;\n const filteredCount = filtered.length;\n\n // Sort by position within parent groups\n filtered.sort((a, b) => (a.position ?? 0) - (b.position ?? 0));\n\n // Apply pagination\n const limit = options.limit ?? 0;\n const offset = options.offset ?? 0;\n\n if (limit > 0) {\n const paginated = filtered.slice(offset, offset + limit);\n return {\n tasks: paginated,\n total,\n filtered: filteredCount,\n pagination: {\n limit,\n offset,\n hasMore: offset + limit < filteredCount,\n },\n };\n }\n\n if (offset > 0) {\n filtered = filtered.slice(offset);\n }\n\n return {\n tasks: filtered,\n total,\n filtered: filteredCount,\n };\n}\n", "/**\n * Fuzzy task search with minimal output.\n * @task T4460\n * @epic T4454\n */\n\nimport { readJsonRequired, readJson } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TaskStatus, TodoFile } from '../../types/task.js';\nimport { getTodoPath, getArchivePath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Minimal task info for search results. */\nexport interface FindResult {\n id: string;\n title: string;\n status: string;\n priority: string;\n type?: string;\n parentId?: string | null;\n score: number;\n}\n\n/** Options for finding tasks. */\nexport interface FindTasksOptions {\n query?: string;\n id?: string;\n exact?: boolean;\n status?: TaskStatus;\n field?: string;\n includeArchive?: boolean;\n limit?: number;\n offset?: number;\n}\n\n/** Result of finding tasks. */\nexport interface FindTasksResult {\n results: FindResult[];\n total: number;\n query: string;\n searchType: 'fuzzy' | 'id' | 'exact';\n}\n\n/**\n * Calculate fuzzy match score between query and text.\n * Higher score = better match. 0 = no match.\n * @task T4460\n */\nexport function fuzzyScore(query: string, text: string): number {\n const q = query.toLowerCase();\n const t = text.toLowerCase();\n\n // Exact match\n if (t === q) return 100;\n\n // Contains full query\n if (t.includes(q)) return 80;\n\n // Word-boundary match\n const words = t.split(/\\s+/);\n const queryWords = q.split(/\\s+/);\n let wordMatchCount = 0;\n for (const qw of queryWords) {\n if (words.some(w => w.startsWith(qw) || w.includes(qw))) {\n wordMatchCount++;\n }\n }\n if (wordMatchCount > 0) {\n return 40 + (wordMatchCount / queryWords.length) * 40;\n }\n\n // Character sequence match\n let qIdx = 0;\n let matched = 0;\n for (let tIdx = 0; tIdx < t.length && qIdx < q.length; tIdx++) {\n if (t[tIdx] === q[qIdx]) {\n matched++;\n qIdx++;\n }\n }\n if (qIdx === q.length) {\n return 10 + (matched / t.length) * 20;\n }\n\n return 0;\n}\n\n/**\n * Search tasks by fuzzy matching, ID prefix, or exact title.\n * Returns minimal fields only (context-efficient).\n * @task T4460\n */\nexport async function findTasks(options: FindTasksOptions, cwd?: string, accessor?: DataAccessor): Promise<FindTasksResult> {\n if (!options.query && !options.id) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Search query or --id is required');\n }\n\n const todoPath = getTodoPath(cwd);\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(todoPath);\n\n let allTasks: Task[] = [...data.tasks];\n\n // Include archive if requested\n if (options.includeArchive) {\n if (accessor) {\n const archive = await accessor.loadArchive();\n if (archive?.archivedTasks) {\n allTasks = [...allTasks, ...archive.archivedTasks];\n }\n } else {\n const archivePath = getArchivePath(cwd);\n const archive = await readJson<{ archivedTasks: Task[] }>(archivePath);\n if (archive?.archivedTasks) {\n allTasks = [...allTasks, ...archive.archivedTasks];\n }\n }\n }\n\n // Apply status filter\n if (options.status) {\n allTasks = allTasks.filter(t => t.status === options.status);\n }\n\n let results: FindResult[];\n let searchType: FindTasksResult['searchType'];\n let queryStr: string;\n\n if (options.id) {\n // ID prefix search\n searchType = 'id';\n queryStr = options.id;\n const idQuery = options.id.toUpperCase();\n results = allTasks\n .filter(t => t.id.toUpperCase().startsWith(idQuery) || t.id.toUpperCase().includes(idQuery))\n .map(t => ({\n id: t.id,\n title: t.title,\n status: t.status,\n priority: t.priority,\n type: t.type,\n parentId: t.parentId,\n score: t.id.toUpperCase() === idQuery ? 100 : t.id.toUpperCase().startsWith(idQuery) ? 80 : 50,\n }));\n } else if (options.exact) {\n // Exact title match\n searchType = 'exact';\n queryStr = options.query!;\n results = allTasks\n .filter(t => t.title === options.query)\n .map(t => ({\n id: t.id,\n title: t.title,\n status: t.status,\n priority: t.priority,\n type: t.type,\n parentId: t.parentId,\n score: 100,\n }));\n } else {\n // Fuzzy search\n searchType = 'fuzzy';\n queryStr = options.query!;\n const scored: FindResult[] = [];\n\n for (const t of allTasks) {\n const titleScore = fuzzyScore(queryStr, t.title);\n const descScore = t.description ? fuzzyScore(queryStr, t.description) * 0.7 : 0;\n const score = Math.max(titleScore, descScore);\n\n if (score > 0) {\n scored.push({\n id: t.id,\n title: t.title,\n status: t.status,\n priority: t.priority,\n type: t.type,\n parentId: t.parentId,\n score: Math.round(score),\n });\n }\n }\n\n results = scored.sort((a, b) => b.score - a.score);\n }\n\n const total = results.length;\n\n // Apply pagination\n const limit = options.limit ?? 20;\n const offset = options.offset ?? 0;\n results = results.slice(offset, offset + limit);\n\n return {\n results,\n total,\n query: queryStr,\n searchType,\n };\n}\n", "/**\n * Core task non-CRUD operations - business logic extracted from task-engine.ts.\n *\n * These are pure business logic functions that throw on failure and return\n * data directly (no EngineResult wrapper). The engine layer wraps these\n * in try/catch to produce EngineResult.\n *\n * Covers: next, blockers, tree, deps, relates, relatesAdd, analyze, restore,\n * unarchive, reorder, reparent, promote, reopen, complexityEstimate, depends,\n * stats, export, history, lint, batchValidate, import\n *\n * @task T4790\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { readJsonFile as storeReadJsonFile, readLogFileEntries, getDataPath } from '../../mcp/engine/store.js';\n\n// ============================================================================\n// Types (shared)\n// ============================================================================\n\n/** Task record shape expected from the data layer. */\ninterface TaskRecord {\n id: string;\n title: string;\n description: string;\n status: string;\n priority: string;\n type?: string;\n phase?: string;\n createdAt: string;\n updatedAt: string | null;\n completedAt?: string | null;\n cancelledAt?: string | null;\n cancellationReason?: string;\n parentId?: string | null;\n position?: number | null;\n positionVersion?: number;\n depends?: string[];\n relates?: Array<{ taskId: string; type: string; reason?: string }>;\n files?: string[];\n acceptance?: string[];\n notes?: string[];\n labels?: string[];\n size?: string | null;\n [key: string]: unknown;\n}\n\n/** Tree node representation for task hierarchy. */\nexport interface TaskTreeNode {\n id: string;\n title: string;\n status: string;\n type?: string;\n children: TaskTreeNode[];\n}\n\n/** Complexity factor. */\nexport interface ComplexityFactor {\n name: string;\n value: number;\n detail: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst PRIORITY_SCORE: Record<string, number> = {\n critical: 100,\n high: 75,\n medium: 50,\n low: 25,\n};\n\nasync function loadAllTasks(projectRoot: string): Promise<TaskRecord[]> {\n const accessor = await getAccessor(projectRoot);\n const data = await accessor.loadTodoFile();\n return data.tasks as unknown as TaskRecord[];\n}\n\nfunction depsReady(task: TaskRecord, taskMap: Map<string, TaskRecord>): boolean {\n if (!task.depends || task.depends.length === 0) return true;\n return task.depends.every((depId) => {\n const dep = taskMap.get(depId);\n return dep && (dep.status === 'done' || dep.status === 'cancelled');\n });\n}\n\nfunction buildBlockingChain(\n task: TaskRecord,\n taskMap: Map<string, TaskRecord>,\n visited: Set<string> = new Set(),\n): string[] {\n const chain: string[] = [];\n if (visited.has(task.id)) return chain;\n visited.add(task.id);\n\n if (task.depends) {\n for (const depId of task.depends) {\n const dep = taskMap.get(depId);\n if (dep && dep.status !== 'done' && dep.status !== 'cancelled') {\n chain.push(depId);\n chain.push(...buildBlockingChain(dep, taskMap, visited));\n }\n }\n }\n\n return chain;\n}\n\nfunction buildTreeNode(\n task: TaskRecord,\n childrenMap: Map<string, TaskRecord[]>,\n): TaskTreeNode {\n const children = (childrenMap.get(task.id) ?? []).map((child) =>\n buildTreeNode(child, childrenMap),\n );\n return {\n id: task.id,\n title: task.title,\n status: task.status,\n type: task.type,\n children,\n };\n}\n\nfunction countNodes(nodes: TaskTreeNode[]): number {\n let count = nodes.length;\n for (const node of nodes) {\n count += countNodes(node.children);\n }\n return count;\n}\n\nfunction measureDependencyDepth(\n taskId: string,\n taskMap: Map<string, TaskRecord>,\n visited: Set<string> = new Set(),\n): number {\n if (visited.has(taskId)) return 0;\n visited.add(taskId);\n\n const task = taskMap.get(taskId);\n if (!task || !task.depends || task.depends.length === 0) return 0;\n\n let maxDepth = 0;\n for (const depId of task.depends) {\n const depth = 1 + measureDependencyDepth(depId, taskMap, visited);\n if (depth > maxDepth) maxDepth = depth;\n }\n return maxDepth;\n}\n\nfunction getHierarchyLimits(projectRoot: string): { maxDepth: number; maxSiblings: number } {\n const configPath = getDataPath(projectRoot, 'config.json');\n const config = storeReadJsonFile<Record<string, unknown>>(configPath);\n\n let maxDepth = 3;\n let maxSiblings = 7;\n\n if (config) {\n const hierarchy = config.hierarchy as Record<string, unknown> | undefined;\n if (hierarchy) {\n if (typeof hierarchy.maxDepth === 'number') maxDepth = hierarchy.maxDepth;\n if (typeof hierarchy.maxSiblings === 'number') maxSiblings = hierarchy.maxSiblings;\n }\n }\n\n return { maxDepth, maxSiblings };\n}\n\n// ============================================================================\n// taskNext\n// ============================================================================\n\n/**\n * Suggest next task to work on based on priority, phase, age, and deps.\n * @task T4790\n */\nexport async function coreTaskNext(\n projectRoot: string,\n params?: { count?: number; explain?: boolean },\n): Promise<{\n suggestions: Array<{\n id: string;\n title: string;\n priority: string;\n phase: string | null;\n score: number;\n reasons?: string[];\n }>;\n totalCandidates: number;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n\n const todoPath = getDataPath(projectRoot, 'todo.json');\n const todoMeta = storeReadJsonFile<{ project?: { currentPhase?: string | null } }>(todoPath);\n const currentPhase = todoMeta?.project?.currentPhase;\n\n const candidates = allTasks.filter((t) =>\n t.status === 'pending' && depsReady(t, taskMap),\n );\n\n if (candidates.length === 0) {\n return { suggestions: [], totalCandidates: 0 };\n }\n\n const scored = candidates.map((task) => {\n const reasons: string[] = [];\n let score = 0;\n\n score += PRIORITY_SCORE[task.priority] ?? 50;\n reasons.push(`priority: ${task.priority} (+${PRIORITY_SCORE[task.priority] ?? 50})`);\n\n if (currentPhase && task.phase === currentPhase) {\n score += 20;\n reasons.push(`phase alignment: ${currentPhase} (+20)`);\n }\n\n if (depsReady(task, taskMap)) {\n score += 10;\n reasons.push('all dependencies satisfied (+10)');\n }\n\n if (task.createdAt) {\n const ageMs = Date.now() - new Date(task.createdAt).getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n if (ageDays > 7) {\n const ageBonus = Math.min(15, Math.floor(ageDays / 7));\n score += ageBonus;\n reasons.push(`age: ${Math.floor(ageDays)} days (+${ageBonus})`);\n }\n }\n\n return { task, score, reasons };\n }).sort((a, b) => b.score - a.score);\n\n const count = Math.min(params?.count || 1, scored.length);\n const explain = params?.explain ?? false;\n\n const suggestions = scored.slice(0, count).map(({ task, score, reasons }) => ({\n id: task.id,\n title: task.title,\n priority: task.priority,\n phase: task.phase ?? null,\n score,\n ...(explain && { reasons }),\n }));\n\n return { suggestions, totalCandidates: candidates.length };\n}\n\n// ============================================================================\n// taskBlockers\n// ============================================================================\n\n/**\n * Show blocked tasks and analyze blocking chains.\n * @task T4790\n */\nexport async function coreTaskBlockers(\n projectRoot: string,\n params?: { analyze?: boolean },\n): Promise<{\n blockedTasks: Array<{\n id: string;\n title: string;\n status: string;\n depends?: string[];\n blockingChain: string[];\n }>;\n criticalBlockers: Array<{ id: string; title: string; blocksCount: number }>;\n summary: string;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n const analyze = params?.analyze ?? false;\n\n const blockedTasks = allTasks.filter((t) => t.status === 'blocked');\n\n const depBlockedTasks = allTasks.filter((t) =>\n t.status === 'pending' &&\n t.depends &&\n t.depends.length > 0 &&\n t.depends.some((depId) => {\n const dep = taskMap.get(depId);\n return dep && dep.status !== 'done' && dep.status !== 'cancelled';\n }),\n );\n\n const blockerInfos = [\n ...blockedTasks.map((t) => ({\n id: t.id,\n title: t.title,\n status: t.status,\n depends: t.depends,\n blockingChain: analyze ? buildBlockingChain(t, taskMap) : [],\n })),\n ...depBlockedTasks\n .filter((t) => !blockedTasks.some((bt) => bt.id === t.id))\n .map((t) => ({\n id: t.id,\n title: t.title,\n status: t.status,\n depends: t.depends,\n blockingChain: analyze ? buildBlockingChain(t, taskMap) : [],\n })),\n ];\n\n const blockerCounts = new Map<string, number>();\n for (const info of blockerInfos) {\n for (const depId of info.blockingChain) {\n blockerCounts.set(depId, (blockerCounts.get(depId) ?? 0) + 1);\n }\n }\n\n const criticalBlockers = [...blockerCounts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([id, count]) => {\n const task = taskMap.get(id);\n return { id, title: task?.title ?? 'Unknown', blocksCount: count };\n });\n\n return {\n blockedTasks: blockerInfos,\n criticalBlockers,\n summary: blockerInfos.length === 0\n ? 'No blocked tasks found'\n : `${blockerInfos.length} blocked task(s)`,\n };\n}\n\n// ============================================================================\n// taskTree\n// ============================================================================\n\n/**\n * Build hierarchy tree.\n * @task T4790\n */\nexport async function coreTaskTree(\n projectRoot: string,\n taskId?: string,\n): Promise<{ tree: TaskTreeNode[]; totalNodes: number }> {\n const allTasks = await loadAllTasks(projectRoot);\n\n if (taskId) {\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n }\n\n const childrenMap = new Map<string, TaskRecord[]>();\n for (const task of allTasks) {\n const parentKey = task.parentId ?? '__root__';\n if (!childrenMap.has(parentKey)) {\n childrenMap.set(parentKey, []);\n }\n childrenMap.get(parentKey)!.push(task);\n }\n\n let roots: TaskRecord[];\n if (taskId) {\n roots = [allTasks.find((t) => t.id === taskId)!];\n } else {\n roots = childrenMap.get('__root__') ?? [];\n }\n\n const tree = roots.map((root) => buildTreeNode(root, childrenMap));\n\n return { tree, totalNodes: countNodes(tree) };\n}\n\n// ============================================================================\n// taskDeps\n// ============================================================================\n\n/**\n * Show dependencies for a task.\n * @task T4790\n */\nexport async function coreTaskDeps(\n projectRoot: string,\n taskId: string,\n): Promise<{\n taskId: string;\n dependsOn: Array<{ id: string; title: string; status: string }>;\n dependedOnBy: Array<{ id: string; title: string; status: string }>;\n unresolvedDeps: string[];\n allDepsReady: boolean;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n const completedIds = new Set(\n allTasks.filter((t) => t.status === 'done' || t.status === 'cancelled').map((t) => t.id),\n );\n\n const dependsOn = (task.depends ?? [])\n .map((depId) => {\n const dep = taskMap.get(depId);\n return dep ? { id: dep.id, title: dep.title, status: dep.status } : null;\n })\n .filter((d): d is { id: string; title: string; status: string } => d !== null);\n\n const dependedOnBy = allTasks\n .filter((t) => t.depends?.includes(taskId))\n .map((t) => ({ id: t.id, title: t.title, status: t.status }));\n\n const unresolvedDeps = (task.depends ?? []).filter((depId) => !completedIds.has(depId));\n\n return { taskId, dependsOn, dependedOnBy, unresolvedDeps, allDepsReady: unresolvedDeps.length === 0 };\n}\n\n// ============================================================================\n// taskRelates\n// ============================================================================\n\n/**\n * Show task relations.\n * @task T4790\n */\nexport async function coreTaskRelates(\n projectRoot: string,\n taskId: string,\n): Promise<{\n taskId: string;\n relations: Array<{ taskId: string; type: string; reason?: string }>;\n count: number;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const relations = task.relates ?? [];\n return { taskId, relations, count: relations.length };\n}\n\n// ============================================================================\n// taskRelatesAdd\n// ============================================================================\n\n/**\n * Add a relation between two tasks.\n * @task T4790\n */\nexport async function coreTaskRelatesAdd(\n projectRoot: string,\n taskId: string,\n relatedId: string,\n type: string,\n reason?: string,\n): Promise<{ from: string; to: string; type: string; added: boolean }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const fromTask = current.tasks.find((t) => t.id === taskId) as TaskRecord | undefined;\n if (!fromTask) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const toTask = current.tasks.find((t) => t.id === relatedId);\n if (!toTask) {\n throw new Error(`Task '${relatedId}' not found`);\n }\n\n if (!fromTask.relates) {\n fromTask.relates = [];\n }\n\n fromTask.relates.push({\n taskId: relatedId,\n type,\n reason: reason || undefined,\n });\n\n fromTask.updatedAt = new Date().toISOString();\n await accessor.saveTodoFile(current);\n\n return { from: taskId, to: relatedId, type, added: true };\n}\n\n// ============================================================================\n// taskAnalyze\n// ============================================================================\n\n/**\n * Analyze tasks for priority and leverage.\n * @task T4790\n */\nexport async function coreTaskAnalyze(\n projectRoot: string,\n taskId?: string,\n): Promise<{\n recommended: { id: string; title: string; leverage: number; reason: string } | null;\n bottlenecks: Array<{ id: string; title: string; blocksCount: number }>;\n tiers: {\n critical: Array<{ id: string; title: string; leverage: number }>;\n high: Array<{ id: string; title: string; leverage: number }>;\n normal: Array<{ id: string; title: string; leverage: number }>;\n };\n metrics: {\n totalTasks: number;\n actionable: number;\n blocked: number;\n avgLeverage: number;\n };\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n\n const tasks = taskId\n ? allTasks.filter((t) => t.id === taskId || t.parentId === taskId)\n : allTasks;\n\n const blocksMap: Record<string, string[]> = {};\n for (const task of tasks) {\n if (task.depends) {\n for (const dep of task.depends) {\n if (!blocksMap[dep]) blocksMap[dep] = [];\n blocksMap[dep]!.push(task.id);\n }\n }\n }\n\n const leverageMap: Record<string, number> = {};\n for (const task of tasks) {\n leverageMap[task.id] = (blocksMap[task.id] ?? []).length;\n }\n\n const actionable = tasks.filter((t) => t.status === 'pending' || t.status === 'active');\n const blocked = tasks.filter((t) => t.status === 'blocked');\n\n const bottlenecks = tasks\n .filter((t) => (blocksMap[t.id]?.length ?? 0) > 0 && t.status !== 'done')\n .map((t) => ({ id: t.id, title: t.title, blocksCount: blocksMap[t.id]!.length }))\n .sort((a, b) => b.blocksCount - a.blocksCount)\n .slice(0, 5);\n\n const scored = actionable.map((t) => ({\n id: t.id,\n title: t.title,\n leverage: leverageMap[t.id] ?? 0,\n priority: t.priority,\n }));\n\n scored.sort((a, b) => {\n const priorityWeight: Record<string, number> = { critical: 100, high: 50, medium: 20, low: 5 };\n const aScore = (priorityWeight[a.priority ?? 'medium'] ?? 20) + a.leverage * 10;\n const bScore = (priorityWeight[b.priority ?? 'medium'] ?? 20) + b.leverage * 10;\n return bScore - aScore;\n });\n\n const critical = scored.filter((t) => t.priority === 'critical');\n const high = scored.filter((t) => t.priority === 'high');\n const normal = scored.filter((t) => t.priority !== 'critical' && t.priority !== 'high');\n\n const recommended = scored.length > 0\n ? {\n id: scored[0]!.id,\n title: scored[0]!.title,\n leverage: scored[0]!.leverage,\n reason: 'Highest combined priority and leverage score',\n }\n : null;\n\n const totalLeverage = Object.values(leverageMap).reduce((s, v) => s + v, 0);\n const avgLeverage = tasks.length > 0\n ? Math.round((totalLeverage / tasks.length) * 100) / 100\n : 0;\n\n return {\n recommended,\n bottlenecks,\n tiers: {\n critical: critical.map(({ id, title, leverage }) => ({ id, title, leverage })),\n high: high.map(({ id, title, leverage }) => ({ id, title, leverage })),\n normal: normal.slice(0, 10).map(({ id, title, leverage }) => ({ id, title, leverage })),\n },\n metrics: {\n totalTasks: tasks.length,\n actionable: actionable.length,\n blocked: blocked.length,\n avgLeverage,\n },\n };\n}\n\n// ============================================================================\n// taskRestore\n// ============================================================================\n\n/**\n * Restore a cancelled task back to pending.\n * @task T4790\n */\nexport async function coreTaskRestore(\n projectRoot: string,\n taskId: string,\n params?: { cascade?: boolean; notes?: string },\n): Promise<{ task: string; restored: string[]; count: number }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const task = current.tasks.find((t) => t.id === taskId) as TaskRecord | undefined;\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n if (task.status !== 'cancelled') {\n throw new Error(`Task '${taskId}' is not cancelled (status: ${task.status}). Only cancelled tasks can be restored.`);\n }\n\n const tasksToRestore: TaskRecord[] = [task];\n if (params?.cascade) {\n const findCancelledChildren = (parentId: string): void => {\n const children = current.tasks.filter(\n (t) => t.parentId === parentId && t.status === 'cancelled',\n );\n for (const child of children) {\n tasksToRestore.push(child as unknown as TaskRecord);\n findCancelledChildren(child.id);\n }\n };\n findCancelledChildren(taskId);\n }\n\n const now = new Date().toISOString();\n const restored: string[] = [];\n\n for (const t of tasksToRestore) {\n t.status = 'pending';\n t.cancelledAt = null;\n t.cancellationReason = undefined;\n t.updatedAt = now;\n\n if (!t.notes) t.notes = [];\n t.notes.push(`[${now}] Restored from cancelled${params?.notes ? ': ' + params.notes : ''}`);\n restored.push(t.id);\n }\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, restored, count: restored.length };\n}\n\n// ============================================================================\n// taskUnarchive\n// ============================================================================\n\n/**\n * Move an archived task back to todo.json.\n * @task T4790\n */\nexport async function coreTaskUnarchive(\n projectRoot: string,\n taskId: string,\n params?: { status?: string; preserveStatus?: boolean },\n): Promise<{ task: string; unarchived: boolean; title: string; status: string }> {\n const accessor = await getAccessor(projectRoot);\n const todo = await accessor.loadTodoFile();\n if (!todo || !todo.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const archive = await accessor.loadArchive();\n if (!archive || !archive.archivedTasks) {\n throw new Error('No archive file found');\n }\n\n const taskIndex = archive.archivedTasks.findIndex((t) => t.id === taskId);\n if (taskIndex === -1) {\n throw new Error(`Task '${taskId}' not found in archive`);\n }\n\n if (todo.tasks.some((t) => t.id === taskId)) {\n throw new Error(`Task '${taskId}' already exists in todo.json`);\n }\n\n const task = archive.archivedTasks[taskIndex] as TaskRecord & { _archive?: Record<string, unknown> };\n\n delete task._archive;\n\n if (!params?.preserveStatus) {\n const targetStatus = params?.status || 'pending';\n task.status = targetStatus;\n if (targetStatus !== 'done') {\n task.completedAt = null;\n }\n }\n\n task.updatedAt = new Date().toISOString();\n\n (todo.tasks as unknown as TaskRecord[]).push(task);\n archive.archivedTasks.splice(taskIndex, 1);\n\n await accessor.saveTodoFile(todo);\n await accessor.saveArchive(archive);\n\n return { task: taskId, unarchived: true, title: task.title, status: task.status };\n}\n\n// ============================================================================\n// taskReorder\n// ============================================================================\n\n/**\n * Change task position within its sibling group.\n * @task T4790\n */\nexport async function coreTaskReorder(\n projectRoot: string,\n taskId: string,\n position: number,\n): Promise<{ task: string; reordered: boolean; newPosition: number; totalSiblings: number }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const task = current.tasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const allSiblings = current.tasks\n .filter((t) => t.parentId === task.parentId)\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0));\n\n const currentIndex = allSiblings.findIndex((t) => t.id === taskId);\n const newIndex = Math.max(0, Math.min(position - 1, allSiblings.length - 1));\n\n allSiblings.splice(currentIndex, 1);\n allSiblings.splice(newIndex, 0, task);\n\n const now = new Date().toISOString();\n for (let i = 0; i < allSiblings.length; i++) {\n const sibling = current.tasks.find((t) => t.id === allSiblings[i]!.id);\n if (sibling) {\n sibling.position = i + 1;\n sibling.positionVersion = ((sibling.positionVersion as number | undefined) ?? 0) + 1;\n sibling.updatedAt = now;\n }\n }\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, reordered: true, newPosition: newIndex + 1, totalSiblings: allSiblings.length };\n}\n\n// ============================================================================\n// taskReparent\n// ============================================================================\n\n/**\n * Move task under a different parent.\n * @task T4790\n */\nexport async function coreTaskReparent(\n projectRoot: string,\n taskId: string,\n newParentId: string | null,\n): Promise<{\n task: string;\n reparented: boolean;\n oldParent: string | null;\n newParent: string | null;\n newType?: string;\n}> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const taskMap = new Map(current.tasks.map((t) => [t.id, t]));\n const task = taskMap.get(taskId) as TaskRecord | undefined;\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const effectiveParentId = newParentId || null;\n\n if (!effectiveParentId) {\n const oldParent = task.parentId ?? null;\n task.parentId = null;\n if (task.type === 'subtask') task.type = 'task';\n task.updatedAt = new Date().toISOString();\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, reparented: true, oldParent, newParent: null, newType: task.type };\n }\n\n const newParent = taskMap.get(effectiveParentId);\n if (!newParent) {\n throw new Error(`Parent task '${effectiveParentId}' not found`);\n }\n\n if (newParent.type === 'subtask') {\n throw new Error(`Cannot parent under subtask '${effectiveParentId}'`);\n }\n\n // Check circular reference\n let ancestor: TaskRecord | undefined = newParent as unknown as TaskRecord;\n while (ancestor) {\n if (ancestor.id === taskId) {\n throw new Error(`Moving '${taskId}' under '${effectiveParentId}' would create circular reference`);\n }\n if (!ancestor.parentId) break;\n ancestor = taskMap.get(ancestor.parentId) as unknown as TaskRecord | undefined;\n if (!ancestor) break;\n }\n\n // Check depth limit\n let parentDepth = 0;\n let cur: TaskRecord | undefined = newParent as unknown as TaskRecord;\n while (cur?.parentId) {\n parentDepth++;\n cur = taskMap.get(cur.parentId) as unknown as TaskRecord | undefined;\n if (!cur || parentDepth > 10) break;\n }\n const reparentLimits = getHierarchyLimits(projectRoot);\n if (parentDepth + 1 >= reparentLimits.maxDepth) {\n throw new Error(`Move would exceed max depth of ${reparentLimits.maxDepth}`);\n }\n\n // Check sibling limit\n const siblingCount = current.tasks.filter((t) => t.parentId === effectiveParentId && t.id !== taskId).length;\n if (siblingCount >= reparentLimits.maxSiblings) {\n throw new Error(`Cannot add child to ${effectiveParentId}: max siblings (${reparentLimits.maxSiblings}) exceeded`);\n }\n\n const oldParent = task.parentId ?? null;\n task.parentId = effectiveParentId;\n\n const newDepth = parentDepth + 1;\n if (newDepth === 1) task.type = 'task';\n else if (newDepth >= 2) task.type = 'subtask';\n\n task.updatedAt = new Date().toISOString();\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, reparented: true, oldParent, newParent: effectiveParentId, newType: task.type };\n}\n\n// ============================================================================\n// taskPromote\n// ============================================================================\n\n/**\n * Promote a subtask to task or task to root.\n * @task T4790\n */\nexport async function coreTaskPromote(\n projectRoot: string,\n taskId: string,\n): Promise<{ task: string; promoted: boolean; previousParent: string | null; typeChanged: boolean }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const task = current.tasks.find((t) => t.id === taskId) as TaskRecord | undefined;\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n if (!task.parentId) {\n return { task: taskId, promoted: false, previousParent: null, typeChanged: false };\n }\n\n const oldParent = task.parentId;\n task.parentId = null;\n task.updatedAt = new Date().toISOString();\n\n let typeChanged = false;\n if (task.type === 'subtask') {\n task.type = 'task';\n typeChanged = true;\n }\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, promoted: true, previousParent: oldParent, typeChanged };\n}\n\n// ============================================================================\n// taskReopen\n// ============================================================================\n\n/**\n * Reopen a completed task.\n * @task T4790\n */\nexport async function coreTaskReopen(\n projectRoot: string,\n taskId: string,\n params?: { status?: string; reason?: string },\n): Promise<{ task: string; reopened: boolean; previousStatus: string; newStatus: string }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n const task = current.tasks.find((t) => t.id === taskId) as TaskRecord | undefined;\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n if (task.status !== 'done') {\n throw new Error(`Task '${taskId}' is not completed (status: ${task.status}). Only done tasks can be reopened.`);\n }\n\n const targetStatus = params?.status || 'pending';\n if (targetStatus !== 'pending' && targetStatus !== 'active') {\n throw new Error(`Invalid target status: ${targetStatus}. Must be 'pending' or 'active'.`);\n }\n\n const previousStatus = task.status;\n task.status = targetStatus;\n task.completedAt = null;\n task.updatedAt = new Date().toISOString();\n\n if (!task.notes) task.notes = [];\n const reason = params?.reason;\n task.notes.push(`[${task.updatedAt}] Reopened from ${previousStatus}${reason ? ': ' + reason : ''}`);\n\n await accessor.saveTodoFile(current);\n\n return { task: taskId, reopened: true, previousStatus, newStatus: targetStatus };\n}\n\n// ============================================================================\n// taskComplexityEstimate\n// ============================================================================\n\n/**\n * Deterministic complexity scoring from task metadata.\n * @task T4790\n */\nexport async function coreTaskComplexityEstimate(\n projectRoot: string,\n params: { taskId: string },\n): Promise<{\n size: 'small' | 'medium' | 'large';\n score: number;\n factors: ComplexityFactor[];\n dependencyDepth: number;\n subtaskCount: number;\n fileCount: number;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n\n const task = allTasks.find((t) => t.id === params.taskId);\n if (!task) {\n throw new Error(`Task '${params.taskId}' not found`);\n }\n\n const factors: ComplexityFactor[] = [];\n let score = 0;\n\n const descLen = (task.description || '').length;\n let descScore: number;\n let descLabel: string;\n if (descLen < 100) { descScore = 1; descLabel = 'short'; }\n else if (descLen < 500) { descScore = 2; descLabel = 'medium'; }\n else { descScore = 3; descLabel = 'long'; }\n score += descScore;\n factors.push({ name: 'descriptionLength', value: descScore, detail: `${descLabel} (${descLen} chars)` });\n\n const acceptanceCount = task.acceptance?.length ?? 0;\n const acceptanceScore = Math.min(acceptanceCount, 3);\n score += acceptanceScore;\n factors.push({ name: 'acceptanceCriteria', value: acceptanceScore, detail: `${acceptanceCount} criteria` });\n\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n const dependencyDepth = measureDependencyDepth(params.taskId, taskMap);\n const depthScore = Math.min(dependencyDepth, 3);\n score += depthScore;\n factors.push({ name: 'dependencyDepth', value: depthScore, detail: `depth ${dependencyDepth}` });\n\n const subtaskCount = allTasks.filter((t) => t.parentId === params.taskId).length;\n const subtaskScore = Math.min(subtaskCount, 3);\n score += subtaskScore;\n factors.push({ name: 'subtaskCount', value: subtaskScore, detail: `${subtaskCount} subtasks` });\n\n const fileCount = task.files?.length ?? 0;\n const fileScore = Math.min(fileCount, 3);\n score += fileScore;\n factors.push({ name: 'fileReferences', value: fileScore, detail: `${fileCount} files` });\n\n let size: 'small' | 'medium' | 'large';\n if (score <= 3) size = 'small';\n else if (score <= 7) size = 'medium';\n else size = 'large';\n\n return { size, score, factors, dependencyDepth, subtaskCount, fileCount };\n}\n\n// ============================================================================\n// taskDepends\n// ============================================================================\n\n/**\n * List dependencies for a task in a given direction.\n * @task T4790\n */\nexport async function coreTaskDepends(\n projectRoot: string,\n taskId: string,\n direction: 'upstream' | 'downstream' | 'both' = 'both',\n): Promise<{\n taskId: string;\n direction: string;\n upstream: Array<{ id: string; title: string; status: string }>;\n downstream: Array<{ id: string; title: string; status: string }>;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n\n const upstream: Array<{ id: string; title: string; status: string }> = [];\n if (direction === 'upstream' || direction === 'both') {\n for (const depId of task.depends ?? []) {\n const dep = taskMap.get(depId);\n if (dep) {\n upstream.push({ id: dep.id, title: dep.title, status: dep.status });\n }\n }\n }\n\n const downstream: Array<{ id: string; title: string; status: string }> = [];\n if (direction === 'downstream' || direction === 'both') {\n for (const t of allTasks) {\n if (t.depends?.includes(taskId)) {\n downstream.push({ id: t.id, title: t.title, status: t.status });\n }\n }\n }\n\n return { taskId, direction, upstream, downstream };\n}\n\n// ============================================================================\n// taskStats\n// ============================================================================\n\n/**\n * Compute task statistics.\n * @task T4790\n */\nexport async function coreTaskStats(\n projectRoot: string,\n epicId?: string,\n): Promise<{\n total: number;\n pending: number;\n active: number;\n blocked: number;\n done: number;\n cancelled: number;\n byPriority: Record<string, number>;\n byType: Record<string, number>;\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n\n let tasks = allTasks;\n\n if (epicId) {\n const epicIds = new Set<string>();\n epicIds.add(epicId);\n const collectChildren = (parentId: string) => {\n for (const t of allTasks) {\n if (t.parentId === parentId && !epicIds.has(t.id)) {\n epicIds.add(t.id);\n collectChildren(t.id);\n }\n }\n };\n collectChildren(epicId);\n tasks = allTasks.filter((t) => epicIds.has(t.id));\n }\n\n const byStatus: Record<string, number> = {};\n const byPriority: Record<string, number> = {};\n const byType: Record<string, number> = {};\n\n for (const task of tasks) {\n byStatus[task.status] = (byStatus[task.status] ?? 0) + 1;\n byPriority[task.priority] = (byPriority[task.priority] ?? 0) + 1;\n const taskType = task.type ?? 'task';\n byType[taskType] = (byType[taskType] ?? 0) + 1;\n }\n\n return {\n total: tasks.length,\n pending: byStatus['pending'] ?? 0,\n active: byStatus['active'] ?? 0,\n blocked: byStatus['blocked'] ?? 0,\n done: byStatus['done'] ?? 0,\n cancelled: byStatus['cancelled'] ?? 0,\n byPriority,\n byType,\n };\n}\n\n// ============================================================================\n// taskExport\n// ============================================================================\n\n/**\n * Export tasks as JSON or CSV.\n * @task T4790\n */\nexport async function coreTaskExport(\n projectRoot: string,\n params?: { format?: 'json' | 'csv'; status?: string; parent?: string },\n): Promise<unknown> {\n const allTasks = await loadAllTasks(projectRoot);\n\n let tasks = allTasks;\n\n if (params?.status) {\n tasks = tasks.filter((t) => t.status === params.status);\n }\n\n if (params?.parent) {\n const parentIds = new Set<string>();\n parentIds.add(params.parent);\n const collectChildren = (parentId: string) => {\n for (const t of allTasks) {\n if (t.parentId === parentId && !parentIds.has(t.id)) {\n parentIds.add(t.id);\n collectChildren(t.id);\n }\n }\n };\n collectChildren(params.parent);\n tasks = tasks.filter((t) => parentIds.has(t.id));\n }\n\n if (params?.format === 'csv') {\n const headers = ['id', 'title', 'status', 'priority', 'type', 'parentId', 'createdAt'];\n const rows = tasks.map((t) => [\n t.id,\n `\"${(t.title || '').replace(/\"/g, '\"\"')}\"`,\n t.status,\n t.priority,\n t.type ?? 'task',\n t.parentId ?? '',\n t.createdAt,\n ].join(','));\n const csv = [headers.join(','), ...rows].join('\\n');\n return { format: 'csv', content: csv, taskCount: tasks.length };\n }\n\n return { format: 'json', tasks, taskCount: tasks.length };\n}\n\n// ============================================================================\n// taskHistory\n// ============================================================================\n\n/**\n * Get task history from the log file.\n * @task T4790\n */\nexport async function coreTaskHistory(\n projectRoot: string,\n taskId: string,\n limit?: number,\n): Promise<Array<Record<string, unknown>>> {\n const logPath = getDataPath(projectRoot, 'todo-log.jsonl');\n const entries = readLogFileEntries(logPath);\n\n const taskEntries = entries.filter((entry) => {\n if (entry.taskId === taskId) return true;\n if (entry.id === taskId) return true;\n if (typeof entry.details === 'string' && entry.details.includes(taskId)) return true;\n if (typeof entry.message === 'string' && entry.message.includes(taskId)) return true;\n return false;\n });\n\n taskEntries.sort((a, b) => {\n const timeA = String(a.timestamp ?? a.date ?? '');\n const timeB = String(b.timestamp ?? b.date ?? '');\n return timeB.localeCompare(timeA);\n });\n\n return limit && limit > 0 ? taskEntries.slice(0, limit) : taskEntries;\n}\n\n// ============================================================================\n// taskLint\n// ============================================================================\n\n/**\n * Lint tasks for common issues.\n * @task T4790\n */\nexport async function coreTaskLint(\n projectRoot: string,\n taskId?: string,\n): Promise<Array<{\n taskId: string;\n severity: 'error' | 'warning';\n rule: string;\n message: string;\n}>> {\n const allTasks = await loadAllTasks(projectRoot);\n\n const tasks = taskId\n ? allTasks.filter((t) => t.id === taskId)\n : allTasks;\n\n if (taskId && tasks.length === 0) {\n throw new Error(`Task '${taskId}' not found`);\n }\n\n const issues: Array<{\n taskId: string;\n severity: 'error' | 'warning';\n rule: string;\n message: string;\n }> = [];\n\n const allDescriptions = new Set<string>();\n const allIds = new Set<string>();\n\n for (const task of allTasks) {\n if (allIds.has(task.id)) {\n issues.push({\n taskId: task.id,\n severity: 'error',\n rule: 'unique-id',\n message: `Duplicate task ID: ${task.id}`,\n });\n }\n allIds.add(task.id);\n\n if (taskId && task.id !== taskId) {\n if (task.description) allDescriptions.add(task.description.toLowerCase());\n continue;\n }\n\n if (!task.title || task.title.trim().length === 0) {\n issues.push({ taskId: task.id, severity: 'error', rule: 'title-required', message: 'Task is missing a title' });\n }\n\n if (!task.description || task.description.trim().length === 0) {\n issues.push({ taskId: task.id, severity: 'warning', rule: 'description-required', message: 'Task is missing a description' });\n }\n\n if (task.title && task.description && task.title.trim() === task.description.trim()) {\n issues.push({ taskId: task.id, severity: 'warning', rule: 'title-description-different', message: 'Title and description should not be identical' });\n }\n\n if (task.description) {\n const descLower = task.description.toLowerCase();\n if (allDescriptions.has(descLower)) {\n issues.push({ taskId: task.id, severity: 'warning', rule: 'unique-description', message: 'Duplicate task description found' });\n }\n allDescriptions.add(descLower);\n }\n\n const validStatuses = ['pending', 'active', 'blocked', 'done', 'cancelled'];\n if (!validStatuses.includes(task.status)) {\n issues.push({ taskId: task.id, severity: 'error', rule: 'valid-status', message: `Invalid status: ${task.status}` });\n }\n\n const now = new Date();\n if (task.createdAt && new Date(task.createdAt) > now) {\n issues.push({ taskId: task.id, severity: 'warning', rule: 'no-future-timestamps', message: 'createdAt is in the future' });\n }\n\n if (task.parentId && !allTasks.some((t) => t.id === task.parentId)) {\n issues.push({ taskId: task.id, severity: 'error', rule: 'valid-parent', message: `Parent task '${task.parentId}' does not exist` });\n }\n\n for (const depId of task.depends ?? []) {\n if (!allTasks.some((t) => t.id === depId)) {\n issues.push({ taskId: task.id, severity: 'warning', rule: 'valid-dependency', message: `Dependency '${depId}' does not exist` });\n }\n }\n }\n\n return issues;\n}\n\n// ============================================================================\n// taskBatchValidate\n// ============================================================================\n\n/**\n * Validate multiple tasks at once.\n * @task T4790\n */\nexport async function coreTaskBatchValidate(\n projectRoot: string,\n taskIds: string[],\n checkMode: 'full' | 'quick' = 'full',\n): Promise<{\n results: Record<string, Array<{ severity: 'error' | 'warning'; rule: string; message: string }>>;\n summary: {\n totalTasks: number;\n validTasks: number;\n invalidTasks: number;\n totalIssues: number;\n errors: number;\n warnings: number;\n };\n}> {\n const allTasks = await loadAllTasks(projectRoot);\n\n const results: Record<string, Array<{ severity: 'error' | 'warning'; rule: string; message: string }>> = {};\n\n let totalErrors = 0;\n let totalWarnings = 0;\n\n for (const id of taskIds) {\n const task = allTasks.find((t) => t.id === id);\n if (!task) {\n results[id] = [{ severity: 'error', rule: 'exists', message: `Task '${id}' not found` }];\n totalErrors++;\n continue;\n }\n\n const taskIssues: Array<{ severity: 'error' | 'warning'; rule: string; message: string }> = [];\n\n if (!task.title || task.title.trim().length === 0) {\n taskIssues.push({ severity: 'error', rule: 'title-required', message: 'Missing title' });\n }\n if (!task.description || task.description.trim().length === 0) {\n taskIssues.push({ severity: 'warning', rule: 'description-required', message: 'Missing description' });\n }\n\n const validStatuses = ['pending', 'active', 'blocked', 'done', 'cancelled'];\n if (!validStatuses.includes(task.status)) {\n taskIssues.push({ severity: 'error', rule: 'valid-status', message: `Invalid status: ${task.status}` });\n }\n\n if (checkMode === 'full') {\n if (task.title && task.description && task.title.trim() === task.description.trim()) {\n taskIssues.push({ severity: 'warning', rule: 'title-description-different', message: 'Title equals description' });\n }\n\n if (task.parentId && !allTasks.some((t) => t.id === task.parentId)) {\n taskIssues.push({ severity: 'error', rule: 'valid-parent', message: `Parent '${task.parentId}' not found` });\n }\n\n for (const depId of task.depends ?? []) {\n if (!allTasks.some((t) => t.id === depId)) {\n taskIssues.push({ severity: 'warning', rule: 'valid-dependency', message: `Dependency '${depId}' not found` });\n }\n }\n\n const now = new Date();\n if (task.createdAt && new Date(task.createdAt) > now) {\n taskIssues.push({ severity: 'warning', rule: 'no-future-timestamps', message: 'createdAt in future' });\n }\n }\n\n results[id] = taskIssues;\n totalErrors += taskIssues.filter((i) => i.severity === 'error').length;\n totalWarnings += taskIssues.filter((i) => i.severity === 'warning').length;\n }\n\n const invalidTasks = Object.values(results).filter((issues) =>\n issues.some((i) => i.severity === 'error'),\n ).length;\n\n return {\n results,\n summary: {\n totalTasks: taskIds.length,\n validTasks: taskIds.length - invalidTasks,\n invalidTasks,\n totalIssues: totalErrors + totalWarnings,\n errors: totalErrors,\n warnings: totalWarnings,\n },\n };\n}\n\n// ============================================================================\n// taskImport\n// ============================================================================\n\n/**\n * Import tasks from a JSON source string.\n * @task T4790\n */\nexport async function coreTaskImport(\n projectRoot: string,\n source: string,\n overwrite?: boolean,\n): Promise<{ imported: number; skipped: number; errors: string[]; remapTable?: Record<string, string> }> {\n const accessor = await getAccessor(projectRoot);\n const current = await accessor.loadTodoFile();\n if (!current || !current.tasks) {\n throw new Error('No valid todo.json found');\n }\n\n let importData: unknown;\n try {\n importData = JSON.parse(source);\n } catch {\n throw new Error('Invalid JSON in import source');\n }\n\n let importTasks: TaskRecord[] = [];\n if (Array.isArray(importData)) {\n importTasks = importData as TaskRecord[];\n } else if (typeof importData === 'object' && importData !== null) {\n const data = importData as Record<string, unknown>;\n if (Array.isArray(data.tasks)) {\n importTasks = data.tasks as TaskRecord[];\n }\n }\n\n if (importTasks.length === 0) {\n return { imported: 0, skipped: 0, errors: ['No tasks found in import source'] };\n }\n\n const existingIds = new Set(current.tasks.map((t) => t.id));\n const allIds = new Set(current.tasks.map((t) => t.id));\n const errors: string[] = [];\n let imported = 0;\n let skipped = 0;\n const remapTable: Record<string, string> = {};\n\n let nextIdNum = 0;\n for (const t of current.tasks) {\n const num = parseInt(t.id.replace('T', ''), 10);\n if (!isNaN(num) && num > nextIdNum) nextIdNum = num;\n }\n\n const tasksList = current.tasks as unknown as TaskRecord[];\n\n for (const importTask of importTasks) {\n if (!importTask.id || !importTask.title) {\n errors.push(`Skipped task with missing id or title`);\n skipped++;\n continue;\n }\n\n if (existingIds.has(importTask.id) && !overwrite) {\n skipped++;\n continue;\n }\n\n let newId = importTask.id;\n if (allIds.has(importTask.id) && !overwrite) {\n nextIdNum++;\n newId = `T${String(nextIdNum).padStart(3, '0')}`;\n remapTable[importTask.id] = newId;\n }\n\n const now = new Date().toISOString();\n const newTask: TaskRecord = {\n ...importTask,\n id: newId,\n createdAt: importTask.createdAt || now,\n updatedAt: now,\n };\n\n if (overwrite && existingIds.has(importTask.id)) {\n const idx = tasksList.findIndex((t) => t.id === importTask.id);\n if (idx !== -1) {\n tasksList[idx] = newTask;\n }\n } else {\n tasksList.push(newTask);\n }\n\n allIds.add(newId);\n imported++;\n }\n\n if (imported > 0) {\n await accessor.saveTodoFile(current);\n }\n\n return {\n imported,\n skipped,\n errors,\n ...(Object.keys(remapTable).length > 0 ? { remapTable } : {}),\n };\n}\n", "/**\n * Task Engine\n *\n * Native TypeScript implementation of core task CRUD operations.\n * Uses StoreProvider (via getStore()) for task/session data access,\n * falling back to direct JSON for config and specialized operations.\n *\n * CRUD operations (show, list, find, exists, create, update, complete, delete, archive)\n * delegate to src/core/tasks/*.\n *\n * Non-CRUD operations delegate to src/core/tasks/task-ops.ts.\n *\n * @task T4657\n * @task T4790\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport type { Task } from '../../types/task.js';\n// validation-rules.js still used by other engines; core modules handle their own validation\n// Core module imports for accessor-based operations\nimport { addTask as coreAddTask } from '../../core/tasks/add.js';\nimport { updateTask as coreUpdateTask } from '../../core/tasks/update.js';\nimport { deleteTask as coreDeleteTask } from '../../core/tasks/delete.js';\nimport { archiveTasks as coreArchiveTasks } from '../../core/tasks/archive.js';\nimport { showTask as coreShowTask } from '../../core/tasks/show.js';\nimport { listTasks as coreListTasks } from '../../core/tasks/list.js';\nimport { findTasks as coreFindTasks } from '../../core/tasks/find.js';\n// Non-CRUD core operations\nimport {\n coreTaskNext,\n coreTaskBlockers,\n coreTaskTree,\n coreTaskDeps,\n coreTaskRelates,\n coreTaskRelatesAdd,\n coreTaskAnalyze,\n coreTaskRestore,\n coreTaskUnarchive,\n coreTaskReorder,\n coreTaskReparent,\n coreTaskPromote,\n coreTaskReopen,\n coreTaskComplexityEstimate,\n coreTaskDepends,\n coreTaskStats,\n coreTaskExport,\n coreTaskHistory,\n coreTaskLint,\n coreTaskBatchValidate,\n coreTaskImport,\n type TaskTreeNode,\n type ComplexityFactor,\n} from '../../core/tasks/task-ops.js';\n\n/**\n * Convert a core Task to a TaskRecord for backward compatibility.\n * TaskRecord has string-typed status/priority; Task has union types.\n *\n * @task T4657\n * @epic T4654\n */\nfunction taskToRecord(task: Task): TaskRecord {\n return task as unknown as TaskRecord;\n}\n\n/**\n * Convert an array of core Tasks to TaskRecords.\n *\n * @task T4657\n * @epic T4654\n */\nfunction tasksToRecords(tasks: Task[]): TaskRecord[] {\n return tasks as unknown as TaskRecord[];\n}\n\n/**\n * Task object as stored in todo.json\n */\nexport interface TaskRecord {\n id: string;\n title: string;\n description: string;\n status: string;\n priority: string;\n type?: string;\n phase?: string;\n createdAt: string;\n updatedAt: string | null;\n completedAt?: string | null;\n cancelledAt?: string | null;\n parentId?: string | null;\n position?: number | null;\n positionVersion?: number;\n depends?: string[];\n relates?: Array<{\n taskId: string;\n type: string;\n reason?: string;\n }>;\n files?: string[];\n acceptance?: string[];\n notes?: string[];\n labels?: string[];\n size?: string | null;\n epicLifecycle?: string | null;\n noAutoComplete?: boolean | null;\n verification?: Record<string, unknown> | null;\n origin?: string | null;\n createdBy?: string | null;\n validatedBy?: string | null;\n testedBy?: string | null;\n lifecycleState?: string | null;\n validationHistory?: Array<Record<string, unknown>>;\n blockedBy?: string[];\n cancellationReason?: string;\n}\n\n// Local TodoFile interface removed \u2014 DataAccessor uses the canonical TodoFile from types/task.ts.\n\n/**\n * Minimal task representation for find results\n */\nexport interface MinimalTaskRecord {\n id: string;\n title: string;\n status: string;\n priority: string;\n parentId?: string | null;\n}\n\n/**\n * Engine result wrapper\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n exitCode?: number;\n };\n}\n\n// loadTodoFile and saveTodoFile removed \u2014 all operations now use DataAccessor.\n// Config reads (hierarchy limits, phase meta) still use readJsonFile directly\n// since they are NOT domain data (they don't go through the accessor).\n\n// Priority normalization moved to core/tasks/add.ts (normalizePriority)\n\n// ===== Query Operations =====\n\n/**\n * Get a single task by ID\n * @task T4657\n * @epic T4654\n */\nexport async function taskShow(\n projectRoot: string,\n taskId: string\n): Promise<EngineResult<TaskRecord>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const detail = await coreShowTask(taskId, projectRoot, accessor);\n return { success: true, data: taskToRecord(detail) };\n } catch (err: unknown) {\n const code = (err as { code?: number })?.code;\n if (code === 4 /* NOT_FOUND */) {\n return {\n success: false,\n error: { code: 'E_NOT_FOUND', message: (err as Error).message || `Task '${taskId}' not found` },\n };\n }\n if (code === 2 /* INVALID_INPUT */) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: (err as Error).message || 'Invalid input' },\n };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message || 'No todo.json found' } };\n }\n}\n\n/**\n * List tasks with optional filters\n * @task T4657\n * @epic T4654\n */\nexport async function taskList(\n projectRoot: string,\n params?: {\n parent?: string;\n status?: string;\n limit?: number;\n }\n): Promise<EngineResult<TaskRecord[]>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await coreListTasks({\n parentId: params?.parent ?? undefined,\n status: params?.status as import('../../types/task.js').TaskStatus | undefined,\n limit: params?.limit,\n }, projectRoot, accessor);\n return { success: true, data: tasksToRecords(result.tasks) };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Fuzzy search tasks by title/description/ID\n * @task T4657\n * @epic T4654\n */\nexport async function taskFind(\n projectRoot: string,\n query: string,\n limit?: number\n): Promise<EngineResult<MinimalTaskRecord[]>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const findResult = await coreFindTasks({\n query,\n limit: limit ?? 20,\n }, projectRoot, accessor);\n\n const results: MinimalTaskRecord[] = findResult.results.map((r) => ({\n id: r.id,\n title: r.title,\n status: r.status,\n priority: r.priority,\n parentId: r.parentId,\n }));\n\n return { success: true, data: results };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Check if a task exists\n * @task T4657\n * @epic T4654\n */\nexport async function taskExists(\n projectRoot: string,\n taskId: string\n): Promise<EngineResult<{ exists: boolean; taskId: string }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const data = await accessor.loadTodoFile();\n const exists = data.tasks.some((t) => t.id === taskId);\n return { success: true, data: { exists, taskId } };\n } catch {\n return { success: true, data: { exists: false, taskId } };\n }\n}\n\n// ===== Mutate Operations =====\n\n/**\n * Create a new task\n */\nexport async function taskCreate(\n projectRoot: string,\n params: {\n title: string;\n description: string;\n parent?: string;\n depends?: string[];\n priority?: string;\n labels?: string[];\n type?: string;\n }\n): Promise<EngineResult<TaskRecord>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await coreAddTask({\n title: params.title,\n description: params.description,\n parentId: params.parent || null,\n depends: params.depends,\n priority: (params.priority as import('../../types/task.js').TaskPriority) || 'medium',\n labels: params.labels,\n type: (params.type as import('../../types/task.js').TaskType) || undefined,\n }, projectRoot, accessor);\n\n if (result.duplicate) {\n return {\n success: true,\n data: taskToRecord(result.task),\n };\n }\n\n return { success: true, data: taskToRecord(result.task) };\n } catch (err: unknown) {\n const cleoErr = err as { code?: number; message?: string };\n // Map CleoError exit codes to engine error codes (see src/types/exit-codes.ts)\n if (cleoErr.code === 10 /* PARENT_NOT_FOUND */) {\n return { success: false, error: { code: 'E_PARENT_NOT_FOUND', message: cleoErr.message ?? 'Parent task not found', exitCode: 10 } };\n }\n if (cleoErr.code === 11 /* DEPTH_EXCEEDED */) {\n return { success: false, error: { code: 'E_DEPTH_EXCEEDED', message: cleoErr.message ?? 'Max hierarchy depth exceeded', exitCode: 11 } };\n }\n if (cleoErr.code === 12 /* SIBLING_LIMIT */) {\n return { success: false, error: { code: 'E_SIBLING_LIMIT', message: cleoErr.message ?? 'Max siblings exceeded', exitCode: 12 } };\n }\n if (cleoErr.code === 13 /* INVALID_PARENT_TYPE */) {\n return { success: false, error: { code: 'E_INVALID_PARENT', message: cleoErr.message ?? 'Invalid parent type', exitCode: 13 } };\n }\n if (cleoErr.code === 14 /* CIRCULAR_REFERENCE */) {\n return { success: false, error: { code: 'E_CIRCULAR_REFERENCE', message: cleoErr.message ?? 'Circular reference detected', exitCode: 14 } };\n }\n if (cleoErr.code === 6 /* VALIDATION_ERROR */ || cleoErr.code === 2 /* INVALID_INPUT */) {\n return { success: false, error: { code: 'E_VALIDATION_FAILED', message: cleoErr.message ?? 'Validation failed', exitCode: cleoErr.code } };\n }\n if (cleoErr.code === 4 /* NOT_FOUND */) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: cleoErr.message ?? 'Task not found', exitCode: 4 } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: cleoErr.message ?? 'No valid todo.json found' } };\n }\n}\n\n/**\n * Update a task\n */\nexport async function taskUpdate(\n projectRoot: string,\n taskId: string,\n updates: {\n title?: string;\n description?: string;\n status?: string;\n priority?: string;\n notes?: string;\n labels?: string[];\n addLabels?: string[];\n removeLabels?: string[];\n depends?: string[];\n addDepends?: string[];\n removeDepends?: string[];\n acceptance?: string[];\n parent?: string | null;\n type?: string;\n size?: string;\n }\n): Promise<EngineResult<TaskRecord>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await coreUpdateTask({\n taskId,\n title: updates.title,\n description: updates.description,\n status: updates.status as import('../../types/task.js').TaskStatus | undefined,\n priority: updates.priority as import('../../types/task.js').TaskPriority | undefined,\n notes: updates.notes,\n labels: updates.labels,\n addLabels: updates.addLabels,\n removeLabels: updates.removeLabels,\n depends: updates.depends,\n addDepends: updates.addDepends,\n removeDepends: updates.removeDepends,\n acceptance: updates.acceptance,\n parentId: updates.parent,\n type: updates.type as import('../../types/task.js').TaskType | undefined,\n size: updates.size as import('../../types/task.js').TaskSize | undefined,\n }, projectRoot, accessor);\n\n return { success: true, data: taskToRecord(result.task) };\n } catch (err: unknown) {\n const cleoErr = err as { code?: number; message?: string };\n if (cleoErr.code === 4 /* NOT_FOUND */) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: cleoErr.message ?? `Task '${taskId}' not found` } };\n }\n if (cleoErr.code === 6 /* VALIDATION_ERROR */ || cleoErr.code === 2 /* INVALID_INPUT */) {\n return { success: false, error: { code: 'E_VALIDATION_FAILED', message: cleoErr.message ?? 'Validation failed' } };\n }\n if (cleoErr.code === 102 /* NO_CHANGE */) {\n return { success: false, error: { code: 'E_NO_CHANGE', message: cleoErr.message ?? 'No changes specified' } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: cleoErr.message ?? 'No valid todo.json found' } };\n }\n}\n\n/**\n * Complete a task (set status to done)\n */\nexport async function taskComplete(\n projectRoot: string,\n taskId: string,\n notes?: string\n): Promise<EngineResult<TaskRecord>> {\n return taskUpdate(projectRoot, taskId, {\n status: 'done',\n notes: notes || undefined,\n });\n}\n\n/**\n * Delete a task\n */\nexport async function taskDelete(\n projectRoot: string,\n taskId: string,\n force?: boolean\n): Promise<EngineResult<{ deleted: boolean; taskId: string }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n await coreDeleteTask({\n taskId,\n force: force ?? false,\n cascade: force ?? false,\n }, projectRoot, accessor);\n\n return { success: true, data: { deleted: true, taskId } };\n } catch (err: unknown) {\n const cleoErr = err as { code?: number; message?: string };\n if (cleoErr.code === 4 /* NOT_FOUND */) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: cleoErr.message ?? `Task '${taskId}' not found` } };\n }\n if (cleoErr.code === 16 /* HAS_CHILDREN */) {\n return { success: false, error: { code: 'E_HAS_CHILDREN', message: cleoErr.message ?? `Task '${taskId}' has children` } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: cleoErr.message ?? 'No valid todo.json found' } };\n }\n}\n\n/**\n * Archive completed tasks.\n * Moves done/cancelled tasks from todo.json to todo-archive.json.\n */\nexport async function taskArchive(\n projectRoot: string,\n taskId?: string,\n before?: string\n): Promise<EngineResult<{ archived: number; taskIds: string[] }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await coreArchiveTasks({\n taskIds: taskId ? [taskId] : undefined,\n before,\n }, projectRoot, accessor);\n\n return {\n success: true,\n data: { archived: result.archived.length, taskIds: result.archived },\n };\n } catch (err: unknown) {\n const cleoErr = err as { code?: number; message?: string };\n if (cleoErr.code === 4 /* NOT_FOUND */) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: cleoErr.message ?? `Task not found` } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: cleoErr.message ?? 'No valid todo.json found' } };\n }\n}\n\n// ===== Non-CRUD Operations (delegated to core/tasks/task-ops.ts) =====\n\n/**\n * Suggest next task to work on based on priority, phase alignment, age, and dependency readiness.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskNext(\n projectRoot: string,\n params?: {\n count?: number;\n explain?: boolean;\n }\n): Promise<EngineResult<{\n suggestions: Array<{\n id: string;\n title: string;\n priority: string;\n phase: string | null;\n score: number;\n reasons?: string[];\n }>;\n totalCandidates: number;\n}>> {\n try {\n const result = await coreTaskNext(projectRoot, params);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Show blocked tasks and analyze blocking chains.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskBlockers(\n projectRoot: string,\n params?: { analyze?: boolean }\n): Promise<EngineResult<{\n blockedTasks: Array<{\n id: string;\n title: string;\n status: string;\n depends?: string[];\n blockingChain: string[];\n }>;\n criticalBlockers: Array<{\n id: string;\n title: string;\n blocksCount: number;\n }>;\n summary: string;\n}>> {\n try {\n const result = await coreTaskBlockers(projectRoot, params);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Build hierarchy tree.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskTree(\n projectRoot: string,\n taskId?: string\n): Promise<EngineResult<{ tree: TaskTreeNode[]; totalNodes: number }>> {\n try {\n const result = await coreTaskTree(projectRoot, taskId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Show dependencies for a task - both what it depends on and what depends on it.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskDeps(\n projectRoot: string,\n taskId: string\n): Promise<EngineResult<{\n taskId: string;\n dependsOn: Array<{ id: string; title: string; status: string }>;\n dependedOnBy: Array<{ id: string; title: string; status: string }>;\n unresolvedDeps: string[];\n allDepsReady: boolean;\n}>> {\n try {\n const result = await coreTaskDeps(projectRoot, taskId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Show task relations (existing relates entries).\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskRelates(\n projectRoot: string,\n taskId: string\n): Promise<EngineResult<{\n taskId: string;\n relations: Array<{\n taskId: string;\n type: string;\n reason?: string;\n }>;\n count: number;\n}>> {\n try {\n const result = await coreTaskRelates(projectRoot, taskId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Add a relation between two tasks.\n * @task T4790\n */\nexport async function taskRelatesAdd(\n projectRoot: string,\n taskId: string,\n relatedId: string,\n type: string,\n reason?: string\n): Promise<EngineResult<{ from: string; to: string; type: string; added: boolean }>> {\n try {\n const result = await coreTaskRelatesAdd(projectRoot, taskId, relatedId, type, reason);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to update task relations' } };\n }\n}\n\n/**\n * Analyze a task for description quality, missing fields, and dependency health.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskAnalyze(\n projectRoot: string,\n taskId?: string\n): Promise<EngineResult<{\n recommended: { id: string; title: string; leverage: number; reason: string } | null;\n bottlenecks: Array<{ id: string; title: string; blocksCount: number }>;\n tiers: {\n critical: Array<{ id: string; title: string; leverage: number }>;\n high: Array<{ id: string; title: string; leverage: number }>;\n normal: Array<{ id: string; title: string; leverage: number }>;\n };\n metrics: {\n totalTasks: number;\n actionable: number;\n blocked: number;\n avgLeverage: number;\n };\n}>> {\n try {\n const result = await coreTaskAnalyze(projectRoot, taskId);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Restore a cancelled task back to pending.\n * @task T4790\n */\nexport async function taskRestore(\n projectRoot: string,\n taskId: string,\n params?: { cascade?: boolean; notes?: string }\n): Promise<EngineResult<{ task: string; restored: string[]; count: number }>> {\n try {\n const result = await coreTaskRestore(projectRoot, taskId, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n if (message.includes('not cancelled')) {\n return { success: false, error: { code: 'E_INVALID_STATUS', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to restore task' } };\n }\n}\n\n/**\n * Move an archived task back to todo.json with status 'done' (or specified status).\n * @task T4790\n */\nexport async function taskUnarchive(\n projectRoot: string,\n taskId: string,\n params?: { status?: string; preserveStatus?: boolean }\n): Promise<EngineResult<{ task: string; unarchived: boolean; title: string; status: string }>> {\n try {\n const result = await coreTaskUnarchive(projectRoot, taskId, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n if (message.includes('already exists')) {\n return { success: false, error: { code: 'E_ID_COLLISION', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to unarchive task' } };\n }\n}\n\n/**\n * Change task position within its sibling group.\n * @task T4790\n */\nexport async function taskReorder(\n projectRoot: string,\n taskId: string,\n position: number\n): Promise<EngineResult<{ task: string; reordered: boolean; newPosition: number; totalSiblings: number }>> {\n try {\n const result = await coreTaskReorder(projectRoot, taskId, position);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to reorder task' } };\n }\n}\n\n/**\n * Move task under a different parent.\n * @task T4790\n */\nexport async function taskReparent(\n projectRoot: string,\n taskId: string,\n newParentId: string | null\n): Promise<EngineResult<{\n task: string;\n reparented: boolean;\n oldParent: string | null;\n newParent: string | null;\n newType?: string;\n}>> {\n try {\n const result = await coreTaskReparent(projectRoot, taskId, newParentId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n const code = message.includes('Parent') ? 'E_PARENT_NOT_FOUND' : 'E_NOT_FOUND';\n return { success: false, error: { code, message } };\n }\n if (message.includes('subtask')) {\n return { success: false, error: { code: 'E_INVALID_PARENT_TYPE', message } };\n }\n if (message.includes('circular')) {\n return { success: false, error: { code: 'E_CIRCULAR_REFERENCE', message } };\n }\n if (message.includes('depth')) {\n return { success: false, error: { code: 'E_DEPTH_EXCEEDED', message } };\n }\n if (message.includes('siblings')) {\n return { success: false, error: { code: 'E_SIBLING_LIMIT', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to reparent task' } };\n }\n}\n\n/**\n * Promote a subtask to task or task to root (remove parent).\n * @task T4790\n */\nexport async function taskPromote(\n projectRoot: string,\n taskId: string\n): Promise<EngineResult<{ task: string; promoted: boolean; previousParent: string | null; typeChanged: boolean }>> {\n try {\n const result = await coreTaskPromote(projectRoot, taskId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to promote task' } };\n }\n}\n\n/**\n * Reopen a completed task (set status back to pending).\n * @task T4790\n */\nexport async function taskReopen(\n projectRoot: string,\n taskId: string,\n params?: { status?: string; reason?: string }\n): Promise<EngineResult<{ task: string; reopened: boolean; previousStatus: string; newStatus: string }>> {\n try {\n const result = await coreTaskReopen(projectRoot, taskId, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n if (message.includes('not completed')) {\n return { success: false, error: { code: 'E_INVALID_STATUS', message } };\n }\n if (message.includes('Invalid target')) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to reopen task' } };\n }\n}\n\n/**\n * Deterministic complexity scoring from task metadata.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskComplexityEstimate(\n projectRoot: string,\n params: { taskId: string }\n): Promise<EngineResult<{\n size: 'small' | 'medium' | 'large';\n score: number;\n factors: ComplexityFactor[];\n dependencyDepth: number;\n subtaskCount: number;\n fileCount: number;\n}>> {\n try {\n const result = await coreTaskComplexityEstimate(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * List dependencies for a task in a given direction.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskDepends(\n projectRoot: string,\n taskId: string,\n direction: 'upstream' | 'downstream' | 'both' = 'both'\n): Promise<EngineResult<{\n taskId: string;\n direction: string;\n upstream: Array<{ id: string; title: string; status: string }>;\n downstream: Array<{ id: string; title: string; status: string }>;\n}>> {\n try {\n const result = await coreTaskDepends(projectRoot, taskId, direction);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Compute task statistics, optionally scoped to an epic.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskStats(\n projectRoot: string,\n epicId?: string\n): Promise<EngineResult<{\n total: number;\n pending: number;\n active: number;\n blocked: number;\n done: number;\n cancelled: number;\n byPriority: Record<string, number>;\n byType: Record<string, number>;\n}>> {\n try {\n const result = await coreTaskStats(projectRoot, epicId);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Export tasks as JSON or CSV.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskExport(\n projectRoot: string,\n params?: {\n format?: 'json' | 'csv';\n status?: string;\n parent?: string;\n }\n): Promise<EngineResult<unknown>> {\n try {\n const result = await coreTaskExport(projectRoot, params);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Get task history from the log file.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskHistory(\n projectRoot: string,\n taskId: string,\n limit?: number\n): Promise<EngineResult<Array<Record<string, unknown>>>> {\n try {\n const result = await coreTaskHistory(projectRoot, taskId, limit);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to read task history' } };\n }\n}\n\n/**\n * Lint tasks for common issues.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskLint(\n projectRoot: string,\n taskId?: string\n): Promise<EngineResult<Array<{\n taskId: string;\n severity: 'error' | 'warning';\n rule: string;\n message: string;\n}>>> {\n try {\n const result = await coreTaskLint(projectRoot, taskId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('not found')) {\n return { success: false, error: { code: 'E_NOT_FOUND', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Validate multiple tasks at once.\n * @task T4657\n * @task T4790\n * @epic T4654\n */\nexport async function taskBatchValidate(\n projectRoot: string,\n taskIds: string[],\n checkMode: 'full' | 'quick' = 'full'\n): Promise<EngineResult<{\n results: Record<string, Array<{\n severity: 'error' | 'warning';\n rule: string;\n message: string;\n }>>;\n summary: {\n totalTasks: number;\n validTasks: number;\n invalidTasks: number;\n totalIssues: number;\n errors: number;\n warnings: number;\n };\n}>> {\n try {\n const result = await coreTaskBatchValidate(projectRoot, taskIds, checkMode);\n return { success: true, data: result };\n } catch {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' } };\n }\n}\n\n/**\n * Import tasks from a JSON source string or export package.\n * @task T4790\n */\nexport async function taskImport(\n projectRoot: string,\n source: string,\n overwrite?: boolean\n): Promise<EngineResult<{ imported: number; skipped: number; errors: string[]; remapTable?: Record<string, string> }>> {\n try {\n const result = await coreTaskImport(projectRoot, source, overwrite);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes('Invalid JSON')) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message } };\n }\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: 'Failed to import tasks' } };\n }\n}\n", "/**\n * Session management operations.\n * @task T4463\n * @epic T4454\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { readJson, saveJson } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Session, SessionsFile, SessionScope, SessionScopeType } from '../../types/session.js';\nimport { getSessionsPath, getBackupDir } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Options for starting a session. */\nexport interface StartSessionOptions {\n name: string;\n scope: string; // e.g. \"epic:T001\" or \"global\"\n autoStart?: boolean;\n startTask?: string;\n focus?: string;\n agent?: string;\n}\n\n/** Options for ending a session. */\nexport interface EndSessionOptions {\n sessionId?: string;\n note?: string;\n}\n\n/** Options for listing sessions. */\nexport interface ListSessionsOptions {\n status?: string;\n limit?: number;\n}\n\n/**\n * Parse a scope string into a SessionScope.\n * @task T4463\n */\nexport function parseScope(scopeStr: string): SessionScope {\n if (scopeStr === 'global') {\n return { type: 'global' as SessionScopeType };\n }\n const match = scopeStr.match(/^epic:(T\\d+)$/);\n if (match) {\n return { type: 'epic' as SessionScopeType, epicId: match[1] };\n }\n throw new CleoError(\n ExitCode.SCOPE_INVALID,\n `Invalid scope format: ${scopeStr}. Use 'epic:T###' or 'global'.`,\n );\n}\n\n/**\n * Generate a session ID.\n * @task T4463\n */\nfunction generateSessionId(): string {\n return `session-${Date.now()}-${randomBytes(3).toString('hex')}`;\n}\n\n/**\n * Read or create sessions file.\n * @task T4463\n */\nasync function readSessions(cwd?: string, accessor?: DataAccessor): Promise<SessionsFile> {\n if (accessor) {\n const data = await accessor.loadSessions() as SessionsFile;\n if (data && data.sessions) return data;\n return {\n version: '1.0.0',\n sessions: [],\n _meta: {\n schemaVersion: '1.0.0',\n lastUpdated: new Date().toISOString(),\n },\n };\n }\n const sessionsPath = getSessionsPath(cwd);\n const data = await readJson<SessionsFile>(sessionsPath);\n if (data) return data;\n\n return {\n version: '1.0.0',\n sessions: [],\n _meta: {\n schemaVersion: '1.0.0',\n lastUpdated: new Date().toISOString(),\n },\n };\n}\n\n/**\n * Save sessions file.\n * @task T4463\n */\nasync function saveSessions(data: SessionsFile, cwd?: string, accessor?: DataAccessor): Promise<void> {\n data._meta.lastUpdated = new Date().toISOString();\n if (accessor) {\n await accessor.saveSessions(data);\n return;\n }\n const sessionsPath = getSessionsPath(cwd);\n const backupDir = getBackupDir(cwd);\n await saveJson(sessionsPath, data, { backupDir });\n}\n\n/**\n * Start a new session.\n * @task T4463\n */\nexport async function startSession(options: StartSessionOptions, cwd?: string, accessor?: DataAccessor): Promise<Session> {\n const scope = parseScope(options.scope);\n const data = await readSessions(cwd, accessor);\n\n // Check for conflicting active sessions\n const activeSessions = data.sessions.filter(s => s.status === 'active');\n for (const active of activeSessions) {\n if (\n active.scope.type === scope.type &&\n active.scope.epicId === scope.epicId\n ) {\n throw new CleoError(\n ExitCode.SCOPE_CONFLICT,\n `Active session already exists for scope ${options.scope}: ${active.id}`,\n {\n fix: `Resume with 'cleo session resume ${active.id}' or end it first`,\n alternatives: [\n { action: 'Resume existing', command: `cleo session resume ${active.id}` },\n { action: 'End existing', command: `cleo session end` },\n ],\n },\n );\n }\n }\n\n const focusTaskId = options.focus ?? options.startTask ?? null;\n const session: Session = {\n id: generateSessionId(),\n name: options.name,\n status: 'active',\n scope,\n taskWork: {\n taskId: options.startTask ?? null,\n setAt: options.startTask ? new Date().toISOString() : null,\n },\n focus: {\n taskId: focusTaskId,\n setAt: focusTaskId ? new Date().toISOString() : null,\n },\n startedAt: new Date().toISOString(),\n agent: options.agent ?? null,\n notes: [],\n tasksCompleted: [],\n tasksCreated: [],\n };\n\n data.sessions.push(session);\n await saveSessions(data, cwd, accessor);\n\n return session;\n}\n\n/**\n * End a session.\n * @task T4463\n */\nexport async function endSession(options: EndSessionOptions = {}, cwd?: string, accessor?: DataAccessor): Promise<Session> {\n const data = await readSessions(cwd, accessor);\n\n let session: Session | undefined;\n\n if (options.sessionId) {\n session = data.sessions.find(s => s.id === options.sessionId);\n } else {\n // Find most recent active session\n session = data.sessions\n .filter(s => s.status === 'active')\n .sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime())[0];\n }\n\n if (!session) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n options.sessionId\n ? `Session not found: ${options.sessionId}`\n : 'No active session found',\n { fix: \"Use 'cleo session list' to see available sessions\" },\n );\n }\n\n if (session.status !== 'active') {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session ${session.id} is already ${session.status}`,\n );\n }\n\n session.status = 'ended';\n session.endedAt = new Date().toISOString();\n\n if (options.note) {\n if (!session.notes) session.notes = [];\n session.notes.push(options.note);\n }\n\n await saveSessions(data, cwd, accessor);\n\n return session;\n}\n\n/**\n * Get current session status.\n * @task T4463\n */\nexport async function sessionStatus(cwd?: string, accessor?: DataAccessor): Promise<Session | null> {\n const data = await readSessions(cwd, accessor);\n\n const active = data.sessions\n .filter(s => s.status === 'active')\n .sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime())[0];\n\n return active ?? null;\n}\n\n/**\n * Resume an existing session.\n * @task T4463\n */\nexport async function resumeSession(sessionId: string, cwd?: string, accessor?: DataAccessor): Promise<Session> {\n const data = await readSessions(cwd, accessor);\n\n const session = data.sessions.find(s => s.id === sessionId);\n if (!session) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session not found: ${sessionId}`,\n { fix: \"Use 'cleo session list' to see available sessions\" },\n );\n }\n\n if (session.status === 'active') {\n return session; // Already active\n }\n\n if (session.status === 'orphaned' || session.status === 'ended') {\n session.status = 'active';\n session.endedAt = null;\n if (!session.notes) session.notes = [];\n session.notes.push(`Resumed at ${new Date().toISOString()}`);\n\n await saveSessions(data, cwd, accessor);\n }\n\n return session;\n}\n\n/**\n * List sessions with optional filtering.\n * @task T4463\n */\nexport async function listSessions(options: ListSessionsOptions = {}, cwd?: string, accessor?: DataAccessor): Promise<Session[]> {\n const data = await readSessions(cwd, accessor);\n\n let sessions = data.sessions;\n\n if (options.status) {\n sessions = sessions.filter(s => s.status === options.status);\n }\n\n // Sort by start time, most recent first\n sessions.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());\n\n if (options.limit) {\n sessions = sessions.slice(0, options.limit);\n }\n\n return sessions;\n}\n\n/**\n * Garbage collect old sessions.\n * Marks orphaned sessions that have been active too long.\n * @task T4463\n */\nexport async function gcSessions(maxAgeHours: number = 24, cwd?: string, accessor?: DataAccessor): Promise<{ orphaned: string[]; removed: string[] }> {\n const data = await readSessions(cwd, accessor);\n const now = Date.now();\n const maxAgeMs = maxAgeHours * 60 * 60 * 1000;\n\n const orphaned: string[] = [];\n const removed: string[] = [];\n\n for (const session of data.sessions) {\n if (session.status === 'active') {\n const age = now - new Date(session.startedAt).getTime();\n if (age > maxAgeMs) {\n session.status = 'orphaned';\n session.endedAt = new Date().toISOString();\n orphaned.push(session.id);\n }\n }\n }\n\n // Remove very old ended/orphaned sessions (> 30 days)\n const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;\n data.sessions = data.sessions.filter(s => {\n if (s.status === 'active') return true;\n const endedAt = s.endedAt ? new Date(s.endedAt).getTime() : new Date(s.startedAt).getTime();\n if (now - endedAt > thirtyDaysMs) {\n removed.push(s.id);\n return false;\n }\n return true;\n });\n\n if (orphaned.length > 0 || removed.length > 0) {\n await saveSessions(data, cwd, accessor);\n }\n\n return { orphaned, removed };\n}\n\n// Re-export extended session modules (engine-compatible)\nexport { isMultiSession } from './multi-session.js';\nexport { showSession } from './session-show.js';\nexport { suspendSession } from './session-suspend.js';\nexport { getSessionHistory } from './session-history.js';\nexport type { SessionHistoryEntry, SessionHistoryParams } from './session-history.js';\nexport { cleanupSessions } from './session-cleanup.js';\nexport { getSessionStats } from './session-stats.js';\nexport type { SessionStatsResult } from './session-stats.js';\nexport { switchSession } from './session-switch.js';\nexport { archiveSessions } from './session-archive.js';\nexport { getContextDrift } from './session-drift.js';\nexport type { ContextDriftResult } from './session-drift.js';\nexport { recordDecision, getDecisionLog } from './decisions.js';\nexport type { RecordDecisionParams, DecisionLogParams } from './decisions.js';\nexport { recordAssumption } from './assumptions.js';\nexport type { RecordAssumptionParams } from './assumptions.js';\nexport type { SessionRecord, FocusState, SessionsFileExt, TodoFileExt, DecisionRecord, AssumptionRecord } from './types.js';\n\n// =============================================================================\n// CROSS-SESSION RESUME INTEGRATION\n// @task T4805 - SQLite-backed resume flow integration\n// =============================================================================\n\nimport { checkSessionResume, SessionResumeCheckResult } from '../lifecycle/resume.js';\n\n/** Options for starting a session with resume check. */\nexport interface StartSessionWithResumeOptions extends StartSessionOptions {\n /** Whether to check for resumable pipelines on start */\n checkResume?: boolean;\n /** Whether to auto-resume if single candidate found */\n autoResume?: boolean;\n /** Minimum priority for resume candidates */\n minResumePriority?: 'critical' | 'high' | 'medium' | 'low';\n}\n\n/** Result of starting a session with resume check. */\nexport interface StartSessionWithResumeResult {\n /** The created/resumed session */\n session: Session;\n /** Resume check result if checkResume was enabled */\n resumeCheck?: SessionResumeCheckResult;\n /** Whether a pipeline was auto-resumed */\n autoResumed: boolean;\n}\n\n/**\n * Start a new session with optional resume check.\n *\n * This enhanced version of startSession integrates with the lifecycle\n * resume flow (T4805) to check for active pipelines and optionally\n * auto-resume work from a previous session.\n *\n * @param options - Session options with resume check configuration\n * @param cwd - Working directory\n * @param accessor - Data accessor for testing\n * @returns Promise resolving to session and resume check results\n *\n * @example\n * ```typescript\n * // Start session and check for resumable work\n * const result = await startSessionWithResume({\n * name: 'Development Session',\n * scope: 'epic:T4805',\n * checkResume: true,\n * autoResume: true\n * });\n *\n * if (result.autoResumed) {\n * console.log(`Auto-resumed ${result.resumeCheck?.resumedTaskId}`);\n * } else if (result.resumeCheck?.requiresUserChoice) {\n * console.log('Choose a pipeline to resume:', result.resumeCheck.options);\n * }\n * ```\n *\n * @task T4805\n * @integration Session Start Hook\n */\nexport async function startSessionWithResume(\n options: StartSessionWithResumeOptions,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<StartSessionWithResumeResult> {\n // First, start the session normally\n const session = await startSession(options, cwd, accessor);\n\n // If resume check not enabled, return just the session\n if (!options.checkResume) {\n return { session, autoResumed: false };\n }\n\n // Check for resumable pipelines\n const scope = options.scope.startsWith('epic:')\n ? { type: 'epic' as const, epicId: options.scope.replace('epic:', '') }\n : { type: 'global' as const };\n\n const resumeCheck = await checkSessionResume(\n {\n autoResume: options.autoResume,\n scope,\n minPriority: options.minResumePriority,\n includeBlocked: true,\n },\n cwd,\n );\n\n return {\n session,\n resumeCheck,\n autoResumed: resumeCheck.didResume,\n };\n}\n", "/**\n * Show a specific session by ID.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { SessionRecord, SessionsFileExt } from './types.js';\n\n/**\n * Show a specific session.\n * Looks in active sessions first, then session history.\n * Throws CleoError if not found.\n */\nexport async function showSession(\n projectRoot: string,\n sessionId: string,\n): Promise<SessionRecord> {\n const accessor = await getAccessor(projectRoot);\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n const session = sessions.sessions?.find((s) => s.id === sessionId);\n if (session) {\n return session;\n }\n\n // Check history\n const historical = sessions.sessionHistory?.find((s) => s.id === sessionId);\n if (historical) {\n return historical;\n }\n\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n}\n", "/**\n * Suspend an active session.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { SessionRecord, SessionsFileExt, TodoFileExt } from './types.js';\n\n/**\n * Suspend an active session.\n * Sets status to 'suspended' and records the reason.\n * Throws if multi-session mode is not enabled or session not found/not active.\n */\nexport async function suspendSession(\n projectRoot: string,\n sessionId: string,\n reason?: string,\n): Promise<SessionRecord> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n const multiSession = current._meta?.multiSessionEnabled === true;\n\n if (!multiSession) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n 'Session suspend requires multi-session mode',\n );\n }\n\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n const session = sessions.sessions.find((s) => s.id === sessionId);\n\n if (!session) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n if (session.status !== 'active') {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' is ${session.status}, not active`,\n );\n }\n\n const now = new Date().toISOString();\n\n session.status = 'suspended';\n session.suspendedAt = now;\n session.lastActivity = now;\n\n if (session.stats) {\n session.stats.suspendCount = (session.stats.suspendCount || 0) + 1;\n }\n\n if (reason) {\n session.focus = session.focus || { currentTask: null, currentPhase: null };\n session.focus.sessionNote = reason;\n }\n\n // Clear active session in todo.json if this was the active one\n if (current._meta?.activeSession === sessionId) {\n current._meta.activeSession = null;\n current._meta.generation = (current._meta.generation || 0) + 1;\n (current as Record<string, unknown>).lastUpdated = now;\n await accessor.saveTodoFile(todoData);\n }\n\n if (sessions._meta) {\n sessions._meta.lastModified = now;\n }\n\n await accessor.saveSessions(sessionsData);\n\n return session;\n}\n", "/**\n * Session history with focus changes and completed tasks.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport type { SessionRecord, SessionsFileExt } from './types.js';\n\nexport interface SessionHistoryEntry {\n id: string;\n name?: string;\n status: string;\n startedAt: string;\n endedAt?: string | null;\n tasksCompleted: number;\n focusChanges: number;\n focusHistory: Array<{ taskId: string; timestamp: string }>;\n}\n\nexport interface SessionHistoryParams {\n sessionId?: string;\n limit?: number;\n}\n\n/**\n * List session history with focus changes and completed tasks.\n * If sessionId is provided, returns history for that specific session.\n * Otherwise, returns history across all sessions.\n */\nexport async function getSessionHistory(\n projectRoot: string,\n params?: SessionHistoryParams,\n): Promise<{ sessions: SessionHistoryEntry[] }> {\n const accessor = await getAccessor(projectRoot);\n\n // Verify project is initialized by loading todo file\n await accessor.loadTodoFile();\n\n const sessionsFile = (await accessor.loadSessions()) as unknown as SessionsFileExt;\n\n if (!sessionsFile || !sessionsFile.sessions) {\n return { sessions: [] };\n }\n\n // Combine active sessions and history\n const allSessions: SessionRecord[] = [\n ...(sessionsFile.sessions || []),\n ...(sessionsFile.sessionHistory || []),\n ];\n\n let filtered = allSessions;\n\n if (params?.sessionId) {\n filtered = filtered.filter((s) => s.id === params.sessionId);\n }\n\n // Sort by startedAt descending (most recent first)\n filtered.sort(\n (a, b) =>\n new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime(),\n );\n\n if (params?.limit && params.limit > 0) {\n filtered = filtered.slice(0, params.limit);\n }\n\n const result = filtered.map((s) => ({\n id: s.id,\n name: s.name,\n status: s.status,\n startedAt: s.startedAt,\n endedAt: s.endedAt,\n tasksCompleted: s.stats?.tasksCompleted || 0,\n focusChanges: s.stats?.focusChanges || 0,\n focusHistory: s.focus?.focusHistory || [],\n }));\n\n return { sessions: result };\n}\n", "/**\n * Compute session statistics.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { SessionRecord, SessionsFileExt, TodoFileExt } from './types.js';\n\nexport interface SessionStatsResult {\n totalSessions: number;\n activeSessions: number;\n suspendedSessions: number;\n endedSessions: number;\n archivedSessions: number;\n totalTasksCompleted: number;\n totalFocusChanges: number;\n averageResumeCount: number;\n session?: {\n id: string;\n status: string;\n tasksCompleted: number;\n focusChanges: number;\n resumeCount: number;\n durationMinutes: number;\n };\n}\n\n/**\n * Compute session statistics, optionally for a specific session.\n * Throws CleoError if a specific session is requested but not found.\n */\nexport async function getSessionStats(\n projectRoot: string,\n sessionId?: string,\n): Promise<SessionStatsResult> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const todo = todoData as unknown as TodoFileExt;\n\n const multiSession = todo._meta?.multiSessionEnabled === true;\n\n if (!multiSession) {\n // Single-session mode: return basic stats\n return {\n totalSessions: todo.focus?.currentTask ? 1 : 0,\n activeSessions: todo.focus?.currentTask ? 1 : 0,\n suspendedSessions: 0,\n endedSessions: 0,\n archivedSessions: 0,\n totalTasksCompleted: 0,\n totalFocusChanges: 0,\n averageResumeCount: 0,\n };\n }\n\n const sessionsFile = (await accessor.loadSessions()) as unknown as SessionsFileExt;\n\n if (!sessionsFile) {\n return {\n totalSessions: 0,\n activeSessions: 0,\n suspendedSessions: 0,\n endedSessions: 0,\n archivedSessions: 0,\n totalTasksCompleted: 0,\n totalFocusChanges: 0,\n averageResumeCount: 0,\n };\n }\n\n const allSessions: SessionRecord[] = [\n ...(sessionsFile.sessions || []),\n ...(sessionsFile.sessionHistory || []),\n ];\n\n // If specific session requested\n if (sessionId) {\n const session = allSessions.find((s) => s.id === sessionId);\n if (!session) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n const startedAt = new Date(session.startedAt).getTime();\n const endedAt = session.endedAt\n ? new Date(session.endedAt).getTime()\n : Date.now();\n const durationMinutes = Math.round((endedAt - startedAt) / (1000 * 60));\n\n return {\n totalSessions: allSessions.length,\n activeSessions: allSessions.filter((s) => s.status === 'active').length,\n suspendedSessions: allSessions.filter((s) => s.status === 'suspended').length,\n endedSessions: allSessions.filter((s) => s.status === 'ended').length,\n archivedSessions: allSessions.filter((s) => s.status === 'archived').length,\n totalTasksCompleted: allSessions.reduce(\n (sum, s) => sum + (s.stats?.tasksCompleted ?? 0),\n 0,\n ),\n totalFocusChanges: allSessions.reduce(\n (sum, s) => sum + (s.stats?.focusChanges ?? 0),\n 0,\n ),\n averageResumeCount:\n allSessions.length > 0\n ? Math.round(\n (allSessions.reduce(\n (sum, s) => sum + (s.resumeCount ?? 0),\n 0,\n ) /\n allSessions.length) *\n 100,\n ) / 100\n : 0,\n session: {\n id: session.id,\n status: session.status,\n tasksCompleted: session.stats?.tasksCompleted ?? 0,\n focusChanges: session.stats?.focusChanges ?? 0,\n resumeCount: session.resumeCount ?? 0,\n durationMinutes,\n },\n };\n }\n\n const activeSessions = allSessions.filter((s) => s.status === 'active').length;\n const suspendedSessions = allSessions.filter((s) => s.status === 'suspended').length;\n const endedSessions = allSessions.filter((s) => s.status === 'ended').length;\n const archivedSessions = allSessions.filter((s) => s.status === 'archived').length;\n const totalTasksCompleted = allSessions.reduce(\n (sum, s) => sum + (s.stats?.tasksCompleted ?? 0),\n 0,\n );\n const totalFocusChanges = allSessions.reduce(\n (sum, s) => sum + (s.stats?.focusChanges ?? 0),\n 0,\n );\n const averageResumeCount =\n allSessions.length > 0\n ? Math.round(\n (allSessions.reduce(\n (sum, s) => sum + (s.resumeCount ?? 0),\n 0,\n ) /\n allSessions.length) *\n 100,\n ) / 100\n : 0;\n\n return {\n totalSessions: allSessions.length,\n activeSessions,\n suspendedSessions,\n endedSessions,\n archivedSessions,\n totalTasksCompleted,\n totalFocusChanges,\n averageResumeCount,\n };\n}\n", "/**\n * Switch to a different session.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { SessionRecord, SessionsFileExt, TodoFileExt } from './types.js';\n\n/**\n * Switch to a different session.\n * Suspends the current active session and activates the target.\n * Throws if multi-session mode is not enabled, session not found, or archived.\n */\nexport async function switchSession(\n projectRoot: string,\n sessionId: string,\n): Promise<SessionRecord> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n const multiSession = current._meta?.multiSessionEnabled === true;\n if (!multiSession) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n 'Session switch requires multi-session mode',\n );\n }\n\n const sessions = (await accessor.loadSessions()) as unknown as SessionsFileExt;\n\n if (!sessions) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n // Find target session\n let targetSession = sessions.sessions.find((s) => s.id === sessionId);\n let fromHistory = false;\n\n if (!targetSession && sessions.sessionHistory) {\n const histIndex = sessions.sessionHistory.findIndex(\n (s) => s.id === sessionId,\n );\n if (histIndex !== -1) {\n targetSession = sessions.sessionHistory[histIndex];\n sessions.sessionHistory.splice(histIndex, 1);\n fromHistory = true;\n }\n }\n\n if (!targetSession) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' not found`,\n );\n }\n\n if (targetSession.status === 'archived') {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${sessionId}' is archived and cannot be switched to`,\n );\n }\n\n const now = new Date().toISOString();\n\n // Suspend the current active session (if different from target)\n const currentActiveId = current._meta?.activeSession;\n if (currentActiveId && currentActiveId !== sessionId) {\n const currentSession = sessions.sessions.find(\n (s) => s.id === currentActiveId,\n );\n if (currentSession && currentSession.status === 'active') {\n currentSession.status = 'suspended';\n currentSession.suspendedAt = now;\n currentSession.lastActivity = now;\n if (currentSession.stats) {\n currentSession.stats.suspendCount =\n (currentSession.stats.suspendCount || 0) + 1;\n }\n }\n }\n\n // Activate the target session\n targetSession.status = 'active';\n targetSession.lastActivity = now;\n targetSession.suspendedAt = null;\n targetSession.endedAt = null;\n targetSession.resumeCount = (targetSession.resumeCount || 0) + 1;\n\n if (fromHistory) {\n sessions.sessions.push(targetSession);\n }\n\n // Update todo.json\n if (current._meta) {\n current._meta.activeSession = sessionId;\n current._meta.generation = (current._meta.generation || 0) + 1;\n }\n\n if (targetSession.focus?.currentTask && current.focus) {\n current.focus.currentTask = targetSession.focus.currentTask;\n }\n\n current.lastUpdated = now;\n\n if (sessions._meta) {\n sessions._meta.lastModified = now;\n }\n\n await accessor.saveTodoFile(todoData);\n await accessor.saveSessions(sessions as any);\n\n return targetSession;\n}\n", "/**\n * Compute context drift score for a session.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { SessionRecord, SessionsFileExt, TodoFileExt } from './types.js';\n\nexport interface ContextDriftResult {\n score: number;\n factors: string[];\n completedInScope: number;\n totalInScope: number;\n outOfScope: number;\n}\n\n/**\n * Collect all descendant task IDs for a given parent task.\n */\nfunction collectDescendantIds(\n parentId: string,\n tasks: Array<{ id: string; [key: string]: unknown }>,\n): Set<string> {\n const result = new Set<string>();\n\n for (const task of tasks) {\n if (task.parentId === parentId) {\n result.add(task.id);\n const grandchildren = collectDescendantIds(task.id, tasks);\n for (const gc of grandchildren) {\n result.add(gc);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Compute context drift score for the current session.\n * Compares session progress against original scope by counting\n * completed vs total tasks in scope, and detecting out-of-scope work.\n */\nexport async function getContextDrift(\n projectRoot: string,\n params?: { sessionId?: string },\n): Promise<ContextDriftResult> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const todo = todoData as unknown as TodoFileExt;\n\n // Find the active session (or specified session)\n let session: SessionRecord | undefined;\n\n if (params?.sessionId) {\n const sessionsFile = (await accessor.loadSessions()) as unknown as SessionsFileExt;\n if (sessionsFile) {\n session =\n sessionsFile.sessions?.find((s) => s.id === params.sessionId) ||\n sessionsFile.sessionHistory?.find((s) => s.id === params.sessionId);\n }\n if (!session) {\n throw new CleoError(\n ExitCode.SESSION_NOT_FOUND,\n `Session '${params.sessionId}' not found`,\n );\n }\n } else {\n const activeSessionId = todo._meta?.activeSession;\n if (activeSessionId && todo._meta?.multiSessionEnabled) {\n const sessionsFile = (await accessor.loadSessions()) as unknown as SessionsFileExt;\n session = sessionsFile?.sessions?.find((s) => s.id === activeSessionId);\n }\n }\n\n const tasks = todo.tasks || [];\n const factors: string[] = [];\n\n // If no session with scope, compute a basic drift from focus state\n if (!session) {\n const focusTask = todo.focus?.currentTask;\n if (!focusTask) {\n return {\n score: 0,\n factors: ['No active session or focus'],\n completedInScope: 0,\n totalInScope: 0,\n outOfScope: 0,\n };\n }\n\n const rootTaskId = focusTask;\n const inScopeIds = collectDescendantIds(rootTaskId, tasks);\n inScopeIds.add(rootTaskId);\n\n const inScopeTasks = tasks.filter((t) => inScopeIds.has(t.id));\n const completedInScope = inScopeTasks.filter(\n (t) => t.status === 'done',\n ).length;\n const totalInScope = inScopeTasks.length;\n\n const score =\n totalInScope > 0\n ? Math.round((completedInScope / totalInScope) * 100)\n : 0;\n factors.push('Single-session mode (focus-based scope)');\n if (completedInScope === 0)\n factors.push('No tasks completed in scope yet');\n\n return { score, factors, completedInScope, totalInScope, outOfScope: 0 };\n }\n\n // Multi-session: use session scope to determine in-scope tasks\n const rootTaskId = session.scope.rootTaskId;\n const inScopeIds = new Set<string>();\n\n if (\n session.scope.explicitTaskIds &&\n session.scope.explicitTaskIds.length > 0\n ) {\n for (const id of session.scope.explicitTaskIds) {\n inScopeIds.add(id);\n }\n } else {\n inScopeIds.add(rootTaskId);\n if (session.scope.includeDescendants !== false) {\n const descendants = collectDescendantIds(rootTaskId, tasks);\n for (const id of descendants) {\n inScopeIds.add(id);\n }\n }\n }\n\n if (session.scope.excludeTaskIds) {\n for (const id of session.scope.excludeTaskIds) {\n inScopeIds.delete(id);\n }\n }\n\n const inScopeTasks = tasks.filter((t) => inScopeIds.has(t.id));\n const completedInScope = inScopeTasks.filter(\n (t) => t.status === 'done',\n ).length;\n const totalInScope = inScopeTasks.length;\n\n // Detect out-of-scope work: tasks completed during session that are NOT in scope\n let outOfScope = 0;\n const sessionStartTime = new Date(session.startedAt).getTime();\n for (const task of tasks) {\n if (!inScopeIds.has(task.id) && task.status === 'done') {\n const completedAt =\n typeof task.completedAt === 'string'\n ? new Date(task.completedAt).getTime()\n : 0;\n if (completedAt >= sessionStartTime) {\n outOfScope++;\n }\n }\n }\n\n // Calculate drift score (0 = no progress, 100 = all done in scope)\n let score = 0;\n if (totalInScope > 0) {\n const progressRatio = completedInScope / totalInScope;\n const driftPenalty =\n outOfScope > 0 ? Math.min(outOfScope / totalInScope, 0.5) : 0;\n score = Math.round(\n Math.max(0, Math.min(100, progressRatio * 100 - driftPenalty * 50)),\n );\n }\n\n if (totalInScope === 0) factors.push('No tasks found in session scope');\n if (completedInScope === 0 && totalInScope > 0)\n factors.push('No tasks completed in scope yet');\n if (completedInScope === totalInScope && totalInScope > 0)\n factors.push('All in-scope tasks completed');\n if (outOfScope > 0)\n factors.push(\n `${outOfScope} task(s) completed outside of session scope`,\n );\n if (outOfScope === 0 && completedInScope > 0)\n factors.push('All completed work is within scope');\n if (session.scope.type)\n factors.push(`Scope type: ${session.scope.type}`);\n\n return { score, factors, completedInScope, totalInScope, outOfScope };\n}\n", "/**\n * Decision recording and retrieval for session audit trail.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { readFileSync, appendFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { DecisionRecord } from './types.js';\n\nexport interface RecordDecisionParams {\n sessionId: string;\n taskId: string;\n decision: string;\n rationale: string;\n alternatives?: string[];\n}\n\nexport interface DecisionLogParams {\n sessionId?: string;\n taskId?: string;\n}\n\n/**\n * Record a decision to the audit trail.\n * Appends a JSON line to `.cleo/audit/decisions.jsonl`.\n * Throws if required params are missing.\n */\nexport async function recordDecision(\n projectRoot: string,\n params: RecordDecisionParams,\n): Promise<DecisionRecord> {\n if (\n !params.sessionId ||\n !params.taskId ||\n !params.decision ||\n !params.rationale\n ) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n 'sessionId, taskId, decision, and rationale are required',\n );\n }\n\n const auditDir = join(projectRoot, '.cleo', 'audit');\n if (!existsSync(auditDir)) {\n mkdirSync(auditDir, { recursive: true });\n }\n\n const decisionPath = join(auditDir, 'decisions.jsonl');\n\n const record: DecisionRecord = {\n id: `dec-${randomBytes(8).toString('hex')}`,\n sessionId: params.sessionId,\n taskId: params.taskId,\n decision: params.decision,\n rationale: params.rationale,\n alternatives: params.alternatives || [],\n timestamp: new Date().toISOString(),\n };\n\n appendFileSync(decisionPath, JSON.stringify(record) + '\\n', 'utf-8');\n\n return record;\n}\n\n/**\n * Read the decision log, optionally filtered by sessionId and/or taskId.\n */\nexport async function getDecisionLog(\n projectRoot: string,\n params?: DecisionLogParams,\n): Promise<DecisionRecord[]> {\n const decisionPath = join(projectRoot, '.cleo', 'audit', 'decisions.jsonl');\n\n if (!existsSync(decisionPath)) {\n return [];\n }\n\n const content = readFileSync(decisionPath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim().length > 0);\n\n let entries: DecisionRecord[] = [];\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line) as DecisionRecord);\n } catch {\n // Skip malformed lines\n }\n }\n\n if (params?.sessionId) {\n entries = entries.filter((e) => e.sessionId === params.sessionId);\n }\n\n if (params?.taskId) {\n entries = entries.filter((e) => e.taskId === params.taskId);\n }\n\n return entries;\n}\n", "/**\n * Assumption recording for session audit trail.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { appendFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { AssumptionRecord, TodoFileExt } from './types.js';\n\nexport interface RecordAssumptionParams {\n sessionId?: string;\n taskId?: string;\n assumption: string;\n confidence: 'high' | 'medium' | 'low';\n}\n\n/**\n * Record an assumption made during a session.\n * Appends to .cleo/audit/assumptions.jsonl (creates dir if needed).\n * Throws if required params are missing or invalid.\n */\nexport async function recordAssumption(\n projectRoot: string,\n params: RecordAssumptionParams,\n): Promise<Omit<AssumptionRecord, 'validatedAt'> & { timestamp: string }> {\n if (!params?.assumption) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n 'assumption is required',\n );\n }\n\n if (\n !params?.confidence ||\n !['high', 'medium', 'low'].includes(params.confidence)\n ) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n 'confidence must be one of: high, medium, low',\n );\n }\n\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const todo = todoData as unknown as TodoFileExt;\n\n const sessionId =\n params.sessionId || todo._meta?.activeSession || 'default';\n const id = `asm-${randomBytes(8).toString('hex')}`;\n const now = new Date().toISOString();\n\n const record: AssumptionRecord = {\n id,\n sessionId,\n taskId: params.taskId || null,\n assumption: params.assumption,\n confidence: params.confidence,\n validatedAt: null,\n timestamp: now,\n };\n\n const auditDir = join(projectRoot, '.cleo', 'audit');\n if (!existsSync(auditDir)) {\n mkdirSync(auditDir, { recursive: true });\n }\n\n const assumptionsPath = join(auditDir, 'assumptions.jsonl');\n appendFileSync(assumptionsPath, JSON.stringify(record) + '\\n', 'utf-8');\n\n return {\n id,\n sessionId,\n taskId: params.taskId || null,\n assumption: params.assumption,\n confidence: params.confidence,\n timestamp: now,\n };\n}\n", "/**\n * Cross-Session Pipeline Resume Flow\n *\n * Enables automated cross-session pipeline resume using the SQLite lifecycle schema.\n * Integrates with session initialization to check for and present resumable work.\n *\n * @task T4805 - Implement SQLite-backed Cross-Session Resume Flow\n * @epic T4798 - Lifecycle persistence improvements\n * @ref T4801 - SQLite schema with lifecycle tables\n * @ref T4800 - Pipeline state machine\n * @ref T4804 - Gate/evidence recording stubs\n * @ref T4798 - RCSD-IVTR lifecycle\n *\n * Functions:\n * - findResumablePipelines(): Query active pipelines from SQLite\n * - loadPipelineContext(): Load stage context via SQL JOINs\n * - resumeStage(): Resume a specific stage\n * - autoResume(): Auto-detect where to resume\n *\n * Usage:\n * ```typescript\n * import { findResumablePipelines, autoResume } from './resume.js';\n *\n * // Check for resumable work on session start\n * const resumable = await findResumablePipelines();\n * if (resumable.length > 0) {\n * console.log(`Found ${resumable.length} resumable pipelines`);\n * }\n *\n * // Auto-detect resume point\n * const resumePoint = await autoResume();\n * if (resumePoint.canResume) {\n * await resumeStage(resumePoint.taskId, resumePoint.stage);\n * }\n * ```\n */\n\nimport { eq, and, inArray, desc, asc, sql as drizzleSql } from 'drizzle-orm';\nimport { getDb } from '../../store/sqlite.js';\nimport * as schema from '../../store/schema.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Stage } from './stages.js';\nimport { validateStage, getNextStage } from './stages.js';\n\n// =============================================================================\n// TYPE DEFINITIONS\n// =============================================================================\n\n/**\n * Database stage status values from schema.\n * @ref T4801\n */\ntype DbStageStatus = 'pending' | 'active' | 'blocked' | 'completed' | 'skipped';\n\n/**\n * Resumable pipeline information returned to callers.\n *\n * @task T4805\n * @ref T4798\n */\nexport interface ResumablePipeline {\n /** Task ID (e.g., T4805) */\n taskId: string;\n\n /** Pipeline ID */\n pipelineId: string;\n\n /** Current stage in the pipeline */\n currentStage: Stage;\n\n /** Pipeline status */\n status: 'active' | 'completed' | 'aborted';\n\n /** When the pipeline started */\n startedAt: Date;\n\n /** When the pipeline was last updated */\n updatedAt: Date;\n\n /** Task title */\n taskTitle: string;\n\n /** Current stage status */\n stageStatus: DbStageStatus;\n\n /** Stage started at (if active) */\n stageStartedAt?: Date;\n\n /** Block reason if blocked */\n blockReason?: string;\n\n /** Previous session ID if known */\n previousSessionId?: string;\n\n /** Resume priority (lower = higher priority) */\n resumePriority: number;\n}\n\n/**\n * Pipeline context for session resume.\n *\n * @task T4805\n */\nexport interface PipelineContext {\n /** Task ID */\n taskId: string;\n\n /** Pipeline ID */\n pipelineId: string;\n\n /** Current stage */\n currentStage: Stage;\n\n /** All stages with their status */\n stages: StageContext[];\n\n /** Gate results for current stage */\n gateResults: GateResultContext[];\n\n /** Evidence linked to current stage */\n evidence: EvidenceContext[];\n\n /** Recent transitions */\n recentTransitions: TransitionContext[];\n\n /** Task details */\n task: TaskContext;\n}\n\n/**\n * Stage context within a pipeline.\n *\n * @task T4805\n */\nexport interface StageContext {\n /** Stage name */\n stage: Stage;\n\n /** Stage status */\n status: DbStageStatus;\n\n /** Sequence order */\n sequence: number;\n\n /** When started */\n startedAt?: Date;\n\n /** When completed */\n completedAt?: Date;\n\n /** Block information */\n blockedAt?: Date;\n blockReason?: string;\n\n /** Skip information */\n skippedAt?: Date;\n skipReason?: string;\n\n /** Stage notes */\n notes: string[];\n\n /** Stage metadata */\n metadata: Record<string, unknown>;\n}\n\n/**\n * Gate result context.\n *\n * @task T4805\n * @ref T4804\n */\nexport interface GateResultContext {\n /** Gate name */\n gateName: string;\n\n /** Result status */\n result: 'pass' | 'fail' | 'warn';\n\n /** When checked */\n checkedAt: Date;\n\n /** Who checked */\n checkedBy: string;\n\n /** Details */\n details?: string;\n\n /** Reason if failed */\n reason?: string;\n}\n\n/**\n * Evidence context.\n *\n * @task T4805\n * @ref T4804\n */\nexport interface EvidenceContext {\n /** Evidence ID */\n id: string;\n\n /** URI to evidence */\n uri: string;\n\n /** Evidence type */\n type: 'file' | 'url' | 'manifest';\n\n /** When recorded */\n recordedAt: Date;\n\n /** Who recorded */\n recordedBy?: string;\n\n /** Description */\n description?: string;\n}\n\n/**\n * Transition context.\n *\n * @task T4805\n */\nexport interface TransitionContext {\n /** From stage */\n fromStage: string;\n\n /** To stage */\n toStage: string;\n\n /** When transitioned */\n transitionedAt: Date;\n\n /** Who initiated */\n transitionedBy: string;\n\n /** Reason */\n reason?: string;\n}\n\n/**\n * Task context.\n *\n * @task T4805\n */\nexport interface TaskContext {\n /** Task ID */\n id: string;\n\n /** Task title */\n title: string;\n\n /** Task description */\n description?: string;\n\n /** Task status */\n status: string;\n\n /** Task priority */\n priority: string;\n\n /** Parent task ID */\n parentId?: string;\n}\n\n/**\n * Result of a resume operation.\n *\n * @task T4805\n */\nexport interface ResumeResult {\n /** Whether resume was successful */\n success: boolean;\n\n /** Task ID */\n taskId: string;\n\n /** Stage resumed */\n stage: Stage;\n\n /** Previous status */\n previousStatus: DbStageStatus;\n\n /** New status */\n newStatus: DbStageStatus;\n\n /** Resume timestamp */\n resumedAt: Date;\n\n /** Message for user */\n message: string;\n\n /** Any warnings */\n warnings: string[];\n}\n\n/**\n * Auto-resume detection result.\n *\n * @task T4805\n */\nexport interface AutoResumeResult {\n /** Whether auto-resume is possible */\n canResume: boolean;\n\n /** Task ID to resume */\n taskId?: string;\n\n /** Stage to resume */\n stage?: Stage;\n\n /** Pipeline context if available */\n context?: PipelineContext;\n\n /** Resume options if multiple */\n options?: ResumablePipeline[];\n\n /** Recommended action */\n recommendation: 'resume' | 'choose' | 'none';\n\n /** Message for user */\n message: string;\n}\n\n/**\n * Options for finding resumable pipelines.\n *\n * @task T4805\n */\nexport interface FindResumableOptions {\n /** Filter by specific task IDs */\n taskIds?: string[];\n\n /** Filter by stages */\n stages?: Stage[];\n\n /** Include blocked pipelines */\n includeBlocked?: boolean;\n\n /** Include aborted pipelines */\n includeAborted?: boolean;\n\n /** Maximum results */\n limit?: number;\n\n /** Minimum priority (tasks with priority >= this) */\n minPriority?: 'critical' | 'high' | 'medium' | 'low';\n}\n\n// =============================================================================\n// CORE FUNCTIONS\n// =============================================================================\n\n/**\n * Query active pipelines that can be resumed.\n *\n * Searches the lifecycle_pipelines table for pipelines with status 'active'\n * and joins with lifecycle_stages to determine current stage status.\n * Also joins with tasks table to get task metadata.\n *\n * @param options - Query options for filtering\n * @param cwd - Working directory for database\n * @returns Promise resolving to array of resumable pipelines\n *\n * @example\n * ```typescript\n * // Find all active pipelines\n * const resumable = await findResumablePipelines();\n *\n * // Find specific tasks\n * const specific = await findResumablePipelines({\n * taskIds: ['T4805', 'T4806']\n * });\n *\n * // Include blocked pipelines\n * const withBlocked = await findResumablePipelines({\n * includeBlocked: true\n * });\n * ```\n *\n * @task T4805\n * @ref T4801 - Uses lifecycle_pipelines, lifecycle_stages tables\n */\nexport async function findResumablePipelines(\n options: FindResumableOptions = {},\n cwd?: string,\n): Promise<ResumablePipeline[]> {\n const db = await getDb(cwd);\n\n // Build base query conditions\n const conditions = [\n eq(schema.lifecyclePipelines.status, 'active'),\n ];\n\n if (options.taskIds && options.taskIds.length > 0) {\n conditions.push(inArray(schema.lifecyclePipelines.taskId, options.taskIds));\n }\n\n // Query all active pipelines with their stages and tasks\n // We need to find the current stage for each pipeline\n const results = await db\n .select({\n pipeline: schema.lifecyclePipelines,\n stage: schema.lifecycleStages,\n task: schema.tasks,\n })\n .from(schema.lifecyclePipelines)\n .innerJoin(\n schema.lifecycleStages,\n eq(schema.lifecycleStages.pipelineId, schema.lifecyclePipelines.id),\n )\n .innerJoin(\n schema.tasks,\n eq(schema.tasks.id, schema.lifecyclePipelines.taskId),\n )\n .where(and(...conditions))\n .orderBy(\n asc(schema.tasks.priority),\n desc(schema.lifecyclePipelines.startedAt),\n )\n .all();\n\n // Group by pipeline and find current stage for each\n const pipelineMap = new Map<string, typeof results[0]>();\n \n for (const row of results) {\n const pipelineId = row.pipeline.id;\n const currentStageId = row.pipeline.currentStageId;\n \n // If this row's stage matches the pipeline's current stage, use it\n if (currentStageId && row.stage.stageName === currentStageId) {\n pipelineMap.set(pipelineId, row);\n } else if (!pipelineMap.has(pipelineId)) {\n // Otherwise, keep the first one we find and check if it matches\n pipelineMap.set(pipelineId, row);\n }\n }\n\n // Map to ResumablePipeline format\n let pipelines: ResumablePipeline[] = Array.from(pipelineMap.values()).map((row) => ({\n taskId: row.pipeline.taskId,\n pipelineId: row.pipeline.id,\n currentStage: row.stage.stageName as Stage,\n status: row.pipeline.status as 'active' | 'completed' | 'aborted',\n startedAt: new Date(row.pipeline.startedAt),\n updatedAt: row.pipeline.completedAt\n ? new Date(row.pipeline.completedAt)\n : new Date(row.pipeline.startedAt),\n taskTitle: row.task.title,\n stageStatus: row.stage.status as DbStageStatus,\n stageStartedAt: row.stage.startedAt ? new Date(row.stage.startedAt) : undefined,\n blockReason: row.stage.blockReason || undefined,\n resumePriority: calculateResumePriority(row.task.priority, row.stage.status),\n }));\n\n // Filter by stage if specified\n if (options.stages && options.stages.length > 0) {\n pipelines = pipelines.filter((p) => options.stages!.includes(p.currentStage));\n }\n\n // Filter by status if needed\n if (!options.includeBlocked) {\n pipelines = pipelines.filter((p) => p.stageStatus !== 'blocked');\n }\n\n // Filter by minimum priority\n if (options.minPriority) {\n const priorityOrder = { critical: 1, high: 2, medium: 3, low: 4 };\n const minValue = priorityOrder[options.minPriority];\n pipelines = pipelines.filter((p) => {\n const row = results.find((r) => r.pipeline.taskId === p.taskId);\n if (!row) return false;\n const taskPriorityValue = priorityOrder[row.task.priority as keyof typeof priorityOrder] || 4;\n return taskPriorityValue <= minValue;\n });\n }\n\n // Sort by resume priority\n pipelines.sort((a, b) => a.resumePriority - b.resumePriority);\n\n // Apply limit\n if (options.limit) {\n pipelines = pipelines.slice(0, options.limit);\n }\n\n return pipelines;\n}\n\n/**\n * Calculate resume priority based on task priority and stage status.\n *\n * @param priority - Task priority\n * @param stageStatus - Current stage status\n * @returns Priority number (lower = higher priority)\n *\n * @task T4805\n */\nfunction calculateResumePriority(\n priority: string | null | undefined,\n stageStatus: string | null | undefined,\n): number {\n const priorityOrder = { critical: 1, high: 2, medium: 3, low: 4 };\n const priorityValue = priorityOrder[priority as keyof typeof priorityOrder] || 4;\n\n // Active stages get higher priority (lower number)\n const statusModifier = stageStatus === 'active' ? 0 : stageStatus === 'blocked' ? 10 : 5;\n\n return priorityValue + statusModifier;\n}\n\n/**\n * Load complete pipeline context for session resume.\n *\n * Uses SQL JOINs to efficiently load all related data:\n * - Pipeline and current stage\n * - All stages with their status\n * - Gate results for current stage\n * - Evidence linked to current stage\n * - Recent transitions\n * - Task details\n *\n * @param taskId - The task ID to load context for\n * @param cwd - Working directory for database\n * @returns Promise resolving to pipeline context\n *\n * @example\n * ```typescript\n * const context = await loadPipelineContext('T4805');\n * console.log(`Current stage: ${context.currentStage}`);\n * console.log(`Stage status: ${context.stages.find(s => s.stage === context.currentStage)?.status}`);\n * ```\n *\n * @task T4805\n * @ref T4801 - Uses lifecycle_pipelines, lifecycle_stages, lifecycle_gate_results, lifecycle_evidence tables\n * @ref T4804 - Loads gate results and evidence\n */\nexport async function loadPipelineContext(\n taskId: string,\n cwd?: string,\n): Promise<PipelineContext> {\n const db = await getDb(cwd);\n\n // Load pipeline with current stage\n const pipelineResult = await db\n .select({\n pipeline: schema.lifecyclePipelines,\n stage: schema.lifecycleStages,\n task: schema.tasks,\n })\n .from(schema.lifecyclePipelines)\n .innerJoin(\n schema.lifecycleStages,\n eq(schema.lifecycleStages.pipelineId, schema.lifecyclePipelines.id),\n )\n .innerJoin(\n schema.tasks,\n eq(schema.tasks.id, schema.lifecyclePipelines.taskId),\n )\n .where(\n and(\n eq(schema.lifecyclePipelines.taskId, taskId),\n eq(schema.lifecycleStages.stageName, drizzleSql`${schema.lifecyclePipelines.currentStageId}`),\n ),\n )\n .limit(1)\n .all();\n\n if (pipelineResult.length === 0) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `No active pipeline found for task ${taskId}`,\n {\n fix: 'Check that the task exists and has an active pipeline',\n alternatives: [\n { action: 'List active pipelines', command: 'cleo lifecycle list --status active' },\n ],\n },\n );\n }\n\n const { pipeline, stage, task } = pipelineResult[0];\n\n // Load all stages for this pipeline\n const stagesResult = await db\n .select()\n .from(schema.lifecycleStages)\n .where(eq(schema.lifecycleStages.pipelineId, pipeline.id))\n .orderBy(asc(schema.lifecycleStages.sequence))\n .all();\n\n const stages: StageContext[] = stagesResult.map((s) => ({\n stage: s.stageName as Stage,\n status: s.status as DbStageStatus,\n sequence: s.sequence,\n startedAt: s.startedAt ? new Date(s.startedAt) : undefined,\n completedAt: s.completedAt ? new Date(s.completedAt) : undefined,\n blockedAt: s.blockedAt ? new Date(s.blockedAt) : undefined,\n blockReason: s.blockReason || undefined,\n skippedAt: s.skippedAt ? new Date(s.skippedAt) : undefined,\n skipReason: s.skipReason || undefined,\n notes: s.notesJson ? JSON.parse(s.notesJson) : [],\n metadata: s.metadataJson ? JSON.parse(s.metadataJson) : {},\n }));\n\n // Load gate results for current stage\n const gateResultsResult = await db\n .select()\n .from(schema.lifecycleGateResults)\n .where(eq(schema.lifecycleGateResults.stageId, stage.id))\n .orderBy(desc(schema.lifecycleGateResults.checkedAt))\n .all();\n\n const gateResults: GateResultContext[] = gateResultsResult.map((g) => ({\n gateName: g.gateName,\n result: g.result as 'pass' | 'fail' | 'warn',\n checkedAt: new Date(g.checkedAt),\n checkedBy: g.checkedBy,\n details: g.details || undefined,\n reason: g.reason || undefined,\n }));\n\n // Load evidence for current stage\n const evidenceResult = await db\n .select()\n .from(schema.lifecycleEvidence)\n .where(eq(schema.lifecycleEvidence.stageId, stage.id))\n .orderBy(desc(schema.lifecycleEvidence.recordedAt))\n .all();\n\n const evidence: EvidenceContext[] = evidenceResult.map((e) => ({\n id: e.id,\n uri: e.uri,\n type: e.type as 'file' | 'url' | 'manifest',\n recordedAt: new Date(e.recordedAt),\n recordedBy: e.recordedBy || undefined,\n description: e.description || undefined,\n }));\n\n // Load recent transitions\n const transitionsResult = await db\n .select()\n .from(schema.lifecycleTransitions)\n .where(eq(schema.lifecycleTransitions.pipelineId, pipeline.id))\n .orderBy(desc(schema.lifecycleTransitions.createdAt))\n .limit(10)\n .all();\n\n const recentTransitions: TransitionContext[] = transitionsResult.map((t) => ({\n fromStage: t.fromStageId,\n toStage: t.toStageId,\n transitionedAt: new Date(t.createdAt),\n transitionedBy: 'system', // TODO: Store agent in transitions table\n reason: undefined,\n }));\n\n return {\n taskId,\n pipelineId: pipeline.id,\n currentStage: stage.stageName as Stage,\n stages,\n gateResults,\n evidence,\n recentTransitions,\n task: {\n id: task.id,\n title: task.title,\n description: task.description || undefined,\n status: task.status,\n priority: task.priority,\n parentId: task.parentId || undefined,\n },\n };\n}\n\n/**\n * Resume a specific stage in a pipeline.\n *\n * Updates the stage status from 'blocked' or 'pending' to 'active',\n * records the transition, and returns the resume result.\n *\n * @param taskId - The task ID\n * @param targetStage - The stage to resume\n * @param options - Resume options\n * @param cwd - Working directory for database\n * @returns Promise resolving to resume result\n *\n * @example\n * ```typescript\n * const result = await resumeStage('T4805', 'implement');\n * if (result.success) {\n * console.log(`Resumed ${result.taskId} at ${result.stage}`);\n * }\n * ```\n *\n * @task T4805\n * @ref T4801 - Updates lifecycle_stages table\n * @ref T4800 - Integrates with pipeline state machine\n */\nexport async function resumeStage(\n taskId: string,\n targetStage: Stage,\n options: {\n reason?: string;\n agent?: string;\n force?: boolean;\n } = {},\n cwd?: string,\n): Promise<ResumeResult> {\n const validatedStage = validateStage(targetStage);\n const db = await getDb(cwd);\n\n // Find the pipeline and stage\n const pipelineResult = await db\n .select({\n pipeline: schema.lifecyclePipelines,\n stageRecord: schema.lifecycleStages,\n })\n .from(schema.lifecyclePipelines)\n .innerJoin(\n schema.lifecycleStages,\n and(\n eq(schema.lifecycleStages.pipelineId, schema.lifecyclePipelines.id),\n eq(schema.lifecycleStages.stageName, validatedStage),\n ),\n )\n .where(eq(schema.lifecyclePipelines.taskId, taskId))\n .limit(1)\n .all();\n\n if (pipelineResult.length === 0) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `No pipeline found for task ${taskId} with stage ${validatedStage}`,\n );\n }\n\n const { pipeline, stageRecord } = pipelineResult[0];\n\n // Check if resume is possible\n const previousStatus = stageRecord.status as DbStageStatus;\n const warnings: string[] = [];\n\n if (previousStatus === 'completed') {\n if (!options.force) {\n throw new CleoError(\n ExitCode.LIFECYCLE_TRANSITION_INVALID,\n `Stage ${validatedStage} is already completed. Use force=true to resume completed stages.`,\n );\n }\n warnings.push(`Resuming already-completed stage ${validatedStage}`);\n }\n\n if (previousStatus === 'active') {\n return {\n success: true,\n taskId,\n stage: validatedStage,\n previousStatus,\n newStatus: 'active',\n resumedAt: new Date(),\n message: `Stage ${validatedStage} is already active`,\n warnings: [],\n };\n }\n\n const now = new Date();\n\n // Update stage status to active\n await db\n .update(schema.lifecycleStages)\n .set({\n status: 'active',\n startedAt: now.toISOString(),\n blockedAt: null,\n blockReason: null,\n })\n .where(eq(schema.lifecycleStages.id, stageRecord.id))\n .run();\n\n // Record the resume transition\n const previousStage = pipeline.currentStageId;\n if (previousStage && previousStage !== validatedStage) {\n await db\n .insert(schema.lifecycleTransitions)\n .values({\n id: `transition-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n pipelineId: pipeline.id,\n fromStageId: previousStage,\n toStageId: stageRecord.id,\n transitionType: 'manual',\n createdAt: now.toISOString(),\n })\n .run();\n }\n\n // Update pipeline current stage if different\n if (pipeline.currentStageId !== validatedStage) {\n await db\n .update(schema.lifecyclePipelines)\n .set({\n currentStageId: validatedStage,\n })\n .where(eq(schema.lifecyclePipelines.id, pipeline.id))\n .run();\n }\n\n return {\n success: true,\n taskId,\n stage: validatedStage,\n previousStatus,\n newStatus: 'active',\n resumedAt: now,\n message: `Resumed ${taskId} at stage ${validatedStage}`,\n warnings,\n };\n}\n\n/**\n * Auto-detect where to resume across all active pipelines.\n *\n * Finds the best candidate for resuming work based on:\n * 1. Active stages (currently in progress)\n * 2. Blocked stages (can be unblocked)\n * 3. Failed stages (can be retried)\n * 4. Priority ordering\n *\n * @param cwd - Working directory for database\n * @returns Promise resolving to auto-resume result\n *\n * @example\n * ```typescript\n * const result = await autoResume();\n * if (result.canResume) {\n * console.log(`Recommended: Resume ${result.taskId} at ${result.stage}`);\n * } else if (result.options && result.options.length > 0) {\n * console.log('Multiple options available:', result.options);\n * }\n * ```\n *\n * @task T4805\n * @ref T4801 - Queries lifecycle_pipelines, lifecycle_stages tables\n * @ref T4798 - Implements RCSD-IVTR resume logic\n */\nexport async function autoResume(cwd?: string): Promise<AutoResumeResult> {\n const db = await getDb(cwd);\n\n // Find all active pipelines with their current stages\n const activePipelines = await db\n .select({\n pipeline: schema.lifecyclePipelines,\n stage: schema.lifecycleStages,\n task: schema.tasks,\n })\n .from(schema.lifecyclePipelines)\n .innerJoin(\n schema.lifecycleStages,\n eq(schema.lifecycleStages.pipelineId, schema.lifecyclePipelines.id),\n )\n .innerJoin(\n schema.tasks,\n eq(schema.tasks.id, schema.lifecyclePipelines.taskId),\n )\n .where(eq(schema.lifecyclePipelines.status, 'active'))\n .orderBy(asc(schema.tasks.priority), desc(schema.lifecycleStages.startedAt))\n .all();\n\n if (activePipelines.length === 0) {\n return {\n canResume: false,\n recommendation: 'none',\n message: 'No active pipelines found for resume',\n };\n }\n\n // Score and rank resume candidates\n interface Candidate {\n taskId: string;\n stage: Stage;\n stageStatus: DbStageStatus;\n pipelineId: string;\n score: number;\n reason: string;\n }\n\n const candidates: Candidate[] = activePipelines.map((row) => {\n const stageStatus = row.stage.status as DbStageStatus;\n const priority = row.task.priority;\n let score = 0;\n let reason = '';\n\n // Score based on stage status\n switch (stageStatus) {\n case 'active':\n score = 100;\n reason = 'Stage already active';\n break;\n case 'blocked':\n score = 70;\n reason = 'Blocked stage can be unblocked';\n break;\n case 'pending':\n score = 40;\n reason = 'Pending stage ready to start';\n break;\n case 'completed':\n case 'skipped':\n // These are lower priority - pipeline might need to advance\n score = 20;\n reason = 'Stage completed, may need to advance';\n break;\n default:\n score = 30;\n reason = 'Unknown stage status';\n }\n\n // Adjust score based on priority\n const priorityMultiplier = { critical: 2.0, high: 1.5, medium: 1.0, low: 0.8 };\n score *= priorityMultiplier[priority as keyof typeof priorityMultiplier] || 1.0;\n\n // Boost score for recently started stages\n if (row.stage.startedAt) {\n const hoursSinceStart = (Date.now() - new Date(row.stage.startedAt).getTime()) / (1000 * 60 * 60);\n if (hoursSinceStart < 24) {\n score *= 1.2; // Boost recent work\n }\n }\n\n return {\n taskId: row.pipeline.taskId,\n stage: row.stage.stageName as Stage,\n stageStatus,\n pipelineId: row.pipeline.id,\n score,\n reason,\n };\n });\n\n // Sort by score descending\n candidates.sort((a, b) => b.score - a.score);\n\n // Get top candidates\n const topCandidate = candidates[0];\n const highScoreCandidates = candidates.filter((c) => c.score >= 80);\n\n if (highScoreCandidates.length === 1) {\n // Clear winner - load context and recommend\n const context = await loadPipelineContext(topCandidate.taskId, cwd);\n return {\n canResume: true,\n taskId: topCandidate.taskId,\n stage: topCandidate.stage,\n context,\n recommendation: 'resume',\n message: `Resume ${topCandidate.taskId} at ${topCandidate.stage}: ${topCandidate.reason}`,\n };\n }\n\n if (highScoreCandidates.length > 1) {\n // Multiple good options - present choices\n const options = await findResumablePipelines(\n {\n taskIds: highScoreCandidates.map((c) => c.taskId),\n limit: 5,\n },\n cwd,\n );\n\n return {\n canResume: true,\n recommendation: 'choose',\n message: `Found ${highScoreCandidates.length} resumable pipelines. Please choose one.`,\n options,\n };\n }\n\n // No high-scoring candidates but some pipelines exist\n if (candidates.length > 0) {\n // Check if we should advance any pipelines\n const completedStages = candidates.filter((c) => c.stageStatus === 'completed' || c.stageStatus === 'skipped');\n\n if (completedStages.length > 0) {\n // These pipelines may need to advance to next stage\n return {\n canResume: false,\n recommendation: 'none',\n message: `Found ${completedStages.length} pipelines that may need to advance to next stage`,\n };\n }\n\n // Return all options for user to choose\n const options = await findResumablePipelines({ limit: 5 }, cwd);\n return {\n canResume: true,\n recommendation: 'choose',\n message: `Found ${candidates.length} potential resume points. Please review options.`,\n options,\n };\n }\n\n return {\n canResume: false,\n recommendation: 'none',\n message: 'No suitable resume points found',\n };\n}\n\n// =============================================================================\n// SESSION INTEGRATION\n// =============================================================================\n\n/**\n * Options for session start with resume check.\n *\n * @task T4805\n */\nexport interface SessionResumeCheckOptions {\n /** Whether to auto-resume if only one candidate */\n autoResume?: boolean;\n\n /** Scope to filter resumable pipelines */\n scope?: {\n type: 'epic' | 'global';\n epicId?: string;\n };\n\n /** Minimum priority to consider */\n minPriority?: 'critical' | 'high' | 'medium' | 'low';\n\n /** Whether to include blocked pipelines */\n includeBlocked?: boolean;\n}\n\n/**\n * Result of session resume check.\n *\n * @task T4805\n */\nexport interface SessionResumeCheckResult {\n /** Whether resume was performed */\n didResume: boolean;\n\n /** Resumed task ID if auto-resumed */\n resumedTaskId?: string;\n\n /** Resumed stage if auto-resumed */\n resumedStage?: Stage;\n\n /** Available resume options if not auto-resumed */\n options?: ResumablePipeline[];\n\n /** Message for user */\n message: string;\n\n /** Whether user action is required */\n requiresUserChoice: boolean;\n}\n\n/**\n * Check for resumable work on session start.\n *\n * Integrates with session initialization to check for active pipelines\n * and present resumable work to the user. Can auto-resume if there's\n * a clear single candidate.\n *\n * @param options - Resume check options\n * @param cwd - Working directory for database\n * @returns Promise resolving to resume check result\n *\n * @example\n * ```typescript\n * // On session start\n * const resumeCheck = await checkSessionResume({ autoResume: true });\n * if (resumeCheck.didResume) {\n * console.log(`Auto-resumed ${resumeCheck.resumedTaskId}`);\n * } else if (resumeCheck.requiresUserChoice) {\n * console.log('Multiple options:', resumeCheck.options);\n * }\n * ```\n *\n * @task T4805\n * @integration Session Start Hook\n */\nexport async function checkSessionResume(\n options: SessionResumeCheckOptions = {},\n cwd?: string,\n): Promise<SessionResumeCheckResult> {\n // Find resumable pipelines\n const findOptions: FindResumableOptions = {\n includeBlocked: options.includeBlocked ?? true,\n minPriority: options.minPriority,\n limit: 10,\n };\n\n const resumable = await findResumablePipelines(findOptions, cwd);\n\n if (resumable.length === 0) {\n return {\n didResume: false,\n message: 'No resumable pipelines found. Starting fresh session.',\n requiresUserChoice: false,\n };\n }\n\n // Filter by scope if provided\n let filtered = resumable;\n if (options.scope?.type === 'epic' && options.scope.epicId) {\n // For epic scope, we'd need to check task parent hierarchy\n // This is a simplified version\n filtered = resumable.filter((r) => r.taskId === options.scope!.epicId || r.taskId.startsWith(options.scope!.epicId!));\n }\n\n if (filtered.length === 0) {\n return {\n didResume: false,\n message: `No resumable pipelines in scope ${options.scope?.type === 'epic' ? options.scope.epicId : 'global'}.`,\n requiresUserChoice: false,\n };\n }\n\n // If only one candidate and autoResume enabled, resume it\n if (filtered.length === 1 && options.autoResume) {\n const candidate = filtered[0];\n\n // Only auto-resume if stage is active, blocked, or pending\n if (['active', 'blocked', 'pending'].includes(candidate.stageStatus)) {\n try {\n await resumeStage(\n candidate.taskId,\n candidate.currentStage,\n { reason: 'Auto-resumed on session start' },\n cwd,\n );\n\n return {\n didResume: true,\n resumedTaskId: candidate.taskId,\n resumedStage: candidate.currentStage,\n message: `Auto-resumed ${candidate.taskId} at ${candidate.currentStage} stage`,\n requiresUserChoice: false,\n };\n } catch (error) {\n // Auto-resume failed, present options\n return {\n didResume: false,\n options: filtered,\n message: `Found ${filtered.length} resumable pipeline(s). Auto-resume failed, please choose.`,\n requiresUserChoice: true,\n };\n }\n }\n }\n\n // Multiple candidates or auto-resume disabled - present options\n return {\n didResume: false,\n options: filtered,\n message:\n filtered.length === 1\n ? `Found 1 resumable pipeline: ${filtered[0].taskTitle} (${filtered[0].taskId})`\n : `Found ${filtered.length} resumable pipelines. Please choose one to resume.`,\n requiresUserChoice: true,\n };\n}\n\n/**\n * Get resume summary for display to user.\n *\n * Formats resumable pipelines into a human-readable summary.\n *\n * @param pipelines - Resumable pipelines\n * @returns Formatted summary string\n *\n * @task T4805\n */\nexport function formatResumeSummary(pipelines: ResumablePipeline[]): string {\n if (pipelines.length === 0) {\n return 'No resumable pipelines found.';\n }\n\n const lines: string[] = [`Found ${pipelines.length} resumable pipeline(s):`, ''];\n\n pipelines.forEach((p, index) => {\n const statusIcon = p.stageStatus === 'active' ? '\u25B6' : p.stageStatus === 'blocked' ? '\u23F8' : '\u23F9';\n const priorityIcon = p.taskTitle.toLowerCase().includes('critical')\n ? '\uD83D\uDD34'\n : p.taskTitle.toLowerCase().includes('high')\n ? '\uD83D\uDFE0'\n : '\uD83D\uDFE1';\n\n lines.push(`${index + 1}. ${statusIcon} ${priorityIcon} ${p.taskTitle}`);\n lines.push(` Task: ${p.taskId} | Stage: ${p.currentStage} (${p.stageStatus})`);\n\n if (p.blockReason) {\n lines.push(` Blocked: ${p.blockReason}`);\n }\n\n if (p.stageStartedAt) {\n const hoursAgo = Math.floor((Date.now() - p.stageStartedAt.getTime()) / (1000 * 60 * 60));\n lines.push(` Started: ${hoursAgo}h ago`);\n }\n\n lines.push('');\n });\n\n lines.push('Use `cleo lifecycle resume <taskId>` to resume a specific pipeline.');\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// EDGE CASE HANDLING\n// =============================================================================\n\n/**\n * Handle completed stage edge case.\n *\n * If the current stage is completed, suggests advancing to next stage.\n *\n * @param context - Pipeline context\n * @returns Recommendation for handling completed stage\n *\n * @task T4805\n */\nexport function handleCompletedStage(context: PipelineContext): {\n action: 'advance' | 'stay' | 'review';\n message: string;\n nextStage?: Stage;\n} {\n const currentStageContext = context.stages.find((s) => s.stage === context.currentStage);\n\n if (!currentStageContext || currentStageContext.status !== 'completed') {\n return {\n action: 'stay',\n message: `Stage ${context.currentStage} is not completed`,\n };\n }\n\n const nextStage = getNextStage(context.currentStage);\n\n if (!nextStage) {\n return {\n action: 'review',\n message: `All stages completed for ${context.taskId}. Pipeline is ready for completion.`,\n };\n }\n\n return {\n action: 'advance',\n message: `Stage ${context.currentStage} is completed. Ready to advance to ${nextStage}.`,\n nextStage,\n };\n}\n\n/**\n * Handle blocked stage edge case.\n *\n * Provides information about why a stage is blocked and potential resolutions.\n *\n * @param context - Pipeline context\n * @returns Block analysis and resolution hints\n *\n * @task T4805\n */\nexport function handleBlockedStage(context: PipelineContext): {\n isBlocked: boolean;\n blockReason?: string;\n blockedSince?: Date;\n resolutions: string[];\n canUnblock: boolean;\n} {\n const currentStageContext = context.stages.find((s) => s.stage === context.currentStage);\n\n if (!currentStageContext || currentStageContext.status !== 'blocked') {\n return {\n isBlocked: false,\n canUnblock: false,\n resolutions: [],\n };\n }\n\n const resolutions: string[] = [];\n\n // Check gate results for failures\n const failedGates = context.gateResults.filter((g) => g.result === 'fail');\n if (failedGates.length > 0) {\n resolutions.push(`Address failed gate(s): ${failedGates.map((g) => g.gateName).join(', ')}`);\n }\n\n // Check for missing evidence\n if (context.evidence.length === 0) {\n resolutions.push('Add required evidence to complete stage');\n }\n\n // Check prerequisite stages\n const prerequisiteStages = context.stages.filter(\n (s) => s.sequence < currentStageContext.sequence && s.status !== 'completed' && s.status !== 'skipped',\n );\n if (prerequisiteStages.length > 0) {\n resolutions.push(`Complete prerequisite stage(s): ${prerequisiteStages.map((s) => s.stage).join(', ')}`);\n }\n\n // Generic resolution\n if (resolutions.length === 0) {\n resolutions.push('Review block reason and address underlying issue');\n resolutions.push('Use force flag to override block if appropriate');\n }\n\n return {\n isBlocked: true,\n blockReason: currentStageContext.blockReason,\n blockedSince: currentStageContext.blockedAt,\n resolutions,\n canUnblock: resolutions.length > 0,\n };\n}\n\n/**\n * Handle blocked stage edge case - async version with database lookup.\n *\n * @param taskId - Task ID to check\n * @param cwd - Working directory\n * @returns Block analysis with prerequisite details\n *\n * @task T4805\n */\nexport async function checkBlockedStageDetails(\n taskId: string,\n cwd?: string,\n): Promise<{\n isBlocked: boolean;\n blockReason?: string;\n blockedSince?: Date;\n resolutions: string[];\n canUnblock: boolean;\n prerequisites?: { stage: Stage; status: DbStageStatus; completed: boolean }[];\n}> {\n const db = await getDb(cwd);\n\n // Find pipeline and current stage\n const pipelineResult = await db\n .select({\n pipeline: schema.lifecyclePipelines,\n stage: schema.lifecycleStages,\n })\n .from(schema.lifecyclePipelines)\n .innerJoin(\n schema.lifecycleStages,\n eq(schema.lifecycleStages.pipelineId, schema.lifecyclePipelines.id),\n )\n .where(\n and(\n eq(schema.lifecyclePipelines.taskId, taskId),\n eq(schema.lifecycleStages.stageName, drizzleSql`${schema.lifecyclePipelines.currentStageId}`),\n ),\n )\n .limit(1)\n .all();\n\n if (pipelineResult.length === 0) {\n return {\n isBlocked: false,\n canUnblock: false,\n resolutions: ['No pipeline found for task'],\n };\n }\n\n const { pipeline, stage } = pipelineResult[0];\n const stageStatus = stage.status as DbStageStatus;\n\n if (stageStatus !== 'blocked') {\n return {\n isBlocked: false,\n canUnblock: false,\n resolutions: [],\n };\n }\n\n // Get all stages to check prerequisites\n const allStages = await db\n .select()\n .from(schema.lifecycleStages)\n .where(eq(schema.lifecycleStages.pipelineId, pipeline.id))\n .orderBy(asc(schema.lifecycleStages.sequence))\n .all();\n\n const currentSequence = stage.sequence;\n const prerequisites = allStages\n .filter((s) => s.sequence < currentSequence)\n .map((s) => ({\n stage: s.stageName as Stage,\n status: s.status as DbStageStatus,\n completed: s.status === 'completed' || s.status === 'skipped',\n }));\n\n const incompletePrereqs = prerequisites.filter((p) => !p.completed);\n\n const resolutions: string[] = [];\n\n if (stage.blockReason) {\n resolutions.push(`Address block reason: ${stage.blockReason}`);\n }\n\n if (incompletePrereqs.length > 0) {\n resolutions.push(\n `Complete prerequisite stage(s): ${incompletePrereqs.map((p) => p.stage).join(', ')}`,\n );\n }\n\n // Check for failed gates\n const gateResults = await db\n .select()\n .from(schema.lifecycleGateResults)\n .where(eq(schema.lifecycleGateResults.stageId, stage.id))\n .all();\n\n const failedGates = gateResults.filter((g) => g.result === 'fail');\n if (failedGates.length > 0) {\n resolutions.push(`Fix failed gate(s): ${failedGates.map((g) => g.gateName).join(', ')}`);\n }\n\n if (resolutions.length === 0) {\n resolutions.push('Review pipeline state and address block conditions');\n }\n\n return {\n isBlocked: true,\n blockReason: stage.blockReason || undefined,\n blockedSince: stage.blockedAt ? new Date(stage.blockedAt) : undefined,\n resolutions,\n canUnblock: resolutions.length > 0,\n prerequisites,\n };\n}\n", "/**\n * Pipeline Stage Definitions and Transitions\n * \n * Defines the 9-stage RCSD-IVTR pipeline with stage metadata,\n * transition rules, and prerequisite mappings.\n * \n * Stages (in order):\n * 1. Research - Information gathering and exploration\n * 2. Consensus - Multi-agent decisions and validation\n * 3. ADR - Architecture Decision Records\n * 4. Spec - Specification and documentation\n * 5. Decompose - Task breakdown and planning\n * 6. Implement - Code execution and building\n * 7. Verify - Validation and quality checks\n * 8. Test - Test execution and coverage\n * 9. Release - Version management and publishing\n * \n * @task T4800 - Implement Canonical SQLite Pipeline State Machine\n * @epic T4798 - Lifecycle persistence improvements\n * @audit T4799 - Unified stage names (replaces scattered definitions)\n * \n * NOTE: This file provides the canonical stage definitions. All other\n * stage definitions in the codebase should reference these.\n */\n\n// =============================================================================\n// STAGE TYPE DEFINITIONS\n// =============================================================================\n\n/**\n * Canonical pipeline stages in execution order.\n * \n * This is the single source of truth for stage names across CLEO.\n * All other stage arrays should be derived from this.\n * \n * @task T4800\n * @audit T4799 - Consolidates: RCSD_STAGES, EXECUTION_STAGES, ENGINE_LIFECYCLE_STAGES\n */\nexport const PIPELINE_STAGES = [\n 'research',\n 'consensus',\n 'adr',\n 'spec',\n 'decompose',\n 'implement',\n 'verify',\n 'test',\n 'release',\n] as const;\n\n/**\n * Stage type derived from canonical stage list.\n * \n * @task T4800\n */\nexport type Stage = typeof PIPELINE_STAGES[number];\n\n/**\n * Stage status values.\n * \n * @task T4800\n * @audit T4799 - Unifies: StageStatus, EngineStageStatus\n */\nexport type StageStatus = \n | 'not_started' // Stage hasn't begun\n | 'in_progress' // Stage is currently active\n | 'completed' // Stage finished successfully\n | 'skipped' // Stage was intentionally bypassed\n | 'blocked' // Stage cannot proceed due to dependencies\n | 'failed'; // Stage execution failed\n\n/**\n * Stage category for grouping related stages.\n * \n * @task T4800\n */\nexport type StageCategory = 'planning' | 'decision' | 'execution' | 'validation' | 'delivery';\n\n/**\n * Stage metadata with descriptive information.\n * \n * @task T4800\n */\nexport interface StageDefinition {\n /** Stage identifier */\n stage: Stage;\n \n /** Display name for the stage */\n name: string;\n \n /** Detailed description of what happens in this stage */\n description: string;\n \n /** Execution order (1-based) */\n order: number;\n \n /** Category for grouping */\n category: StageCategory;\n \n /** Whether this stage can be skipped */\n skippable: boolean;\n \n /** Default timeout in hours (null = no timeout) */\n defaultTimeoutHours: number | null;\n \n /** Required gate checks before completing this stage */\n requiredGates: string[];\n \n /** Expected artifacts produced by this stage */\n expectedArtifacts: string[];\n}\n\n// =============================================================================\n// CANONICAL STAGE DEFINITIONS\n// =============================================================================\n\n/**\n * Canonical stage definitions with complete metadata.\n * \n * @task T4800\n * @audit T4799 - Replaces STAGE_DEFINITIONS from index.ts\n */\nexport const STAGE_DEFINITIONS: Record<Stage, StageDefinition> = {\n research: {\n stage: 'research',\n name: 'Research',\n description: 'Information gathering, exploration, and knowledge acquisition',\n order: 1,\n category: 'planning',\n skippable: false,\n defaultTimeoutHours: 48,\n requiredGates: ['prerequisites-met'],\n expectedArtifacts: ['research-report', 'findings-document'],\n },\n consensus: {\n stage: 'consensus',\n name: 'Consensus',\n description: 'Multi-agent decision making and validation of research findings',\n order: 2,\n category: 'decision',\n skippable: true,\n defaultTimeoutHours: 24,\n requiredGates: ['research-complete', 'agreement-reached'],\n expectedArtifacts: ['consensus-record', 'decision-log'],\n },\n adr: {\n stage: 'adr',\n name: 'ADR',\n description: 'Architecture Decision Records - documenting significant technical decisions',\n order: 3,\n category: 'decision',\n skippable: true,\n defaultTimeoutHours: 24,\n requiredGates: ['decisions-documented', 'review-completed'],\n expectedArtifacts: ['adr-document'],\n },\n spec: {\n stage: 'spec',\n name: 'Spec',\n description: 'Specification writing - RFC-style documentation of requirements and design',\n order: 4,\n category: 'planning',\n skippable: false,\n defaultTimeoutHours: 72,\n requiredGates: ['spec-complete', 'spec-reviewed'],\n expectedArtifacts: ['spec-document', 'api-spec', 'design-doc'],\n },\n decompose: {\n stage: 'decompose',\n name: 'Decompose',\n description: 'Task breakdown - splitting work into atomic, executable tasks',\n order: 5,\n category: 'planning',\n skippable: false,\n defaultTimeoutHours: 24,\n requiredGates: ['tasks-created', 'dependencies-mapped'],\n expectedArtifacts: ['task-breakdown', 'dependency-graph'],\n },\n implement: {\n stage: 'implement',\n name: 'Implement',\n description: 'Implementation - writing code and building features',\n order: 6,\n category: 'execution',\n skippable: false,\n defaultTimeoutHours: null, // Varies by task size\n requiredGates: ['code-complete', 'lint-passing'],\n expectedArtifacts: ['source-code', 'implementation-notes'],\n },\n verify: {\n stage: 'verify',\n name: 'Verify',\n description: 'Verification - static analysis, type checking, and quality gates',\n order: 7,\n category: 'validation',\n skippable: false,\n defaultTimeoutHours: 12,\n requiredGates: ['static-analysis-pass', 'type-check-pass'],\n expectedArtifacts: ['verification-report'],\n },\n test: {\n stage: 'test',\n name: 'Test',\n description: 'Testing - running test suites and ensuring coverage',\n order: 8,\n category: 'validation',\n skippable: false,\n defaultTimeoutHours: 24,\n requiredGates: ['tests-pass', 'coverage-met'],\n expectedArtifacts: ['test-results', 'coverage-report'],\n },\n release: {\n stage: 'release',\n name: 'Release',\n description: 'Release - versioning, publishing, and deployment',\n order: 9,\n category: 'delivery',\n skippable: true,\n defaultTimeoutHours: 4,\n requiredGates: ['version-bumped', 'changelog-updated', 'artifacts-published'],\n expectedArtifacts: ['version-tag', 'release-notes', 'published-package'],\n },\n};\n\n// =============================================================================\n// STAGE ORDER AND INDEXING\n// =============================================================================\n\n/**\n * Stage order mapping for quick lookups.\n * \n * @task T4800\n */\nexport const STAGE_ORDER: Record<Stage, number> = {\n research: 1,\n consensus: 2,\n adr: 3,\n spec: 4,\n decompose: 5,\n implement: 6,\n verify: 7,\n test: 8,\n release: 9,\n};\n\n/**\n * Get the order/index of a stage (1-based).\n * \n * @param stage - The stage to look up\n * @returns The stage order (1-9)\n * \n * @task T4800\n */\nexport function getStageOrder(stage: Stage): number {\n return STAGE_ORDER[stage];\n}\n\n/**\n * Check if stage A comes before stage B in the pipeline.\n * \n * @param stageA - First stage to compare\n * @param stageB - Second stage to compare\n * @returns True if stageA comes before stageB\n * \n * @task T4800\n */\nexport function isStageBefore(stageA: Stage, stageB: Stage): boolean {\n return STAGE_ORDER[stageA] < STAGE_ORDER[stageB];\n}\n\n/**\n * Check if stage A comes after stage B in the pipeline.\n * \n * @param stageA - First stage to compare\n * @param stageB - Second stage to compare\n * @returns True if stageA comes after stageB\n * \n * @task T4800\n */\nexport function isStageAfter(stageA: Stage, stageB: Stage): boolean {\n return STAGE_ORDER[stageA] > STAGE_ORDER[stageB];\n}\n\n/**\n * Get the next stage in the pipeline.\n * \n * @param stage - Current stage\n * @returns The next stage, or null if at the end\n * \n * @task T4800\n */\nexport function getNextStage(stage: Stage): Stage | null {\n const order = STAGE_ORDER[stage];\n if (order >= 9) return null;\n \n return PIPELINE_STAGES[order]; // order is 1-based, array is 0-based\n}\n\n/**\n * Get the previous stage in the pipeline.\n * \n * @param stage - Current stage\n * @returns The previous stage, or null if at the start\n * \n * @task T4800\n */\nexport function getPreviousStage(stage: Stage): Stage | null {\n const order = STAGE_ORDER[stage];\n if (order <= 1) return null;\n \n return PIPELINE_STAGES[order - 2]; // order is 1-based, array is 0-based\n}\n\n/**\n * Get all stages between two stages (inclusive).\n * \n * @param from - Starting stage\n * @param to - Ending stage\n * @returns Array of stages between from and to\n * \n * @task T4800\n */\nexport function getStagesBetween(from: Stage, to: Stage): Stage[] {\n const fromOrder = STAGE_ORDER[from];\n const toOrder = STAGE_ORDER[to];\n \n const start = Math.min(fromOrder, toOrder);\n const end = Math.max(fromOrder, toOrder);\n \n return PIPELINE_STAGES.slice(start - 1, end);\n}\n\n// =============================================================================\n// PREREQUISITE MAPPINGS\n// =============================================================================\n\n/**\n * Prerequisites for each stage - which stages must be completed before entering.\n * \n * @task T4800\n * @audit T4799 - Replaces STAGE_PREREQUISITES from index.ts\n */\nexport const STAGE_PREREQUISITES: Record<Stage, Stage[]> = {\n research: [], // No prerequisites\n consensus: ['research'],\n adr: ['research', 'consensus'],\n spec: ['research', 'consensus', 'adr'],\n decompose: ['research', 'spec'],\n implement: ['research', 'spec', 'decompose'],\n verify: ['implement'],\n test: ['implement', 'verify'],\n release: ['implement', 'verify', 'test'],\n};\n\n/**\n * Get prerequisites for a stage.\n * \n * @param stage - The stage to get prerequisites for\n * @returns Array of prerequisite stages\n * \n * @task T4800\n */\nexport function getPrerequisites(stage: Stage): Stage[] {\n return [...STAGE_PREREQUISITES[stage]];\n}\n\n/**\n * Check if one stage is a prerequisite of another.\n * \n * @param potentialPrereq - Stage that might be a prerequisite\n * @param stage - Stage to check against\n * @returns True if potentialPrereq is required before stage\n * \n * @task T4800\n */\nexport function isPrerequisite(potentialPrereq: Stage, stage: Stage): boolean {\n return STAGE_PREREQUISITES[stage].includes(potentialPrereq);\n}\n\n/**\n * Get all stages that depend on a given stage.\n * \n * @param stage - The stage to find dependents for\n * @returns Array of stages that require this stage\n * \n * @task T4800\n */\nexport function getDependents(stage: Stage): Stage[] {\n return PIPELINE_STAGES.filter(s => STAGE_PREREQUISITES[s].includes(stage));\n}\n\n// =============================================================================\n// STAGE VALIDATION\n// =============================================================================\n\n/**\n * Check if a stage name is valid.\n * \n * @param stage - Stage name to validate\n * @returns True if valid stage name\n * \n * @task T4800\n */\nexport function isValidStage(stage: string): stage is Stage {\n return PIPELINE_STAGES.includes(stage as Stage);\n}\n\n/**\n * Validate a stage name and throw if invalid.\n * \n * @param stage - Stage name to validate\n * @throws {Error} If stage is invalid\n * @returns The validated Stage\n * \n * @task T4800\n */\nexport function validateStage(stage: string): Stage {\n if (!isValidStage(stage)) {\n throw new Error(\n `Invalid stage: \"${stage}\". ` +\n `Valid stages: ${PIPELINE_STAGES.join(', ')}`\n );\n }\n return stage;\n}\n\n/**\n * Check if a stage status is valid.\n * \n * @param status - Status to validate\n * @returns True if valid status\n * \n * @task T4800\n */\nexport function isValidStageStatus(status: string): status is StageStatus {\n const validStatuses: StageStatus[] = [\n 'not_started',\n 'in_progress',\n 'completed',\n 'skipped',\n 'blocked',\n 'failed',\n ];\n return validStatuses.includes(status as StageStatus);\n}\n\n/**\n * Get stages by category.\n * \n * @param category - Category to filter by\n * @returns Array of stages in that category\n * \n * @task T4800\n */\nexport function getStagesByCategory(category: StageCategory): Stage[] {\n return PIPELINE_STAGES.filter(\n stage => STAGE_DEFINITIONS[stage].category === category\n );\n}\n\n/**\n * Get skippable stages.\n * \n * @returns Array of stages that can be skipped\n * \n * @task T4800\n */\nexport function getSkippableStages(): Stage[] {\n return PIPELINE_STAGES.filter(\n stage => STAGE_DEFINITIONS[stage].skippable\n );\n}\n\n// =============================================================================\n// STAGE TRANSITION RULES\n// =============================================================================\n\n/**\n * Transition rule - defines if a transition is allowed.\n * \n * @task T4800\n */\nexport interface TransitionRule {\n from: Stage | 'any';\n to: Stage | 'any';\n allowed: boolean;\n requiresForce?: boolean;\n reason?: string;\n}\n\n/**\n * Allowed transitions between stages.\n * \n * By default, stages progress linearly. These rules define exceptions.\n * \n * @task T4800\n */\nexport const TRANSITION_RULES: TransitionRule[] = [\n // Forward progressions (always allowed)\n { from: 'research', to: 'consensus', allowed: true },\n { from: 'consensus', to: 'adr', allowed: true },\n { from: 'adr', to: 'spec', allowed: true },\n { from: 'spec', to: 'decompose', allowed: true },\n { from: 'decompose', to: 'implement', allowed: true },\n { from: 'implement', to: 'verify', allowed: true },\n { from: 'verify', to: 'test', allowed: true },\n { from: 'test', to: 'release', allowed: true },\n \n // Skip patterns (allowed with force)\n { from: 'research', to: 'spec', allowed: true, requiresForce: true, reason: 'Skipping consensus and ADR' },\n { from: 'spec', to: 'implement', allowed: true, requiresForce: true, reason: 'Skipping decomposition' },\n \n // Backward transitions (allowed with force, for rework)\n { from: 'implement', to: 'spec', allowed: true, requiresForce: true, reason: 'Rework required' },\n { from: 'test', to: 'implement', allowed: true, requiresForce: true, reason: 'Fix test failures' },\n \n // Disallowed transitions\n { from: 'release', to: 'any', allowed: false, reason: 'Pipeline completed' },\n];\n\n/**\n * Check if a transition is allowed.\n * \n * @param from - Source stage\n * @param to - Target stage\n * @param force - Whether to allow forced transitions\n * @returns Object with allowed flag and reason\n * \n * @task T4800\n */\nexport function checkTransition(\n from: Stage,\n to: Stage,\n force: boolean = false\n): { allowed: boolean; requiresForce: boolean; reason?: string } {\n // Same stage - no transition needed\n if (from === to) {\n return { allowed: true, requiresForce: false };\n }\n \n // Find explicit rule\n const rule = TRANSITION_RULES.find(\n r => (r.from === from || r.from === 'any') && \n (r.to === to || r.to === 'any')\n );\n \n if (rule) {\n if (!rule.allowed) {\n return { \n allowed: false, \n requiresForce: false, \n reason: rule.reason || 'Transition not allowed' \n };\n }\n \n if (rule.requiresForce && !force) {\n return { \n allowed: false, \n requiresForce: true, \n reason: rule.reason || 'Transition requires force flag' \n };\n }\n \n return { allowed: true, requiresForce: rule.requiresForce || false };\n }\n \n // Linear forward progression is always allowed\n if (isStageBefore(from, to) && !isStageAfter(from, to)) {\n // Check if skipping any non-skippable stages\n const between = getStagesBetween(from, to);\n const nonSkippableSkipped = between\n .filter(s => s !== from && s !== to)\n .filter(s => !STAGE_DEFINITIONS[s].skippable);\n \n if (nonSkippableSkipped.length > 0) {\n return {\n allowed: false,\n requiresForce: true,\n reason: `Would skip non-skippable stages: ${nonSkippableSkipped.join(', ')}`,\n };\n }\n \n return { allowed: true, requiresForce: false };\n }\n \n // Backward progression requires force\n return {\n allowed: force,\n requiresForce: true,\n reason: 'Backward transition requires force flag',\n };\n}\n\n// =============================================================================\n// UTILITY EXPORTS\n// =============================================================================\n\n/**\n * Total number of stages in the pipeline.\n * \n * @task T4800\n */\nexport const STAGE_COUNT = PIPELINE_STAGES.length;\n\n/**\n * First stage in the pipeline.\n * \n * @task T4800\n */\nexport const FIRST_STAGE: Stage = 'research';\n\n/**\n * Last stage in the pipeline.\n * \n * @task T4800\n */\nexport const LAST_STAGE: Stage = 'release';\n\n/**\n * Planning stages.\n * \n * @task T4800\n */\nexport const PLANNING_STAGES: Stage[] = getStagesByCategory('planning');\n\n/**\n * Decision stages.\n * \n * @task T4800\n */\nexport const DECISION_STAGES: Stage[] = getStagesByCategory('decision');\n\n/**\n * Execution stages.\n * \n * @task T4800\n */\nexport const EXECUTION_STAGES: Stage[] = getStagesByCategory('execution');\n\n/**\n * Validation stages.\n * \n * @task T4800\n */\nexport const VALIDATION_STAGES: Stage[] = getStagesByCategory('validation');\n\n/**\n * Delivery stages.\n * \n * @task T4800\n */\nexport const DELIVERY_STAGES: Stage[] = getStagesByCategory('delivery');\n", "/**\n * Task work management operations (start/stop/current).\n * @task T4462\n * @task T4750\n * @epic T4454\n */\n\nimport { readJsonRequired, saveJson, computeChecksum } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { TodoFile } from '../../types/task.js';\nimport { getTodoPath, getLogPath, getBackupDir } from '../paths.js';\nimport { logOperation } from '../tasks/add.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Result of getting current task. */\nexport interface TaskCurrentResult {\n currentTask: string | null;\n currentPhase: string | null;\n sessionNote: string | null;\n nextAction: string | null;\n}\n\n/** Result of starting work on a task. */\nexport interface TaskStartResult {\n taskId: string;\n taskTitle: string;\n previousTask: string | null;\n}\n\n/** Task work history entry. */\nexport interface TaskWorkHistoryEntry {\n taskId: string;\n timestamp: string;\n}\n\n/**\n * Show current task work state.\n * @task T4462\n * @task T4750\n */\nexport async function currentTask(cwd?: string, accessor?: DataAccessor): Promise<TaskCurrentResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n\n const focus = data.focus ?? {};\n\n return {\n currentTask: focus.currentTask ?? null,\n currentPhase: focus.currentPhase ?? null,\n sessionNote: focus.sessionNote ?? null,\n nextAction: focus.nextAction ?? null,\n };\n}\n\n/**\n * Start working on a specific task.\n * @task T4462\n * @task T4750\n */\nexport async function startTask(taskId: string, cwd?: string, accessor?: DataAccessor): Promise<TaskStartResult> {\n if (!taskId) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Task ID is required');\n }\n\n const todoPath = getTodoPath(cwd);\n const logPath = getLogPath(cwd);\n const backupDir = getBackupDir(cwd);\n\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(todoPath);\n\n // Verify task exists\n const task = data.tasks.find(t => t.id === taskId);\n if (!task) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Task not found: ${taskId}`,\n { fix: `Use 'cleo find \"${taskId}\"' to search` },\n );\n }\n\n const previousTask = data.focus?.currentTask ?? null;\n\n // Update focus\n if (!data.focus) {\n data.focus = {};\n }\n data.focus.currentTask = taskId;\n data.focus.currentPhase = task.phase ?? null;\n\n // Add to session notes for work history tracking\n const noteEntry = {\n note: `Started work on ${taskId}: ${task.title}`,\n timestamp: new Date().toISOString(),\n };\n if (!data.focus.sessionNotes) {\n data.focus.sessionNotes = [];\n }\n data.focus.sessionNotes.push(noteEntry);\n\n // Update metadata\n const now = new Date().toISOString();\n data._meta.checksum = computeChecksum(data.tasks);\n data.lastUpdated = now;\n\n if (accessor) {\n await accessor.saveTodoFile(data);\n } else {\n await saveJson(todoPath, data, { backupDir });\n }\n\n await logOperation(logPath, 'task_start', taskId, {\n previousTask,\n title: task.title,\n }, accessor);\n\n return {\n taskId,\n taskTitle: task.title,\n previousTask,\n };\n}\n\n/**\n * Stop working on the current task.\n * @task T4462\n * @task T4750\n */\nexport async function stopTask(cwd?: string, accessor?: DataAccessor): Promise<{ previousTask: string | null }> {\n const todoPath = getTodoPath(cwd);\n const logPath = getLogPath(cwd);\n const backupDir = getBackupDir(cwd);\n\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(todoPath);\n\n const previousTask = data.focus?.currentTask ?? null;\n\n if (!data.focus) {\n return { previousTask: null };\n }\n\n data.focus.currentTask = null;\n data.focus.nextAction = null;\n\n const now = new Date().toISOString();\n data._meta.checksum = computeChecksum(data.tasks);\n data.lastUpdated = now;\n\n if (accessor) {\n await accessor.saveTodoFile(data);\n } else {\n await saveJson(todoPath, data, { backupDir });\n }\n\n await logOperation(logPath, 'task_stop', previousTask ?? 'none', {\n previousTask,\n }, accessor);\n\n return { previousTask };\n}\n\n/**\n * Get task work history from session notes.\n * @task T4462\n * @task T4750\n */\nexport async function getWorkHistory(cwd?: string, accessor?: DataAccessor): Promise<TaskWorkHistoryEntry[]> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n\n const notes = data.focus?.sessionNotes ?? [];\n const history: TaskWorkHistoryEntry[] = [];\n\n for (const note of notes) {\n // Match both old \"Focus set to\" and new \"Started work on\" patterns\n const match = note.note.match(/^(?:Focus set to|Started work on) (T\\d+)/);\n if (match) {\n history.push({\n taskId: match[1]!,\n timestamp: note.timestamp,\n });\n }\n }\n\n return history.reverse(); // Most recent first\n}\n\n// ---- Backward-compatible aliases (deprecated) ----\n\n/** @deprecated Use TaskCurrentResult instead. */\nexport type FocusShowResult = TaskCurrentResult;\n/** @deprecated Use TaskStartResult instead. */\nexport type FocusSetResult = TaskStartResult;\n/** @deprecated Use TaskWorkHistoryEntry instead. */\nexport type FocusHistoryEntry = TaskWorkHistoryEntry;\n\n/** @deprecated Use currentTask() instead. */\nexport const showFocus = currentTask;\n/** @deprecated Use startTask() instead. */\nexport const setFocus = startTask;\n/** @deprecated Use stopTask() instead. */\nexport const clearFocus = stopTask;\n/** @deprecated Use getWorkHistory() instead. */\nexport const getFocusHistory = getWorkHistory;\n", "/**\n * Session Engine \u2014 thin wrapper layer.\n *\n * Delegates all business logic to src/core/sessions/ and src/core/task-work/.\n * Each function catches errors from core and wraps them into EngineResult.\n *\n * @task T4782\n * @epic T4654\n */\n\nimport { getAccessor } from '../../store/data-accessor.js';\nimport {\n isMultiSession as coreIsMultiSession,\n showSession,\n suspendSession,\n getSessionHistory,\n cleanupSessions,\n getSessionStats,\n switchSession,\n archiveSessions,\n getContextDrift,\n recordDecision,\n getDecisionLog,\n recordAssumption,\n} from '../../core/sessions/index.js';\nimport type {\n SessionRecord,\n FocusState,\n SessionsFileExt,\n TodoFileExt,\n DecisionRecord,\n} from '../../core/sessions/types.js';\nimport {\n currentTask,\n startTask,\n stopTask,\n} from '../../core/task-work/index.js';\n\n// Re-export types for consumers\nexport type { SessionRecord, DecisionRecord };\n\n/**\n * Engine result wrapper\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\n/**\n * Check if multi-session mode is enabled.\n * @task T4782\n */\nexport async function isMultiSession(projectRoot: string): Promise<boolean> {\n return coreIsMultiSession(projectRoot);\n}\n\n/**\n * Get current session status.\n * Note: This function has engine-specific logic for combining single-session\n * and multi-session views, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionStatus(\n projectRoot: string,\n): Promise<\n EngineResult<{\n hasActiveSession: boolean;\n multiSessionEnabled: boolean;\n session?: SessionRecord | null;\n focus?: FocusState | null;\n }>\n> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const todo = todoData as unknown as TodoFileExt;\n\n const multiSession = todo._meta?.multiSessionEnabled === true;\n\n if (multiSession) {\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n const active = sessions?.sessions?.find((s) => s.status === 'active');\n\n return {\n success: true,\n data: {\n hasActiveSession: !!active,\n multiSessionEnabled: true,\n session: active || null,\n focus: null,\n },\n };\n }\n\n return {\n success: true,\n data: {\n hasActiveSession: !!todo.focus?.currentTask,\n multiSessionEnabled: false,\n session: null,\n focus: todo.focus || null,\n },\n };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * List sessions (multi-session mode).\n * Note: This function has engine-specific logic for synthetic single-session\n * fallback, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionList(\n projectRoot: string,\n params?: { active?: boolean; limit?: number },\n): Promise<EngineResult<SessionRecord[]>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const todo = todoData as unknown as TodoFileExt;\n\n const multiSession = todo._meta?.multiSessionEnabled === true;\n\n if (!multiSession) {\n // Single-session mode: return synthetic session if focus is set\n if (todo.focus?.currentTask) {\n const syntheticSession: SessionRecord = {\n id: todo._meta?.activeSession || 'default',\n status: 'active',\n scope: { type: 'task', rootTaskId: todo.focus.currentTask },\n focus: {\n currentTask: todo.focus.currentTask,\n currentPhase: todo.focus.currentPhase,\n },\n startedAt: new Date().toISOString(),\n lastActivity: new Date().toISOString(),\n };\n return { success: true, data: [syntheticSession] };\n }\n return { success: true, data: [] };\n }\n\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions) {\n return { success: true, data: [] };\n }\n\n let result = sessions.sessions || [];\n\n if (params?.active === true) {\n result = result.filter((s) => s.status === 'active');\n } else if (params?.active === false) {\n result = result.filter((s) => s.status !== 'active');\n }\n\n if (params?.limit && params.limit > 0) {\n result = result.slice(0, params.limit);\n }\n\n return { success: true, data: result };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Show a specific session.\n * @task T4782\n */\nexport async function sessionShow(\n projectRoot: string,\n sessionId: string,\n): Promise<EngineResult<SessionRecord>> {\n try {\n const result = await showSession(projectRoot, sessionId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Get current task being worked on.\n * Delegates to core/task-work/currentTask.\n * @task T4782\n */\nexport async function taskCurrentGet(\n projectRoot: string,\n): Promise<EngineResult<{ currentTask: string | null; currentPhase: string | null }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await currentTask(undefined, accessor);\n return {\n success: true,\n data: {\n currentTask: result.currentTask,\n currentPhase: result.currentPhase,\n },\n };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Start working on a specific task.\n * Delegates to core/task-work/startTask.\n * @task T4782\n */\nexport async function taskStart(\n projectRoot: string,\n taskId: string,\n): Promise<EngineResult<{ taskId: string; previousTask: string | null }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await startTask(taskId, undefined, accessor);\n return {\n success: true,\n data: { taskId: result.taskId, previousTask: result.previousTask },\n };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Stop working on the current task.\n * Delegates to core/task-work/stopTask.\n * @task T4782\n */\nexport async function taskStop(\n projectRoot: string,\n): Promise<EngineResult<{ cleared: boolean; previousTask: string | null }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await stopTask(undefined, accessor);\n return {\n success: true,\n data: { cleared: true, previousTask: result.previousTask },\n };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No valid todo.json found' },\n };\n }\n}\n\n/**\n * Start a new session.\n * Note: This function has engine-specific logic for todo.json focus management\n * and multi-session session file updates, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionStart(\n projectRoot: string,\n params: {\n scope: string;\n name?: string;\n autoStart?: boolean;\n focus?: string;\n },\n): Promise<EngineResult<SessionRecord>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n // Parse scope (e.g., \"epic:T001\" -> { type: 'epic', rootTaskId: 'T001' })\n const scopeParts = params.scope.split(':');\n const scopeType = scopeParts[0] || 'task';\n const rootTaskId = scopeParts[1] || '';\n\n if (!rootTaskId) {\n return {\n success: false,\n error: {\n code: 'E_INVALID_INPUT',\n message: 'Scope must include a task ID (e.g., epic:T001)',\n },\n };\n }\n\n // Verify root task exists\n const rootTask = current.tasks?.find((t) => t.id === rootTaskId);\n if (!rootTask) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Root task '${rootTaskId}' not found`,\n },\n };\n }\n\n const now = new Date().toISOString();\n const { randomBytes } = await import('node:crypto');\n const date = now.replace(/[-:T]/g, '').substring(0, 8);\n const time = now.replace(/[-:T]/g, '').substring(8, 14);\n const hex = randomBytes(3).toString('hex');\n const sessionId = `session_${date}_${time}_${hex}`;\n\n const newSession: SessionRecord = {\n id: sessionId,\n status: 'active',\n name: params.name,\n scope: {\n type: scopeType,\n rootTaskId,\n includeDescendants: true,\n },\n focus: {\n currentTask: params.focus || (params.autoStart ? rootTaskId : null),\n currentPhase: null,\n previousTask: null,\n },\n startedAt: now,\n lastActivity: now,\n resumeCount: 0,\n stats: {\n tasksCompleted: 0,\n tasksCreated: 0,\n tasksUpdated: 0,\n focusChanges: 0,\n totalActiveMinutes: 0,\n suspendCount: 0,\n },\n };\n\n // Update focus in todo.json\n if (!current.focus) {\n current.focus = {\n currentTask: null,\n currentPhase: null,\n blockedUntil: null,\n sessionNote: null,\n sessionNotes: [],\n nextAction: null,\n primarySession: null,\n };\n }\n\n if (params.focus) {\n current.focus.currentTask = params.focus;\n } else if (params.autoStart) {\n current.focus.currentTask = rootTaskId;\n }\n\n if (current._meta) {\n current._meta.lastSessionId = sessionId;\n current._meta.activeSession = sessionId;\n current._meta.generation = (current._meta.generation || 0) + 1;\n }\n\n (current as Record<string, unknown>).lastUpdated = now;\n await accessor.saveTodoFile(todoData);\n\n // Always write to sessions.json so resume/suspend can find the session.\n // Previously only written when multi-session enabled, but session resume\n // always looks in sessions.json regardless of multi-session mode.\n {\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions.sessions) sessions.sessions = [];\n sessions.sessions.push(newSession);\n if (sessions._meta) {\n sessions._meta.lastModified = now;\n sessions._meta.lastSessionId = sessionId;\n sessions._meta.totalSessionsCreated =\n (sessions._meta.totalSessionsCreated || 0) + 1;\n }\n\n await accessor.saveSessions(sessionsData);\n }\n\n return { success: true, data: newSession };\n } catch {\n return {\n success: false,\n error: {\n code: 'E_NOT_INITIALIZED',\n message: 'No valid todo.json found',\n },\n };\n }\n}\n\n/**\n * End the current session.\n * Note: This function has engine-specific logic for todo.json focus management\n * and session history management, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionEnd(\n projectRoot: string,\n notes?: string,\n): Promise<EngineResult<{ sessionId: string; ended: boolean }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n const sessionId = current._meta?.activeSession || 'default';\n const now = new Date().toISOString();\n\n // Clear focus\n if (current.focus) {\n current.focus.currentTask = null;\n if (notes) {\n if (!current.focus.sessionNotes) current.focus.sessionNotes = [];\n current.focus.sessionNotes.push({ timestamp: now, note: notes });\n }\n }\n\n if (current._meta) {\n current._meta.activeSession = null;\n current._meta.generation = (current._meta.generation || 0) + 1;\n }\n\n (current as Record<string, unknown>).lastUpdated = now;\n await accessor.saveTodoFile(todoData);\n\n // Update sessions.json if multi-session\n if (current._meta?.multiSessionEnabled && sessionId !== 'default') {\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n if (sessions) {\n const sessionIndex = sessions.sessions.findIndex(\n (s) => s.id === sessionId,\n );\n if (sessionIndex !== -1) {\n const session = sessions.sessions[sessionIndex];\n session.status = 'ended';\n session.endedAt = now;\n session.lastActivity = now;\n\n // Move to history\n if (!sessions.sessionHistory) sessions.sessionHistory = [];\n sessions.sessionHistory.push(session);\n sessions.sessions.splice(sessionIndex, 1);\n\n if (sessions._meta) {\n sessions._meta.lastModified = now;\n }\n\n await accessor.saveSessions(sessionsData);\n }\n }\n }\n\n return { success: true, data: { sessionId, ended: true } };\n } catch {\n return {\n success: false,\n error: {\n code: 'E_NOT_INITIALIZED',\n message: 'No valid todo.json found',\n },\n };\n }\n}\n\n/**\n * Resume an ended or suspended session.\n * Note: This function has engine-specific logic for session history management\n * and todo.json focus sync, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionResume(\n projectRoot: string,\n sessionId: string,\n): Promise<EngineResult<SessionRecord>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n // Sessions are always written to sessions.json (even without multi-session mode),\n // so resume can always look them up there.\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Session '${sessionId}' not found`,\n },\n };\n }\n\n // Look in active sessions list first\n let session = sessions.sessions.find((s) => s.id === sessionId);\n let fromHistory = false;\n\n // Check session history if not found in active list\n if (!session && sessions.sessionHistory) {\n const histIndex = sessions.sessionHistory.findIndex(\n (s) => s.id === sessionId,\n );\n if (histIndex !== -1) {\n session = sessions.sessionHistory[histIndex];\n sessions.sessionHistory.splice(histIndex, 1);\n fromHistory = true;\n }\n }\n\n if (!session) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Session '${sessionId}' not found`,\n },\n };\n }\n\n if (session.status === 'active') {\n return { success: true, data: session };\n }\n\n if (session.status === 'archived') {\n return {\n success: false,\n error: {\n code: 'E_INVALID_STATE',\n message: `Session '${sessionId}' is archived and cannot be resumed`,\n },\n };\n }\n\n const now = new Date().toISOString();\n\n session.status = 'active';\n session.lastActivity = now;\n session.suspendedAt = null;\n session.endedAt = null;\n session.resumeCount = (session.resumeCount || 0) + 1;\n\n if (fromHistory) {\n sessions.sessions.push(session);\n }\n\n // Update todo.json to reflect active session\n if (current._meta) {\n current._meta.activeSession = sessionId;\n current._meta.generation = (current._meta.generation || 0) + 1;\n }\n\n if (session.focus?.currentTask && current.focus) {\n current.focus.currentTask = session.focus.currentTask;\n }\n\n (current as Record<string, unknown>).lastUpdated = now;\n\n if (sessions._meta) {\n sessions._meta.lastModified = now;\n }\n\n await accessor.saveTodoFile(todoData);\n await accessor.saveSessions(sessionsData);\n\n return { success: true, data: session };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Garbage collect old sessions.\n * Note: This function has engine-specific logic for multi-session GC\n * with session history management, so it remains in the engine layer.\n * @task T4782\n */\nexport async function sessionGc(\n projectRoot: string,\n maxAgeDays: number = 1,\n): Promise<EngineResult<{ orphaned: string[]; removed: string[] }>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTodoFile();\n const current = todoData as unknown as TodoFileExt;\n\n const multiSession = current._meta?.multiSessionEnabled === true;\n if (!multiSession) {\n return { success: true, data: { orphaned: [], removed: [] } };\n }\n\n const sessionsData = await accessor.loadSessions();\n const sessions = sessionsData as unknown as SessionsFileExt;\n\n if (!sessions) {\n return { success: true, data: { orphaned: [], removed: [] } };\n }\n\n const now = Date.now();\n const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;\n const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;\n const orphaned: string[] = [];\n const removed: string[] = [];\n\n // Mark stale active sessions as orphaned\n for (const session of sessions.sessions) {\n if (session.status === 'active') {\n const lastActive = new Date(\n session.lastActivity || session.startedAt,\n ).getTime();\n if (now - lastActive > maxAgeMs) {\n session.status = 'ended';\n session.endedAt = new Date().toISOString();\n session.lastActivity = new Date().toISOString();\n orphaned.push(session.id);\n }\n }\n }\n\n // Remove very old ended sessions\n sessions.sessions = sessions.sessions.filter((s) => {\n if (s.status === 'active') return true;\n const endedAt = s.endedAt\n ? new Date(s.endedAt).getTime()\n : new Date(s.startedAt).getTime();\n if (now - endedAt > thirtyDaysMs) {\n removed.push(s.id);\n return false;\n }\n return true;\n });\n\n // Also clean old session history\n if (sessions.sessionHistory) {\n sessions.sessionHistory = sessions.sessionHistory.filter((s) => {\n const endedAt = s.endedAt\n ? new Date(s.endedAt).getTime()\n : new Date(s.startedAt).getTime();\n if (now - endedAt > thirtyDaysMs) {\n if (!removed.includes(s.id)) {\n removed.push(s.id);\n }\n return false;\n }\n return true;\n });\n }\n\n if (orphaned.length > 0 || removed.length > 0) {\n if (sessions._meta) {\n sessions._meta.lastModified = new Date().toISOString();\n }\n await accessor.saveSessions(sessionsData);\n }\n\n return { success: true, data: { orphaned, removed } };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Suspend an active session.\n * @task T4782\n */\nexport async function sessionSuspend(\n projectRoot: string,\n sessionId: string,\n reason?: string,\n): Promise<EngineResult<SessionRecord>> {\n try {\n const result = await suspendSession(projectRoot, sessionId, reason);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found')\n ? 'E_NOT_FOUND'\n : message.includes('not active')\n ? 'E_INVALID_STATE'\n : message.includes('requires multi-session')\n ? 'E_NOT_SUPPORTED'\n : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * List session history with focus changes and completed tasks.\n * @task T4782\n */\nexport async function sessionHistory(\n projectRoot: string,\n params?: { sessionId?: string; limit?: number },\n): Promise<\n EngineResult<{\n sessions: Array<{\n id: string;\n name?: string;\n status: string;\n startedAt: string;\n endedAt?: string | null;\n tasksCompleted: number;\n focusChanges: number;\n focusHistory: Array<{ taskId: string; timestamp: string }>;\n }>;\n }>\n> {\n try {\n const result = await getSessionHistory(projectRoot, params);\n return { success: true, data: result };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Remove orphaned sessions and clean up stale data.\n * @task T4782\n */\nexport async function sessionCleanup(\n projectRoot: string,\n): Promise<EngineResult<{ removed: string[]; cleaned: boolean }>> {\n try {\n const result = await cleanupSessions(projectRoot);\n return { success: true, data: result };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n\n/**\n * Record a decision to the audit trail.\n * @task T4782\n */\nexport async function sessionRecordDecision(\n projectRoot: string,\n params: {\n sessionId: string;\n taskId: string;\n decision: string;\n rationale: string;\n alternatives?: string[];\n },\n): Promise<EngineResult<DecisionRecord>> {\n try {\n const result = await recordDecision(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message },\n };\n }\n}\n\n/**\n * Read the decision log, optionally filtered by sessionId and/or taskId.\n * @task T4782\n */\nexport async function sessionDecisionLog(\n projectRoot: string,\n params?: { sessionId?: string; taskId?: string },\n): Promise<EngineResult<DecisionRecord[]>> {\n try {\n const result = await getDecisionLog(projectRoot, params);\n return { success: true, data: result };\n } catch {\n return { success: true, data: [] };\n }\n}\n\n/**\n * Compute context drift score for the current session.\n * @task T4782\n */\nexport async function sessionContextDrift(\n projectRoot: string,\n params?: { sessionId?: string },\n): Promise<\n EngineResult<{\n score: number;\n factors: string[];\n completedInScope: number;\n totalInScope: number;\n outOfScope: number;\n }>\n> {\n try {\n const result = await getContextDrift(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found')\n ? 'E_NOT_FOUND'\n : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Record an assumption made during a session.\n * @task T4782\n */\nexport async function sessionRecordAssumption(\n projectRoot: string,\n params: {\n sessionId?: string;\n taskId?: string;\n assumption: string;\n confidence: 'high' | 'medium' | 'low';\n },\n): Promise<\n EngineResult<{\n id: string;\n sessionId: string;\n taskId: string | null;\n assumption: string;\n confidence: string;\n timestamp: string;\n }>\n> {\n try {\n const result = await recordAssumption(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('required') || message.includes('must be')\n ? 'E_INVALID_INPUT'\n : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Compute session statistics, optionally for a specific session.\n * @task T4782\n */\nexport async function sessionStats(\n projectRoot: string,\n sessionId?: string,\n): Promise<\n EngineResult<{\n totalSessions: number;\n activeSessions: number;\n suspendedSessions: number;\n endedSessions: number;\n archivedSessions: number;\n totalTasksCompleted: number;\n totalFocusChanges: number;\n averageResumeCount: number;\n session?: {\n id: string;\n status: string;\n tasksCompleted: number;\n focusChanges: number;\n resumeCount: number;\n durationMinutes: number;\n };\n }>\n> {\n try {\n const result = await getSessionStats(projectRoot, sessionId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found')\n ? 'E_NOT_FOUND'\n : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Switch to a different session.\n * @task T4782\n */\nexport async function sessionSwitch(\n projectRoot: string,\n sessionId: string,\n): Promise<EngineResult<SessionRecord>> {\n try {\n const result = await switchSession(projectRoot, sessionId);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found')\n ? 'E_NOT_FOUND'\n : message.includes('archived')\n ? 'E_INVALID_STATE'\n : message.includes('requires multi-session')\n ? 'E_NOT_SUPPORTED'\n : 'E_NOT_INITIALIZED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * Archive old/ended sessions.\n * @task T4782\n */\nexport async function sessionArchive(\n projectRoot: string,\n olderThan?: string,\n): Promise<EngineResult<{ archived: string[]; count: number }>> {\n try {\n const result = await archiveSessions(projectRoot, olderThan);\n return { success: true, data: result };\n } catch {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No todo.json found' },\n };\n }\n}\n", "/**\n * System Engine\n *\n * Thin wrapper layer that delegates to core modules.\n * All business logic lives in src/core/.\n *\n * Read-only queries: dash, stats, labels, archive-stats, log, context, sequence,\n * metrics, health, diagnostics, help, roadmap, compliance\n * Mutate operations: inject.generate, backup, restore, migrate, cleanup, audit,\n * sync, safestop, uncancel\n *\n * @task T4631\n * @task T4783\n */\n\nimport { readFileSync, existsSync, readdirSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { readLogFileEntries, getDataPath } from './store.js';\nimport { getAccessor } from '../../store/data-accessor.js';\nimport type { EngineResult, TaskRecord } from './task-engine.js';\n\n// Core module imports\nimport { getDashboard, getProjectStats } from '../../core/stats/index.js';\nimport { getLabels } from '../../core/system/labels.js';\nimport { getArchiveStats } from '../../core/system/archive-stats.js';\nimport { generateInjection } from '../../core/system/inject-generate.js';\nimport { getSystemMetrics } from '../../core/system/metrics.js';\nimport { getSystemHealth, getSystemDiagnostics } from '../../core/system/health.js';\nimport { getRoadmap } from '../../core/roadmap/index.js';\nimport { createBackup, restoreBackup } from '../../core/system/backup.js';\nimport { getMigrationStatus } from '../../core/system/migrate.js';\nimport { cleanupSystem } from '../../core/system/cleanup.js';\nimport { auditData } from '../../core/system/audit.js';\nimport { safestop, uncancelTask } from '../../core/system/safestop.js';\n\n// Re-export types for downstream consumers\nexport type { LabelsResult as LabelsData } from '../../core/system/labels.js';\nexport type { ArchiveStatsResult as ArchiveStatsData } from '../../core/system/archive-stats.js';\nexport type { HealthResult as HealthData } from '../../core/system/health.js';\nexport type { DiagnosticsResult as DiagnosticsData } from '../../core/system/health.js';\nexport type { BackupResult as BackupData } from '../../core/system/backup.js';\nexport type { RestoreResult as RestoreData } from '../../core/system/backup.js';\nexport type { CleanupResult as CleanupData } from '../../core/system/cleanup.js';\nexport type { AuditResult as AuditData } from '../../core/system/audit.js';\nexport type { SafestopResult as SafestopData } from '../../core/system/safestop.js';\nexport type { UncancelResult as UncancelData } from '../../core/system/safestop.js';\nexport type { MigrateResult as MigrateData } from '../../core/system/migrate.js';\nexport type { SystemMetricsResult as MetricsData } from '../../core/system/metrics.js';\nexport type { InjectGenerateResult as InjectGenerateData } from '../../core/system/inject-generate.js';\n\n// ===== Dashboard Data type (re-exported for consumers) =====\nexport interface DashboardData {\n project: string;\n currentPhase: string | null;\n summary: {\n pending: number;\n active: number;\n blocked: number;\n done: number;\n cancelled: number;\n total: number;\n };\n focus: {\n currentTask: string | null;\n task: TaskRecord | null;\n };\n activeSession: string | null;\n highPriority: {\n count: number;\n tasks: TaskRecord[];\n };\n blockedTasks: {\n count: number;\n tasks: TaskRecord[];\n };\n recentCompletions: TaskRecord[];\n topLabels: Array<{ label: string; count: number }>;\n}\n\n// ===== Stats Data type =====\nexport interface StatsData {\n currentState: {\n pending: number;\n active: number;\n done: number;\n blocked: number;\n cancelled: number;\n totalActive: number;\n };\n byPriority: Record<string, number>;\n byType: Record<string, number>;\n byPhase: Record<string, number>;\n completionMetrics: {\n periodDays: number;\n completedInPeriod: number;\n createdInPeriod: number;\n completionRate: number;\n };\n activityMetrics: {\n createdInPeriod: number;\n completedInPeriod: number;\n archivedInPeriod: number;\n };\n allTime: {\n totalCreated: number;\n totalCompleted: number;\n totalArchived: number;\n };\n cycleTimes: {\n averageDays: number | null;\n samples: number;\n };\n}\n\n// ===== Log Query Data type =====\nexport interface LogQueryData {\n entries: Array<{ operation: string; taskId?: string; timestamp: string; [key: string]: unknown }>;\n pagination: {\n total: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n };\n}\n\n// ===== Context Data type =====\nexport interface ContextData {\n available: boolean;\n status: string;\n percentage: number;\n currentTokens: number;\n maxTokens: number;\n timestamp: string | null;\n stale: boolean;\n sessions: Array<{\n file: string;\n sessionId: string | null;\n percentage: number;\n status: string;\n timestamp: string;\n }>;\n}\n\n// ===== Sequence Data type =====\nexport interface SequenceData {\n counter: number;\n lastId: string;\n checksum: string;\n nextId: string;\n}\n\n// ===== Roadmap Data type =====\nexport interface RoadmapData {\n currentVersion: string;\n upcoming: Array<{\n id: string;\n title: string;\n status: string;\n priority: string;\n phase?: string;\n childCount: number;\n completedChildren: number;\n }>;\n releaseHistory?: Array<{ version: string; date: string }>;\n completedEpics?: number;\n summary: {\n totalUpcoming: number;\n totalTasks: number;\n };\n}\n\n// ===== Compliance Data type =====\nexport interface ComplianceData {\n totalEntries: number;\n averagePassRate: number;\n averageAdherence: number;\n totalViolations: number;\n trend?: string;\n dataPoints?: Array<{\n date: string;\n entries: number;\n avgPassRate: number;\n violations: number;\n }>;\n}\n\n// ===== Help Data type =====\nexport interface HelpData {\n topic?: string;\n content: string;\n relatedCommands?: string[];\n}\n\n// ===== Help topics (static data, stays in engine) =====\nconst HELP_TOPICS: Record<string, HelpData> = {\n session: {\n topic: 'session',\n content: [\n 'Session Management',\n '',\n ' ct session list - List all sessions',\n ' ct session start --scope epic:T001 - Start session',\n ' ct session end --note \"Progress\" - End session',\n ' ct session resume <id> - Resume session',\n ].join('\\n'),\n relatedCommands: ['ct session list', 'ct session start', 'ct session end'],\n },\n tasks: {\n topic: 'tasks',\n content: [\n 'Task Operations',\n '',\n ' ct add \"Title\" --desc \"Description\" - Create task',\n ' ct update T1234 --status active - Update task',\n ' ct complete T1234 - Complete task',\n ' ct find \"query\" - Search tasks',\n ' ct show T1234 - Show task details',\n ].join('\\n'),\n relatedCommands: ['ct add', 'ct update', 'ct complete', 'ct find', 'ct show'],\n },\n focus: {\n topic: 'focus',\n content: [\n 'Task Work Management',\n '',\n ' ct start T1234 - Start working on task',\n ' ct current - Show current task',\n ' ct stop - Stop working on current task',\n ].join('\\n'),\n relatedCommands: ['ct start', 'ct current', 'ct stop'],\n },\n labels: {\n topic: 'labels',\n content: [\n 'Label Operations',\n '',\n ' ct labels - List all labels',\n ' ct labels show <name> - Show tasks with label',\n ].join('\\n'),\n relatedCommands: ['ct labels'],\n },\n compliance: {\n topic: 'compliance',\n content: [\n 'Compliance Monitoring',\n '',\n ' ct compliance summary - Compliance overview',\n ' ct compliance violations - List violations',\n ' ct compliance trend - Compliance trend',\n ].join('\\n'),\n relatedCommands: ['ct compliance summary', 'ct compliance violations'],\n },\n};\n\n// ===== Dashboard =====\n\n/**\n * Project dashboard: task counts by status, active session info,\n * current focus, recent completions.\n */\nexport async function systemDash(\n projectRoot: string,\n): Promise<EngineResult<DashboardData>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getDashboard({ cwd: projectRoot }, accessor);\n // Add missing fields that core doesn't produce\n const data = result as Record<string, unknown>;\n const summary = data.summary as Record<string, number>;\n return {\n success: true,\n data: {\n project: data.project as string,\n currentPhase: data.currentPhase as string | null,\n summary: {\n pending: summary.pending,\n active: summary.active,\n blocked: summary.blocked,\n done: summary.done,\n cancelled: (summary as Record<string, number>).cancelled ?? 0,\n total: summary.total,\n },\n focus: data.focus as DashboardData['focus'],\n activeSession: (data as Record<string, unknown>).activeSession as string | null ?? null,\n highPriority: data.highPriority as DashboardData['highPriority'],\n blockedTasks: data.blockedTasks as DashboardData['blockedTasks'],\n recentCompletions: (data.recentCompletions ?? []) as TaskRecord[],\n topLabels: data.topLabels as DashboardData['topLabels'],\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message } };\n }\n}\n\n// ===== Stats =====\n\n/**\n * Detailed statistics: tasks by status/priority/type/phase,\n * completion rate, average cycle time.\n */\nexport async function systemStats(\n projectRoot: string,\n params?: { period?: number },\n): Promise<EngineResult<StatsData>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getProjectStats({ period: String(params?.period ?? 30), cwd: projectRoot }, accessor);\n // Core stats lacks byPriority, byType, byPhase, cycleTimes \u2014 fill from accessor\n const todoData = await accessor.loadTodoFile();\n const tasks = (todoData as { tasks: TaskRecord[] })?.tasks ?? [];\n\n const byPriority: Record<string, number> = {};\n for (const t of tasks) {\n byPriority[t.priority] = (byPriority[t.priority] ?? 0) + 1;\n }\n const byType: Record<string, number> = {};\n for (const t of tasks) {\n const type = t.type || 'task';\n byType[type] = (byType[type] ?? 0) + 1;\n }\n const byPhase: Record<string, number> = {};\n for (const t of tasks) {\n const phase = t.phase || 'unassigned';\n byPhase[phase] = (byPhase[phase] ?? 0) + 1;\n }\n\n // Cycle times\n const completedTasks = tasks.filter(t => t.status === 'done' && t.completedAt && t.createdAt);\n let totalCycleDays = 0;\n let samples = 0;\n for (const t of completedTasks) {\n const created = new Date(t.createdAt).getTime();\n const completed = new Date(t.completedAt!).getTime();\n if (completed > created) {\n totalCycleDays += (completed - created) / 86400000;\n samples++;\n }\n }\n const averageDays = samples > 0 ? Math.round((totalCycleDays / samples) * 100) / 100 : null;\n\n const coreData = result as Record<string, unknown>;\n const currentState = coreData.currentState as Record<string, number>;\n const completionMetrics = coreData.completionMetrics as Record<string, number>;\n const activityMetrics = coreData.activityMetrics as Record<string, number>;\n const allTime = coreData.allTime as Record<string, number>;\n\n return {\n success: true,\n data: {\n currentState: {\n pending: currentState.pending,\n active: currentState.active,\n done: currentState.done,\n blocked: currentState.blocked,\n cancelled: tasks.filter(t => t.status === 'cancelled').length,\n totalActive: currentState.totalActive,\n },\n byPriority,\n byType,\n byPhase,\n completionMetrics: completionMetrics as StatsData['completionMetrics'],\n activityMetrics: activityMetrics as StatsData['activityMetrics'],\n allTime: allTime as StatsData['allTime'],\n cycleTimes: { averageDays, samples },\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message } };\n }\n}\n\n// ===== Labels =====\n\n/**\n * List all unique labels across tasks with counts and task IDs per label.\n */\nexport async function systemLabels(\n projectRoot: string,\n): Promise<EngineResult<import('../../core/system/labels.js').LabelsResult>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getLabels(projectRoot, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message } };\n }\n}\n\n// ===== Archive Stats =====\n\n/**\n * Archive metrics: total archived, by reason, average cycle time, archive rate.\n */\nexport async function systemArchiveStats(\n projectRoot: string,\n params?: { period?: number },\n): Promise<EngineResult<import('../../core/system/archive-stats.js').ArchiveStatsResult>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getArchiveStats({ period: params?.period, cwd: projectRoot }, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message } };\n }\n}\n\n// ===== Log =====\n\n/**\n * Query todo-log.jsonl with optional filters.\n */\nexport function systemLog(\n projectRoot: string,\n filters?: {\n operation?: string;\n taskId?: string;\n since?: string;\n until?: string;\n limit?: number;\n offset?: number;\n },\n): EngineResult<LogQueryData> {\n try {\n const logPath = getDataPath(projectRoot, 'todo-log.jsonl');\n const raw = readLogFileEntries(logPath) as Array<{ operation: string; timestamp: string; taskId?: string; [key: string]: unknown }>;\n let entries = raw;\n\n if (filters?.operation) {\n entries = entries.filter(e => e.operation === filters.operation);\n }\n if (filters?.taskId) {\n entries = entries.filter(e => e.taskId === filters.taskId);\n }\n if (filters?.since) {\n entries = entries.filter(e => e.timestamp >= filters.since!);\n }\n if (filters?.until) {\n entries = entries.filter(e => e.timestamp <= filters.until!);\n }\n\n entries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n\n const total = entries.length;\n const offset = filters?.offset ?? 0;\n const limit = filters?.limit ?? 20;\n const paginated = entries.slice(offset, offset + limit);\n\n return {\n success: true,\n data: {\n entries: paginated,\n pagination: { total, offset, limit, hasMore: offset + limit < total },\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_LOG_ERROR', message: (err as Error).message } };\n }\n}\n\n// ===== Context =====\n\n/**\n * Context window tracking: estimate token usage from current session/state.\n */\nexport function systemContext(\n projectRoot: string,\n params?: { session?: string },\n): EngineResult<ContextData> {\n try {\n const cleoDir = join(projectRoot, '.cleo');\n\n // Resolve state file\n let stateFile: string;\n if (params?.session) {\n const sessionFile = join(cleoDir, 'context-states', `context-state-${params.session}.json`);\n stateFile = existsSync(sessionFile) ? sessionFile : join(cleoDir, '.context-state.json');\n } else {\n const currentSessionPath = join(cleoDir, '.current-session');\n if (existsSync(currentSessionPath)) {\n const currentSession = readFileSync(currentSessionPath, 'utf-8').trim();\n if (currentSession) {\n const sessionFile = join(cleoDir, 'context-states', `context-state-${currentSession}.json`);\n stateFile = existsSync(sessionFile) ? sessionFile : join(cleoDir, '.context-state.json');\n } else {\n stateFile = join(cleoDir, '.context-state.json');\n }\n } else {\n stateFile = join(cleoDir, '.context-state.json');\n }\n }\n\n // Collect session files\n const sessions: ContextData['sessions'] = [];\n const statesDir = join(cleoDir, 'context-states');\n if (existsSync(statesDir)) {\n for (const file of readdirSync(statesDir) as string[]) {\n if (file.startsWith('context-state-') && file.endsWith('.json')) {\n try {\n const state = JSON.parse(readFileSync(join(statesDir, file), 'utf-8'));\n sessions.push({\n file: basename(file),\n sessionId: state.sessionId ?? null,\n percentage: state.contextWindow?.percentage ?? 0,\n status: state.status ?? 'unknown',\n timestamp: state.timestamp,\n });\n } catch {\n // skip invalid files\n }\n }\n }\n }\n\n const singletonFile = join(cleoDir, '.context-state.json');\n if (existsSync(singletonFile)) {\n try {\n const state = JSON.parse(readFileSync(singletonFile, 'utf-8'));\n sessions.push({\n file: '.context-state.json',\n sessionId: state.sessionId ?? 'global',\n percentage: state.contextWindow?.percentage ?? 0,\n status: state.status ?? 'unknown',\n timestamp: state.timestamp,\n });\n } catch {\n // skip\n }\n }\n\n if (!existsSync(stateFile)) {\n return {\n success: true,\n data: {\n available: false,\n status: 'unavailable',\n percentage: 0,\n currentTokens: 0,\n maxTokens: 0,\n timestamp: null,\n stale: true,\n sessions,\n },\n };\n }\n\n try {\n const state = JSON.parse(readFileSync(stateFile, 'utf-8'));\n const timestamp = state.timestamp;\n const staleMs = state.staleAfterMs ?? 5000;\n const percentage = state.contextWindow?.percentage ?? 0;\n const current = state.contextWindow?.currentTokens ?? 0;\n const max = state.contextWindow?.maxTokens ?? 0;\n let status = state.status ?? 'unknown';\n\n const fileTime = new Date(timestamp).getTime();\n if ((Date.now() - fileTime) > staleMs) {\n status = 'stale';\n }\n\n return {\n success: true,\n data: {\n available: true,\n status,\n percentage,\n currentTokens: current,\n maxTokens: max,\n timestamp,\n stale: status === 'stale',\n sessions,\n },\n };\n } catch {\n return {\n success: true,\n data: {\n available: false,\n status: 'error',\n percentage: 0,\n currentTokens: 0,\n maxTokens: 0,\n timestamp: null,\n stale: true,\n sessions,\n },\n };\n }\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_CONTEXT_ERROR', message: (err as Error).message } };\n }\n}\n\n// ===== Sequence =====\n\n/**\n * Read the .sequence.json file and return current sequence state.\n */\nexport function systemSequence(\n projectRoot: string,\n): EngineResult<SequenceData> {\n try {\n const seqPath = join(projectRoot, '.cleo', '.sequence.json');\n\n if (!existsSync(seqPath)) {\n return {\n success: false,\n error: { code: 'E_NOT_FOUND', message: 'Sequence file not found (.cleo/.sequence.json)' },\n };\n }\n\n const seq = JSON.parse(readFileSync(seqPath, 'utf-8'));\n return {\n success: true,\n data: {\n counter: seq.counter,\n lastId: seq.lastId,\n checksum: seq.checksum,\n nextId: `T${seq.counter + 1}`,\n },\n };\n } catch {\n return {\n success: false,\n error: { code: 'E_PARSE_ERROR', message: 'Failed to parse sequence file' },\n };\n }\n}\n\n// ===== Inject Generate (MVI) =====\n\n/**\n * Generate Minimum Viable Injection (MVI).\n */\nexport async function systemInjectGenerate(\n projectRoot?: string,\n): Promise<EngineResult<import('../../core/system/inject-generate.js').InjectGenerateResult>> {\n try {\n const root = projectRoot || process.cwd();\n const result = await generateInjection(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_INJECT_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Metrics =====\n\n/**\n * System metrics: token usage, compliance summary, session counts.\n * @task T4631\n */\nexport async function systemMetrics(\n projectRoot: string,\n params?: { scope?: string; since?: string },\n): Promise<EngineResult<import('../../core/system/metrics.js').SystemMetricsResult>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getSystemMetrics(projectRoot, params, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_METRICS_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Health =====\n\n/**\n * System health check: verify core data files exist and are valid.\n * @task T4631\n */\nexport function systemHealth(\n projectRoot: string,\n params?: { detailed?: boolean },\n): EngineResult<import('../../core/system/health.js').HealthResult> {\n try {\n const result = getSystemHealth(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_HEALTH_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Diagnostics =====\n\n/**\n * System diagnostics: extended health checks with fix suggestions.\n * @task T4631\n */\nexport function systemDiagnostics(\n projectRoot: string,\n params?: { checks?: string[] },\n): EngineResult<import('../../core/system/health.js').DiagnosticsResult> {\n try {\n const result = getSystemDiagnostics(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_DIAGNOSTICS_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Help =====\n\n/**\n * Return help text for the system.\n * @task T4631\n */\nexport function systemHelp(\n _projectRoot: string,\n params?: { topic?: string },\n): EngineResult<HelpData> {\n const topic = params?.topic;\n\n if (topic) {\n const topicHelp = HELP_TOPICS[topic];\n if (topicHelp) {\n return { success: true, data: topicHelp };\n }\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Unknown help topic: ${topic}. Available topics: ${Object.keys(HELP_TOPICS).join(', ')}`,\n },\n };\n }\n\n return {\n success: true,\n data: {\n content: [\n 'CLEO Task Management System',\n '',\n 'Essential Commands:',\n ' ct find \"query\" - Fuzzy search tasks',\n ' ct show T1234 - Full task details',\n ' ct add \"Task\" - Create task',\n ' ct done <id> - Complete task',\n ' ct start <id> - Start working on task',\n ' ct dash - Project overview',\n ' ct session list - List sessions',\n '',\n 'Help Topics: session, tasks, focus, labels, compliance',\n ].join('\\n'),\n relatedCommands: ['ct find', 'ct show', 'ct add', 'ct done', 'ct dash'],\n },\n };\n}\n\n// ===== Roadmap =====\n\n/**\n * Generate roadmap from pending epics and optional CHANGELOG history.\n * @task T4631\n */\nexport async function systemRoadmap(\n projectRoot: string,\n params?: { includeHistory?: boolean; upcomingOnly?: boolean },\n): Promise<EngineResult<RoadmapData>> {\n try {\n const accessor = await getAccessor(projectRoot);\n const result = await getRoadmap(\n { includeHistory: params?.includeHistory, upcomingOnly: params?.upcomingOnly, cwd: projectRoot },\n accessor,\n );\n return { success: true, data: result as unknown as RoadmapData };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_NOT_INITIALIZED', message: (err as Error).message } };\n }\n}\n\n// ===== Compliance =====\n\n/**\n * System compliance report from COMPLIANCE.jsonl.\n * @task T4631\n */\nexport function systemCompliance(\n projectRoot: string,\n params?: { subcommand?: string; days?: number; epic?: string },\n): EngineResult<ComplianceData> {\n try {\n if (params?.subcommand === 'trend') {\n const compliancePath = join(projectRoot, '.cleo', 'metrics', 'COMPLIANCE.jsonl');\n let entries: Record<string, unknown>[] = [];\n\n if (existsSync(compliancePath)) {\n const content = readFileSync(compliancePath, 'utf-8').trim();\n if (content) {\n entries = content.split('\\n').filter((l: string) => l.trim()).map((l: string) => JSON.parse(l));\n }\n }\n\n if (params.epic) {\n entries = entries.filter(e => {\n const ctx = (e._context ?? {}) as Record<string, unknown>;\n return ctx.epic_id === params.epic || ctx.task_id === params.epic;\n });\n }\n if (params.days) {\n const cutoff = new Date(Date.now() - params.days * 86400000).toISOString();\n entries = entries.filter(e => (e.timestamp as string) >= cutoff);\n }\n\n const totalEntries = entries.length;\n const compliance = entries.map(e => (e.compliance ?? {}) as Record<string, unknown>);\n const avgPassRate = totalEntries > 0\n ? Math.round(compliance.reduce((sum, c) => sum + ((c.compliance_pass_rate as number) ?? 0), 0) / totalEntries * 1000) / 1000\n : 0;\n const avgAdherence = totalEntries > 0\n ? Math.round(compliance.reduce((sum, c) => sum + ((c.rule_adherence_score as number) ?? 0), 0) / totalEntries * 1000) / 1000\n : 0;\n const totalViolations = compliance.reduce(\n (sum, c) => sum + ((c.violation_count as number) ?? 0), 0,\n );\n\n const byDate: Record<string, Record<string, unknown>[]> = {};\n for (const e of entries) {\n const date = (e.timestamp as string).split('T')[0]!;\n if (!byDate[date]) byDate[date] = [];\n byDate[date]!.push(e);\n }\n\n const dataPoints = Object.entries(byDate)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([date, dayEntries]) => {\n const dayCompliance = dayEntries.map(de => (de.compliance ?? {}) as Record<string, unknown>);\n return {\n date,\n entries: dayEntries.length,\n avgPassRate: dayCompliance.reduce((s, c) => s + ((c.compliance_pass_rate as number) ?? 0), 0) / dayEntries.length,\n violations: dayCompliance.reduce((s, c) => s + ((c.violation_count as number) ?? 0), 0),\n };\n });\n\n let trend: string;\n if (dataPoints.length >= 2) {\n const first = dataPoints[0]!.avgPassRate;\n const last = dataPoints[dataPoints.length - 1]!.avgPassRate;\n trend = last > first ? 'improving' : last < first ? 'declining' : 'stable';\n } else {\n trend = 'insufficient_data';\n }\n\n return {\n success: true,\n data: { totalEntries, averagePassRate: avgPassRate, averageAdherence: avgAdherence, totalViolations, trend, dataPoints },\n };\n }\n\n // Default: summary (possibly filtered by epic/days)\n const compliancePath = join(projectRoot, '.cleo', 'metrics', 'COMPLIANCE.jsonl');\n let entries: Record<string, unknown>[] = [];\n\n if (existsSync(compliancePath)) {\n const content = readFileSync(compliancePath, 'utf-8').trim();\n if (content) {\n entries = content.split('\\n').filter((l: string) => l.trim()).map((l: string) => JSON.parse(l));\n }\n }\n\n if (params?.epic) {\n entries = entries.filter(e => {\n const ctx = (e._context ?? {}) as Record<string, unknown>;\n return ctx.epic_id === params.epic || ctx.task_id === params.epic;\n });\n }\n if (params?.days) {\n const cutoff = new Date(Date.now() - params.days * 86400000).toISOString();\n entries = entries.filter(e => (e.timestamp as string) >= cutoff);\n }\n\n const totalEntries = entries.length;\n const compliance = entries.map(e => (e.compliance ?? {}) as Record<string, unknown>);\n const avgPassRate = totalEntries > 0\n ? Math.round(compliance.reduce((sum, c) => sum + ((c.compliance_pass_rate as number) ?? 0), 0) / totalEntries * 1000) / 1000\n : 0;\n const avgAdherence = totalEntries > 0\n ? Math.round(compliance.reduce((sum, c) => sum + ((c.rule_adherence_score as number) ?? 0), 0) / totalEntries * 1000) / 1000\n : 0;\n const totalViolations = compliance.reduce(\n (sum, c) => sum + ((c.violation_count as number) ?? 0), 0,\n );\n\n return {\n success: true,\n data: { totalEntries, averagePassRate: avgPassRate, averageAdherence: avgAdherence, totalViolations },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_COMPLIANCE_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Backup =====\n\n/**\n * Create a backup of CLEO data files.\n * @task T4631\n */\nexport function systemBackup(\n projectRoot: string,\n params?: { type?: string; note?: string },\n): EngineResult<import('../../core/system/backup.js').BackupResult> {\n try {\n const result = createBackup(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_BACKUP_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Restore =====\n\n/**\n * Restore from a backup.\n * @task T4631\n */\nexport function systemRestore(\n projectRoot: string,\n params: { backupId: string; force?: boolean },\n): EngineResult<import('../../core/system/backup.js').RestoreResult> {\n try {\n const result = restoreBackup(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_RESTORE_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n// ===== Migrate =====\n\n/**\n * Check/run schema migrations.\n * @task T4631\n */\nexport function systemMigrate(\n projectRoot: string,\n params?: { target?: string; dryRun?: boolean },\n): EngineResult<import('../../core/system/migrate.js').MigrateResult> {\n try {\n const result = getMigrationStatus(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_MIGRATE_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n// ===== Cleanup =====\n\n/**\n * Cleanup stale data (sessions, backups, logs).\n * @task T4631\n */\nexport function systemCleanup(\n projectRoot: string,\n params: { target: string; olderThan?: string; dryRun?: boolean },\n): EngineResult<import('../../core/system/cleanup.js').CleanupResult> {\n try {\n const result = cleanupSystem(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_CLEANUP_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n// ===== Audit =====\n\n/**\n * Audit data integrity.\n * @task T4631\n */\nexport function systemAudit(\n projectRoot: string,\n params?: { scope?: string; fix?: boolean },\n): EngineResult<import('../../core/system/audit.js').AuditResult> {\n try {\n const result = auditData(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_AUDIT_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Sync =====\n\nexport interface SyncData {\n direction: string;\n synced: number;\n conflicts: number;\n message: string;\n}\n\n/**\n * Sync check (no external sync targets in native mode).\n * @task T4631\n */\nexport function systemSync(\n _projectRoot: string,\n params?: { direction?: string },\n): EngineResult<SyncData> {\n return {\n success: true,\n data: {\n direction: params?.direction ?? 'up',\n synced: 0,\n conflicts: 0,\n message: 'Sync is a no-op in native mode (no external sync targets configured)',\n },\n };\n}\n\n// ===== Safestop =====\n\n/**\n * Safe stop: signal clean shutdown for agents.\n * @task T4631\n */\nexport function systemSafestop(\n projectRoot: string,\n params?: { reason?: string; commit?: boolean; handoff?: string; noSessionEnd?: boolean; dryRun?: boolean },\n): EngineResult<import('../../core/system/safestop.js').SafestopResult> {\n try {\n const result = safestop(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_SAFESTOP_FAILED', message: (err as Error).message } };\n }\n}\n\n// ===== Uncancel =====\n\n/**\n * Uncancel a cancelled task (restore to pending).\n * @task T4631\n */\nexport function systemUncancel(\n projectRoot: string,\n params: { taskId: string; cascade?: boolean; notes?: string; dryRun?: boolean },\n): EngineResult<import('../../core/system/safestop.js').UncancelResult> {\n try {\n const result = uncancelTask(projectRoot, params);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_UNCANCEL_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n", "/**\n * Statistics and analytics core module.\n * @task T4535\n * @epic T4454\n */\n\nimport { readJson, readLogEntries } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport { getTodoPath, getLogPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Period alias resolution. */\nfunction resolvePeriod(period: string): number {\n const aliases: Record<string, number> = {\n today: 1, t: 1,\n week: 7, w: 7,\n month: 30, m: 30,\n quarter: 90, q: 90,\n year: 365, y: 365,\n };\n const resolved = aliases[period];\n if (resolved) return resolved;\n const num = parseInt(period, 10);\n if (isNaN(num) || num <= 0) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Invalid period: ${period}`);\n }\n return num;\n}\n\n/** Get project statistics. */\nexport async function getProjectStats(opts: {\n period?: string;\n verbose?: boolean;\n cwd?: string;\n}, accessor?: DataAccessor): Promise<Record<string, unknown>> {\n const periodDays = resolvePeriod(opts.period ?? '30');\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(opts.cwd));\n if (!data) {\n throw new CleoError(ExitCode.CONFIG_ERROR, 'Not in a CLEO project. Run cleo init first.');\n }\n\n const tasks = data.tasks ?? [];\n const pending = tasks.filter(t => t.status === 'pending').length;\n const active = tasks.filter(t => t.status === 'active').length;\n const done = tasks.filter(t => t.status === 'done').length;\n const blocked = tasks.filter(t => t.status === 'blocked').length;\n const totalActive = tasks.length;\n\n const cutoff = new Date(Date.now() - periodDays * 86400000).toISOString();\n\n // Read log for period metrics (handles hybrid JSON/JSONL format)\n const entries = await readLogEntries(getLogPath(opts.cwd));\n\n // Match both legacy (action: \"task_created\") and status_changed entries\n const isCreate = (e: Record<string, unknown>) => e.action === 'task_created';\n const isComplete = (e: Record<string, unknown>) =>\n e.action === 'task_completed' ||\n (e.action === 'status_changed' && (e.after as Record<string, unknown>)?.status === 'done');\n const isArchive = (e: Record<string, unknown>) => e.action === 'task_archived';\n\n const createdInPeriod = entries.filter(\n (e) => isCreate(e) && (e.timestamp as string) >= cutoff,\n ).length;\n const completedInPeriod = entries.filter(\n (e) => isComplete(e) && (e.timestamp as string) >= cutoff,\n ).length;\n const archivedInPeriod = entries.filter(\n (e) => isArchive(e) && (e.timestamp as string) >= cutoff,\n ).length;\n\n const completionRate = createdInPeriod > 0\n ? Math.round((completedInPeriod / createdInPeriod) * 10000) / 100\n : 0;\n\n // All-time from log\n const totalCreated = entries.filter(isCreate).length;\n const totalCompleted = entries.filter(isComplete).length;\n const totalArchived = entries.filter(isArchive).length;\n\n return {\n currentState: { pending, active, done, blocked, totalActive },\n completionMetrics: {\n periodDays,\n completedInPeriod,\n createdInPeriod,\n completionRate,\n },\n activityMetrics: {\n createdInPeriod,\n completedInPeriod,\n archivedInPeriod,\n },\n allTime: { totalCreated, totalCompleted, totalArchived },\n };\n}\n\n/** Get project dashboard data. */\nexport async function getDashboard(opts: {\n compact?: boolean;\n period?: number;\n showCharts?: boolean;\n sections?: string[];\n verbose?: boolean;\n quiet?: boolean;\n cwd?: string;\n}, accessor?: DataAccessor): Promise<Record<string, unknown>> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(opts.cwd));\n if (!data) {\n throw new CleoError(ExitCode.CONFIG_ERROR, 'Not in a CLEO project. Run cleo init first.');\n }\n\n const tasks = data.tasks ?? [];\n const pending = tasks.filter(t => t.status === 'pending').length;\n const active = tasks.filter(t => t.status === 'active').length;\n const done = tasks.filter(t => t.status === 'done').length;\n const blocked = tasks.filter(t => t.status === 'blocked').length;\n const total = tasks.length;\n\n const project = data.project?.name ?? 'Unknown Project';\n const currentPhase = data.project?.currentPhase ?? null;\n\n const focusId = data.focus?.currentTask ?? null;\n let focusTask = null;\n if (focusId) {\n focusTask = tasks.find(t => t.id === focusId) ?? null;\n }\n\n const highPriority = tasks.filter(\n t => (t.priority === 'critical' || t.priority === 'high') && t.status !== 'done',\n );\n const blockedTasks = tasks.filter(t => t.status === 'blocked');\n\n // Label aggregation\n const labelMap: Record<string, number> = {};\n for (const t of tasks) {\n for (const label of t.labels ?? []) {\n labelMap[label] = (labelMap[label] ?? 0) + 1;\n }\n }\n const topLabels = Object.entries(labelMap)\n .map(([label, count]) => ({ label, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 8);\n\n return {\n project,\n currentPhase,\n summary: { pending, active, blocked, done, total },\n focus: { currentTask: focusId, task: focusTask },\n highPriority: { count: highPriority.length, tasks: highPriority.slice(0, 5) },\n blockedTasks: { count: blockedTasks.length, tasks: blockedTasks },\n topLabels,\n periodDays: opts.period ?? 7,\n };\n}\n\n/** Get completion history data. */\nexport async function getCompletionHistory(opts: {\n days?: number;\n since?: string;\n until?: string;\n cwd?: string;\n}): Promise<Record<string, unknown>> {\n const allEntries = await readLogEntries(getLogPath(opts.cwd));\n\n const days = opts.days ?? 30;\n const cutoff = opts.since ?? new Date(Date.now() - days * 86400000).toISOString();\n const endDate = opts.until ?? new Date().toISOString();\n\n const completions = allEntries.filter(\n (e) => (e.action === 'task_completed' ||\n (e.action === 'status_changed' && (e.after as Record<string, unknown>)?.status === 'done'))\n && (e.timestamp as string) >= cutoff\n && (e.timestamp as string) <= endDate,\n );\n\n // Group by date\n const byDate: Record<string, number> = {};\n for (const c of completions) {\n const date = (c.timestamp as string).split('T')[0]!;\n byDate[date] = (byDate[date] ?? 0) + 1;\n }\n\n const dailyCounts = Object.entries(byDate)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([date, count]) => ({ date, count }));\n\n const totalCompletions = completions.length;\n const avgPerDay = days > 0 ? Math.round((totalCompletions / days) * 100) / 100 : 0;\n const peakDay = dailyCounts.reduce(\n (max, d) => d.count > max.count ? d : max,\n { date: '', count: 0 },\n );\n\n return {\n period: { days, since: cutoff, until: endDate },\n totalCompletions,\n avgPerDay,\n peakDay,\n dailyCounts,\n };\n}\n", "/**\n * Labels aggregation core module.\n * @task T4783\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface LabelsResult {\n labels: Array<{ label: string; count: number; tasks: string[] }>;\n totalLabels: number;\n totalTagged: number;\n totalUntagged: number;\n}\n\n/** Get all labels with counts and task IDs per label. */\nexport async function getLabels(\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<LabelsResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n if (!data) {\n throw new CleoError(ExitCode.CONFIG_ERROR, 'No todo.json found');\n }\n\n const tasks = data.tasks ?? [];\n const labelMap: Record<string, string[]> = {};\n let taggedCount = 0;\n\n for (const t of tasks) {\n const taskLabels = t.labels ?? [];\n if (taskLabels.length > 0) taggedCount++;\n for (const label of taskLabels) {\n if (!labelMap[label]) labelMap[label] = [];\n labelMap[label]!.push(t.id);\n }\n }\n\n const labels = Object.entries(labelMap)\n .map(([label, taskIds]) => ({ label, count: taskIds.length, tasks: taskIds }))\n .sort((a, b) => b.count - a.count);\n\n return {\n labels,\n totalLabels: labels.length,\n totalTagged: taggedCount,\n totalUntagged: tasks.length - taggedCount,\n };\n}\n", "/**\n * Archive statistics core module.\n * @task T4783\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getArchivePath } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface ArchiveStatsResult {\n totalArchived: number;\n byReason: Record<string, number>;\n averageCycleTimeDays: number | null;\n archiveRate: {\n periodDays: number;\n archivedInPeriod: number;\n };\n lastArchived: string | null;\n}\n\ninterface ArchiveTask {\n createdAt?: string;\n completedAt?: string;\n _archive?: {\n archivedAt?: string;\n reason?: string;\n };\n}\n\ninterface ArchiveFile {\n _meta?: {\n lastArchived: string | null;\n };\n archivedTasks: ArchiveTask[];\n}\n\n/** Get archive statistics. */\nexport async function getArchiveStats(\n opts: { period?: number; cwd?: string },\n accessor?: DataAccessor,\n): Promise<ArchiveStatsResult> {\n const periodDays = opts.period ?? 30;\n const cutoff = new Date(Date.now() - periodDays * 86400000).toISOString();\n\n const archive = accessor\n ? await accessor.loadArchive() as unknown as ArchiveFile | null\n : await readJson<ArchiveFile>(getArchivePath(opts.cwd));\n\n if (!archive?.archivedTasks) {\n return {\n totalArchived: 0,\n byReason: {},\n averageCycleTimeDays: null,\n archiveRate: { periodDays, archivedInPeriod: 0 },\n lastArchived: null,\n };\n }\n\n const archived = archive.archivedTasks;\n\n // By reason\n const byReason: Record<string, number> = {};\n for (const t of archived) {\n const reason = t._archive?.reason || 'unknown';\n byReason[reason] = (byReason[reason] ?? 0) + 1;\n }\n\n // Average cycle time\n let totalCycleDays = 0;\n let samples = 0;\n for (const t of archived) {\n if (t.createdAt && t.completedAt) {\n const created = new Date(t.createdAt).getTime();\n const completed = new Date(t.completedAt).getTime();\n if (completed > created) {\n totalCycleDays += (completed - created) / 86400000;\n samples++;\n }\n }\n }\n const averageCycleTimeDays = samples > 0\n ? Math.round((totalCycleDays / samples) * 100) / 100\n : null;\n\n // Archive rate\n const archivedInPeriod = archived.filter(t => {\n const archivedAt = t._archive?.archivedAt;\n return archivedAt && archivedAt >= cutoff;\n }).length;\n\n const lastArchived = archive._meta?.lastArchived ?? null;\n\n return {\n totalArchived: archived.length,\n byReason,\n averageCycleTimeDays,\n archiveRate: { periodDays, archivedInPeriod },\n lastArchived,\n };\n}\n", "/**\n * MVI injection generation core module.\n * @task T4783\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath, getSessionsPath, getConfigPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface InjectGenerateResult {\n injection: string;\n sizeBytes: number;\n version: string;\n}\n\ninterface SessionRecord {\n id: string;\n status: string;\n name?: string;\n scope?: { type: string; rootTaskId: string };\n focus?: { currentTask?: string | null };\n}\n\n/** Generate Minimum Viable Injection (MVI) markdown. */\nexport async function generateInjection(\n projectRoot: string,\n accessor?: DataAccessor,\n): Promise<InjectGenerateResult> {\n // Read project state\n let version = 'unknown';\n try {\n const pkgPath = join(projectRoot, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n version = pkg.version || 'unknown';\n }\n } catch {\n // fallback\n }\n\n // Active session & focus\n let activeSessionName: string | null = null;\n let focusTask: string | null = null;\n let sessionScope: string | null = null;\n\n const todo = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(projectRoot));\n\n if (todo) {\n focusTask = todo.focus?.currentTask ?? null;\n activeSessionName = todo._meta?.activeSession ?? null;\n }\n\n // Try sessions.json for richer session data\n try {\n const sessionsPath = getSessionsPath(projectRoot);\n if (existsSync(sessionsPath)) {\n const sessionsData = JSON.parse(readFileSync(sessionsPath, 'utf-8')) as { sessions: SessionRecord[] };\n const active = sessionsData.sessions?.find(s => s.status === 'active');\n if (active) {\n activeSessionName = active.name || active.id;\n focusTask = active.focus?.currentTask ?? focusTask;\n sessionScope = `${active.scope?.type}:${active.scope?.rootTaskId}`;\n }\n }\n } catch {\n // fallback to todo.json data\n }\n\n // Storage engine from config\n let storageEngine = 'json';\n try {\n const configPath = getConfigPath(projectRoot);\n if (existsSync(configPath)) {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'));\n storageEngine = config.storage?.engine || 'json';\n }\n } catch {\n // default\n }\n\n // Build MVI markdown\n const mvi = buildMviMarkdown({\n version,\n storageEngine,\n activeSessionName,\n focusTask,\n sessionScope,\n });\n\n const sizeBytes = Buffer.byteLength(mvi, 'utf-8');\n\n return {\n injection: mvi,\n sizeBytes,\n version: '1.0.0',\n };\n}\n\n/** Build the MVI markdown string from current project state. */\nfunction buildMviMarkdown(state: {\n version: string;\n storageEngine: string;\n activeSessionName: string | null;\n focusTask: string | null;\n sessionScope: string | null;\n}): string {\n const sessionLine = state.activeSessionName\n ? `| Session | \\`${state.activeSessionName}\\` (${state.sessionScope || 'unknown'}) |`\n : '| Session | none |';\n const focusLine = state.focusTask\n ? `| Focus | \\`${state.focusTask}\\` |`\n : '| Focus | none |';\n\n return `## CLEO Task Management (MVI)\n\n> **Bootstrap**: Call \\`orchestrate.bootstrap\\` with \\`speed=fast\\` at session start.\n\n| Key | Value |\n|-----|-------|\n| Version | \\`${state.version}\\` |\n| Storage | \\`${state.storageEngine}\\` |\n${sessionLine}\n${focusLine}\n\n### Essential Commands\n\n| Command | Description |\n|---------|-------------|\n| \\`ct find \"query\"\\` | Fuzzy search tasks (minimal context) |\n| \\`ct show T1234\\` | Full task details |\n| \\`ct add \"Title\" --desc \"...\"\\` | Create task |\n| \\`ct done <id>\\` | Complete task |\n| \\`ct start <id>\\` | Start working on task |\n| \\`ct current\\` | Show current task |\n| \\`ct next\\` | Suggest next task |\n| \\`ct session list\\` | List sessions |\n| \\`ct session start --scope epic:T### --auto-start --name \"...\"\\` | Start session |\n| \\`ct session end --note \"...\"\\` | End session |\n| \\`ct dash\\` | Project overview |\n| \\`ct context\\` | Context window usage |\n\n### Session Protocol\n\n1. **START**: \\`ct session list\\` then \\`ct session resume <id>\\` or \\`ct session start --scope epic:T### --auto-start --name \"Work\"\\`\n2. **WORK**: \\`ct current\\` / \\`ct next\\` / \\`ct complete <id>\\` / \\`ct start <id>\\`\n3. **END**: \\`ct complete <id>\\` then \\`ct session end --note \"Progress\"\\`\n\n### Error Handling\n\n| Exit | Code | Fix |\n|:----:|------|-----|\n| 4 | \\`E_NOT_FOUND\\` | Use \\`ct find\\` or \\`ct list\\` to verify |\n| 6 | \\`E_VALIDATION\\` | Check field lengths, escape \\`$\\` as \\`\\\\$\\` |\n| 10 | \\`E_PARENT_NOT_FOUND\\` | Verify with \\`ct exists <parent-id>\\` |\n| 11 | \\`E_DEPTH_EXCEEDED\\` | Max depth 3 (epic->task->subtask) |\n| 12 | \\`E_SIBLING_LIMIT\\` | Max 7 siblings per parent |\n\n**After EVERY command**: Check exit code (\\`0\\` = success), check \\`\"success\"\\` in JSON output, execute \\`error.fix\\` if provided.\n`;\n}\n", "/**\n * System health checks core module.\n * @task T4783\n * @task T4795\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { checkStorageMigration } from '../migration/preflight.js';\nimport { checkCleoGitignore, checkVitalFilesTracked, checkLegacyAgentOutputs, type CheckResult } from '../validation/doctor/checks.js';\n\nconst execAsync = promisify(execFile);\n\nexport interface HealthCheck {\n name: string;\n status: 'pass' | 'warn' | 'fail';\n message?: string;\n}\n\nexport interface HealthResult {\n overall: 'healthy' | 'warning' | 'error';\n checks: HealthCheck[];\n version: string;\n installation: 'ok' | 'degraded';\n}\n\nexport interface DiagnosticsCheck {\n name: string;\n status: 'pass' | 'warn' | 'fail';\n details?: string;\n fix?: string;\n}\n\nexport interface DiagnosticsResult {\n timestamp: string;\n checks: DiagnosticsCheck[];\n summary: {\n total: number;\n passed: number;\n warned: number;\n failed: number;\n };\n}\n\n/** Run system health checks. */\nexport function getSystemHealth(\n projectRoot: string,\n opts?: { detailed?: boolean },\n): HealthResult {\n const cleoDir = join(projectRoot, '.cleo');\n const checks: HealthCheck[] = [];\n\n // Check .cleo directory\n if (existsSync(cleoDir)) {\n checks.push({ name: 'cleo_dir', status: 'pass', message: '.cleo directory exists' });\n } else {\n checks.push({ name: 'cleo_dir', status: 'fail', message: '.cleo directory not found' });\n }\n\n // Check todo.json\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n try {\n JSON.parse(readFileSync(todoPath, 'utf-8'));\n checks.push({ name: 'todo_json', status: 'pass', message: 'todo.json is valid JSON' });\n } catch {\n checks.push({ name: 'todo_json', status: 'fail', message: 'todo.json is not valid JSON' });\n }\n } else {\n checks.push({ name: 'todo_json', status: 'fail', message: 'todo.json not found' });\n }\n\n // Check config.json\n const configPath = join(cleoDir, 'config.json');\n if (existsSync(configPath)) {\n try {\n JSON.parse(readFileSync(configPath, 'utf-8'));\n checks.push({ name: 'config_json', status: 'pass', message: 'config.json is valid JSON' });\n } catch {\n checks.push({ name: 'config_json', status: 'warn', message: 'config.json is not valid JSON' });\n }\n } else {\n checks.push({ name: 'config_json', status: 'warn', message: 'config.json not found' });\n }\n\n // Check sessions.json\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n try {\n JSON.parse(readFileSync(sessionsPath, 'utf-8'));\n checks.push({ name: 'sessions_json', status: 'pass', message: 'sessions.json is valid JSON' });\n } catch {\n checks.push({ name: 'sessions_json', status: 'warn', message: 'sessions.json is not valid JSON' });\n }\n } else {\n checks.push({ name: 'sessions_json', status: 'pass', message: 'sessions.json not present (optional)' });\n }\n\n // Check .sequence.json\n const seqPath = join(cleoDir, '.sequence.json');\n if (existsSync(seqPath)) {\n try {\n JSON.parse(readFileSync(seqPath, 'utf-8'));\n checks.push({ name: 'sequence_json', status: 'pass', message: '.sequence.json is valid' });\n } catch {\n checks.push({ name: 'sequence_json', status: 'warn', message: '.sequence.json is not valid JSON' });\n }\n } else {\n checks.push({ name: 'sequence_json', status: 'warn', message: '.sequence.json not found' });\n }\n\n // Check archive\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (existsSync(archivePath)) {\n try {\n JSON.parse(readFileSync(archivePath, 'utf-8'));\n checks.push({ name: 'archive_json', status: 'pass', message: 'todo-archive.json is valid JSON' });\n } catch {\n checks.push({ name: 'archive_json', status: 'warn', message: 'todo-archive.json is not valid JSON' });\n }\n } else {\n checks.push({ name: 'archive_json', status: 'pass', message: 'todo-archive.json not present (optional)' });\n }\n\n if (opts?.detailed) {\n const logPath = join(cleoDir, 'todo-log.jsonl');\n if (existsSync(logPath)) {\n checks.push({ name: 'log_file', status: 'pass', message: 'todo-log.jsonl exists' });\n } else {\n checks.push({ name: 'log_file', status: 'warn', message: 'todo-log.jsonl not found' });\n }\n\n const backupDir = join(cleoDir, '.backups');\n if (existsSync(backupDir)) {\n checks.push({ name: 'backups_dir', status: 'pass', message: '.backups directory exists' });\n } else {\n checks.push({ name: 'backups_dir', status: 'pass', message: 'No backups directory (created on first write)' });\n }\n }\n\n // Get version\n let version = 'unknown';\n try {\n const pkgPath = join(projectRoot, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n version = pkg.version || 'unknown';\n }\n } catch {\n // fallback\n }\n\n const failCount = checks.filter(c => c.status === 'fail').length;\n const warnCount = checks.filter(c => c.status === 'warn').length;\n const overall: HealthResult['overall'] = failCount > 0 ? 'error' : warnCount > 0 ? 'warning' : 'healthy';\n const installation: HealthResult['installation'] = failCount > 0 ? 'degraded' : 'ok';\n\n return { overall, checks, version, installation };\n}\n\n/** Run extended diagnostics with fix suggestions. */\nexport function getSystemDiagnostics(\n projectRoot: string,\n opts?: { checks?: string[] },\n): DiagnosticsResult {\n const healthResult = getSystemHealth(projectRoot, { detailed: true });\n\n const diagChecks: DiagnosticsCheck[] = healthResult.checks.map(c => ({\n name: c.name,\n status: c.status,\n details: c.message,\n fix: c.status === 'fail'\n ? c.name === 'cleo_dir' ? 'Run: cleo init' :\n c.name === 'todo_json' ? 'Run: cleo init (or restore from backup)' :\n undefined\n : undefined,\n }));\n\n // Storage migration pre-flight check\n const preflight = checkStorageMigration(projectRoot);\n if (preflight.migrationNeeded) {\n diagChecks.push({\n name: 'storage_migration',\n status: 'fail',\n details: preflight.summary,\n fix: preflight.fix ?? undefined,\n });\n } else {\n diagChecks.push({\n name: 'storage_migration',\n status: 'pass',\n details: preflight.summary,\n });\n }\n\n // Schema version check\n const cleoDir = join(projectRoot, '.cleo');\n const todoPath = join(cleoDir, 'todo.json');\n if (existsSync(todoPath)) {\n try {\n const todo = JSON.parse(readFileSync(todoPath, 'utf-8'));\n const schemaVersion = todo._meta?.schemaVersion;\n if (schemaVersion) {\n diagChecks.push({ name: 'schema_version', status: 'pass', details: `Schema version: ${schemaVersion}` });\n } else {\n diagChecks.push({ name: 'schema_version', status: 'warn', details: 'No schema version in _meta', fix: 'Run: cleo migrate' });\n }\n } catch {\n // already caught in health check\n }\n }\n\n // Check for stale sessions\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessionsPath)) {\n try {\n const sessionsData = JSON.parse(readFileSync(sessionsPath, 'utf-8'));\n const activeSessions = (sessionsData.sessions ?? []).filter((s: { status: string }) => s.status === 'active');\n if (activeSessions.length > 3) {\n diagChecks.push({\n name: 'stale_sessions',\n status: 'warn',\n details: `${activeSessions.length} active sessions (may include stale)`,\n fix: 'Run: cleo session gc',\n });\n } else {\n diagChecks.push({ name: 'stale_sessions', status: 'pass', details: `${activeSessions.length} active session(s)` });\n }\n } catch {\n // skip\n }\n }\n\n // Filter checks if specific ones requested\n let filteredChecks = diagChecks;\n if (opts?.checks && opts.checks.length > 0) {\n filteredChecks = diagChecks.filter(c => opts.checks!.includes(c.name));\n }\n\n const passedCount = filteredChecks.filter(c => c.status === 'pass').length;\n const warnedCount = filteredChecks.filter(c => c.status === 'warn').length;\n const failedCount = filteredChecks.filter(c => c.status === 'fail').length;\n\n return {\n timestamp: new Date().toISOString(),\n checks: filteredChecks,\n summary: { total: filteredChecks.length, passed: passedCount, warned: warnedCount, failed: failedCount },\n };\n}\n\n// ============================================================================\n// Doctor Report (Comprehensive)\n// ============================================================================\n\nexport interface DoctorCheck {\n check: string;\n status: 'ok' | 'error' | 'warning';\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport interface DoctorReport {\n healthy: boolean;\n errors: number;\n warnings: number;\n checks: DoctorCheck[];\n}\n\nasync function commandExists(cmd: string): Promise<string | null> {\n try {\n const { stdout } = await execAsync('which', [cmd]);\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\nasync function fileSize(path: string): Promise<number> {\n try {\n return statSync(path).size;\n } catch {\n return -1;\n }\n}\n\nfunction mapCheckResult(cr: CheckResult): DoctorCheck {\n return {\n check: cr.id,\n status: cr.status === 'passed' ? 'ok' : cr.status === 'info' ? 'ok' : cr.status === 'warning' ? 'warning' : 'error',\n message: cr.message,\n ...(cr.fix ? { details: { fix: cr.fix } } : {}),\n };\n}\n\n/**\n * Run comprehensive doctor diagnostics combining dependency checks,\n * directory checks, data file checks, gitignore checks, and environment info.\n * @task T4795\n */\nexport async function coreDoctorReport(\n projectRoot: string,\n): Promise<DoctorReport> {\n const checks: DoctorCheck[] = [];\n\n // 1. Check dependencies\n const jqPath = await commandExists('jq');\n checks.push({\n check: 'jq_installed',\n status: jqPath ? 'ok' : 'error',\n message: jqPath ? `jq found: ${jqPath}` : 'jq not found. Install: https://jqlang.github.io/jq/download/',\n });\n\n const gitPath = await commandExists('git');\n checks.push({\n check: 'git_installed',\n status: gitPath ? 'ok' : 'warning',\n message: gitPath ? `git found: ${gitPath}` : 'git not found (optional)',\n });\n\n // 2. Check CLEO directories\n const cleoDir = join(projectRoot, '.cleo');\n const dirExists = existsSync(cleoDir);\n checks.push({\n check: 'project_dir',\n status: dirExists ? 'ok' : 'error',\n message: dirExists ? `Project dir: ${cleoDir}` : `Project dir not found: ${cleoDir}. Run: cleo init`,\n });\n\n // 3. Check data files\n const todoPath = join(cleoDir, 'todo.json');\n const todoExists = existsSync(todoPath);\n const todoSize = await fileSize(todoPath);\n checks.push({\n check: 'todo_file',\n status: todoExists ? 'ok' : 'error',\n message: todoExists\n ? `todo.json: ${todoSize} bytes`\n : `todo.json not found: ${todoPath}`,\n });\n\n if (todoExists) {\n try {\n const rawData = JSON.parse(readFileSync(todoPath, 'utf-8'));\n const taskCount = rawData.tasks?.length ?? 0;\n const schemaVersion = rawData._meta?.schemaVersion ?? 'unknown';\n checks.push({\n check: 'todo_data',\n status: 'ok',\n message: `${taskCount} tasks, schema v${schemaVersion}`,\n details: { taskCount, schemaVersion },\n });\n } catch {\n checks.push({\n check: 'todo_data',\n status: 'error',\n message: 'Failed to parse todo.json',\n });\n }\n }\n\n const configPath = join(cleoDir, 'config.json');\n const configExists = existsSync(configPath);\n checks.push({\n check: 'config_file',\n status: configExists ? 'ok' : 'warning',\n message: configExists ? 'config.json present' : 'config.json not found (using defaults)',\n });\n\n const archivePath = join(cleoDir, 'todo-archive.json');\n const archiveExists = existsSync(archivePath);\n checks.push({\n check: 'archive_file',\n status: 'ok',\n message: archiveExists ? 'archive file present' : 'no archive file (normal for new projects)',\n });\n\n const logPath = join(cleoDir, 'todo-log.jsonl');\n const logExists = existsSync(logPath);\n checks.push({\n check: 'log_file',\n status: logExists ? 'ok' : 'warning',\n message: logExists ? 'log file present' : 'log file not found',\n });\n\n // 4. Check root .gitignore for .cleo/ blocking\n const rootGitignorePath = join(projectRoot, '.gitignore');\n if (existsSync(rootGitignorePath)) {\n try {\n const gitignoreContent = readFileSync(rootGitignorePath, 'utf-8');\n const blockingLines = gitignoreContent.split('\\n').filter(line => {\n const trimmed = line.trim();\n if (trimmed.startsWith('#') || trimmed === '') return false;\n return /^\\/?\\.cleo\\/?(\\*)?$/.test(trimmed);\n });\n checks.push({\n check: 'root_gitignore',\n status: blockingLines.length > 0 ? 'warning' : 'ok',\n message: blockingLines.length > 0\n ? `.cleo/ is ignored in root .gitignore. Run 'cleo init' to fix.`\n : 'Root .gitignore does not block .cleo/',\n ...(blockingLines.length > 0 ? { details: { blockingLines } } : {}),\n });\n } catch {\n // Ignore read errors for gitignore check\n }\n }\n\n // 5. Gitignore integrity, vital files, legacy paths (delegated to core checks)\n checks.push(mapCheckResult(checkCleoGitignore(projectRoot)));\n checks.push(mapCheckResult(checkVitalFilesTracked(projectRoot)));\n checks.push(mapCheckResult(checkLegacyAgentOutputs(projectRoot)));\n\n // 6. Environment\n checks.push({\n check: 'node_version',\n status: 'ok',\n message: `Node.js ${process.version}`,\n });\n\n checks.push({\n check: 'platform',\n status: 'ok',\n message: `${process.platform} ${process.arch}`,\n });\n\n // Summary\n const errorCount = checks.filter((c) => c.status === 'error').length;\n const warningCount = checks.filter((c) => c.status === 'warning').length;\n const healthy = errorCount === 0;\n\n return { healthy, errors: errorCount, warnings: warningCount, checks };\n}\n", "/**\n * Roadmap generation core module.\n * @task T4538\n * @epic T4454\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Get roadmap from pending epics and CHANGELOG history. */\nexport async function getRoadmap(opts: {\n includeHistory?: boolean;\n upcomingOnly?: boolean;\n cwd?: string;\n}, accessor?: DataAccessor): Promise<Record<string, unknown>> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(opts.cwd));\n const tasks = data?.tasks ?? [];\n\n // Get current version\n const versionPath = join(opts.cwd ?? process.cwd(), 'VERSION');\n const currentVersion = existsSync(versionPath)\n ? readFileSync(versionPath, 'utf-8').trim()\n : 'unknown';\n\n // Find epics (tasks that are parents of other tasks)\n const childParentIds = new Set(tasks.filter(t => t.parentId).map(t => t.parentId!));\n const epics = tasks.filter(t => childParentIds.has(t.id));\n\n // Group epics by status\n const pending = epics.filter(e => e.status !== 'done');\n const completed = epics.filter(e => e.status === 'done');\n\n // Parse CHANGELOG if requested\n let releaseHistory: Array<{ version: string; date: string }> = [];\n if (opts.includeHistory) {\n const changelogPath = join(opts.cwd ?? process.cwd(), 'CHANGELOG.md');\n if (existsSync(changelogPath)) {\n const content = readFileSync(changelogPath, 'utf-8');\n const versionRegex = /^##\\s+\\[?v?(\\d+\\.\\d+\\.\\d+[^\\]]*)\\]?\\s*[-\\(]?\\s*(\\d{4}-\\d{2}-\\d{2})?/gm;\n let match;\n while ((match = versionRegex.exec(content)) !== null) {\n releaseHistory.push({\n version: match[1]!,\n date: match[2] ?? 'unknown',\n });\n }\n }\n }\n\n const upcoming = pending.map(e => ({\n id: e.id,\n title: e.title,\n status: e.status,\n priority: e.priority,\n phase: e.phase,\n childCount: tasks.filter(t => t.parentId === e.id).length,\n completedChildren: tasks.filter(t => t.parentId === e.id && t.status === 'done').length,\n }));\n\n return {\n currentVersion,\n upcoming,\n ...(opts.includeHistory && { releaseHistory }),\n ...(opts.includeHistory && { completedEpics: completed.length }),\n summary: {\n totalUpcoming: upcoming.length,\n totalTasks: tasks.length,\n },\n };\n}\n", "/**\n * Backup and restore core module.\n * @task T4783\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\n\nexport interface BackupResult {\n backupId: string;\n path: string;\n timestamp: string;\n type: string;\n files: string[];\n}\n\nexport interface RestoreResult {\n restored: boolean;\n backupId: string;\n timestamp: string;\n filesRestored: string[];\n}\n\n/** Create a backup of CLEO data files. */\nexport function createBackup(\n projectRoot: string,\n opts?: { type?: string; note?: string },\n): BackupResult {\n const cleoDir = join(projectRoot, '.cleo');\n const btype = opts?.type || 'snapshot';\n const timestamp = new Date().toISOString();\n const backupId = `${btype}-${timestamp.replace(/[:.]/g, '-')}`;\n const backupDir = join(cleoDir, 'backups', btype);\n\n if (!existsSync(backupDir)) {\n mkdirSync(backupDir, { recursive: true });\n }\n\n const filesToBackup = ['todo.json', 'todo-archive.json', 'sessions.json', 'config.json', 'todo-log.jsonl'];\n const backedUp: string[] = [];\n\n for (const file of filesToBackup) {\n const src = join(cleoDir, file);\n if (existsSync(src)) {\n const dest = join(backupDir, `${file}.${backupId}`);\n try {\n const content = readFileSync(src, 'utf-8');\n writeFileSync(dest, content, 'utf-8');\n backedUp.push(file);\n } catch {\n // skip files that fail to copy\n }\n }\n }\n\n // Write metadata\n const metaPath = join(backupDir, `${backupId}.meta.json`);\n try {\n writeFileSync(metaPath, JSON.stringify({\n backupId,\n type: btype,\n timestamp,\n note: opts?.note,\n files: backedUp,\n }, null, 2), 'utf-8');\n } catch {\n // non-fatal\n }\n\n return { backupId, path: backupDir, timestamp, type: btype, files: backedUp };\n}\n\n/** Restore from a backup. */\nexport function restoreBackup(\n projectRoot: string,\n params: { backupId: string; force?: boolean },\n): RestoreResult {\n if (!params.backupId) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'backupId is required');\n }\n\n const cleoDir = join(projectRoot, '.cleo');\n const backupTypes = ['snapshot', 'safety', 'migration'];\n let metaPath: string | null = null;\n let backupDir: string | null = null;\n\n for (const btype of backupTypes) {\n const candidateMeta = join(cleoDir, 'backups', btype, `${params.backupId}.meta.json`);\n if (existsSync(candidateMeta)) {\n metaPath = candidateMeta;\n backupDir = join(cleoDir, 'backups', btype);\n break;\n }\n }\n\n if (!metaPath || !backupDir) {\n throw new CleoError(ExitCode.NOT_FOUND, `Backup not found: ${params.backupId}`);\n }\n\n let meta: { files: string[]; timestamp: string };\n try {\n meta = JSON.parse(readFileSync(metaPath, 'utf-8'));\n } catch {\n throw new CleoError(ExitCode.FILE_ERROR, 'Failed to read backup metadata');\n }\n\n const restored: string[] = [];\n for (const file of meta.files ?? []) {\n const backupFile = join(backupDir, `${file}.${params.backupId}`);\n if (existsSync(backupFile)) {\n try {\n const content = readFileSync(backupFile, 'utf-8');\n writeFileSync(join(cleoDir, file), content, 'utf-8');\n restored.push(file);\n } catch {\n // skip files that fail to restore\n }\n }\n }\n\n return {\n restored: restored.length > 0,\n backupId: params.backupId,\n timestamp: meta.timestamp ?? new Date().toISOString(),\n filesRestored: restored,\n };\n}\n", "/**\n * Migration status core module.\n * @task T4783\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\n\nexport interface MigrateResult {\n from: string;\n to: string;\n migrations: Array<{ name: string; applied: boolean }>;\n dryRun: boolean;\n}\n\n/** Check/report schema migration status. */\nexport function getMigrationStatus(\n projectRoot: string,\n opts?: { target?: string; dryRun?: boolean },\n): MigrateResult {\n const todoPath = join(projectRoot, '.cleo', 'todo.json');\n\n let currentVersion = 'unknown';\n if (existsSync(todoPath)) {\n try {\n const todo = JSON.parse(readFileSync(todoPath, 'utf-8'));\n currentVersion = todo._meta?.schemaVersion ?? todo.version ?? 'unknown';\n } catch {\n throw new CleoError(ExitCode.FILE_ERROR, 'Failed to read todo.json');\n }\n } else {\n throw new CleoError(ExitCode.CONFIG_ERROR, 'No todo.json found');\n }\n\n const targetVersion = opts?.target ?? currentVersion;\n\n return {\n from: currentVersion,\n to: targetVersion,\n migrations: currentVersion === targetVersion\n ? []\n : [{ name: `${currentVersion} -> ${targetVersion}`, applied: false }],\n dryRun: opts?.dryRun ?? false,\n };\n}\n", "/**\n * System cleanup core module.\n * @task T4783\n */\n\nimport { readFileSync, writeFileSync, existsSync, readdirSync, unlinkSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\n\nexport interface CleanupResult {\n target: string;\n deleted: number;\n items: string[];\n dryRun: boolean;\n}\n\n/** Cleanup stale data (sessions, backups, logs). */\nexport function cleanupSystem(\n projectRoot: string,\n params: { target: string; olderThan?: string; dryRun?: boolean },\n): CleanupResult {\n if (!params.target) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'target is required (sessions|backups|logs|archive)');\n }\n\n const cleoDir = join(projectRoot, '.cleo');\n const dryRun = params.dryRun ?? false;\n const items: string[] = [];\n\n switch (params.target) {\n case 'sessions': {\n const sessPath = join(cleoDir, 'sessions.json');\n if (existsSync(sessPath)) {\n try {\n const data = JSON.parse(readFileSync(sessPath, 'utf-8'));\n const sessions = data.sessions ?? [];\n const stale = sessions.filter((s: { status: string; lastActivity?: string; id: string }) => {\n if (s.status !== 'active') return false;\n if (params.olderThan && s.lastActivity) {\n return s.lastActivity < params.olderThan;\n }\n const cutoff = new Date(Date.now() - 86400000).toISOString();\n return s.lastActivity && s.lastActivity < cutoff;\n });\n for (const s of stale) {\n items.push((s as { id: string }).id);\n }\n if (!dryRun && stale.length > 0) {\n const staleIds = new Set(stale.map((s: { id: string }) => s.id));\n data.sessions = sessions.filter((s: { id: string }) => !staleIds.has(s.id));\n writeFileSync(sessPath, JSON.stringify(data, null, 2), 'utf-8');\n }\n } catch {\n // skip\n }\n }\n break;\n }\n case 'backups': {\n const backupBaseDir = join(cleoDir, 'backups');\n if (existsSync(backupBaseDir)) {\n for (const typeDir of readdirSync(backupBaseDir)) {\n const fullDir = join(backupBaseDir, typeDir);\n try {\n for (const file of readdirSync(fullDir)) {\n if (file.endsWith('.meta.json')) {\n const metaFilePath = join(fullDir, file);\n try {\n const meta = JSON.parse(readFileSync(metaFilePath, 'utf-8'));\n if (params.olderThan && meta.timestamp < params.olderThan) {\n items.push(file.replace('.meta.json', ''));\n if (!dryRun) {\n unlinkSync(metaFilePath);\n for (const bf of readdirSync(fullDir)) {\n if (bf.includes(meta.backupId)) {\n try { unlinkSync(join(fullDir, bf)); } catch { /* skip */ }\n }\n }\n }\n }\n } catch { /* skip */ }\n }\n }\n } catch { /* skip */ }\n }\n }\n break;\n }\n case 'logs': {\n const auditPattern = /^audit-log-.*\\.json$/;\n if (existsSync(cleoDir)) {\n for (const file of readdirSync(cleoDir)) {\n if (auditPattern.test(file)) {\n items.push(file);\n if (!dryRun) {\n try { unlinkSync(join(cleoDir, file)); } catch { /* skip */ }\n }\n }\n }\n }\n break;\n }\n default:\n throw new CleoError(ExitCode.INVALID_INPUT, `Invalid cleanup target: ${params.target}`);\n }\n\n return { target: params.target, deleted: dryRun ? 0 : items.length, items, dryRun };\n}\n", "/**\n * Safestop and uncancel core module.\n * @task T4783\n */\n\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\n\nexport interface SafestopResult {\n stopped: boolean;\n reason: string;\n sessionEnded: boolean;\n handoff?: string;\n dryRun: boolean;\n}\n\nexport interface UncancelResult {\n taskId: string;\n uncancelled: boolean;\n previousStatus: string;\n newStatus: string;\n cascadeCount: number;\n dryRun: boolean;\n}\n\n/** Safe stop: signal clean shutdown for agents. */\nexport function safestop(\n projectRoot: string,\n opts?: { reason?: string; commit?: boolean; handoff?: string; noSessionEnd?: boolean; dryRun?: boolean },\n): SafestopResult {\n const dryRun = opts?.dryRun ?? false;\n const reason = opts?.reason ?? 'Manual safestop';\n let sessionEnded = false;\n\n if (!dryRun && !opts?.noSessionEnd) {\n const sessPath = join(projectRoot, '.cleo', 'sessions.json');\n if (existsSync(sessPath)) {\n try {\n const data = JSON.parse(readFileSync(sessPath, 'utf-8'));\n const sessions = data.sessions ?? [];\n let changed = false;\n for (const s of sessions) {\n if (s.status === 'active') {\n s.status = 'ended';\n s.endedAt = new Date().toISOString();\n s.endNote = `Safestop: ${reason}`;\n changed = true;\n sessionEnded = true;\n }\n }\n if (changed) {\n writeFileSync(sessPath, JSON.stringify(data, null, 2), 'utf-8');\n }\n } catch {\n // non-fatal\n }\n }\n }\n\n return { stopped: !dryRun, reason, sessionEnded, handoff: opts?.handoff, dryRun };\n}\n\n/** Uncancel a cancelled task (restore to pending). */\nexport function uncancelTask(\n projectRoot: string,\n params: { taskId: string; cascade?: boolean; notes?: string; dryRun?: boolean },\n): UncancelResult {\n if (!params.taskId) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'taskId is required');\n }\n\n const todoPath = join(projectRoot, '.cleo', 'todo.json');\n if (!existsSync(todoPath)) {\n throw new CleoError(ExitCode.CONFIG_ERROR, 'No todo.json found');\n }\n\n let todo: { tasks: Array<{ id: string; status: string; parentId?: string; notes?: Array<{ text: string; timestamp: string }> }> };\n try {\n todo = JSON.parse(readFileSync(todoPath, 'utf-8'));\n } catch {\n throw new CleoError(ExitCode.FILE_ERROR, 'Failed to parse todo.json');\n }\n\n const task = todo.tasks.find(t => t.id === params.taskId);\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${params.taskId}`);\n }\n if (task.status !== 'cancelled') {\n throw new CleoError(ExitCode.INVALID_INPUT, `Task ${params.taskId} is not cancelled (status: ${task.status})`);\n }\n\n const dryRun = params.dryRun ?? false;\n let cascadeCount = 0;\n\n if (!dryRun) {\n task.status = 'pending';\n if (params.notes) {\n if (!task.notes) task.notes = [];\n task.notes.push({ text: params.notes, timestamp: new Date().toISOString() });\n }\n if (params.cascade) {\n for (const t of todo.tasks) {\n if (t.parentId === params.taskId && t.status === 'cancelled') {\n t.status = 'pending';\n cascadeCount++;\n }\n }\n }\n writeFileSync(todoPath, JSON.stringify(todo, null, 2), 'utf-8');\n } else if (params.cascade) {\n cascadeCount = todo.tasks.filter(t => t.parentId === params.taskId && t.status === 'cancelled').length;\n }\n\n return {\n taskId: params.taskId,\n uncancelled: !dryRun,\n previousStatus: 'cancelled',\n newStatus: dryRun ? 'cancelled' : 'pending',\n cascadeCount,\n dryRun,\n };\n}\n", "/**\n * Config Engine\n *\n * Thin wrapper around core config operations.\n * Business logic lives in src/core/config.ts.\n *\n * @task T4789\n */\n\nimport { getRawConfig, getRawConfigValue, setConfigValue } from '../../core/config.js';\n\n/**\n * Engine result wrapper\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\n/**\n * Get config value by key (dot-notation supported)\n */\nexport async function configGet(\n projectRoot: string,\n key?: string\n): Promise<EngineResult<unknown>> {\n try {\n if (!key) {\n const config = await getRawConfig(projectRoot);\n if (!config) {\n return {\n success: false,\n error: { code: 'E_NOT_INITIALIZED', message: 'No config.json found' },\n };\n }\n return { success: true, data: config };\n }\n\n const value = await getRawConfigValue(key, projectRoot);\n if (value === undefined) {\n return {\n success: false,\n error: {\n code: 'E_CONFIG_KEY_NOT_FOUND',\n message: `Config key '${key}' not found`,\n },\n };\n }\n\n return { success: true, data: value };\n } catch (err: unknown) {\n return {\n success: false,\n error: { code: 'E_CONFIG_READ_FAILED', message: (err as Error).message },\n };\n }\n}\n\n/**\n * Set a config value by key (dot-notation supported)\n */\nexport async function configSet(\n projectRoot: string,\n key: string,\n value: unknown\n): Promise<EngineResult<{ key: string; value: unknown }>> {\n try {\n const result = await setConfigValue(key, value, projectRoot);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: { code: 'E_CONFIG_WRITE_FAILED', message: (err as Error).message },\n };\n }\n}\n", "/**\n * Core init logic - project initialization and maintenance.\n *\n * Single source of truth for all init operations. Both CLI and MCP\n * delegate here (shared-core pattern).\n *\n * Handles:\n * 1. .cleo/ directory structure creation\n * 2. Core data files (todo.json, config.json, sessions.json, etc.)\n * 3. Schema file installation (.cleo/schemas/)\n * 4. Sequence counter (.cleo/.sequence.json)\n * 5. Project info (.cleo/project-info.json)\n * 6. CAAMP injection into agent instruction files\n * 7. MCP server installation to detected providers\n * 8. Agent definition installation (cleo-subagent)\n * 9. Core skill installation via CAAMP\n * 10. NEXUS project registration\n * 11. Project type detection (--detect)\n * 12. Injection refresh (--update-docs)\n *\n * @task T4681\n * @task T4682\n * @task T4684\n * @task T4685\n * @task T4686\n * @task T4687\n * @task T4689\n * @task T4706\n * @task T4707\n * @epic T4663\n */\n\nimport { mkdir, access, writeFile, readFile, copyFile, symlink, lstat, unlink } from 'node:fs/promises';\nimport { constants as fsConstants, existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { join, resolve, basename, dirname } from 'node:path';\nimport { readJson } from '../store/json.js';\nimport { fileURLToPath } from 'node:url';\nimport { createHash } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { saveJson } from '../store/json.js';\nimport { getCleoDirAbsolute, getTaskPath, getConfigPath, getProjectRoot, getCleoHome } from './paths.js';\nimport type { TaskFile } from '../types/task.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Options for the init operation. */\nexport interface InitOptions {\n /** Project name override. */\n name?: string;\n /** Overwrite existing files. */\n force?: boolean;\n /** Auto-detect project configuration. */\n detect?: boolean;\n /** Update agent documentation injections only. */\n updateDocs?: boolean;\n}\n\n/** Result of the init operation. */\nexport interface InitResult {\n initialized: boolean;\n directory: string;\n created: string[];\n skipped: string[];\n warnings: string[];\n updateDocsOnly?: boolean;\n}\n\n// \u2500\u2500 Internal helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Check if a file exists and is readable.\n * @task T4681\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path, fsConstants.R_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Create default todo.json content.\n * @task T4681\n */\nfunction createDefaultTodo(projectName: string): TaskFile {\n const now = new Date().toISOString();\n return {\n version: '2.10.0',\n project: {\n name: projectName,\n currentPhase: null,\n phases: {},\n },\n lastUpdated: now,\n _meta: {\n schemaVersion: '2.10.0',\n checksum: '',\n configVersion: '2.10.0',\n },\n focus: {\n currentTask: null,\n },\n tasks: [],\n };\n}\n\n/**\n * Create default config.json content.\n * @task T4681\n */\nfunction createDefaultConfig(): Record<string, unknown> {\n return {\n version: '2.10.0',\n output: {\n defaultFormat: 'json',\n showColor: true,\n showUnicode: true,\n dateFormat: 'relative',\n },\n backup: {\n maxOperationalBackups: 10,\n maxSafetyBackups: 5,\n },\n hierarchy: {\n maxDepth: 3,\n maxSiblings: 7,\n },\n session: {\n autoStart: false,\n multiSession: false,\n },\n lifecycle: {\n mode: 'strict',\n },\n };\n}\n\n/**\n * Create default sessions.json content.\n * @task T4681\n */\nfunction createDefaultSessions(projectName: string): Record<string, unknown> {\n return {\n version: '1.0.0',\n project: { name: projectName },\n sessions: [],\n _meta: { schemaVersion: '1.0.0' },\n };\n}\n\n/**\n * Resolve the package root directory (where schemas/ and templates/ live).\n * @task T4681\n */\nfunction getPackageRoot(): string {\n const thisFile = fileURLToPath(import.meta.url);\n // src/core/init.ts -> 3 levels up to package root\n return resolve(dirname(thisFile), '..', '..');\n}\n\n/**\n * Load the gitignore template from the package's templates/ directory.\n * Falls back to embedded content if file not found.\n * @task T4700\n */\nfunction getGitignoreContent(): string {\n try {\n const packageRoot = getPackageRoot();\n const templatePath = join(packageRoot, 'templates', 'cleo-gitignore');\n if (existsSync(templatePath)) {\n return readFileSync(templatePath, 'utf-8');\n }\n } catch {\n // fallback\n }\n return CLEO_GITIGNORE_FALLBACK;\n}\n\n/** Embedded fallback for .cleo/.gitignore content. */\nconst CLEO_GITIGNORE_FALLBACK = `# CLEO Project Data - Selective Git Tracking\n# Tracked: todo.json, config.json, sessions.json, templates/, schemas/\n# IGNORED:\n*.lock\n*.tmp\n.backups/\nbackups/\nmetrics/\naudit-log-*.json\n.context-state.json\n.context-state-session_*.json\ncontext-states/\n*.db-journal\n*.db-wal\n*.db-shm\nresearch/\nrcsd/\n.current-session\n.git-checkpoint-state\nbackup-metadata.json\n*.corrupted\n*.bak\n*.bak*\n*.backup-*\nagent-outputs/\n.cache/\n`;\n\n/**\n * Remove .cleo/ or .cleo entries from the project root .gitignore.\n * @task T4641\n */\nasync function removeCleoFromRootGitignore(projectRoot: string): Promise<boolean> {\n const rootGitignorePath = join(projectRoot, '.gitignore');\n if (!(await fileExists(rootGitignorePath))) {\n return false;\n }\n const content = await readFile(rootGitignorePath, 'utf-8');\n const lines = content.split('\\n');\n const filtered = lines.filter(line => {\n const trimmed = line.trim();\n return !/^\\/?\\.cleo\\/?(\\*)?$/.test(trimmed);\n });\n if (filtered.length === lines.length) {\n return false;\n }\n await writeFile(rootGitignorePath, filtered.join('\\n'));\n return true;\n}\n\n/**\n * Generate a 12-character hex hash from a project path.\n * @task T4684\n */\nfunction generateProjectHash(projectPath: string): string {\n return createHash('sha256').update(projectPath).digest('hex').substring(0, 12);\n}\n\n/**\n * Read CLEO version from package.json.\n * @task T4684\n */\nfunction getCleoVersion(): string {\n try {\n const pkgPath = join(getPackageRoot(), 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\n/**\n * Get the CLEO-INJECTION.md template content.\n * Looks in the package templates/ directory first, then falls back\n * to the project .cleo/templates/ directory.\n * @task T4682\n */\nfunction getInjectionTemplateContent(): string | null {\n // First check package templates/\n const packageRoot = getPackageRoot();\n const packageTemplatePath = join(packageRoot, 'templates', 'CLEO-INJECTION.md');\n if (existsSync(packageTemplatePath)) {\n return readFileSync(packageTemplatePath, 'utf-8');\n }\n return null;\n}\n\n// \u2500\u2500 Core init operations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Create core .cleo/ directory structure and data files.\n * @task T4681\n */\nasync function initCoreFiles(\n cleoDir: string,\n projectName: string,\n force: boolean,\n created: string[],\n skipped: string[],\n): Promise<void> {\n // Create .cleo directory\n await mkdir(cleoDir, { recursive: true });\n\n // Create todo.json\n const todoPath = getTaskPath();\n if (await fileExists(todoPath) && !force) {\n skipped.push('tasks.json');\n } else {\n await saveJson(todoPath, createDefaultTodo(projectName));\n created.push('tasks.json');\n }\n\n // Create config.json\n const configPath = getConfigPath();\n if (await fileExists(configPath) && !force) {\n skipped.push('config.json');\n } else {\n await saveJson(configPath, createDefaultConfig());\n created.push('config.json');\n }\n\n // Create sessions.json\n const sessionsPath = join(cleoDir, 'sessions.json');\n if (await fileExists(sessionsPath) && !force) {\n skipped.push('sessions.json');\n } else {\n await saveJson(sessionsPath, createDefaultSessions(projectName));\n created.push('sessions.json');\n }\n\n // Create .sequence.json (task ID counter \u2014 JSON format for sequence module)\n const sequencePath = join(cleoDir, '.sequence.json');\n if (await fileExists(sequencePath) && !force) {\n skipped.push('.sequence.json');\n } else {\n await writeFile(sequencePath, JSON.stringify({ counter: 0, lastId: 'T000', checksum: '' }, null, 2));\n created.push('.sequence.json');\n }\n\n // Remove legacy .sequence plain-text file if it exists (migration)\n const legacySequencePath = join(cleoDir, '.sequence');\n try { await unlink(legacySequencePath); } catch { /* ignore if absent */ }\n\n // Create backup directories\n const backupDir = join(cleoDir, 'backups');\n await mkdir(join(backupDir, 'operational'), { recursive: true });\n await mkdir(join(backupDir, 'safety'), { recursive: true });\n\n // Create log file\n const logPath = join(cleoDir, 'todo-log.jsonl');\n if (!(await fileExists(logPath))) {\n const legacyLogPath = join(cleoDir, 'todo-log.json');\n if (await fileExists(legacyLogPath)) {\n const { rename: renameFile } = await import('node:fs/promises');\n await renameFile(legacyLogPath, logPath);\n created.push('todo-log.jsonl (migrated from todo-log.json)');\n } else {\n await writeFile(logPath, '');\n created.push('todo-log.jsonl');\n }\n }\n\n // Create archive file\n const archivePath = join(cleoDir, 'todo-archive.json');\n if (!(await fileExists(archivePath))) {\n await writeFile(archivePath, JSON.stringify({\n version: '2.10.0',\n _meta: { schemaVersion: '2.10.0' },\n archivedTasks: [],\n }, null, 2));\n created.push('todo-archive.json');\n }\n\n // Create .cleo/.gitignore\n const gitignorePath = join(cleoDir, '.gitignore');\n if (await fileExists(gitignorePath) && !force) {\n skipped.push('.gitignore');\n } else {\n await writeFile(gitignorePath, getGitignoreContent());\n created.push('.gitignore');\n }\n}\n\n/**\n * Copy JSON schema files from the package schemas/ directory to .cleo/schemas/.\n * @task T4681\n */\nasync function initSchemas(\n cleoDir: string,\n force: boolean,\n created: string[],\n warnings: string[],\n): Promise<void> {\n const schemasDir = join(cleoDir, 'schemas');\n await mkdir(schemasDir, { recursive: true });\n\n const packageRoot = getPackageRoot();\n const sourceSchemaDir = join(packageRoot, 'schemas');\n\n if (!existsSync(sourceSchemaDir)) {\n warnings.push('schemas/ directory not found in package root, skipping schema installation');\n return;\n }\n\n // Core schemas to copy\n const coreSchemas = [\n 'todo.schema.json',\n 'config.schema.json',\n 'archive.schema.json',\n 'log.schema.json',\n 'sessions.schema.json',\n 'project-info.schema.json',\n 'project-context.schema.json',\n ];\n\n let copiedCount = 0;\n for (const schemaFile of coreSchemas) {\n const sourcePath = join(sourceSchemaDir, schemaFile);\n const destPath = join(schemasDir, schemaFile);\n\n if (!existsSync(sourcePath)) {\n continue;\n }\n\n if (await fileExists(destPath) && !force) {\n continue;\n }\n\n try {\n await copyFile(sourcePath, destPath);\n copiedCount++;\n } catch (err) {\n warnings.push(`Failed to copy schema ${schemaFile}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (copiedCount > 0) {\n created.push(`schemas/ (${copiedCount} files)`);\n }\n}\n\n/**\n * Create project-info.json with project metadata.\n * @task T4684\n */\nasync function initProjectInfo(\n cleoDir: string,\n projectRoot: string,\n force: boolean,\n created: string[],\n skipped: string[],\n): Promise<void> {\n const projectInfoPath = join(cleoDir, 'project-info.json');\n\n if (await fileExists(projectInfoPath) && !force) {\n skipped.push('project-info.json');\n return;\n }\n\n const projectHash = generateProjectHash(projectRoot);\n const cleoVersion = getCleoVersion();\n const now = new Date().toISOString();\n\n const projectInfo = {\n $schema: './schemas/project-info.schema.json',\n schemaVersion: '1.0.0',\n projectHash,\n cleoVersion,\n lastUpdated: now,\n schemas: {\n todo: '2.10.0',\n config: '2.10.0',\n archive: '2.10.0',\n log: '1.0.0',\n },\n injection: {\n 'CLAUDE.md': null,\n 'AGENTS.md': null,\n 'GEMINI.md': null,\n },\n health: {\n status: 'unknown',\n lastCheck: null,\n issues: [],\n },\n features: {\n multiSession: false,\n verification: false,\n contextAlerts: false,\n },\n };\n\n await writeFile(projectInfoPath, JSON.stringify(projectInfo, null, 2));\n created.push('project-info.json');\n}\n\n/**\n * Inject CLEO-INJECTION.md template into agent instruction files via CAAMP.\n *\n * Injects the template reference `@.cleo/templates/AGENT-INJECTION.md`\n * into CLAUDE.md, AGENTS.md, GEMINI.md etc. using CAAMP's inject/injectAll.\n *\n * @task T4682\n */\nasync function initInjection(\n projectRoot: string,\n created: string[],\n warnings: string[],\n): Promise<void> {\n try {\n const {\n getInstalledProviders,\n injectAll,\n } = await import('@cleocode/caamp');\n\n const providers = getInstalledProviders();\n if (providers.length === 0) {\n warnings.push('No AI agent providers detected, skipping injection');\n return;\n }\n\n // The injection content references the local template which references\n // the global CLEO-INJECTION.md\n const injectionContent = '@.cleo/templates/AGENT-INJECTION.md';\n\n const results = await injectAll(providers, projectRoot, 'project', injectionContent);\n\n const injected: string[] = [];\n for (const [filePath, action] of results) {\n const fileName = basename(filePath);\n injected.push(`${fileName} (${action})`);\n }\n\n if (injected.length > 0) {\n created.push(`injection: ${injected.join(', ')}`);\n }\n } catch (err) {\n warnings.push(`CAAMP injection: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n/**\n * Install the AGENT-INJECTION.md template to .cleo/templates/.\n * This is the project-local copy that references the global CLEO-INJECTION.md.\n * @task T4682\n */\nasync function initInjectionTemplate(\n cleoDir: string,\n force: boolean,\n created: string[],\n skipped: string[],\n _warnings: string[],\n): Promise<void> {\n const templatesDir = join(cleoDir, 'templates');\n await mkdir(templatesDir, { recursive: true });\n\n const targetPath = join(templatesDir, 'AGENT-INJECTION.md');\n\n if (await fileExists(targetPath) && !force) {\n skipped.push('templates/AGENT-INJECTION.md');\n return;\n }\n\n // The AGENT-INJECTION.md template references the global CLEO-INJECTION.md\n const content = getInjectionTemplateContent();\n if (content) {\n // Install CLEO-INJECTION.md to the global templates dir as well\n const globalTemplatesDir = join(getCleoHome(), 'templates');\n await mkdir(globalTemplatesDir, { recursive: true });\n const globalPath = join(globalTemplatesDir, 'CLEO-INJECTION.md');\n if (!existsSync(globalPath) || force) {\n await writeFile(globalPath, content);\n }\n }\n\n // Create the project-local AGENT-INJECTION.md that references global\n const agentInjectionContent = [\n '<!-- Unified into CLEO-INJECTION.md (v2.0.0). This file retained for backward compatibility. -->',\n '<!-- Agents receive the appropriate MVI tier from CLEO-INJECTION.md -->',\n '@~/.cleo/templates/CLEO-INJECTION.md',\n '',\n ].join('\\n');\n\n await writeFile(targetPath, agentInjectionContent);\n created.push('templates/AGENT-INJECTION.md');\n}\n\n/**\n * Install cleo-subagent agent definition to ~/.agents/agents/.\n * @task T4685\n */\nasync function initAgentDefinition(\n created: string[],\n warnings: string[],\n): Promise<void> {\n const packageRoot = getPackageRoot();\n const agentSourceDir = join(packageRoot, 'agents', 'cleo-subagent');\n\n if (!existsSync(agentSourceDir)) {\n warnings.push('agents/cleo-subagent/ not found in package, skipping agent definition install');\n return;\n }\n\n const globalAgentsDir = join(homedir(), '.agents', 'agents', 'cleo-subagent');\n await mkdir(dirname(globalAgentsDir), { recursive: true });\n\n try {\n // Check if symlink already exists\n try {\n const stat = await lstat(globalAgentsDir);\n if (stat.isSymbolicLink() || stat.isDirectory()) {\n // Already installed\n return;\n }\n } catch {\n // Doesn't exist, proceed to create\n }\n\n // Create symlink from ~/.agents/agents/cleo-subagent -> package agents/cleo-subagent/\n await symlink(agentSourceDir, globalAgentsDir, 'dir');\n created.push('agent: cleo-subagent (symlinked)');\n } catch (err) {\n // If symlink fails (e.g., permissions), try copying\n try {\n await mkdir(globalAgentsDir, { recursive: true });\n const files = readdirSync(agentSourceDir);\n for (const file of files) {\n await copyFile(join(agentSourceDir, file), join(globalAgentsDir, file));\n }\n created.push('agent: cleo-subagent (copied)');\n } catch (copyErr) {\n warnings.push(`Agent definition install: ${copyErr instanceof Error ? copyErr.message : String(copyErr)}`);\n }\n }\n}\n\n/**\n * Install MCP server config to all detected providers via CAAMP.\n * @task T4706\n */\nasync function initMcpServer(\n projectRoot: string,\n created: string[],\n warnings: string[],\n): Promise<void> {\n try {\n const { detectEnvMode, generateMcpServerEntry } = await import('./mcp/index.js');\n const {\n getInstalledProviders,\n installMcpServerToAll,\n } = await import('@cleocode/caamp');\n type McpServerConfig = import('@cleocode/caamp').McpServerConfig;\n\n const env = detectEnvMode();\n const serverEntry = generateMcpServerEntry(env) as McpServerConfig;\n const providers = getInstalledProviders();\n\n if (providers.length === 0) {\n return;\n }\n\n const results = await installMcpServerToAll(\n providers, 'cleo', serverEntry, 'project', projectRoot,\n );\n\n const successes = results.filter(r => r.success);\n const failures = results.filter(r => !r.success);\n\n if (successes.length > 0) {\n created.push(`MCP server: ${successes.map(r => r.provider.id).join(', ')}`);\n }\n\n for (const f of failures) {\n if (f.error) {\n warnings.push(`MCP install to ${f.provider.id}: ${f.error}`);\n }\n }\n } catch (err) {\n warnings.push(`MCP server install: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n/**\n * Install CLEO core skills to the canonical skills directory via CAAMP.\n * @task T4707\n * @task T4689\n */\nasync function initCoreSkills(\n created: string[],\n warnings: string[],\n): Promise<void> {\n try {\n const {\n getInstalledProviders,\n installSkill,\n } = await import('@cleocode/caamp');\n\n const providers = getInstalledProviders();\n if (providers.length === 0) {\n return;\n }\n\n // Find ct-skills package\n let ctSkillsRoot: string | null = null;\n try {\n // resolve from package root\n const packageRoot = getPackageRoot();\n const ctSkillsPath = join(packageRoot, 'node_modules', '@cleocode', 'ct-skills');\n if (existsSync(join(ctSkillsPath, 'skills.json'))) {\n ctSkillsRoot = ctSkillsPath;\n }\n } catch {\n // not found\n }\n\n if (!ctSkillsRoot) {\n warnings.push('ct-skills package not found, skipping core skill installation');\n return;\n }\n\n // Read the skills catalog to find core skills\n const catalogPath = join(ctSkillsRoot, 'skills.json');\n const catalog = JSON.parse(readFileSync(catalogPath, 'utf-8'));\n const skills: Array<{ name: string; path: string; core: boolean; category: string; tier: number }> = catalog.skills ?? [];\n\n // Install core and recommended skills (tier 0, 1, 2)\n const coreSkills = skills.filter(s => s.tier <= 2);\n\n const installed: string[] = [];\n for (const skill of coreSkills) {\n const skillSourceDir = dirname(join(ctSkillsRoot, skill.path));\n\n if (!existsSync(skillSourceDir)) {\n continue;\n }\n\n try {\n const result = await installSkill(skillSourceDir, skill.name, providers, true);\n if (result.success) {\n installed.push(skill.name);\n }\n } catch {\n // Skill may already be installed, continue\n }\n }\n\n if (installed.length > 0) {\n created.push(`skills: ${installed.length} core skills installed`);\n }\n } catch (err) {\n warnings.push(`Core skill install: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n/**\n * Register project with NEXUS.\n * @task T4684\n */\nasync function initNexusRegistration(\n projectRoot: string,\n projectName: string,\n created: string[],\n warnings: string[],\n): Promise<void> {\n try {\n const { nexusInit, nexusRegister } = await import('./nexus/registry.js');\n await nexusInit();\n await nexusRegister(projectRoot, projectName);\n created.push('NEXUS registration');\n } catch (err) {\n const errStr = String(err);\n if (!errStr.includes('already registered') && !errStr.includes('NEXUS_PROJECT_EXISTS')) {\n warnings.push(`NEXUS registration: ${err instanceof Error ? err.message : errStr}`);\n }\n }\n}\n\n/**\n * Detect project type and write project-context.json.\n * @task T4687\n */\nasync function initProjectDetect(\n cleoDir: string,\n projectRoot: string,\n created: string[],\n warnings: string[],\n): Promise<void> {\n try {\n const { detectProjectType } = await import('../store/project-detect.js');\n const info = detectProjectType(projectRoot);\n const contextPath = join(cleoDir, 'project-context.json');\n const context = {\n ...info,\n detectedAt: new Date().toISOString(),\n };\n await writeFile(contextPath, JSON.stringify(context, null, 2));\n created.push('project-context.json');\n } catch (err) {\n warnings.push(`Project detection failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Run update-docs only: refresh all injections without reinitializing.\n * Re-injects CLEO-INJECTION.md into all detected agent instruction files.\n *\n * @task T4686\n */\nexport async function updateDocs(): Promise<InitResult> {\n const cleoDir = getCleoDirAbsolute();\n const projRoot = getProjectRoot();\n const created: string[] = [];\n const warnings: string[] = [];\n\n // Re-install the injection template\n await initInjectionTemplate(cleoDir, true, created, [], warnings);\n\n // Re-inject into all provider instruction files\n await initInjection(projRoot, created, warnings);\n\n return {\n initialized: true,\n directory: cleoDir,\n created,\n skipped: [],\n warnings,\n updateDocsOnly: true,\n };\n}\n\n/**\n * Run full project initialization.\n *\n * Creates the .cleo/ directory structure, installs schemas, templates,\n * agent definitions, MCP server configs, skills, and registers with NEXUS.\n *\n * @task T4681\n * @task T4682\n * @task T4684\n * @task T4685\n * @task T4686\n * @task T4687\n * @task T4689\n * @task T4706\n * @task T4707\n */\nexport async function initProject(opts: InitOptions = {}): Promise<InitResult> {\n // Handle --update-docs (T4686)\n if (opts.updateDocs) {\n return updateDocs();\n }\n\n const cleoDir = getCleoDirAbsolute();\n const projRoot = getProjectRoot();\n const projectName = opts.name ?? projRoot.split('/').pop() ?? 'My Project';\n const force = !!opts.force;\n\n const created: string[] = [];\n const skipped: string[] = [];\n const warnings: string[] = [];\n\n // T4681: Core files (todo.json, config.json, sessions.json, .sequence.json, etc.)\n await initCoreFiles(cleoDir, projectName, force, created, skipped);\n\n // T4681: Schema files (.cleo/schemas/)\n await initSchemas(cleoDir, force, created, warnings);\n\n // T4684: Project info (.cleo/project-info.json)\n await initProjectInfo(cleoDir, projRoot, force, created, skipped);\n\n // T4682: Injection template (.cleo/templates/AGENT-INJECTION.md)\n await initInjectionTemplate(cleoDir, force, created, skipped, warnings);\n\n // T4682: Inject into agent instruction files via CAAMP\n await initInjection(projRoot, created, warnings);\n\n // T4685: Agent definition (cleo-subagent)\n await initAgentDefinition(created, warnings);\n\n // T4706: MCP server installation\n await initMcpServer(projRoot, created, warnings);\n\n // T4707 + T4689: Core skills installation\n await initCoreSkills(created, warnings);\n\n // T4684: NEXUS registration\n await initNexusRegistration(projRoot, projectName, created, warnings);\n\n // Remove .cleo/ from root .gitignore if present\n const rootGitignoreChanged = await removeCleoFromRootGitignore(projRoot);\n if (rootGitignoreChanged) {\n warnings.push('.cleo/ was found in root .gitignore and has been removed. CLEO uses .cleo/.gitignore for selective tracking.');\n }\n\n // T4687: Project detection (--detect flag)\n if (opts.detect) {\n await initProjectDetect(cleoDir, projRoot, created, warnings);\n }\n\n return {\n initialized: true,\n directory: cleoDir,\n created,\n skipped,\n warnings,\n };\n}\n\n/**\n * Check if auto-init is enabled via environment variable.\n * @task T4789\n */\nexport function isAutoInitEnabled(): boolean {\n return process.env.CLEO_AUTO_INIT === 'true';\n}\n\n/**\n * Check if a project is initialized and auto-init if configured.\n * Returns { initialized: true } if ready, throws otherwise.\n * @task T4789\n */\nexport async function ensureInitialized(projectRoot?: string): Promise<{ initialized: boolean }> {\n const root = projectRoot ?? getProjectRoot();\n const cleoDir = join(root, '.cleo');\n const isInit = existsSync(cleoDir) && existsSync(join(cleoDir, 'todo.json'));\n\n if (isInit) {\n return { initialized: true };\n }\n\n if (isAutoInitEnabled()) {\n await initProject({ name: basename(root) });\n return { initialized: true };\n }\n\n throw new Error('CLEO project not initialized. Run system.init or set CLEO_AUTO_INIT=true');\n}\n\n/**\n * Get the current CLEO/project version.\n * Checks VERSION file, then package.json.\n * @task T4789\n */\nexport async function getVersion(projectRoot?: string): Promise<{ version: string }> {\n const root = projectRoot ?? getProjectRoot();\n\n // Try VERSION file\n const versionPaths = [\n join(root, 'VERSION'),\n join(root, '..', 'VERSION'),\n ];\n\n for (const versionPath of versionPaths) {\n try {\n const content = await readFile(versionPath, 'utf-8');\n const version = content.trim();\n if (version) {\n return { version };\n }\n } catch {\n // Try next path\n }\n }\n\n // Fallback: package.json\n const pkg = await readJson<{ version: string }>(join(root, 'package.json'));\n if (pkg?.version) {\n return { version: pkg.version };\n }\n\n return { version: '0.0.0' };\n}\n", "/**\n * Init Engine\n *\n * Thin wrapper around core init operations.\n * Business logic lives in src/core/init.ts.\n *\n * CRITICAL: Init is explicit, not automatic. The MCP server MUST NOT\n * silently create .cleo/ directories on first write.\n *\n * @task T4789\n */\n\nimport {\n initProject as coreInitProject,\n isAutoInitEnabled as coreIsAutoInitEnabled,\n ensureInitialized as coreEnsureInitialized,\n getVersion as coreGetVersion,\n} from '../../core/init.js';\n\n/**\n * Engine result wrapper\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\n/**\n * Initialize a CLEO project directory.\n *\n * Creates the .cleo/ directory structure with empty data files.\n * Returns error if already initialized (unless force=true).\n */\nexport async function initProject(\n projectRoot: string,\n options?: {\n projectName?: string;\n force?: boolean;\n }\n): Promise<EngineResult<{\n initialized: boolean;\n projectRoot: string;\n filesCreated: string[];\n}>> {\n try {\n const result = await coreInitProject({\n name: options?.projectName,\n force: options?.force,\n });\n\n return {\n success: true,\n data: {\n initialized: result.initialized,\n projectRoot,\n filesCreated: result.created,\n },\n };\n } catch (err: unknown) {\n const message = (err as Error).message;\n if (message.includes('already initialized')) {\n return {\n success: false,\n error: {\n code: 'E_ALREADY_INITIALIZED',\n message: 'CLEO project already initialized. Use force=true to reinitialize.',\n },\n };\n }\n return {\n success: false,\n error: { code: 'E_INIT_FAILED', message },\n };\n }\n}\n\n/**\n * Check if auto-init is enabled via environment variable\n */\nexport function isAutoInitEnabled(): boolean {\n return coreIsAutoInitEnabled();\n}\n\n/**\n * Check initialization status and auto-init if configured\n */\nexport async function ensureInitialized(\n projectRoot: string\n): Promise<EngineResult<{ initialized: boolean }>> {\n try {\n const result = await coreEnsureInitialized(projectRoot);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_NOT_INITIALIZED',\n message: (err as Error).message,\n },\n };\n }\n}\n\n/**\n * Get current version (native implementation)\n */\nexport async function getVersion(\n projectRoot: string\n): Promise<EngineResult<{ version: string }>> {\n try {\n const result = await coreGetVersion(projectRoot);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: { code: 'E_VERSION_FAILED', message: (err as Error).message },\n };\n }\n}\n", "/**\n * CAAMP Adapter - Canonical implementation\n *\n * Wraps @cleocode/caamp APIs for use across CLEO subsystems.\n * Provides provider registry, MCP config management, injection operations,\n * and batch/orchestration functions as EngineResult-returning functions.\n *\n * This is the SINGLE SOURCE OF TRUTH for all CAAMP adapter logic.\n * MCP engine layer re-exports from here.\n *\n * @task T4678\n * @task T4705\n * @epic T4663\n */\n\nimport {\n // Provider Registry\n getAllProviders,\n getProvider,\n resolveAlias,\n detectAllProviders,\n getInstalledProviders,\n getProviderCount,\n getRegistryVersion,\n getInstructionFiles,\n // MCP Config\n installMcpServer,\n listMcpServers,\n listAllMcpServers,\n removeMcpServer,\n resolveConfigPath,\n buildServerConfig,\n // Instructions\n inject,\n checkInjection,\n checkAllInjections,\n injectAll,\n generateInjectionContent,\n // Batch / Orchestration\n installBatchWithRollback,\n configureProviderGlobalAndProject,\n // Types\n type Provider,\n type McpServerConfig,\n type DetectionResult,\n type InstallResult,\n type InjectionStatus,\n type BatchInstallOptions,\n type BatchInstallResult,\n type DualScopeConfigureOptions,\n type DualScopeConfigureResult,\n} from '@cleocode/caamp';\n\n// ============================================================\n// EngineResult type (shared interface for engine-layer responses)\n// ============================================================\n\n/**\n * Generic result wrapper for engine-layer operations.\n * @task T4678\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\n// ============================================================\n// Provider Operations\n// ============================================================\n\n/**\n * List all registered providers.\n * @task T4332\n */\nexport function providerList(): EngineResult<Provider[]> {\n try {\n const providers = getAllProviders();\n return { success: true, data: providers };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_LIST',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Get a single provider by ID or alias.\n * @task T4332\n */\nexport function providerGet(idOrAlias: string): EngineResult<Provider> {\n try {\n const provider = getProvider(idOrAlias);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${idOrAlias}`,\n },\n };\n }\n return { success: true, data: provider };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_GET',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Detect all providers installed on the system.\n * @task T4332\n */\nexport function providerDetect(): EngineResult<DetectionResult[]> {\n try {\n const results = detectAllProviders();\n return { success: true, data: results };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_DETECT',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Get providers that are installed on the system.\n * @task T4332\n */\nexport function providerInstalled(): EngineResult<Provider[]> {\n try {\n const providers = getInstalledProviders();\n return { success: true, data: providers };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_INSTALLED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Get count of registered providers.\n * @task T4332\n */\nexport function providerCount(): EngineResult<{ count: number }> {\n try {\n const count = getProviderCount();\n return { success: true, data: { count } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_COUNT',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Get CAAMP registry version.\n * @task T4332\n */\nexport function registryVersion(): EngineResult<{ version: string }> {\n try {\n const version = getRegistryVersion();\n return { success: true, data: { version } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_REGISTRY_VERSION',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n// ============================================================\n// MCP Config Operations\n// ============================================================\n\n/**\n * List MCP servers for a specific provider.\n * @task T4332\n */\nexport async function mcpList(\n providerId: string,\n scope: 'project' | 'global',\n projectDir?: string\n): Promise<EngineResult<{ servers: unknown[] }>> {\n try {\n const provider = getProvider(providerId);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${providerId}`,\n },\n };\n }\n const servers = await listMcpServers(provider, scope, projectDir);\n return { success: true, data: { servers } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_MCP_LIST',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * List MCP servers across all installed providers.\n * @task T4332\n */\nexport async function mcpListAll(\n scope: 'project' | 'global',\n projectDir?: string\n): Promise<EngineResult<{ servers: unknown[] }>> {\n try {\n const providers = getInstalledProviders();\n const servers = await listAllMcpServers(providers, scope, projectDir);\n return { success: true, data: { servers } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_MCP_LIST_ALL',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Install an MCP server to a provider's config.\n * @task T4332\n */\nexport async function mcpInstall(\n providerId: string,\n serverName: string,\n config: McpServerConfig,\n scope?: 'project' | 'global',\n projectDir?: string\n): Promise<EngineResult<InstallResult>> {\n try {\n const provider = getProvider(providerId);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${providerId}`,\n },\n };\n }\n const result = await installMcpServer(provider, serverName, config, scope, projectDir);\n return { success: true, data: result };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_MCP_INSTALL',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Remove an MCP server from a provider's config.\n * @task T4332\n */\nexport async function mcpRemove(\n providerId: string,\n serverName: string,\n scope: 'project' | 'global',\n projectDir?: string\n): Promise<EngineResult<{ removed: boolean }>> {\n try {\n const provider = getProvider(providerId);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${providerId}`,\n },\n };\n }\n const removed = await removeMcpServer(provider, serverName, scope, projectDir);\n return { success: true, data: { removed } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_MCP_REMOVE',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Resolve the config file path for a provider.\n * @task T4332\n */\nexport function mcpConfigPath(\n providerId: string,\n scope: 'project' | 'global',\n projectDir?: string\n): EngineResult<{ path: string | null }> {\n try {\n const provider = getProvider(providerId);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${providerId}`,\n },\n };\n }\n const path = resolveConfigPath(provider, scope, projectDir);\n return { success: true, data: { path } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_MCP_CONFIG_PATH',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n// ============================================================\n// Injection Operations\n// ============================================================\n\n/**\n * Check injection status for a single file.\n * @task T4332\n */\nexport async function injectionCheck(\n filePath: string,\n expectedContent?: string\n): Promise<EngineResult<InjectionStatus>> {\n try {\n const status = await checkInjection(filePath, expectedContent);\n return { success: true, data: status };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_INJECTION_CHECK',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Check injection status across all providers.\n * @task T4332\n */\nexport async function injectionCheckAll(\n projectDir: string,\n scope: 'project' | 'global',\n expectedContent?: string\n): Promise<EngineResult<{ results: unknown[] }>> {\n try {\n const providers = getInstalledProviders();\n const results = await checkAllInjections(providers, projectDir, scope, expectedContent);\n return { success: true, data: { results } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_INJECTION_CHECK_ALL',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Inject or update content in a single file.\n * @task T4332\n */\nexport async function injectionUpdate(\n filePath: string,\n content: string\n): Promise<EngineResult<{ action: string }>> {\n try {\n const action = await inject(filePath, content);\n return { success: true, data: { action } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_INJECTION_UPDATE',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Inject content to all providers' instruction files.\n * @task T4332\n */\nexport async function injectionUpdateAll(\n projectDir: string,\n scope: 'project' | 'global',\n content: string\n): Promise<EngineResult<{ results: Record<string, string> }>> {\n try {\n const providers = getInstalledProviders();\n const resultMap = await injectAll(providers, projectDir, scope, content);\n // Convert Map to plain object for serialization\n const results: Record<string, string> = {};\n resultMap.forEach((action, key) => {\n results[key] = action;\n });\n return { success: true, data: { results } };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_INJECTION_UPDATE_ALL',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n// ============================================================\n// Batch / Orchestration Operations (T4705)\n// ============================================================\n\n/**\n * Install multiple MCP servers atomically with rollback on failure.\n * Supports Wave 4 init rewrite which needs to install multiple\n * skills/configs as a single atomic operation.\n *\n * @task T4705\n * @epic T4663\n */\nexport async function batchInstallWithRollback(\n options: BatchInstallOptions\n): Promise<EngineResult<BatchInstallResult>> {\n try {\n const result = await installBatchWithRollback(options);\n return { success: true, data: result };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_BATCH_INSTALL',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * Configure a provider at both global and project scope simultaneously.\n * Used during init to set up MCP configs in both scopes atomically.\n *\n * @task T4705\n * @epic T4663\n */\nexport async function dualScopeConfigure(\n providerId: string,\n options: DualScopeConfigureOptions\n): Promise<EngineResult<DualScopeConfigureResult>> {\n try {\n const provider = getProvider(providerId);\n if (!provider) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_PROVIDER_NOT_FOUND',\n message: `Provider not found: ${providerId}`,\n },\n };\n }\n const result = await configureProviderGlobalAndProject(provider, options);\n return { success: true, data: result };\n } catch (err) {\n return {\n success: false,\n error: {\n code: 'E_CAAMP_DUAL_SCOPE_CONFIGURE',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n// ============================================================\n// Utility Re-exports (passthrough, no EngineResult wrapping)\n// ============================================================\n\nexport {\n resolveAlias as caampResolveAlias,\n buildServerConfig as caampBuildServerConfig,\n generateInjectionContent as caampGenerateInjectionContent,\n getInstructionFiles as caampGetInstructionFiles,\n};\n\n// Re-export CAAMP types for downstream consumers\nexport type {\n Provider as CaampProvider,\n McpServerConfig as CaampMcpServerConfig,\n DetectionResult as CaampDetectionResult,\n InstallResult as CaampInstallResult,\n InjectionStatus as CaampInjectionStatus,\n BatchInstallOptions as CaampBatchInstallOptions,\n BatchInstallResult as CaampBatchInstallResult,\n DualScopeConfigureOptions as CaampDualScopeConfigureOptions,\n DualScopeConfigureResult as CaampDualScopeConfigureResult,\n};\n", "/**\n * Template Parser Engine\n *\n * Native TypeScript implementation for parsing GitHub issue template YAML files\n * and producing structured JSON config. Both the MCP server and the Bash CLI\n * can consume the generated config at .cleo/issue-templates.json.\n *\n * Supports: parseIssueTemplates, getTemplateForSubcommand, generateTemplateConfig, validateLabels\n *\n * @task T4492\n */\n\nimport { readFileSync, readdirSync, existsSync } from 'fs';\nimport { join} from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { writeJsonFileAtomic, getDataPath } from './store.js';\n\n/**\n * Engine result wrapper (matches config-engine.ts pattern)\n */\nexport interface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\n/**\n * A single section/field within an issue template\n */\nexport interface TemplateSection {\n id: string;\n type: 'textarea' | 'dropdown' | 'input' | 'markdown' | 'checkboxes';\n label: string;\n required: boolean;\n options?: string[]; // For dropdown type\n placeholder?: string;\n}\n\n/**\n * A parsed issue template\n */\nexport interface IssueTemplate {\n filename: string; // e.g., \"bug_report.yml\"\n subcommand: string; // e.g., \"bug\" (derived from filename)\n name: string; // e.g., \"Bug Report\"\n titlePrefix: string; // e.g., \"[Bug]: \"\n labels: string[]; // e.g., [\"bug\", \"triage\"]\n sections: TemplateSection[];\n}\n\n/**\n * The full template config output\n */\nexport interface TemplateConfig {\n templates: IssueTemplate[];\n generatedAt: string; // ISO timestamp\n sourceDir: string; // Path to .github/ISSUE_TEMPLATE/\n}\n\n/**\n * Known filename suffixes to strip when deriving subcommand.\n * Pattern: strip _report, _request, _question, then take the first word.\n */\nconst SUFFIX_PATTERNS = ['_report', '_request', '_question'];\n\n/**\n * Derive a subcommand name from a template filename.\n *\n * Examples:\n * bug_report.yml -> \"bug\"\n * feature_request.yml -> \"feature\"\n * help_question.yml -> \"help\"\n */\nfunction deriveSubcommand(filename: string): string {\n // Remove .yml / .yaml extension\n let stem = filename.replace(/\\.ya?ml$/i, '');\n\n // Strip known suffixes\n for (const suffix of SUFFIX_PATTERNS) {\n if (stem.endsWith(suffix)) {\n stem = stem.slice(0, -suffix.length);\n break;\n }\n }\n\n // Take the first word (split on underscore, hyphen, or space)\n const firstWord = stem.split(/[_\\-\\s]/)[0];\n return firstWord.toLowerCase();\n}\n\n/**\n * Parse a single YAML template file into an IssueTemplate.\n */\nfunction parseTemplateFile(templateDir: string, filename: string): IssueTemplate {\n const filePath = join(templateDir, filename);\n const raw = readFileSync(filePath, 'utf-8');\n const parsed = parseYaml(raw) as Record<string, unknown>;\n\n const name = typeof parsed.name === 'string' ? parsed.name : filename;\n const titlePrefix = typeof parsed.title === 'string' ? parsed.title : '';\n\n // Parse labels - can be an array of strings\n let labels: string[] = [];\n if (Array.isArray(parsed.labels)) {\n labels = parsed.labels.map((l: unknown) => String(l));\n }\n\n // Parse body sections\n const sections: TemplateSection[] = [];\n if (Array.isArray(parsed.body)) {\n for (const item of parsed.body) {\n if (typeof item !== 'object' || item === null) continue;\n\n const entry = item as Record<string, unknown>;\n const type = String(entry.type || 'unknown') as TemplateSection['type'];\n const attributes = (entry.attributes || {}) as Record<string, unknown>;\n const validations = (entry.validations || {}) as Record<string, unknown>;\n\n // For markdown type, use 'value' hash as a pseudo-id since they lack an id field\n const id = typeof entry.id === 'string'\n ? entry.id\n : (type === 'markdown' ? `markdown-${sections.length}` : `section-${sections.length}`);\n\n const label = typeof attributes.label === 'string'\n ? attributes.label\n : (type === 'markdown' ? 'Markdown' : '');\n\n const required = validations.required === true;\n\n const section: TemplateSection = {\n id,\n type,\n label,\n required,\n };\n\n // Add options for dropdown type\n if (type === 'dropdown' && Array.isArray(attributes.options)) {\n section.options = attributes.options.map((o: unknown) => String(o));\n }\n\n // Add options for checkboxes type\n if (type === 'checkboxes' && Array.isArray(attributes.options)) {\n section.options = (attributes.options as Array<Record<string, unknown>>).map(\n (o) => typeof o.label === 'string' ? o.label : String(o)\n );\n }\n\n // Add placeholder if present\n if (typeof attributes.placeholder === 'string') {\n section.placeholder = attributes.placeholder;\n }\n\n sections.push(section);\n }\n }\n\n return {\n filename,\n subcommand: deriveSubcommand(filename),\n name,\n titlePrefix,\n labels,\n sections,\n };\n}\n\n/**\n * Parse all templates from the repo's .github/ISSUE_TEMPLATE/ directory.\n *\n * Reads YAML files directly (live parse, no caching).\n * Excludes config.yml which is the GitHub template chooser config.\n */\nexport function parseIssueTemplates(projectRoot: string): EngineResult<TemplateConfig> {\n const templateDir = join(projectRoot, '.github', 'ISSUE_TEMPLATE');\n\n if (!existsSync(templateDir)) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Issue template directory not found: ${templateDir}`,\n },\n };\n }\n\n let files: string[];\n try {\n files = readdirSync(templateDir)\n .filter((f) => /\\.ya?ml$/i.test(f) && f !== 'config.yml');\n } catch (error: unknown) {\n return {\n success: false,\n error: {\n code: 'E_PARSE_ERROR',\n message: `Failed to read template directory: ${(error as Error).message}`,\n },\n };\n }\n\n if (files.length === 0) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: 'No issue template YAML files found (excluding config.yml)',\n },\n };\n }\n\n const templates: IssueTemplate[] = [];\n\n for (const file of files.sort()) {\n try {\n templates.push(parseTemplateFile(templateDir, file));\n } catch (error: unknown) {\n return {\n success: false,\n error: {\n code: 'E_PARSE_ERROR',\n message: `Failed to parse template ${file}: ${(error as Error).message}`,\n details: { filename: file },\n },\n };\n }\n }\n\n return {\n success: true,\n data: {\n templates,\n generatedAt: new Date().toISOString(),\n sourceDir: templateDir,\n },\n };\n}\n\n/**\n * Get template config for a specific subcommand (bug/feature/help).\n *\n * Performs a live parse and filters to the matching template.\n */\nexport function getTemplateForSubcommand(\n projectRoot: string,\n subcommand: string\n): EngineResult<IssueTemplate> {\n const result = parseIssueTemplates(projectRoot);\n\n if (!result.success || !result.data) {\n return {\n success: false,\n error: result.error || {\n code: 'E_PARSE_ERROR',\n message: 'Failed to parse issue templates',\n },\n };\n }\n\n const template = result.data.templates.find(\n (t) => t.subcommand === subcommand.toLowerCase()\n );\n\n if (!template) {\n const available = result.data.templates.map((t) => t.subcommand).join(', ');\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `No template found for subcommand '${subcommand}'. Available: ${available}`,\n details: { available: result.data.templates.map((t) => t.subcommand) },\n },\n };\n }\n\n return { success: true, data: template };\n}\n\n/**\n * Generate and cache the config as .cleo/issue-templates.json.\n *\n * Performs a live parse, then writes the result using writeJsonFileAtomic.\n */\nexport async function generateTemplateConfig(\n projectRoot: string\n): Promise<EngineResult<TemplateConfig>> {\n const result = parseIssueTemplates(projectRoot);\n\n if (!result.success || !result.data) {\n return {\n success: false,\n error: result.error || {\n code: 'E_PARSE_ERROR',\n message: 'Failed to parse issue templates',\n },\n };\n }\n\n const outputPath = getDataPath(projectRoot, 'issue-templates.json');\n\n try {\n writeJsonFileAtomic(outputPath, result.data);\n } catch (error: unknown) {\n return {\n success: false,\n error: {\n code: 'E_PARSE_ERROR',\n message: `Failed to write template config: ${(error as Error).message}`,\n details: { outputPath },\n },\n };\n }\n\n return { success: true, data: result.data };\n}\n\n/**\n * Validate that labels exist on a GitHub repo.\n *\n * Compares the template labels against a list of known repo labels.\n * Returns which labels exist and which are missing.\n */\nexport function validateLabels(\n labels: string[],\n repoLabels: string[]\n): EngineResult<{ existing: string[]; missing: string[] }> {\n const repoLabelSet = new Set(repoLabels.map((l) => l.toLowerCase()));\n\n const existing: string[] = [];\n const missing: string[] = [];\n\n for (const label of labels) {\n if (repoLabelSet.has(label.toLowerCase())) {\n existing.push(label);\n } else {\n missing.push(label);\n }\n }\n\n return {\n success: true,\n data: { existing, missing },\n };\n}\n", "/**\n * Lifecycle Engine\n *\n * Thin wrapper over src/core/lifecycle/ for MCP engine layer.\n * Types, constants, and business logic are defined in core;\n * this file provides synchronous EngineResult-wrapped access\n * for the MCP domain handlers.\n *\n * @task T4785\n */\n\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { resolveProjectRoot, readJsonFile, writeJsonFileAtomic } from './store.js';\nimport {\n ENGINE_LIFECYCLE_STAGES,\n STAGE_DEFINITIONS,\n STAGE_PREREQUISITES,\n type EngineLifecycleStage,\n type EngineStageStatus,\n type EngineRcsdManifest,\n type GateData,\n type StageInfo,\n} from '../../core/lifecycle/index.js';\n\n/**\n * Re-export types and constants for consumers that import from engine.\n */\nexport { ENGINE_LIFECYCLE_STAGES as LIFECYCLE_STAGES };\nexport type LifecycleStage = EngineLifecycleStage;\nexport type StageStatus = EngineStageStatus;\nexport type { StageInfo, GateData };\nexport type RcsdManifest = EngineRcsdManifest;\n\n/**\n * Engine result type\n */\ninterface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: { code: string; message: string; details?: unknown };\n}\n\n// ============================================================================\n// Internal I/O helpers (synchronous, using store.ts)\n// ============================================================================\n\nfunction getRcsdDir(epicId: string, projectRoot?: string): string {\n const root = projectRoot || resolveProjectRoot();\n return join(root, '.cleo', 'rcsd', epicId);\n}\n\nfunction getRcsdManifestPath(epicId: string, projectRoot?: string): string {\n return join(getRcsdDir(epicId, projectRoot), '_manifest.json');\n}\n\nfunction readRcsdManifest(epicId: string, projectRoot?: string): EngineRcsdManifest | null {\n return readJsonFile<EngineRcsdManifest>(getRcsdManifestPath(epicId, projectRoot));\n}\n\nfunction writeRcsdManifest(epicId: string, manifest: EngineRcsdManifest, projectRoot?: string): void {\n const dir = getRcsdDir(epicId, projectRoot);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeJsonFileAtomic(getRcsdManifestPath(epicId, projectRoot), manifest);\n}\n\n// ============================================================================\n// Exported engine functions\n// ============================================================================\n\n/**\n * List all epic IDs that have RCSD data\n */\nexport function listRcsdEpics(projectRoot?: string): string[] {\n const root = projectRoot || resolveProjectRoot();\n const rcsdDir = join(root, '.cleo', 'rcsd');\n\n if (!existsSync(rcsdDir)) {\n return [];\n }\n\n try {\n return readdirSync(rcsdDir, { withFileTypes: true })\n .filter(d => d.isDirectory() && d.name.startsWith('T'))\n .map(d => d.name);\n } catch {\n return [];\n }\n}\n\n/**\n * lifecycle.check / lifecycle.status - Get lifecycle status for epic\n * @task T4785\n */\nexport function lifecycleStatus(\n epicId: string,\n projectRoot?: string,\n): EngineResult {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n const manifest = readRcsdManifest(epicId, projectRoot);\n\n if (!manifest) {\n return {\n success: true,\n data: {\n epicId,\n currentStage: null,\n stages: ENGINE_LIFECYCLE_STAGES.map(s => ({\n stage: s,\n status: 'pending' as EngineStageStatus,\n })),\n nextStage: 'research',\n blockedOn: [],\n initialized: false,\n },\n };\n }\n\n const stages = ENGINE_LIFECYCLE_STAGES.map(s => {\n const stageData = manifest.stages[s];\n return {\n stage: s,\n status: (stageData?.status || 'pending') as EngineStageStatus,\n completedAt: stageData?.completedAt,\n notes: stageData?.notes,\n };\n });\n\n let currentStage: EngineLifecycleStage | null = null;\n let nextStage: EngineLifecycleStage | null = null;\n\n for (let i = ENGINE_LIFECYCLE_STAGES.length - 1; i >= 0; i--) {\n const s = ENGINE_LIFECYCLE_STAGES[i];\n const status = manifest.stages[s]?.status;\n if (status === 'completed' || status === 'skipped') {\n currentStage = s;\n if (i < ENGINE_LIFECYCLE_STAGES.length - 1) {\n nextStage = ENGINE_LIFECYCLE_STAGES[i + 1];\n }\n break;\n }\n }\n\n if (!currentStage) {\n nextStage = 'research';\n }\n\n const blockedOn: string[] = [];\n if (nextStage) {\n const prereqs = STAGE_PREREQUISITES[nextStage] || [];\n for (const prereq of prereqs) {\n const prereqStatus = manifest.stages[prereq]?.status;\n if (prereqStatus !== 'completed' && prereqStatus !== 'skipped') {\n blockedOn.push(prereq);\n }\n }\n }\n\n return {\n success: true,\n data: {\n epicId,\n title: manifest.title,\n currentStage,\n stages,\n nextStage,\n blockedOn,\n initialized: true,\n },\n };\n}\n\n/**\n * lifecycle.history - Stage transition history\n * @task T4785\n */\nexport function lifecycleHistory(\n taskId: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'taskId is required' } };\n }\n\n const manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n return {\n success: true,\n data: {\n taskId,\n history: [],\n message: 'No lifecycle data found for this task',\n },\n };\n }\n\n const history: Array<{\n stage: string;\n action: string;\n timestamp: string;\n notes?: string;\n }> = [];\n\n for (const [stageName, stageData] of Object.entries(manifest.stages)) {\n if (stageData.status === 'completed' && stageData.completedAt) {\n history.push({\n stage: stageName,\n action: 'completed',\n timestamp: stageData.completedAt,\n notes: stageData.notes,\n });\n }\n if (stageData.status === 'skipped' && stageData.skippedAt) {\n history.push({\n stage: stageName,\n action: 'skipped',\n timestamp: stageData.skippedAt,\n notes: stageData.skippedReason,\n });\n }\n\n if (stageData.gates) {\n for (const [gateName, gateData] of Object.entries(stageData.gates)) {\n if (gateData.timestamp) {\n history.push({\n stage: stageName,\n action: `gate.${gateData.status}: ${gateName}`,\n timestamp: gateData.timestamp,\n notes: gateData.notes || gateData.reason,\n });\n }\n }\n }\n }\n\n history.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n return {\n success: true,\n data: { taskId, history },\n };\n}\n\n/**\n * lifecycle.gates - Get all gate statuses for an epic\n * @task T4785\n */\nexport function lifecycleGates(\n taskId: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'taskId is required' } };\n }\n\n const manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n return {\n success: true,\n data: {\n taskId,\n gates: {},\n message: 'No lifecycle data found for this task',\n },\n };\n }\n\n const gates: Record<string, Record<string, GateData>> = {};\n\n for (const [stageName, stageData] of Object.entries(manifest.stages)) {\n if (stageData.gates && Object.keys(stageData.gates).length > 0) {\n gates[stageName] = stageData.gates;\n }\n }\n\n return {\n success: true,\n data: { taskId, gates },\n };\n}\n\n/**\n * lifecycle.prerequisites - Get required prior stages for a target stage\n * @task T4785\n */\nexport function lifecyclePrerequisites(\n targetStage: string,\n _projectRoot?: string,\n): EngineResult {\n if (!targetStage) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'targetStage is required' } };\n }\n\n if (!ENGINE_LIFECYCLE_STAGES.includes(targetStage as EngineLifecycleStage)) {\n return {\n success: false,\n error: {\n code: 'E_INVALID_STAGE',\n message: `Invalid stage: ${targetStage}. Valid stages: ${ENGINE_LIFECYCLE_STAGES.join(', ')}`,\n },\n };\n }\n\n const prereqs = STAGE_PREREQUISITES[targetStage] || [];\n\n return {\n success: true,\n data: {\n targetStage,\n prerequisites: prereqs,\n stageInfo: STAGE_DEFINITIONS.find(s => s.stage === targetStage),\n },\n };\n}\n\n/**\n * lifecycle.check - Check if a stage's prerequisites are met\n * @task T4785\n */\nexport function lifecycleCheck(\n epicId: string,\n targetStage: string,\n projectRoot?: string,\n): EngineResult {\n if (!epicId || !targetStage) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId and targetStage are required' } };\n }\n\n if (!ENGINE_LIFECYCLE_STAGES.includes(targetStage as EngineLifecycleStage)) {\n return {\n success: false,\n error: {\n code: 'E_INVALID_STAGE',\n message: `Invalid stage: ${targetStage}. Valid stages: ${ENGINE_LIFECYCLE_STAGES.join(', ')}`,\n },\n };\n }\n\n const manifest = readRcsdManifest(epicId, projectRoot);\n const prereqs = STAGE_PREREQUISITES[targetStage] || [];\n\n const missingPrerequisites: string[] = [];\n const issues: Array<{ stage: string; severity: string; message: string }> = [];\n\n for (const prereq of prereqs) {\n const prereqStatus = manifest?.stages[prereq]?.status;\n if (prereqStatus !== 'completed' && prereqStatus !== 'skipped') {\n missingPrerequisites.push(prereq);\n issues.push({\n stage: prereq,\n severity: 'error',\n message: `Stage '${prereq}' must be completed or skipped before '${targetStage}'`,\n });\n }\n }\n\n return {\n success: true,\n data: {\n epicId,\n targetStage,\n valid: missingPrerequisites.length === 0,\n canProgress: missingPrerequisites.length === 0,\n missingPrerequisites,\n issues,\n },\n };\n}\n\n/**\n * lifecycle.progress / lifecycle.record - Record stage completion\n * @task T4785\n */\nexport function lifecycleProgress(\n taskId: string,\n stage: string,\n status: string,\n notes?: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !stage || !status) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId, stage, and status are required' },\n };\n }\n\n if (!ENGINE_LIFECYCLE_STAGES.includes(stage as EngineLifecycleStage)) {\n return {\n success: false,\n error: { code: 'E_INVALID_STAGE', message: `Invalid stage: ${stage}` },\n };\n }\n\n const validStatuses: EngineStageStatus[] = ['pending', 'completed', 'skipped', 'blocked'];\n if (!validStatuses.includes(status as EngineStageStatus)) {\n return {\n success: false,\n error: { code: 'E_INVALID_STATUS', message: `Invalid status: ${status}. Valid: ${validStatuses.join(', ')}` },\n };\n }\n\n let manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n manifest = { epicId: taskId, stages: {} };\n }\n\n if (!manifest.stages[stage]) {\n manifest.stages[stage] = { status: 'pending' };\n }\n\n const now = new Date().toISOString();\n manifest.stages[stage].status = status as EngineStageStatus;\n\n if (status === 'completed') {\n manifest.stages[stage].completedAt = now;\n }\n\n if (notes) {\n manifest.stages[stage].notes = notes;\n }\n\n writeRcsdManifest(taskId, manifest, projectRoot);\n\n return {\n success: true,\n data: {\n epicId: taskId,\n stage,\n status,\n recorded: true,\n timestamp: now,\n },\n };\n}\n\n/**\n * lifecycle.skip - Skip a stage with reason\n * @task T4785\n */\nexport function lifecycleSkip(\n taskId: string,\n stage: string,\n reason: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !stage || !reason) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId, stage, and reason are required' },\n };\n }\n\n let manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n manifest = { epicId: taskId, stages: {} };\n }\n\n if (!manifest.stages[stage]) {\n manifest.stages[stage] = { status: 'pending' };\n }\n\n const now = new Date().toISOString();\n manifest.stages[stage].status = 'skipped';\n manifest.stages[stage].skippedAt = now;\n manifest.stages[stage].skippedReason = reason;\n\n writeRcsdManifest(taskId, manifest, projectRoot);\n\n return {\n success: true,\n data: {\n epicId: taskId,\n stage,\n skipped: true,\n reason,\n timestamp: now,\n },\n };\n}\n\n/**\n * lifecycle.reset - Reset a stage (emergency)\n * @task T4785\n */\nexport function lifecycleReset(\n taskId: string,\n stage: string,\n reason: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !stage || !reason) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId, stage, and reason are required' },\n };\n }\n\n const manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n return {\n success: false,\n error: { code: 'E_NOT_FOUND', message: `No lifecycle data found for ${taskId}` },\n };\n }\n\n if (!manifest.stages[stage]) {\n return {\n success: false,\n error: { code: 'E_NOT_FOUND', message: `Stage '${stage}' not found for ${taskId}` },\n };\n }\n\n manifest.stages[stage] = {\n status: 'pending',\n notes: `Reset: ${reason}`,\n };\n\n writeRcsdManifest(taskId, manifest, projectRoot);\n\n return {\n success: true,\n data: {\n taskId,\n stage,\n reset: 'pending',\n reason,\n warning: 'Stage has been reset to pending. Previous data was cleared.',\n },\n };\n}\n\n/**\n * lifecycle.gate.pass - Mark gate as passed\n * @task T4785\n */\nexport function lifecycleGatePass(\n taskId: string,\n gateName: string,\n agent?: string,\n notes?: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !gateName) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId and gateName are required' },\n };\n }\n\n let manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n manifest = { epicId: taskId, stages: {} };\n }\n\n const stageParts = gateName.split('-');\n const stageName = stageParts[0];\n\n if (!manifest.stages[stageName]) {\n manifest.stages[stageName] = { status: 'pending' };\n }\n\n if (!manifest.stages[stageName].gates) {\n manifest.stages[stageName].gates = {};\n }\n\n const now = new Date().toISOString();\n manifest.stages[stageName].gates![gateName] = {\n status: 'passed',\n agent,\n notes,\n timestamp: now,\n };\n\n writeRcsdManifest(taskId, manifest, projectRoot);\n\n return {\n success: true,\n data: {\n taskId,\n gateName,\n status: 'passed',\n timestamp: now,\n },\n };\n}\n\n/**\n * lifecycle.gate.fail - Mark gate as failed\n * @task T4785\n */\nexport function lifecycleGateFail(\n taskId: string,\n gateName: string,\n reason?: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !gateName) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId and gateName are required' },\n };\n }\n\n let manifest = readRcsdManifest(taskId, projectRoot);\n\n if (!manifest) {\n manifest = { epicId: taskId, stages: {} };\n }\n\n const stageParts = gateName.split('-');\n const stageName = stageParts[0];\n\n if (!manifest.stages[stageName]) {\n manifest.stages[stageName] = { status: 'pending' };\n }\n\n if (!manifest.stages[stageName].gates) {\n manifest.stages[stageName].gates = {};\n }\n\n const now = new Date().toISOString();\n manifest.stages[stageName].gates![gateName] = {\n status: 'failed',\n reason,\n timestamp: now,\n };\n\n writeRcsdManifest(taskId, manifest, projectRoot);\n\n return {\n success: true,\n data: {\n taskId,\n gateName,\n status: 'failed',\n reason,\n timestamp: now,\n },\n };\n}\n", "/**\n * RCSD pipeline lifecycle - stage transitions and gate enforcement.\n * @task T4467\n * @epic T4454\n */\n\nimport { readJson, saveJson } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport { getCleoDirAbsolute, getBackupDir } from '../paths.js';\nimport { join } from 'node:path';\n\n/** RCSD pipeline stages in order. */\nexport const RCSD_STAGES = ['research', 'consensus', 'specification', 'decomposition'] as const;\nexport type RcsdStage = typeof RCSD_STAGES[number];\n\n/** Execution stages. */\nexport const EXECUTION_STAGES = ['implementation', 'contribution', 'release'] as const;\nexport type ExecutionStage = typeof EXECUTION_STAGES[number];\n\n/** All lifecycle stages. */\nexport type LifecycleStage = RcsdStage | ExecutionStage;\n\n/** Stage status values. */\nexport type StageStatus = 'not_started' | 'in_progress' | 'completed' | 'skipped';\n\n/** RCSD manifest for an epic. */\nexport interface RcsdManifest {\n epicId: string;\n createdAt: string;\n updatedAt: string;\n stages: Record<LifecycleStage, {\n status: StageStatus;\n startedAt?: string;\n completedAt?: string;\n artifacts?: string[];\n }>;\n}\n\n/** Lifecycle enforcement modes. */\nexport type EnforcementMode = 'strict' | 'advisory' | 'off';\n\n/** Gate check result. */\nexport interface GateCheckResult {\n allowed: boolean;\n mode: EnforcementMode;\n missingPrerequisites: string[];\n currentStage: LifecycleStage;\n message: string;\n}\n\n/** Stage transition result. */\nexport interface StageTransitionResult {\n epicId: string;\n stage: LifecycleStage;\n previousStatus: StageStatus;\n newStatus: StageStatus;\n timestamp: string;\n}\n\n/**\n * Get RCSD manifest path for an epic.\n * @task T4467\n */\nfunction getRcsdPath(epicId: string, cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'rcsd', epicId, '_manifest.json');\n}\n\n/**\n * Read or initialize RCSD manifest for an epic.\n * @task T4467\n */\nasync function readRcsdManifest(epicId: string, cwd?: string): Promise<RcsdManifest> {\n const path = getRcsdPath(epicId, cwd);\n const existing = await readJson<RcsdManifest>(path);\n if (existing) return existing;\n\n // Initialize new manifest\n const now = new Date().toISOString();\n const allStages = [...RCSD_STAGES, ...EXECUTION_STAGES] as const;\n const stages: RcsdManifest['stages'] = {} as RcsdManifest['stages'];\n\n for (const stage of allStages) {\n stages[stage] = { status: 'not_started' };\n }\n\n return {\n epicId,\n createdAt: now,\n updatedAt: now,\n stages,\n };\n}\n\n/**\n * Save RCSD manifest.\n * @task T4467\n */\nasync function saveRcsdManifest(manifest: RcsdManifest, cwd?: string): Promise<void> {\n const path = getRcsdPath(manifest.epicId, cwd);\n manifest.updatedAt = new Date().toISOString();\n await saveJson(path, manifest, { backupDir: getBackupDir(cwd) });\n}\n\n/**\n * Get the current lifecycle state for an epic.\n * @task T4467\n */\nexport async function getLifecycleState(\n epicId: string,\n cwd?: string,\n): Promise<RcsdManifest> {\n return readRcsdManifest(epicId, cwd);\n}\n\n/**\n * Start a lifecycle stage.\n * @task T4467\n */\nexport async function startStage(\n epicId: string,\n stage: LifecycleStage,\n cwd?: string,\n): Promise<StageTransitionResult> {\n const manifest = await readRcsdManifest(epicId, cwd);\n\n // Gate check\n const gateResult = await checkGate(epicId, stage, cwd);\n if (!gateResult.allowed) {\n throw new CleoError(\n ExitCode.LIFECYCLE_GATE_FAILED,\n gateResult.message,\n );\n }\n\n const stageData = manifest.stages[stage];\n if (!stageData) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Unknown stage: ${stage}`);\n }\n\n const previousStatus = stageData.status;\n if (previousStatus === 'completed') {\n throw new CleoError(\n ExitCode.LIFECYCLE_TRANSITION_INVALID,\n `Stage '${stage}' is already completed`,\n );\n }\n\n const now = new Date().toISOString();\n stageData.status = 'in_progress';\n stageData.startedAt = now;\n\n await saveRcsdManifest(manifest, cwd);\n\n return {\n epicId,\n stage,\n previousStatus,\n newStatus: 'in_progress',\n timestamp: now,\n };\n}\n\n/**\n * Complete a lifecycle stage.\n * @task T4467\n */\nexport async function completeStage(\n epicId: string,\n stage: LifecycleStage,\n artifacts?: string[],\n cwd?: string,\n): Promise<StageTransitionResult> {\n const manifest = await readRcsdManifest(epicId, cwd);\n const stageData = manifest.stages[stage];\n\n if (!stageData) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Unknown stage: ${stage}`);\n }\n\n const previousStatus = stageData.status;\n if (previousStatus !== 'in_progress' && previousStatus !== 'not_started') {\n throw new CleoError(\n ExitCode.LIFECYCLE_TRANSITION_INVALID,\n `Cannot complete stage '${stage}' from status '${previousStatus}'`,\n );\n }\n\n const now = new Date().toISOString();\n stageData.status = 'completed';\n stageData.completedAt = now;\n if (artifacts?.length) {\n stageData.artifacts = artifacts;\n }\n\n await saveRcsdManifest(manifest, cwd);\n\n return {\n epicId,\n stage,\n previousStatus,\n newStatus: 'completed',\n timestamp: now,\n };\n}\n\n/**\n * Skip a lifecycle stage.\n * @task T4467\n */\nexport async function skipStage(\n epicId: string,\n stage: LifecycleStage,\n _reason: string,\n cwd?: string,\n): Promise<StageTransitionResult> {\n const manifest = await readRcsdManifest(epicId, cwd);\n const stageData = manifest.stages[stage];\n\n if (!stageData) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Unknown stage: ${stage}`);\n }\n\n const previousStatus = stageData.status;\n if (previousStatus === 'completed') {\n throw new CleoError(\n ExitCode.LIFECYCLE_TRANSITION_INVALID,\n `Cannot skip stage '${stage}' - already completed`,\n );\n }\n\n const now = new Date().toISOString();\n stageData.status = 'skipped';\n\n await saveRcsdManifest(manifest, cwd);\n\n return {\n epicId,\n stage,\n previousStatus,\n newStatus: 'skipped',\n timestamp: now,\n };\n}\n\n/**\n * Check lifecycle gate before starting a stage.\n * @task T4467\n */\nexport async function checkGate(\n epicId: string,\n targetStage: LifecycleStage,\n cwd?: string,\n): Promise<GateCheckResult> {\n // Get enforcement mode from config\n const mode = await getEnforcementMode(cwd);\n\n if (mode === 'off') {\n return {\n allowed: true,\n mode,\n missingPrerequisites: [],\n currentStage: targetStage,\n message: 'Gate check disabled',\n };\n }\n\n const manifest = await readRcsdManifest(epicId, cwd);\n const allStages = [...RCSD_STAGES, ...EXECUTION_STAGES] as LifecycleStage[];\n const targetIndex = allStages.indexOf(targetStage);\n\n if (targetIndex === -1) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Unknown stage: ${targetStage}`);\n }\n\n // Check all prior stages are completed or skipped\n const missing: string[] = [];\n for (let i = 0; i < targetIndex; i++) {\n const stage = allStages[i]!;\n const status = manifest.stages[stage]?.status ?? 'not_started';\n if (status !== 'completed' && status !== 'skipped') {\n missing.push(stage);\n }\n }\n\n const allowed = mode === 'advisory' || missing.length === 0;\n const message = missing.length > 0\n ? `SPAWN BLOCKED: Lifecycle prerequisites not met. Missing: ${missing.join(', ')}`\n : 'All prerequisites met';\n\n return {\n allowed,\n mode,\n missingPrerequisites: missing,\n currentStage: targetStage,\n message,\n };\n}\n\n/**\n * Get lifecycle enforcement mode from config.\n * @task T4467\n */\nasync function getEnforcementMode(cwd?: string): Promise<EnforcementMode> {\n // Check environment variable first\n const envMode = process.env['LIFECYCLE_ENFORCEMENT_MODE'];\n if (envMode && ['strict', 'advisory', 'off'].includes(envMode)) {\n return envMode as EnforcementMode;\n }\n\n // Read from config\n try {\n const configPath = join(getCleoDirAbsolute(cwd), 'config.json');\n const config = await readJson<{ lifecycleEnforcement?: { mode?: string } }>(configPath);\n const mode = config?.lifecycleEnforcement?.mode;\n if (mode && ['strict', 'advisory', 'off'].includes(mode)) {\n return mode as EnforcementMode;\n }\n } catch {\n // Config may not exist\n }\n\n return 'strict';\n}\n\n// ============================================================================\n// Engine-compatible lifecycle stages (superset including validation/testing)\n// These are used by the MCP engine layer for RCSD-IVTR pipeline support.\n// ============================================================================\n\n/** Full RCSD-IVTR stage list used by the engine layer. */\nexport const ENGINE_LIFECYCLE_STAGES = [\n 'research', 'consensus', 'specification', 'decomposition',\n 'implementation', 'validation', 'testing', 'release',\n] as const;\n\nexport type EngineLifecycleStage = (typeof ENGINE_LIFECYCLE_STAGES)[number];\n\n/** Engine-compatible stage status (includes 'pending' and 'blocked'). */\nexport type EngineStageStatus = 'pending' | 'completed' | 'skipped' | 'blocked';\n\n/** Gate data within a stage. */\nexport interface GateData {\n status: 'passed' | 'failed' | 'pending';\n agent?: string;\n notes?: string;\n reason?: string;\n timestamp?: string;\n}\n\n/** Engine-compatible stage data with extended fields. */\nexport interface EngineStageData {\n status: EngineStageStatus;\n completedAt?: string;\n skippedAt?: string;\n skippedReason?: string;\n artifacts?: string[];\n notes?: string;\n gates?: Record<string, GateData>;\n}\n\n/** Engine-compatible RCSD manifest with extended fields. */\nexport interface EngineRcsdManifest {\n epicId: string;\n title?: string;\n stages: Record<string, EngineStageData>;\n}\n\n/** Stage definition with metadata. */\nexport interface StageInfo {\n stage: EngineLifecycleStage;\n name: string;\n description: string;\n order: number;\n optional: boolean;\n pipeline: 'rcsd' | 'ivtr';\n}\n\n/** Stage definitions with metadata. */\nexport const STAGE_DEFINITIONS: StageInfo[] = [\n { stage: 'research', name: 'Research', description: 'Information gathering and exploration', order: 1, optional: false, pipeline: 'rcsd' },\n { stage: 'consensus', name: 'Consensus', description: 'Multi-agent decisions and validation', order: 2, optional: true, pipeline: 'rcsd' },\n { stage: 'specification', name: 'Specification', description: 'Document creation and RFC design', order: 3, optional: false, pipeline: 'rcsd' },\n { stage: 'decomposition', name: 'Decomposition', description: 'Task breakdown and planning', order: 4, optional: false, pipeline: 'rcsd' },\n { stage: 'implementation', name: 'Implementation', description: 'Code execution and building', order: 5, optional: false, pipeline: 'ivtr' },\n { stage: 'validation', name: 'Validation', description: 'Validation and quality checks', order: 6, optional: false, pipeline: 'ivtr' },\n { stage: 'testing', name: 'Testing', description: 'Test execution and coverage', order: 7, optional: false, pipeline: 'ivtr' },\n { stage: 'release', name: 'Release', description: 'Version management and publishing', order: 8, optional: true, pipeline: 'ivtr' },\n];\n\n/** Prerequisite map: stage -> required prior stages. */\nexport const STAGE_PREREQUISITES: Record<string, string[]> = {\n research: [],\n consensus: ['research'],\n specification: ['research'],\n decomposition: ['research', 'specification'],\n implementation: ['research', 'specification', 'decomposition'],\n validation: ['implementation'],\n testing: ['implementation'],\n release: ['implementation', 'validation', 'testing'],\n};\n\n/**\n * Read engine-compatible RCSD manifest (returns null if no data exists).\n * @task T4785\n */\nasync function readEngineManifest(epicId: string, cwd?: string): Promise<EngineRcsdManifest | null> {\n const path = join(getCleoDirAbsolute(cwd), 'rcsd', epicId, '_manifest.json');\n return readJson<EngineRcsdManifest>(path);\n}\n\n/**\n * Save engine-compatible RCSD manifest.\n * @task T4785\n */\nasync function saveEngineManifest(epicId: string, manifest: EngineRcsdManifest, cwd?: string): Promise<void> {\n const path = join(getCleoDirAbsolute(cwd), 'rcsd', epicId, '_manifest.json');\n await saveJson(path, manifest, { backupDir: getBackupDir(cwd) });\n}\n\n/**\n * Get lifecycle status for an epic (engine-compatible format).\n * Returns stage progress, current/next stage, and blockers.\n * @task T4785\n */\nexport async function getLifecycleStatus(\n epicId: string,\n cwd?: string,\n): Promise<{\n epicId: string;\n title?: string;\n currentStage: EngineLifecycleStage | null;\n stages: Array<{ stage: string; status: EngineStageStatus; completedAt?: string; notes?: string }>;\n nextStage: EngineLifecycleStage | null;\n blockedOn: string[];\n initialized: boolean;\n}> {\n const manifest = await readEngineManifest(epicId, cwd);\n\n if (!manifest) {\n return {\n epicId,\n currentStage: null,\n stages: ENGINE_LIFECYCLE_STAGES.map(s => ({ stage: s, status: 'pending' as EngineStageStatus })),\n nextStage: 'research',\n blockedOn: [],\n initialized: false,\n };\n }\n\n const stages = ENGINE_LIFECYCLE_STAGES.map(s => {\n const stageData = manifest.stages[s];\n return {\n stage: s,\n status: (stageData?.status || 'pending') as EngineStageStatus,\n completedAt: stageData?.completedAt,\n notes: stageData?.notes,\n };\n });\n\n let currentStage: EngineLifecycleStage | null = null;\n let nextStage: EngineLifecycleStage | null = null;\n\n for (let i = ENGINE_LIFECYCLE_STAGES.length - 1; i >= 0; i--) {\n const s = ENGINE_LIFECYCLE_STAGES[i];\n const status = manifest.stages[s]?.status;\n if (status === 'completed' || status === 'skipped') {\n currentStage = s;\n if (i < ENGINE_LIFECYCLE_STAGES.length - 1) {\n nextStage = ENGINE_LIFECYCLE_STAGES[i + 1];\n }\n break;\n }\n }\n\n if (!currentStage) {\n nextStage = 'research';\n }\n\n const blockedOn: string[] = [];\n if (nextStage) {\n const prereqs = STAGE_PREREQUISITES[nextStage] || [];\n for (const prereq of prereqs) {\n const prereqStatus = manifest.stages[prereq]?.status;\n if (prereqStatus !== 'completed' && prereqStatus !== 'skipped') {\n blockedOn.push(prereq);\n }\n }\n }\n\n return {\n epicId,\n title: manifest.title,\n currentStage,\n stages,\n nextStage,\n blockedOn,\n initialized: true,\n };\n}\n\n/** History entry for stage transitions. */\nexport interface LifecycleHistoryEntry {\n stage: string;\n action: string;\n timestamp: string;\n notes?: string;\n}\n\n/**\n * Get lifecycle history for an epic.\n * Returns stage transitions and gate events sorted by timestamp.\n * @task T4785\n */\nexport async function getLifecycleHistory(\n epicId: string,\n cwd?: string,\n): Promise<{ epicId: string; history: LifecycleHistoryEntry[] }> {\n const manifest = await readEngineManifest(epicId, cwd);\n\n if (!manifest) {\n return { epicId, history: [] };\n }\n\n const history: LifecycleHistoryEntry[] = [];\n\n for (const [stageName, stageData] of Object.entries(manifest.stages)) {\n if (stageData.status === 'completed' && stageData.completedAt) {\n history.push({\n stage: stageName,\n action: 'completed',\n timestamp: stageData.completedAt,\n notes: stageData.notes,\n });\n }\n if (stageData.status === 'skipped' && stageData.skippedAt) {\n history.push({\n stage: stageName,\n action: 'skipped',\n timestamp: stageData.skippedAt,\n notes: stageData.skippedReason,\n });\n }\n\n if (stageData.gates) {\n for (const [gateName, gateData] of Object.entries(stageData.gates)) {\n if (gateData.timestamp) {\n history.push({\n stage: stageName,\n action: `gate.${gateData.status}: ${gateName}`,\n timestamp: gateData.timestamp,\n notes: gateData.notes || gateData.reason,\n });\n }\n }\n }\n }\n\n history.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n return { epicId, history };\n}\n\n/**\n * Get all gate statuses for an epic.\n * @task T4785\n */\nexport async function getLifecycleGates(\n epicId: string,\n cwd?: string,\n): Promise<Record<string, Record<string, GateData>>> {\n const manifest = await readEngineManifest(epicId, cwd);\n\n if (!manifest) {\n return {};\n }\n\n const gates: Record<string, Record<string, GateData>> = {};\n for (const [stageName, stageData] of Object.entries(manifest.stages)) {\n if (stageData.gates && Object.keys(stageData.gates).length > 0) {\n gates[stageName] = stageData.gates;\n }\n }\n\n return gates;\n}\n\n/**\n * Get prerequisites for a target stage.\n * Pure data function, no I/O.\n * @task T4785\n */\nexport function getStagePrerequisites(targetStage: string): {\n prerequisites: string[];\n stageInfo: StageInfo | undefined;\n} {\n if (!ENGINE_LIFECYCLE_STAGES.includes(targetStage as EngineLifecycleStage)) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n `Invalid stage: ${targetStage}. Valid stages: ${ENGINE_LIFECYCLE_STAGES.join(', ')}`,\n );\n }\n\n return {\n prerequisites: STAGE_PREREQUISITES[targetStage] || [],\n stageInfo: STAGE_DEFINITIONS.find(s => s.stage === targetStage),\n };\n}\n\n/**\n * Check if a stage's prerequisites are met for an epic.\n * @task T4785\n */\nexport async function checkStagePrerequisites(\n epicId: string,\n targetStage: string,\n cwd?: string,\n): Promise<{\n epicId: string;\n targetStage: string;\n valid: boolean;\n canProgress: boolean;\n missingPrerequisites: string[];\n issues: Array<{ stage: string; severity: string; message: string }>;\n}> {\n if (!ENGINE_LIFECYCLE_STAGES.includes(targetStage as EngineLifecycleStage)) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n `Invalid stage: ${targetStage}. Valid stages: ${ENGINE_LIFECYCLE_STAGES.join(', ')}`,\n );\n }\n\n const manifest = await readEngineManifest(epicId, cwd);\n const prereqs = STAGE_PREREQUISITES[targetStage] || [];\n\n const missingPrerequisites: string[] = [];\n const issues: Array<{ stage: string; severity: string; message: string }> = [];\n\n for (const prereq of prereqs) {\n const prereqStatus = manifest?.stages[prereq]?.status;\n if (prereqStatus !== 'completed' && prereqStatus !== 'skipped') {\n missingPrerequisites.push(prereq);\n issues.push({\n stage: prereq,\n severity: 'error',\n message: `Stage '${prereq}' must be completed or skipped before '${targetStage}'`,\n });\n }\n }\n\n return {\n epicId,\n targetStage,\n valid: missingPrerequisites.length === 0,\n canProgress: missingPrerequisites.length === 0,\n missingPrerequisites,\n issues,\n };\n}\n\n/**\n * Record a stage status transition (progress/record).\n * @task T4785\n */\nexport async function recordStageProgress(\n epicId: string,\n stage: string,\n status: string,\n notes?: string,\n cwd?: string,\n): Promise<{ epicId: string; stage: string; status: string; timestamp: string }> {\n if (!ENGINE_LIFECYCLE_STAGES.includes(stage as EngineLifecycleStage)) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Invalid stage: ${stage}`);\n }\n\n const validStatuses: EngineStageStatus[] = ['pending', 'completed', 'skipped', 'blocked'];\n if (!validStatuses.includes(status as EngineStageStatus)) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n `Invalid status: ${status}. Valid: ${validStatuses.join(', ')}`,\n );\n }\n\n let manifest = await readEngineManifest(epicId, cwd);\n if (!manifest) {\n manifest = { epicId, stages: {} };\n }\n\n if (!manifest.stages[stage]) {\n manifest.stages[stage] = { status: 'pending' };\n }\n\n const now = new Date().toISOString();\n manifest.stages[stage].status = status as EngineStageStatus;\n\n if (status === 'completed') {\n manifest.stages[stage].completedAt = now;\n }\n\n if (notes) {\n manifest.stages[stage].notes = notes;\n }\n\n await saveEngineManifest(epicId, manifest, cwd);\n\n return { epicId, stage, status, timestamp: now };\n}\n\n/**\n * Skip a stage with a reason (engine-compatible).\n * @task T4785\n */\nexport async function skipStageWithReason(\n epicId: string,\n stage: string,\n reason: string,\n cwd?: string,\n): Promise<{ epicId: string; stage: string; reason: string; timestamp: string }> {\n let manifest = await readEngineManifest(epicId, cwd);\n if (!manifest) {\n manifest = { epicId, stages: {} };\n }\n\n if (!manifest.stages[stage]) {\n manifest.stages[stage] = { status: 'pending' };\n }\n\n const now = new Date().toISOString();\n manifest.stages[stage].status = 'skipped';\n manifest.stages[stage].skippedAt = now;\n manifest.stages[stage].skippedReason = reason;\n\n await saveEngineManifest(epicId, manifest, cwd);\n\n return { epicId, stage, reason, timestamp: now };\n}\n\n/**\n * Reset a stage to pending (emergency).\n * @task T4785\n */\nexport async function resetStage(\n epicId: string,\n stage: string,\n reason: string,\n cwd?: string,\n): Promise<{ epicId: string; stage: string; reason: string }> {\n const manifest = await readEngineManifest(epicId, cwd);\n\n if (!manifest) {\n throw new CleoError(ExitCode.NOT_FOUND, `No lifecycle data found for ${epicId}`);\n }\n\n if (!manifest.stages[stage]) {\n throw new CleoError(ExitCode.NOT_FOUND, `Stage '${stage}' not found for ${epicId}`);\n }\n\n manifest.stages[stage] = {\n status: 'pending',\n notes: `Reset: ${reason}`,\n };\n\n await saveEngineManifest(epicId, manifest, cwd);\n\n return { epicId, stage, reason };\n}\n\n/**\n * Mark a gate as passed.\n * @task T4785\n */\nexport async function passGate(\n epicId: string,\n gateName: string,\n agent?: string,\n notes?: string,\n cwd?: string,\n): Promise<{ epicId: string; gateName: string; timestamp: string }> {\n let manifest = await readEngineManifest(epicId, cwd);\n if (!manifest) {\n manifest = { epicId, stages: {} };\n }\n\n const stageParts = gateName.split('-');\n const stageName = stageParts[0];\n\n if (!manifest.stages[stageName]) {\n manifest.stages[stageName] = { status: 'pending' };\n }\n\n if (!manifest.stages[stageName].gates) {\n manifest.stages[stageName].gates = {};\n }\n\n const now = new Date().toISOString();\n manifest.stages[stageName].gates![gateName] = {\n status: 'passed',\n agent,\n notes,\n timestamp: now,\n };\n\n await saveEngineManifest(epicId, manifest, cwd);\n\n return { epicId, gateName, timestamp: now };\n}\n\n/**\n * Mark a gate as failed.\n * @task T4785\n */\nexport async function failGate(\n epicId: string,\n gateName: string,\n reason?: string,\n cwd?: string,\n): Promise<{ epicId: string; gateName: string; reason?: string; timestamp: string }> {\n let manifest = await readEngineManifest(epicId, cwd);\n if (!manifest) {\n manifest = { epicId, stages: {} };\n }\n\n const stageParts = gateName.split('-');\n const stageName = stageParts[0];\n\n if (!manifest.stages[stageName]) {\n manifest.stages[stageName] = { status: 'pending' };\n }\n\n if (!manifest.stages[stageName].gates) {\n manifest.stages[stageName].gates = {};\n }\n\n const now = new Date().toISOString();\n manifest.stages[stageName].gates![gateName] = {\n status: 'failed',\n reason,\n timestamp: now,\n };\n\n await saveEngineManifest(epicId, manifest, cwd);\n\n return { epicId, gateName, reason, timestamp: now };\n}\n\n/**\n * List all epic IDs that have RCSD data.\n * @task T4785\n */\nexport async function listEpicsWithLifecycle(cwd?: string): Promise<string[]> {\n const rcsdDir = join(getCleoDirAbsolute(cwd), 'rcsd');\n try {\n const { readdirSync, existsSync } = await import('node:fs');\n if (!existsSync(rcsdDir)) {\n return [];\n }\n return readdirSync(rcsdDir, { withFileTypes: true })\n .filter(d => d.isDirectory() && d.name.startsWith('T'))\n .map(d => d.name);\n } catch {\n return [];\n }\n}\n\n// =============================================================================\n// CROSS-SESSION RESUME FLOW EXPORTS\n// @task T4805 - SQLite-backed resume functionality\n// =============================================================================\n\nexport {\n // Core resume functions\n findResumablePipelines,\n loadPipelineContext,\n resumeStage,\n autoResume,\n checkSessionResume,\n checkBlockedStageDetails,\n formatResumeSummary,\n // Edge case handlers\n handleCompletedStage,\n handleBlockedStage,\n} from './resume.js';\n\nexport type {\n // Type definitions\n ResumablePipeline,\n PipelineContext,\n StageContext,\n GateResultContext,\n EvidenceContext,\n TransitionContext,\n TaskContext,\n ResumeResult,\n AutoResumeResult,\n FindResumableOptions,\n SessionResumeCheckOptions,\n SessionResumeCheckResult,\n} from './resume.js';\n", "/**\n * Core validation operations - business logic extracted from validate-engine.ts.\n *\n * These are pure business logic functions that throw on failure and return\n * data directly (no EngineResult wrapper). The engine layer wraps these\n * in try/catch to produce EngineResult.\n *\n * @task T4786\n * @epic T4654\n */\n\nimport { readFileSync, existsSync, appendFileSync, mkdirSync } from 'node:fs';\nimport { execFileSync } from 'node:child_process';\nimport { join, dirname, resolve } from 'node:path';\nimport { getManifestPath as getCentralManifestPath } from '../paths.js';\nimport { getAccessor } from '../../store/data-accessor.js';\nimport { validateSchema as ajvValidateSchema, type SchemaType } from '../../mcp/engine/schema-validator.js';\nimport {\n validateTitleDescription,\n validateTimestamps,\n validateIdUniqueness,\n validateNoDuplicateDescription,\n validateHierarchy,\n hasErrors,\n type RuleViolation,\n} from '../../mcp/engine/validation-rules.js';\nimport { detectCircularDeps, validateDependencies } from '../tasks/dependency-check.js';\nimport { computeChecksum } from '../../store/json.js';\nimport type { Task } from '../../types/task.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Compliance entry stored in COMPLIANCE.jsonl */\nexport interface ComplianceEntry {\n timestamp: string;\n taskId: string;\n protocol: string;\n result: 'pass' | 'fail' | 'partial';\n violations?: Array<{\n code: string;\n message: string;\n severity: 'error' | 'warning';\n }>;\n linkedTask?: string;\n agent?: string;\n}\n\n/** Task-like record used across validation operations. */\ninterface TaskRecord {\n id: string;\n title: string;\n description: string;\n status: string;\n priority: string;\n type?: string;\n phase?: string;\n createdAt: string;\n updatedAt: string | null;\n completedAt?: string | null;\n cancelledAt?: string | null;\n parentId?: string | null;\n depends?: string[];\n relates?: Array<{ taskId: string; type: string; reason?: string }>;\n files?: string[];\n acceptance?: string[];\n notes?: string[];\n labels?: string[];\n [key: string]: unknown;\n}\n\n/** Coherence issue found during graph validation. */\nexport interface CoherenceIssue {\n type: string;\n taskId: string;\n message: string;\n severity: 'error' | 'warning' | 'info';\n}\n\n// ============================================================================\n// Comprehensive Validate Report\n// ============================================================================\n\nexport interface ValidateCheckDetail {\n check: string;\n status: 'ok' | 'error' | 'warning';\n message: string;\n}\n\nexport interface ValidateReportResult {\n valid: boolean;\n schemaVersion: string;\n errors: number;\n warnings: number;\n details: ValidateCheckDetail[];\n}\n\n/**\n * Run comprehensive validation report on tasks.json \u2014 checks business rules,\n * dependencies, checksums, data integrity, and schema compliance.\n * @task T4795\n */\nexport async function coreValidateReport(\n projectRoot: string,\n): Promise<ValidateReportResult> {\n const accessor = await getAccessor(projectRoot);\n const data = await accessor.loadTaskFile();\n\n const details: ValidateCheckDetail[] = [];\n let errors = 0;\n let warnings = 0;\n\n const addOk = (check: string, message: string) => {\n details.push({ check, status: 'ok', message });\n };\n const addError = (check: string, message: string) => {\n details.push({ check, status: 'error', message });\n errors++;\n };\n const addWarn = (check: string, message: string) => {\n details.push({ check, status: 'warning', message });\n warnings++;\n };\n\n // 1. JSON syntax (already parsed above)\n addOk('json_syntax', 'JSON syntax valid');\n\n // 2. Check duplicate task IDs\n const idCounts = new Map<string, number>();\n for (const t of data.tasks) {\n idCounts.set(t.id, (idCounts.get(t.id) ?? 0) + 1);\n }\n const duplicateIds = [...idCounts.entries()].filter(([, c]) => c > 1).map(([id]) => id);\n if (duplicateIds.length > 0) {\n addError('duplicate_ids_todo', `Duplicate task IDs in tasks.json: ${duplicateIds.join(', ')}`);\n } else {\n addOk('duplicate_ids_todo', 'No duplicate task IDs in tasks.json');\n }\n\n // 2b. Cross-file duplicates with archive\n const archive = await accessor.loadArchive();\n if (archive && archive.archivedTasks.length > 0) {\n const archiveIds = new Set(archive.archivedTasks.map((t) => t.id));\n const todoIds = new Set(data.tasks.map((t) => t.id));\n const crossDups = [...todoIds].filter((id) => archiveIds.has(id));\n if (crossDups.length > 0) {\n addError('duplicate_ids_cross', `IDs exist in both tasks.json and archive: ${crossDups.join(', ')}`);\n } else {\n addOk('duplicate_ids_cross', 'No cross-file duplicate IDs');\n }\n }\n\n // 3. Active task limit\n const activeTasks = data.tasks.filter((t) => t.status === 'active');\n if (activeTasks.length > 1) {\n addError('active_task', `Too many active tasks: ${activeTasks.length}. Maximum allowed: 1`);\n } else if (activeTasks.length === 1) {\n addOk('active_task', 'Single active task');\n } else {\n addOk('active_task', 'No active tasks');\n }\n\n // 4. Dependencies exist\n const taskIds = new Set(data.tasks.map((t) => t.id));\n const missingDeps: string[] = [];\n for (const t of data.tasks) {\n if (t.depends) {\n for (const depId of t.depends) {\n if (!taskIds.has(depId)) missingDeps.push(depId);\n }\n }\n }\n if (missingDeps.length > 0) {\n addError('dependencies', `Missing dependency references: ${[...new Set(missingDeps)].join(', ')}`);\n } else {\n addOk('dependencies', 'All dependencies exist');\n }\n\n // 5. Circular dependencies\n const depResult = validateDependencies(data.tasks);\n const circularErrors = depResult.errors.filter((e) => e.code === 'E_CIRCULAR_DEP');\n if (circularErrors.length > 0) {\n for (const err of circularErrors) {\n addError('circular_deps', err.message);\n }\n } else {\n addOk('circular_deps', 'No circular dependencies');\n }\n\n // 6. Blocked tasks have blockedBy\n const blockedNoReason = data.tasks.filter((t) => t.status === 'blocked' && !t.blockedBy);\n if (blockedNoReason.length > 0) {\n addError('blocked_reasons', `${blockedNoReason.length} blocked task(s) missing blockedBy reason`);\n } else {\n addOk('blocked_reasons', 'All blocked tasks have reasons');\n }\n\n // 7. Done tasks have completedAt\n const doneNoDate = data.tasks.filter((t) => t.status === 'done' && !t.completedAt);\n if (doneNoDate.length > 0) {\n addError('completed_at', `${doneNoDate.length} done task(s) missing completedAt`);\n } else {\n addOk('completed_at', 'All done tasks have completedAt');\n }\n\n // 8. Schema version\n const schemaVersion = data._meta?.schemaVersion;\n if (!schemaVersion) {\n addError('schema_version', 'Missing ._meta.schemaVersion field. Run: cleo upgrade');\n } else {\n addOk('schema_version', `Schema version compatible (${schemaVersion})`);\n }\n\n // 9. Required fields\n const missingFieldTasks = data.tasks.filter((t) =>\n !t.id || !t.title || !t.status || !t.priority || !t.createdAt,\n );\n if (missingFieldTasks.length > 0) {\n for (const t of missingFieldTasks) {\n const missing = [];\n if (!t.id) missing.push('id');\n if (!t.title) missing.push('title');\n if (!t.status) missing.push('status');\n if (!t.priority) missing.push('priority');\n if (!t.createdAt) missing.push('createdAt');\n addError('required_fields', `Task ${t.id ?? '(unknown)'} missing: ${missing.join(', ')}`);\n }\n } else {\n addOk('required_fields', 'All tasks have required fields');\n }\n\n // 10. Focus matches active task\n const focusTask = data.focus?.currentTask;\n const activeTaskId = activeTasks[0]?.id ?? null;\n if (focusTask && focusTask !== activeTaskId) {\n addError('focus_match', `focus.currentTask (${focusTask}) doesn't match active task (${activeTaskId ?? 'none'})`);\n } else {\n addOk('focus_match', 'Focus matches active task');\n }\n\n // 11. Checksum\n const storedChecksum = data._meta?.checksum;\n if (storedChecksum) {\n const computed = computeChecksum(data.tasks);\n if (storedChecksum !== computed) {\n addError('checksum', `Checksum mismatch: stored=${storedChecksum}, computed=${computed}`);\n } else {\n addOk('checksum', 'Checksum valid');\n }\n } else {\n addWarn('checksum', 'No checksum found');\n }\n\n // 12. Missing size fields\n const missingSizeTasks = data.tasks.filter((t) => !t.size);\n if (missingSizeTasks.length > 0) {\n addWarn('missing_sizes', `${missingSizeTasks.length} task(s) missing size field`);\n } else {\n addOk('missing_sizes', 'All tasks have size field');\n }\n\n // 13. Stale tasks (pending > 30 days)\n const staleDays = 30;\n const staleThreshold = Date.now() - staleDays * 86400 * 1000;\n const staleTasks = data.tasks.filter(\n (t) => t.status === 'pending' && t.createdAt && new Date(t.createdAt).getTime() < staleThreshold,\n );\n if (staleTasks.length > 0) {\n addWarn('stale_tasks', `${staleTasks.length} task(s) pending for >${staleDays} days`);\n }\n\n return {\n valid: errors === 0,\n schemaVersion: schemaVersion ?? 'unknown',\n errors,\n warnings,\n details,\n };\n}\n\n// ============================================================================\n// Schema Validation\n// ============================================================================\n\n/** Read a JSON file, returning parsed data or null. */\nfunction readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n const raw = readFileSync(filePath, 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Validate data against a JSON schema type.\n * @task T4786\n */\nexport function coreValidateSchema(\n type: string,\n data: unknown | undefined,\n projectRoot: string,\n): { type: string; valid: boolean; errors: unknown[]; errorCount: number } {\n if (!type) {\n throw new Error('type is required (todo, config, archive, log)');\n }\n\n let dataToValidate = data;\n if (!dataToValidate) {\n const fileMap: Record<string, string> = {\n todo: '.cleo/todo.json',\n config: '.cleo/config.json',\n archive: '.cleo/todo-archive.json',\n log: '.cleo/todo-log.jsonl',\n };\n\n const filePath = fileMap[type];\n if (!filePath) {\n throw new Error(`Unknown schema type: ${type}. Valid types: ${Object.keys(fileMap).join(', ')}`);\n }\n\n const fullPath = join(projectRoot, filePath);\n if (!existsSync(fullPath)) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n dataToValidate = readJsonFile(fullPath);\n }\n\n const result = ajvValidateSchema(type as SchemaType, dataToValidate);\n return {\n type,\n valid: result.valid,\n errors: result.errors,\n errorCount: result.errors.length,\n };\n}\n\n// ============================================================================\n// Task Validation (Anti-Hallucination)\n// ============================================================================\n\n/**\n * Validate a single task against anti-hallucination rules.\n * @task T4786\n */\nexport async function coreValidateTask(\n taskId: string,\n projectRoot: string,\n): Promise<{\n taskId: string;\n valid: boolean;\n violations: RuleViolation[];\n errorCount: number;\n warningCount: number;\n}> {\n if (!taskId) {\n throw new Error('taskId is required');\n }\n\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTaskFile() as unknown as { tasks: TaskRecord[] };\n const archiveData = await accessor.loadArchive() as unknown as { tasks: TaskRecord[] } | null;\n\n if (!todoData) {\n throw new Error('todo.json not found');\n }\n\n const allTasks = [\n ...(todoData.tasks || []),\n ...(archiveData?.tasks || []),\n ];\n\n const task = allTasks.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task ${taskId} not found`);\n }\n\n const violations: RuleViolation[] = [];\n\n violations.push(...validateTitleDescription(task.title, task.description));\n violations.push(...validateTimestamps(task as any));\n\n const allIds = new Set(allTasks.map((t) => t.id));\n violations.push(...validateIdUniqueness(task.id, allIds));\n\n const allDescriptions = allTasks\n .filter((t) => t.id !== task.id)\n .map((t) => t.description);\n violations.push(...validateNoDuplicateDescription(task.description, allDescriptions));\n\n if (task.parentId) {\n const parent = allTasks.find((t) => t.id === task.parentId);\n if (parent) {\n violations.push(...validateHierarchy(task.parentId, allTasks as any));\n }\n }\n\n return {\n taskId,\n valid: !hasErrors(violations),\n violations,\n errorCount: violations.filter((v) => v.severity === 'error').length,\n warningCount: violations.filter((v) => v.severity === 'warning').length,\n };\n}\n\n// ============================================================================\n// Protocol Validation\n// ============================================================================\n\n/**\n * Check basic protocol compliance for a task.\n * @task T4786\n */\nexport async function coreValidateProtocol(\n taskId: string,\n protocolType: string | undefined,\n projectRoot: string,\n): Promise<{\n taskId: string;\n protocolType: string;\n compliant: boolean;\n violations: Array<{ code: string; message: string; severity: string }>;\n}> {\n if (!taskId) {\n throw new Error('taskId is required');\n }\n\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTaskFile() as unknown as { tasks: TaskRecord[] };\n\n if (!todoData) {\n throw new Error('todo.json not found');\n }\n\n const task = todoData.tasks?.find((t) => t.id === taskId);\n if (!task) {\n throw new Error(`Task ${taskId} not found`);\n }\n\n const violations: Array<{ code: string; message: string; severity: string }> = [];\n\n if (!task.title) {\n violations.push({ code: 'P_MISSING_TITLE', message: 'Task title is missing', severity: 'error' });\n }\n if (!task.description) {\n violations.push({ code: 'P_MISSING_DESCRIPTION', message: 'Task description is missing', severity: 'error' });\n }\n if (task.title === task.description) {\n violations.push({ code: 'P_SAME_TITLE_DESC', message: 'Title and description must be different', severity: 'error' });\n }\n\n const validStatuses = ['pending', 'active', 'blocked', 'done', 'cancelled'];\n if (!validStatuses.includes(task.status)) {\n violations.push({\n code: 'P_INVALID_STATUS',\n message: `Invalid status: ${task.status}. Valid: ${validStatuses.join(', ')}`,\n severity: 'error',\n });\n }\n\n return {\n taskId,\n protocolType: protocolType || 'generic',\n compliant: violations.filter((v) => v.severity === 'error').length === 0,\n violations,\n };\n}\n\n// ============================================================================\n// Manifest Validation\n// ============================================================================\n\n/**\n * Validate manifest JSONL entries for required fields.\n * @task T4786\n */\nexport function coreValidateManifest(\n projectRoot: string,\n): {\n valid: boolean;\n totalEntries: number;\n validEntries: number;\n invalidEntries: number;\n errors: Array<{ line: number; entryId: string; errors: string[] }>;\n message?: string;\n} {\n const manifestPath = getCentralManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return {\n valid: true,\n totalEntries: 0,\n validEntries: 0,\n invalidEntries: 0,\n errors: [],\n message: 'No manifest file found',\n };\n }\n\n const content = readFileSync(manifestPath, 'utf-8');\n const lines = content.split('\\n').filter((l) => l.trim());\n\n let validCount = 0;\n let invalidCount = 0;\n const errors: Array<{ line: number; entryId: string; errors: string[] }> = [];\n\n for (let i = 0; i < lines.length; i++) {\n try {\n const entry = JSON.parse(lines[i]!);\n const entryErrors: string[] = [];\n\n if (!entry.id) entryErrors.push('missing id');\n if (!entry.file) entryErrors.push('missing file');\n if (!entry.title) entryErrors.push('missing title');\n if (!entry.date) entryErrors.push('missing date');\n if (!entry.status) entryErrors.push('missing status');\n if (!entry.agent_type) entryErrors.push('missing agent_type');\n if (!entry.topics) entryErrors.push('missing topics');\n if (entry.actionable === undefined) entryErrors.push('missing actionable');\n\n if (entryErrors.length > 0) {\n invalidCount++;\n errors.push({ line: i + 1, entryId: entry.id || `line-${i + 1}`, errors: entryErrors });\n } else {\n validCount++;\n }\n } catch {\n invalidCount++;\n errors.push({ line: i + 1, entryId: `line-${i + 1}`, errors: ['invalid JSON'] });\n }\n }\n\n return {\n valid: invalidCount === 0,\n totalEntries: lines.length,\n validEntries: validCount,\n invalidEntries: invalidCount,\n errors,\n };\n}\n\n// ============================================================================\n// Output Validation\n// ============================================================================\n\n/**\n * Validate an output file for required sections.\n * @task T4786\n */\nexport function coreValidateOutput(\n filePath: string,\n taskId: string | undefined,\n projectRoot: string,\n): {\n filePath: string;\n valid: boolean;\n issues: Array<{ code: string; message: string; severity: string }>;\n fileSize: number;\n lineCount: number;\n} {\n if (!filePath) {\n throw new Error('filePath is required');\n }\n\n const fullPath = resolve(projectRoot, filePath);\n\n if (!existsSync(fullPath)) {\n throw new Error(`Output file not found: ${filePath}`);\n }\n\n const content = readFileSync(fullPath, 'utf-8');\n const issues: Array<{ code: string; message: string; severity: string }> = [];\n\n if (!content.includes('# ')) {\n issues.push({ code: 'O_MISSING_TITLE', message: 'Output file should have a markdown title', severity: 'warning' });\n }\n\n if (taskId && !content.includes(taskId)) {\n issues.push({ code: 'O_MISSING_TASK_REF', message: `Output file should reference task ${taskId}`, severity: 'warning' });\n }\n\n if (!content.includes('## Summary') && !content.includes('## summary')) {\n issues.push({ code: 'O_MISSING_SUMMARY', message: 'Output file should have a Summary section', severity: 'warning' });\n }\n\n return {\n filePath,\n valid: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n fileSize: content.length,\n lineCount: content.split('\\n').length,\n };\n}\n\n// ============================================================================\n// Compliance Summary\n// ============================================================================\n\n/** Parse COMPLIANCE.jsonl entries. */\nfunction parseComplianceEntries(projectRoot: string): ComplianceEntry[] {\n const compliancePath = join(projectRoot, '.cleo', 'metrics', 'COMPLIANCE.jsonl');\n\n if (!existsSync(compliancePath)) {\n return [];\n }\n\n const content = readFileSync(compliancePath, 'utf-8');\n const entries: ComplianceEntry[] = [];\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n entries.push(JSON.parse(trimmed));\n } catch {\n continue;\n }\n }\n\n return entries;\n}\n\n/**\n * Get aggregated compliance metrics.\n * @task T4786\n */\nexport function coreComplianceSummary(\n projectRoot: string,\n): {\n total: number;\n pass: number;\n fail: number;\n partial: number;\n passRate: number;\n byProtocol: Record<string, { pass: number; fail: number; partial: number }>;\n} {\n const entries = parseComplianceEntries(projectRoot);\n\n const pass = entries.filter((e) => e.result === 'pass').length;\n const fail = entries.filter((e) => e.result === 'fail').length;\n const partial = entries.filter((e) => e.result === 'partial').length;\n const total = entries.length;\n\n const byProtocol: Record<string, { pass: number; fail: number; partial: number }> = {};\n for (const entry of entries) {\n if (!byProtocol[entry.protocol]) {\n byProtocol[entry.protocol] = { pass: 0, fail: 0, partial: 0 };\n }\n byProtocol[entry.protocol]![entry.result]++;\n }\n\n return {\n total,\n pass,\n fail,\n partial,\n passRate: total > 0 ? Math.round((pass / total) * 100) : 0,\n byProtocol,\n };\n}\n\n// ============================================================================\n// Compliance Violations\n// ============================================================================\n\n/**\n * List compliance violations.\n * @task T4786\n */\nexport function coreComplianceViolations(\n limit: number | undefined,\n projectRoot: string,\n): {\n violations: Array<{\n timestamp: string;\n taskId: string;\n protocol: string;\n result: string;\n violations?: ComplianceEntry['violations'];\n }>;\n total: number;\n} {\n const entries = parseComplianceEntries(projectRoot);\n let violations = entries.filter((e) => e.result === 'fail' || e.result === 'partial');\n\n if (limit && limit > 0) {\n violations = violations.slice(-limit);\n }\n\n return {\n violations: violations.map((v) => ({\n timestamp: v.timestamp,\n taskId: v.taskId,\n protocol: v.protocol,\n result: v.result,\n violations: v.violations,\n })),\n total: violations.length,\n };\n}\n\n// ============================================================================\n// Compliance Record\n// ============================================================================\n\n/**\n * Record a compliance check result to COMPLIANCE.jsonl.\n * @task T4786\n */\nexport function coreComplianceRecord(\n taskId: string,\n result: string,\n protocol: string | undefined,\n violations: Array<{ code: string; message: string; severity: string }> | undefined,\n projectRoot: string,\n): { recorded: boolean; taskId: string; result: string; protocol: string } {\n if (!taskId || !result) {\n throw new Error('taskId and result are required');\n }\n\n const validResults = ['pass', 'fail', 'partial'];\n if (!validResults.includes(result)) {\n throw new Error(`Invalid result: ${result}. Valid: ${validResults.join(', ')}`);\n }\n\n const compliancePath = join(projectRoot, '.cleo', 'metrics', 'COMPLIANCE.jsonl');\n const dir = dirname(compliancePath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const entry: ComplianceEntry = {\n timestamp: new Date().toISOString(),\n taskId,\n protocol: protocol || 'generic',\n result: result as 'pass' | 'fail' | 'partial',\n violations: violations as any,\n linkedTask: taskId,\n };\n\n appendFileSync(compliancePath, JSON.stringify(entry) + '\\n', 'utf-8');\n\n return {\n recorded: true,\n taskId,\n result,\n protocol: protocol || 'generic',\n };\n}\n\n// ============================================================================\n// Test Status\n// ============================================================================\n\n/**\n * Check test suite availability.\n * @task T4786\n */\nexport function coreTestStatus(\n projectRoot: string,\n): {\n batsTests: { available: boolean; directory: string | null };\n mcpTests: { available: boolean; directory: string | null };\n message: string;\n} {\n const testDir = join(projectRoot, 'tests');\n const mcpTestDir = join(projectRoot, 'src', 'mcp', '__tests__');\n\n const hasBatsTests = existsSync(testDir);\n const hasMcpTests = existsSync(mcpTestDir);\n\n return {\n batsTests: {\n available: hasBatsTests,\n directory: hasBatsTests ? 'tests/' : null,\n },\n mcpTests: {\n available: hasMcpTests,\n directory: hasMcpTests ? 'src/mcp/__tests__/' : null,\n },\n message: 'Use validate.test.run to execute tests',\n };\n}\n\n// ============================================================================\n// Coherence Check\n// ============================================================================\n\n/**\n * Cross-validate task graph for consistency.\n * @task T4786\n */\nexport async function coreCoherenceCheck(\n projectRoot: string,\n): Promise<{ coherent: boolean; issues: CoherenceIssue[] }> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTaskFile() as unknown as { tasks: TaskRecord[] };\n\n if (!todoData || !todoData.tasks) {\n throw new Error('No todo.json found');\n }\n\n const tasks = todoData.tasks;\n const taskMap = new Map(tasks.map((t) => [t.id, t]));\n const issues: CoherenceIssue[] = [];\n\n // 1. Done tasks with incomplete subtasks\n for (const task of tasks) {\n if (task.status === 'done') {\n const incompleteChildren = tasks.filter(\n (t) => t.parentId === task.id && t.status !== 'done' && t.status !== 'cancelled',\n );\n for (const child of incompleteChildren) {\n issues.push({\n type: 'done_with_incomplete_subtask',\n taskId: task.id,\n message: `Task ${task.id} is done but child ${child.id} (\"${child.title}\") has status \"${child.status}\"`,\n severity: 'error',\n });\n }\n }\n }\n\n // 2. Dependency cycles\n const reportedCycles = new Set<string>();\n for (const task of tasks) {\n if (task.depends && task.depends.length > 0) {\n const cycle = detectCircularDeps(task.id, tasks as unknown as Task[]);\n if (cycle.length > 0) {\n const cycleKey = [...cycle].sort().join(',');\n if (!reportedCycles.has(cycleKey)) {\n reportedCycles.add(cycleKey);\n issues.push({\n type: 'dependency_cycle',\n taskId: task.id,\n message: `Dependency cycle detected: ${cycle.join(' -> ')}`,\n severity: 'error',\n });\n }\n }\n }\n }\n\n // 3. Orphaned references\n for (const task of tasks) {\n if (task.depends) {\n for (const depId of task.depends) {\n if (!taskMap.has(depId)) {\n issues.push({\n type: 'orphaned_dependency',\n taskId: task.id,\n message: `Task ${task.id} depends on non-existent task ${depId}`,\n severity: 'error',\n });\n }\n }\n }\n }\n\n // 4. Stale tasks\n const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;\n const now = Date.now();\n for (const task of tasks) {\n if (task.status === 'active') {\n const lastUpdate = task.updatedAt || task.createdAt;\n if (lastUpdate) {\n const ageMs = now - new Date(lastUpdate).getTime();\n if (ageMs > thirtyDaysMs) {\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));\n issues.push({\n type: 'stale_task',\n taskId: task.id,\n message: `Task ${task.id} has been active for ${ageDays} days without update`,\n severity: 'warning',\n });\n }\n }\n }\n }\n\n // 5. Status inconsistencies\n for (const task of tasks) {\n if (task.parentId && (task.status === 'active' || task.status === 'pending')) {\n const parent = taskMap.get(task.parentId);\n if (parent && (parent.status === 'done' || parent.status === 'cancelled')) {\n issues.push({\n type: 'status_inconsistency',\n taskId: task.id,\n message: `Task ${task.id} is \"${task.status}\" but parent ${parent.id} is \"${parent.status}\"`,\n severity: 'error',\n });\n }\n }\n }\n\n // 6. Duplicate titles\n const titleMap = new Map<string, string[]>();\n for (const task of tasks) {\n const titleLower = task.title.toLowerCase().trim();\n if (!titleMap.has(titleLower)) {\n titleMap.set(titleLower, []);\n }\n titleMap.get(titleLower)!.push(task.id);\n }\n for (const [title, ids] of titleMap) {\n if (ids.length > 1) {\n issues.push({\n type: 'duplicate_title',\n taskId: ids[0]!,\n message: `Duplicate title \"${title}\" found on tasks: ${ids.join(', ')}`,\n severity: 'info',\n });\n }\n }\n\n return {\n coherent: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n };\n}\n\n// ============================================================================\n// Test Run\n// ============================================================================\n\n/**\n * Execute test suite via subprocess.\n * @task T4786\n */\nexport function coreTestRun(\n params: { scope?: string; pattern?: string; parallel?: boolean } | undefined,\n projectRoot: string,\n): {\n ran: boolean;\n runner?: string;\n output?: unknown;\n exitCode?: number;\n stdout?: string;\n stderr?: string;\n passed?: boolean;\n message?: string;\n} {\n const hasVitest = existsSync(join(projectRoot, 'node_modules', '.bin', 'vitest'));\n const hasBats = existsSync(join(projectRoot, 'tests'));\n\n if (!hasVitest && !hasBats) {\n return {\n ran: false,\n message: 'No test runner found (vitest or bats tests/ directory)',\n };\n }\n\n try {\n const args: string[] = ['vitest', 'run', '--reporter=json'];\n\n if (params?.scope) {\n args.push(params.scope);\n }\n\n if (params?.pattern) {\n args.push('--testNamePattern', params.pattern);\n }\n\n const result = execFileSync('npx', args, {\n cwd: projectRoot,\n timeout: 120000,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result);\n } catch {\n parsed = null;\n }\n\n return {\n ran: true,\n runner: 'vitest',\n output: parsed || result.slice(0, 2000),\n exitCode: 0,\n };\n } catch (error: unknown) {\n const execError = error as { status?: number; stdout?: string; stderr?: string };\n return {\n ran: true,\n runner: 'vitest',\n exitCode: execError.status || 1,\n stdout: (execError.stdout || '').slice(0, 2000),\n stderr: (execError.stderr || '').slice(0, 2000),\n passed: false,\n };\n }\n}\n\n// ============================================================================\n// Batch Validate\n// ============================================================================\n\n/**\n * Batch validate all tasks against schema and rules.\n * @task T4786\n */\nexport async function coreBatchValidate(\n projectRoot: string,\n): Promise<{\n totalTasks: number;\n validTasks: number;\n invalidTasks: number;\n totalErrors: number;\n totalWarnings: number;\n results: Array<{\n taskId: string;\n valid: boolean;\n errorCount: number;\n warningCount: number;\n violations: RuleViolation[];\n }>;\n}> {\n const accessor = await getAccessor(projectRoot);\n const todoData = await accessor.loadTaskFile() as unknown as { tasks: TaskRecord[] };\n\n if (!todoData) {\n throw new Error('todo.json not found');\n }\n\n const archiveData = await accessor.loadArchive() as unknown as { tasks: TaskRecord[] } | null;\n const allTasks = [\n ...(todoData.tasks || []),\n ...(archiveData?.tasks || []),\n ];\n\n const results: Array<{\n taskId: string;\n valid: boolean;\n errorCount: number;\n warningCount: number;\n violations: RuleViolation[];\n }> = [];\n\n let totalErrors = 0;\n let totalWarnings = 0;\n const allIds = new Set(allTasks.map((t) => t.id));\n const allDescriptions = allTasks.map((t) => t.description);\n\n for (const task of allTasks) {\n const violations: RuleViolation[] = [];\n\n violations.push(...validateTitleDescription(task.title, task.description));\n violations.push(...validateTimestamps(task as any));\n violations.push(...validateIdUniqueness(task.id, allIds));\n\n const otherDescs = allDescriptions.filter((_, i) => allTasks[i]!.id !== task.id);\n violations.push(...validateNoDuplicateDescription(task.description, otherDescs));\n\n if (task.parentId) {\n const parent = allTasks.find((t) => t.id === task.parentId);\n if (parent) {\n violations.push(...validateHierarchy(task.parentId, allTasks as any));\n }\n }\n\n const errors = violations.filter((v) => v.severity === 'error').length;\n const warnings = violations.filter((v) => v.severity === 'warning').length;\n totalErrors += errors;\n totalWarnings += warnings;\n\n results.push({\n taskId: task.id,\n valid: errors === 0,\n errorCount: errors,\n warningCount: warnings,\n violations,\n });\n }\n\n return {\n totalTasks: allTasks.length,\n validTasks: results.filter((r) => r.valid).length,\n invalidTasks: results.filter((r) => !r.valid).length,\n totalErrors,\n totalWarnings,\n results: results.filter((r) => !r.valid),\n };\n}\n\n// ============================================================================\n// Test Coverage\n// ============================================================================\n\n/**\n * Get test coverage metrics.\n * @task T4786\n */\nexport function coreTestCoverage(\n projectRoot: string,\n): { available: boolean; message?: string; [key: string]: unknown } {\n const coveragePath = join(projectRoot, 'coverage', 'coverage-summary.json');\n\n if (!existsSync(coveragePath)) {\n return {\n available: false,\n message: 'No coverage data found. Run tests with coverage first.',\n };\n }\n\n const coverageData = readJsonFile<Record<string, unknown>>(coveragePath);\n if (!coverageData) {\n throw new Error('Failed to read coverage data');\n }\n\n return {\n available: true,\n ...coverageData,\n };\n}\n", "/**\n * Dependency checking - validate task dependency graphs.\n * Ported from lib/tasks/dependency-check.sh\n *\n * @epic T4454\n * @task T4529\n */\n\nimport type { Task } from '../../types/task.js';\n\n/** Result of a dependency validation check. */\nexport interface DependencyCheckResult {\n valid: boolean;\n errors: DependencyError[];\n warnings: DependencyWarning[];\n}\n\n/** A dependency error. */\nexport interface DependencyError {\n code: string;\n taskId: string;\n message: string;\n relatedIds?: string[];\n}\n\n/** A dependency warning. */\nexport interface DependencyWarning {\n code: string;\n taskId: string;\n message: string;\n}\n\n/**\n * Detect circular dependencies using DFS.\n * Returns the cycle path if found, empty array otherwise.\n */\nexport function detectCircularDeps(\n taskId: string,\n tasks: Task[],\n): string[] {\n const taskMap = new Map(tasks.map((t) => [t.id, t]));\n\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const path: string[] = [];\n\n function dfs(id: string): string[] {\n visited.add(id);\n recursionStack.add(id);\n path.push(id);\n\n const task = taskMap.get(id);\n if (task?.depends) {\n for (const depId of task.depends) {\n if (!visited.has(depId)) {\n const cycle = dfs(depId);\n if (cycle.length > 0) return cycle;\n } else if (recursionStack.has(depId)) {\n // Found cycle - return path from depId to current + depId\n const cycleStart = path.indexOf(depId);\n return [...path.slice(cycleStart), depId];\n }\n }\n }\n\n path.pop();\n recursionStack.delete(id);\n return [];\n }\n\n return dfs(taskId);\n}\n\n/**\n * Check if adding a dependency would create a cycle.\n */\nexport function wouldCreateCycle(\n fromId: string,\n toId: string,\n tasks: Task[],\n): boolean {\n // Temporarily add the dependency and check\n const modified = tasks.map((t) => {\n if (t.id === fromId) {\n return { ...t, depends: [...(t.depends ?? []), toId] };\n }\n return t;\n });\n return detectCircularDeps(fromId, modified).length > 0;\n}\n\n/**\n * Get tasks that are blocked (have unmet dependencies).\n */\nexport function getBlockedTasks(tasks: Task[]): Task[] {\n const completedIds = new Set(\n tasks.filter((t) => t.status === 'done' || t.status === 'cancelled').map((t) => t.id),\n );\n\n return tasks.filter((t) => {\n if (!t.depends?.length) return false;\n if (t.status === 'done' || t.status === 'cancelled') return false;\n return t.depends.some((depId) => !completedIds.has(depId));\n });\n}\n\n/**\n * Get tasks that are ready (all dependencies met).\n */\nexport function getReadyTasks(tasks: Task[]): Task[] {\n const completedIds = new Set(\n tasks.filter((t) => t.status === 'done' || t.status === 'cancelled').map((t) => t.id),\n );\n\n return tasks.filter((t) => {\n if (t.status === 'done' || t.status === 'cancelled') return false;\n if (!t.depends?.length) return true;\n return t.depends.every((depId) => completedIds.has(depId));\n });\n}\n\n/**\n * Get tasks that depend on a given task.\n */\nexport function getDependents(taskId: string, tasks: Task[]): Task[] {\n return tasks.filter((t) => t.depends?.includes(taskId));\n}\n\n/**\n * Get dependent IDs.\n */\nexport function getDependentIds(taskId: string, tasks: Task[]): string[] {\n return getDependents(taskId, tasks).map((t) => t.id);\n}\n\n/**\n * Get unresolved dependencies for a task (deps that are not done/cancelled).\n */\nexport function getUnresolvedDeps(taskId: string, tasks: Task[]): string[] {\n const task = tasks.find((t) => t.id === taskId);\n if (!task?.depends?.length) return [];\n\n const completedIds = new Set(\n tasks.filter((t) => t.status === 'done' || t.status === 'cancelled').map((t) => t.id),\n );\n\n return task.depends.filter((depId) => !completedIds.has(depId));\n}\n\n/**\n * Validate dependencies for missing references.\n */\nexport function validateDependencyRefs(tasks: Task[]): DependencyError[] {\n const taskIds = new Set(tasks.map((t) => t.id));\n const errors: DependencyError[] = [];\n\n for (const task of tasks) {\n if (!task.depends?.length) continue;\n for (const depId of task.depends) {\n if (!taskIds.has(depId)) {\n errors.push({\n code: 'E_DEP_NOT_FOUND',\n taskId: task.id,\n message: `Task ${task.id} depends on ${depId}, which does not exist`,\n relatedIds: [depId],\n });\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Full dependency graph validation.\n */\nexport function validateDependencies(tasks: Task[]): DependencyCheckResult {\n const errors: DependencyError[] = [];\n const warnings: DependencyWarning[] = [];\n\n // Check for missing references\n errors.push(...validateDependencyRefs(tasks));\n\n // Check for circular dependencies\n const visited = new Set<string>();\n for (const task of tasks) {\n if (visited.has(task.id)) continue;\n if (!task.depends?.length) continue;\n\n const cycle = detectCircularDeps(task.id, tasks);\n if (cycle.length > 0) {\n errors.push({\n code: 'E_CIRCULAR_DEP',\n taskId: task.id,\n message: `Circular dependency detected: ${cycle.join(' -> ')}`,\n relatedIds: cycle,\n });\n // Mark all in cycle as visited to avoid duplicate reports\n cycle.forEach((id) => visited.add(id));\n }\n }\n\n // Check for self-dependencies\n for (const task of tasks) {\n if (task.depends?.includes(task.id)) {\n errors.push({\n code: 'E_SELF_DEP',\n taskId: task.id,\n message: `Task ${task.id} depends on itself`,\n });\n }\n }\n\n // Warn about completed tasks with unmet dependencies\n for (const task of tasks) {\n if (task.status === 'done' && task.depends?.length) {\n const unresolved = getUnresolvedDeps(task.id, tasks);\n if (unresolved.length > 0) {\n warnings.push({\n code: 'W_COMPLETED_WITH_UNMET_DEPS',\n taskId: task.id,\n message: `Completed task ${task.id} has unmet dependencies: ${unresolved.join(', ')}`,\n });\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Topological sort of tasks by dependencies.\n * Returns sorted task IDs or null if cycle detected.\n */\nexport function topologicalSort(tasks: Task[]): string[] | null {\n const inDegree = new Map<string, number>();\n const adjList = new Map<string, string[]>();\n\n // Initialize\n for (const task of tasks) {\n inDegree.set(task.id, 0);\n adjList.set(task.id, []);\n }\n\n // Build adjacency list (dependency -> dependent)\n for (const task of tasks) {\n if (!task.depends?.length) continue;\n for (const depId of task.depends) {\n if (adjList.has(depId)) {\n adjList.get(depId)!.push(task.id);\n inDegree.set(task.id, (inDegree.get(task.id) ?? 0) + 1);\n }\n }\n }\n\n // Kahn's algorithm\n const queue: string[] = [];\n for (const [id, degree] of inDegree) {\n if (degree === 0) queue.push(id);\n }\n\n const sorted: string[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n sorted.push(id);\n\n for (const dependent of adjList.get(id) ?? []) {\n const newDegree = (inDegree.get(dependent) ?? 1) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) queue.push(dependent);\n }\n }\n\n // If not all tasks sorted, there's a cycle\n if (sorted.length !== tasks.length) return null;\n return sorted;\n}\n", "/**\n * Validate Engine\n *\n * Thin wrapper layer around core validation operations.\n * Delegates all business logic to src/core/validation/validate-ops.ts.\n *\n * @task T4477\n * @task T4659\n * @task T4786\n * @epic T4654\n */\n\nimport { resolveProjectRoot } from './store.js';\nimport {\n coreValidateSchema,\n coreValidateTask,\n coreValidateProtocol,\n coreValidateManifest,\n coreValidateOutput,\n coreComplianceSummary,\n coreComplianceViolations,\n coreComplianceRecord,\n coreTestStatus,\n coreCoherenceCheck,\n coreTestRun,\n coreBatchValidate,\n coreTestCoverage,\n type CoherenceIssue,\n} from '../../core/validation/validate-ops.js';\n\n/**\n * Engine result type\n */\ninterface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: { code: string; message: string; details?: unknown };\n}\n\n/**\n * validate.schema - JSON Schema validation\n * @task T4477\n */\nexport function validateSchemaOp(\n type: string,\n data?: unknown,\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreValidateSchema(type, data, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const code = message.includes('not found') ? 'E_NOT_FOUND'\n : message.includes('Unknown schema') ? 'E_INVALID_TYPE'\n : message.includes('required') ? 'E_INVALID_INPUT'\n : 'E_VALIDATION_ERROR';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * validate.task - Anti-hallucination task validation\n * @task T4477\n */\nexport async function validateTask(\n taskId: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = await coreValidateTask(taskId, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_INVALID_INPUT';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * validate.protocol - Protocol compliance check\n * @task T4477\n */\nexport async function validateProtocol(\n taskId: string,\n protocolType?: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = await coreValidateProtocol(taskId, protocolType, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_INVALID_INPUT';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * validate.manifest - Manifest entry validation\n * @task T4477\n */\nexport function validateManifest(\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreValidateManifest(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_MANIFEST_READ_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.output - Output file validation\n * @task T4477\n */\nexport function validateOutput(\n filePath: string,\n taskId?: string,\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreValidateOutput(filePath, taskId, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_INVALID_INPUT';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * validate.compliance.summary - Aggregated compliance metrics\n * @task T4477\n */\nexport function validateComplianceSummary(\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreComplianceSummary(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_COMPLIANCE_READ_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.compliance.violations - List compliance violations\n * @task T4477\n */\nexport function validateComplianceViolations(\n limit?: number,\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreComplianceViolations(limit, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_COMPLIANCE_READ_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.compliance.record - Record compliance check result\n * @task T4477\n */\nexport function validateComplianceRecord(\n taskId: string,\n result: string,\n protocol?: string,\n violations?: Array<{ code: string; message: string; severity: string }>,\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const data = coreComplianceRecord(taskId, result, protocol, violations, root);\n return { success: true, data };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_INVALID_INPUT',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.test.status - Test suite status\n * @task T4477\n */\nexport function validateTestStatus(\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreTestStatus(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_OPERATION_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.coherence-check - Cross-validate task graph for consistency\n * @task T4477\n */\nexport async function validateCoherenceCheck(\n projectRoot?: string\n): Promise<EngineResult<{ coherent: boolean; issues: CoherenceIssue[] }>> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = await coreCoherenceCheck(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_NOT_INITIALIZED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.test.run - Execute test suite via subprocess\n * @task T4632\n */\nexport function validateTestRun(\n params?: { scope?: string; pattern?: string; parallel?: boolean },\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreTestRun(params, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_OPERATION_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.batch-validate - Batch validate all tasks against schema and rules\n * @task T4632\n */\nexport async function validateBatchValidate(\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = await coreBatchValidate(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n\n/**\n * validate.test.coverage - Coverage metrics\n * @task T4477\n */\nexport function validateTestCoverage(\n projectRoot?: string\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = coreTestCoverage(root);\n return { success: true, data: result };\n } catch (err: unknown) {\n return {\n success: false,\n error: {\n code: 'E_COVERAGE_READ_FAILED',\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n}\n", "/**\n * Orchestrate Engine\n *\n * Thin wrapper layer that delegates to core modules.\n * All business logic lives in src/core/orchestration/.\n *\n * @task T4478\n * @task T4784\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolveProjectRoot } from './store.js';\nimport { getManifestPath as getCentralManifestPath } from '../../core/paths.js';\nimport { getAccessor } from '../../store/data-accessor.js';\nimport type { TaskRecord } from './task-engine.js';\nimport type { Task } from '../../types/task.js';\nimport type { BrainState } from '../types/operations/orchestrate.js';\n\n// Core module imports\nimport {\n analyzeEpic,\n getReadyTasks,\n getNextTask,\n prepareSpawn,\n} from '../../core/orchestration/index.js';\nimport { computeWaves, getEnrichedWaves } from '../../core/orchestration/waves.js';\nimport { getCriticalPath } from '../../core/orchestration/critical-path.js';\nimport { getUnblockOpportunities } from '../../core/orchestration/unblock.js';\nimport { startParallelExecution, endParallelExecution, getParallelStatus } from '../../core/orchestration/parallel.js';\nimport { listSkills, getSkillContent } from '../../core/orchestration/skill-ops.js';\nimport { validateSpawnReadiness } from '../../core/orchestration/validate-spawn.js';\nimport { buildBrainState } from '../../core/orchestration/bootstrap.js';\n\n/**\n * Engine result type\n */\ninterface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: { code: string; message: string; details?: unknown };\n}\n\n/**\n * Load all tasks from todo.json\n */\nasync function loadTasks(projectRoot?: string): Promise<TaskRecord[]> {\n const root = projectRoot || resolveProjectRoot();\n try {\n const accessor = await getAccessor(root);\n const todoData = await accessor.loadTaskFile();\n return (todoData as any)?.tasks || [];\n } catch {\n return [];\n }\n}\n\n/**\n * orchestrate.status - Get orchestrator status\n * @task T4478\n */\nexport async function orchestrateStatus(\n epicId?: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const tasks = await loadTasks(root);\n\n if (epicId) {\n const epic = tasks.find(t => t.id === epicId);\n if (!epic) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: `Epic ${epicId} not found` } };\n }\n\n const children = tasks.filter(t => t.parentId === epicId);\n const waves = computeWaves(children as unknown as Task[]);\n\n return {\n success: true,\n data: {\n epicId,\n epicTitle: epic.title,\n totalTasks: children.length,\n byStatus: {\n pending: children.filter(t => t.status === 'pending').length,\n active: children.filter(t => t.status === 'active').length,\n blocked: children.filter(t => t.status === 'blocked').length,\n done: children.filter(t => t.status === 'done').length,\n cancelled: children.filter(t => t.status === 'cancelled').length,\n },\n waves: waves.length,\n currentWave: waves.find(w => w.status !== 'completed')?.waveNumber || null,\n },\n };\n }\n\n // No epicId - return overall status\n const epics = tasks.filter(\n t => !t.parentId && (t.type === 'epic' || tasks.some(c => c.parentId === t.id)),\n );\n\n return {\n success: true,\n data: {\n totalEpics: epics.length,\n totalTasks: tasks.length,\n byStatus: {\n pending: tasks.filter(t => t.status === 'pending').length,\n active: tasks.filter(t => t.status === 'active').length,\n blocked: tasks.filter(t => t.status === 'blocked').length,\n done: tasks.filter(t => t.status === 'done').length,\n },\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_STATUS_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.analyze - Dependency analysis\n * @task T4478\n */\nexport async function orchestrateAnalyze(\n epicId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await analyzeEpic(epicId, root, accessor);\n\n // Add dependency graph and circular dep detection that core analyzeEpic provides\n const tasks = await loadTasks(root);\n const children = tasks.filter(t => t.parentId === epicId);\n\n // Build dependency graph\n const graph = new Map<string, Set<string>>();\n for (const task of children) {\n if (!graph.has(task.id)) graph.set(task.id, new Set());\n if (task.depends) {\n for (const dep of task.depends) {\n graph.get(task.id)!.add(dep);\n }\n }\n }\n\n // Find circular dependencies\n const circularDeps: string[][] = [];\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n function dfs(taskId: string, path: string[]): void {\n visited.add(taskId);\n recursionStack.add(taskId);\n const deps = graph.get(taskId) || new Set();\n for (const dep of deps) {\n if (!visited.has(dep)) {\n dfs(dep, [...path, taskId]);\n } else if (recursionStack.has(dep)) {\n circularDeps.push([...path, taskId, dep]);\n }\n }\n recursionStack.delete(taskId);\n }\n\n for (const task of children) {\n if (!visited.has(task.id)) dfs(task.id, []);\n }\n\n // Missing deps\n const childIds = new Set(children.map(t => t.id));\n const missingDeps: Array<{ taskId: string; missingDep: string }> = [];\n for (const task of children) {\n if (task.depends) {\n for (const dep of task.depends) {\n if (!childIds.has(dep) && !tasks.find(t => t.id === dep && t.status === 'done')) {\n missingDeps.push({ taskId: task.id, missingDep: dep });\n }\n }\n }\n }\n\n return {\n success: true,\n data: {\n epicId: result.epicId,\n epicTitle: tasks.find(t => t.id === epicId)?.title || epicId,\n totalTasks: result.totalTasks,\n waves: result.waves,\n circularDependencies: circularDeps,\n missingDependencies: missingDeps,\n dependencyGraph: Object.fromEntries(\n Array.from(graph.entries()).map(([k, v]) => [k, Array.from(v)]),\n ),\n },\n };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_ANALYZE_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.ready - Get parallel-safe tasks (ready to execute)\n * @task T4478\n */\nexport async function orchestrateReady(\n epicId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const readyTasks = await getReadyTasks(epicId, root, accessor);\n const ready = readyTasks.filter(t => t.ready);\n\n return {\n success: true,\n data: {\n epicId,\n readyTasks: ready.map(t => ({\n id: t.taskId,\n title: t.title,\n priority: 'medium', // getReadyTasks doesn't return priority\n depends: t.blockers,\n })),\n total: ready.length,\n },\n };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_READY_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.next - Next task to spawn\n * @task T4478\n */\nexport async function orchestrateNext(\n epicId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const nextTask = await getNextTask(epicId, root, accessor);\n\n if (!nextTask) {\n return {\n success: true,\n data: {\n epicId,\n nextTask: null,\n message: 'No tasks ready to spawn. All pending tasks may have unmet dependencies.',\n },\n };\n }\n\n // Get all ready tasks for alternatives\n const readyTasks = await getReadyTasks(epicId, root, accessor);\n const ready = readyTasks.filter(t => t.ready);\n\n return {\n success: true,\n data: {\n epicId,\n nextTask: { id: nextTask.taskId, title: nextTask.title, priority: 'medium' },\n alternatives: ready.slice(1, 4).map(t => ({ id: t.taskId, title: t.title, priority: 'medium' })),\n totalReady: ready.length,\n },\n };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_NEXT_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.waves - Compute dependency waves\n * @task T4478\n */\nexport async function orchestrateWaves(\n epicId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await getEnrichedWaves(epicId, root, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_WAVES_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.context - Context usage check\n * @task T4478\n */\nexport async function orchestrateContext(\n epicId?: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const tasks = await loadTasks(root);\n\n let taskCount = tasks.length;\n if (epicId) {\n taskCount = tasks.filter(t => t.parentId === epicId).length;\n }\n\n const estimatedTokens = taskCount * 100;\n\n const manifestPath = getCentralManifestPath(root);\n let manifestEntries = 0;\n if (existsSync(manifestPath)) {\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n manifestEntries = content.split('\\n').filter(l => l.trim()).length;\n } catch {\n // ignore\n }\n }\n\n return {\n success: true,\n data: {\n epicId: epicId || null,\n taskCount,\n manifestEntries,\n estimatedTokens,\n recommendation: estimatedTokens > 5000\n ? 'Consider using manifest summaries instead of full task details'\n : 'Context usage is within recommended limits',\n limits: {\n orchestratorBudget: 10000,\n maxFilesPerAgent: 3,\n currentUsage: estimatedTokens,\n },\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_CONTEXT_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.skill.list - Available skills\n * @task T4478\n */\nexport function orchestrateSkillList(\n projectRoot?: string,\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = listSkills(root);\n return {\n success: true,\n data: {\n skills: result.skills,\n total: result.total,\n ...(result.total === 0 ? { message: 'No skills directory found' } : {}),\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_SKILL_LIST_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.validate - Validate spawn readiness for a task\n * @task T4478\n */\nexport async function orchestrateValidate(\n taskId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!taskId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'taskId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await validateSpawnReadiness(taskId, root, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_VALIDATE_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.spawn - Generate spawn prompt for a task\n * @task T4478\n */\nexport async function orchestrateSpawn(\n taskId: string,\n protocolType?: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!taskId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'taskId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n\n // Validate readiness first\n const accessor = await getAccessor(root);\n const validation = await validateSpawnReadiness(taskId, root, accessor);\n if (!validation.ready) {\n return {\n success: false,\n error: {\n code: 'E_NOT_READY',\n message: `Task ${taskId} is not ready to spawn`,\n details: { issues: validation.issues },\n },\n };\n }\n\n // Prepare spawn context via core\n const spawnContext = await prepareSpawn(taskId, root, accessor);\n\n return {\n success: true,\n data: {\n taskId,\n spawnContext: {\n taskId: spawnContext.taskId,\n protocol: spawnContext.protocol,\n protocolType: protocolType || spawnContext.protocol,\n },\n protocolType: protocolType || spawnContext.protocol,\n tokenResolution: spawnContext.tokenResolution,\n },\n };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_SPAWN_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.startup - Initialize orchestration for an epic\n * @task T4478\n */\nexport async function orchestrateStartup(\n epicId: string,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n\n const tasks = await loadTasks(root);\n const epic = tasks.find(t => t.id === epicId);\n if (!epic) {\n return { success: false, error: { code: 'E_NOT_FOUND', message: `Epic ${epicId} not found` } };\n }\n\n const children = tasks.filter(t => t.parentId === epicId);\n const waves = computeWaves(children as unknown as Task[]);\n const readyTasks = await getReadyTasks(epicId, root, accessor);\n const ready = readyTasks.filter(t => t.ready);\n\n return {\n success: true,\n data: {\n epicId,\n epicTitle: epic.title,\n initialized: true,\n summary: {\n totalTasks: children.length,\n totalWaves: waves.length,\n readyTasks: ready.length,\n byStatus: {\n pending: children.filter(t => t.status === 'pending').length,\n active: children.filter(t => t.status === 'active').length,\n blocked: children.filter(t => t.status === 'blocked').length,\n done: children.filter(t => t.status === 'done').length,\n },\n },\n firstWave: waves[0] || null,\n },\n };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_STARTUP_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.bootstrap - Load brain state for agent bootstrapping\n * @task T4478\n * @task T4657\n */\nexport async function orchestrateBootstrap(\n projectRoot?: string,\n params?: { speed?: 'fast' | 'full' | 'complete' },\n): Promise<EngineResult<BrainState>> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const brain = await buildBrainState(root, params, accessor);\n return { success: true, data: brain };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_BOOTSTRAP_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.critical-path - Find the longest dependency chain\n * @task T4478\n */\nexport async function orchestrateCriticalPath(\n projectRoot?: string,\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await getCriticalPath(root, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_CRITICAL_PATH_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.unblock-opportunities - Analyze dependency graph for unblocking opportunities\n * @task T4478\n */\nexport async function orchestrateUnblockOpportunities(\n projectRoot?: string,\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await getUnblockOpportunities(root, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_UNBLOCK_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.parallel.start - Start parallel execution for a wave\n * @task T4632\n */\nexport async function orchestrateParallelStart(\n epicId: string,\n wave: number,\n projectRoot?: string,\n): Promise<EngineResult> {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n if (wave === undefined || wave === null) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'wave number is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const accessor = await getAccessor(root);\n const result = await startParallelExecution(epicId, wave, root, accessor);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_PARALLEL_START_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.parallel.end - End parallel execution for a wave\n * @task T4632\n */\nexport function orchestrateParallelEnd(\n epicId: string,\n wave: number,\n projectRoot?: string,\n): EngineResult {\n if (!epicId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'epicId is required' } };\n }\n\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = endParallelExecution(epicId, wave, root);\n\n if (result.alreadyEnded) {\n return {\n success: true,\n data: {\n epicId,\n wave,\n message: 'No parallel execution was active',\n alreadyEnded: true,\n },\n };\n }\n\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_PARALLEL_END_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.check - Check current orchestration state\n * @task T4632\n */\nexport async function orchestrateCheck(\n projectRoot?: string,\n): Promise<EngineResult> {\n try {\n const root = projectRoot || resolveProjectRoot();\n const parallelState = getParallelStatus(root);\n const tasks = await loadTasks(root);\n\n const activeTasks = tasks.filter(t => t.status === 'active');\n const total = tasks.length;\n const done = tasks.filter(t => t.status === 'done').length;\n const pending = tasks.filter(t => t.status === 'pending').length;\n const blocked = tasks.filter(t => t.status === 'blocked').length;\n\n return {\n success: true,\n data: {\n parallelExecution: {\n active: parallelState.active,\n epicId: parallelState.epicId || null,\n wave: parallelState.wave || null,\n tasks: parallelState.tasks || [],\n startedAt: parallelState.startedAt || null,\n },\n activeTasks: activeTasks.map(t => ({ id: t.id, title: t.title, status: t.status })),\n progress: {\n total,\n done,\n pending,\n blocked,\n active: activeTasks.length,\n percentComplete: total > 0 ? Math.round((done / total) * 100) : 0,\n },\n },\n };\n } catch (err: unknown) {\n return { success: false, error: { code: 'E_CHECK_FAILED', message: (err as Error).message } };\n }\n}\n\n/**\n * orchestrate.skill.inject - Read skill content for injection into agent context\n * @task T4632\n */\nexport function orchestrateSkillInject(\n skillName: string,\n projectRoot?: string,\n): EngineResult {\n try {\n const root = projectRoot || resolveProjectRoot();\n const result = getSkillContent(skillName, root);\n return { success: true, data: result };\n } catch (err: unknown) {\n const code = (err as { code?: string }).code ?? 'E_SKILL_INJECT_FAILED';\n return { success: false, error: { code, message: (err as Error).message } };\n }\n}\n", "/**\n * Orchestrator commands - coordinate multi-agent workflows.\n * @task T4466\n * @epic T4454\n */\n\nimport { readJsonRequired } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TodoFile } from '../../types/task.js';\nimport { getTodoPath } from '../paths.js';\nimport { getExecutionWaves } from '../phases/deps.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Orchestrator session state. */\nexport interface OrchestratorSession {\n epicId: string;\n startedAt: string;\n status: 'active' | 'paused' | 'completed';\n currentWave: number;\n completedTasks: string[];\n spawnedAgents: string[];\n}\n\n/** Spawn context for a subagent. */\nexport interface SpawnContext {\n taskId: string;\n protocol: string;\n prompt: string;\n tokenResolution: {\n fullyResolved: boolean;\n unresolvedTokens: string[];\n };\n}\n\n/** Task readiness assessment. */\nexport interface TaskReadiness {\n taskId: string;\n title: string;\n ready: boolean;\n blockers: string[];\n protocol: string;\n}\n\n/** Orchestrator analysis result. */\nexport interface AnalysisResult {\n epicId: string;\n totalTasks: number;\n waves: Array<{\n wave: number;\n tasks: Array<{ id: string; title: string; status: string }>;\n }>;\n readyTasks: string[];\n blockedTasks: string[];\n completedTasks: string[];\n}\n\n/**\n * Start an orchestrator session for an epic.\n * @task T4466\n */\nexport async function startOrchestration(\n epicId: string,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<OrchestratorSession> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n const epic = data.tasks.find(t => t.id === epicId);\n\n if (!epic) {\n throw new CleoError(ExitCode.NOT_FOUND, `Epic not found: ${epicId}`);\n }\n\n if (epic.type !== 'epic') {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n `Task ${epicId} is not an epic (type: ${epic.type})`,\n );\n }\n\n const session: OrchestratorSession = {\n epicId,\n startedAt: new Date().toISOString(),\n status: 'active',\n currentWave: 1,\n completedTasks: [],\n spawnedAgents: [],\n };\n\n return session;\n}\n\n/**\n * Analyze an epic's dependency structure.\n * @task T4466\n */\nexport async function analyzeEpic(epicId: string, cwd?: string, accessor?: DataAccessor): Promise<AnalysisResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n const epic = data.tasks.find(t => t.id === epicId);\n\n if (!epic) {\n throw new CleoError(ExitCode.NOT_FOUND, `Epic not found: ${epicId}`);\n }\n\n const childTasks = data.tasks.filter(t => t.parentId === epicId);\n const waves = await getExecutionWaves(epicId, cwd);\n\n const completedTasks = childTasks.filter(t => t.status === 'done').map(t => t.id);\n const blockedTasks = childTasks.filter(t => t.status === 'blocked').map(t => t.id);\n\n // Find ready tasks (all deps complete, not yet started)\n const completedSet = new Set(completedTasks);\n const readyTasks = childTasks\n .filter(t => {\n if (t.status === 'done' || t.status === 'cancelled') return false;\n const deps = t.depends ?? [];\n return deps.every(d => completedSet.has(d));\n })\n .map(t => t.id);\n\n return {\n epicId,\n totalTasks: childTasks.length,\n waves: waves.map(w => ({\n wave: w.wave,\n tasks: w.tasks.map(t => ({ id: t.id, title: t.title, status: t.status })),\n })),\n readyTasks,\n blockedTasks,\n completedTasks,\n };\n}\n\n/**\n * Get parallel-safe ready tasks for an epic.\n * @task T4466\n */\nexport async function getReadyTasks(epicId: string, cwd?: string, accessor?: DataAccessor): Promise<TaskReadiness[]> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n const childTasks = data.tasks.filter(t => t.parentId === epicId);\n const completedIds = new Set(\n data.tasks.filter(t => t.status === 'done').map(t => t.id),\n );\n\n return childTasks\n .filter(t => t.status !== 'done' && t.status !== 'cancelled')\n .map(task => {\n const deps = task.depends ?? [];\n const unmetDeps = deps.filter(d => !completedIds.has(d));\n const protocol = autoDispatch(task);\n\n return {\n taskId: task.id,\n title: task.title,\n ready: unmetDeps.length === 0,\n blockers: unmetDeps,\n protocol,\n };\n });\n}\n\n/**\n * Get the next task to work on for an epic.\n * @task T4466\n */\nexport async function getNextTask(epicId: string, cwd?: string, accessor?: DataAccessor): Promise<TaskReadiness | null> {\n const readyTasks = await getReadyTasks(epicId, cwd, accessor);\n const ready = readyTasks.filter(t => t.ready);\n\n if (ready.length === 0) return null;\n\n return ready[0]!;\n}\n\n/**\n * Prepare a spawn context for a subagent.\n * @task T4466\n */\nexport async function prepareSpawn(taskId: string, cwd?: string, accessor?: DataAccessor): Promise<SpawnContext> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n const task = data.tasks.find(t => t.id === taskId);\n\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n const protocol = autoDispatch(task);\n const prompt = buildSpawnPrompt(task, protocol);\n\n // Check for unresolved tokens\n const unresolvedTokens = findUnresolvedTokens(prompt);\n\n return {\n taskId,\n protocol,\n prompt,\n tokenResolution: {\n fullyResolved: unresolvedTokens.length === 0,\n unresolvedTokens,\n },\n };\n}\n\n/**\n * Validate a subagent's output.\n * @task T4466\n */\nexport async function validateSpawnOutput(\n _taskId: string,\n output: { file?: string; manifestEntry?: boolean },\n): Promise<{ valid: boolean; errors: string[] }> {\n const errors: string[] = [];\n\n if (!output.file) {\n errors.push('No output file specified');\n }\n\n if (!output.manifestEntry) {\n errors.push('No manifest entry appended');\n }\n\n return { valid: errors.length === 0, errors };\n}\n\n/**\n * Get orchestrator context summary.\n * @task T4466\n */\nexport async function getOrchestratorContext(epicId: string, cwd?: string, accessor?: DataAccessor): Promise<{\n epicId: string;\n epicTitle: string;\n totalTasks: number;\n completed: number;\n inProgress: number;\n blocked: number;\n pending: number;\n completionPercent: number;\n}> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(getTodoPath(cwd));\n const epic = data.tasks.find(t => t.id === epicId);\n\n if (!epic) {\n throw new CleoError(ExitCode.NOT_FOUND, `Epic not found: ${epicId}`);\n }\n\n const children = data.tasks.filter(t => t.parentId === epicId);\n const completed = children.filter(t => t.status === 'done').length;\n const inProgress = children.filter(t => t.status === 'active').length;\n const blocked = children.filter(t => t.status === 'blocked').length;\n const pending = children.filter(t => t.status === 'pending').length;\n\n return {\n epicId,\n epicTitle: epic.title,\n totalTasks: children.length,\n completed,\n inProgress,\n blocked,\n pending,\n completionPercent: children.length > 0 ? Math.floor(completed * 100 / children.length) : 0,\n };\n}\n\n// === SKILL DISPATCH ===\n\n/** Protocol dispatch mapping. */\nconst DISPATCH_MAP: Record<string, { keywords: string[]; labels: string[] }> = {\n research: {\n keywords: ['research', 'investigate', 'explore', 'analyze', 'study'],\n labels: ['research', 'investigation', 'analysis'],\n },\n consensus: {\n keywords: ['vote', 'validate', 'decide', 'consensus'],\n labels: ['consensus', 'voting', 'decision'],\n },\n specification: {\n keywords: ['spec', 'rfc', 'design', 'specification'],\n labels: ['specification', 'design', 'rfc'],\n },\n decomposition: {\n keywords: ['epic', 'plan', 'decompose', 'breakdown'],\n labels: ['decomposition', 'planning', 'epic'],\n },\n implementation: {\n keywords: ['implement', 'build', 'create', 'code', 'develop', 'port', 'fix'],\n labels: ['implementation', 'development', 'coding'],\n },\n contribution: {\n keywords: ['pr', 'merge', 'shared', 'contribute'],\n labels: ['contribution', 'pr', 'merge'],\n },\n release: {\n keywords: ['release', 'version', 'publish', 'ship'],\n labels: ['release', 'versioning', 'publishing'],\n },\n};\n\n/**\n * Auto-dispatch: determine the protocol for a task based on metadata.\n * @task T4466\n */\nexport function autoDispatch(task: Task): string {\n // 1. Label-based dispatch (highest priority)\n if (task.labels?.length) {\n for (const [protocol, config] of Object.entries(DISPATCH_MAP)) {\n if (task.labels.some(l => config.labels.includes(l))) {\n return protocol;\n }\n }\n }\n\n // 2. Type-based dispatch\n if (task.type === 'epic') return 'decomposition';\n\n // 3. Keyword-based dispatch\n const text = `${task.title} ${task.description ?? ''}`.toLowerCase();\n for (const [protocol, config] of Object.entries(DISPATCH_MAP)) {\n if (config.keywords.some(kw => text.includes(kw))) {\n return protocol;\n }\n }\n\n // 4. Fallback\n return 'implementation';\n}\n\n/**\n * Build a spawn prompt for a subagent.\n * @task T4466\n */\nfunction buildSpawnPrompt(task: Task, protocol: string): string {\n const epicId = task.parentId ?? 'none';\n const date = new Date().toISOString().split('T')[0];\n\n return [\n `## Task: ${task.id}`,\n `**Title**: ${task.title}`,\n task.description ? `**Description**: ${task.description}` : '',\n `**Protocol**: ${protocol}`,\n `**Epic**: ${epicId}`,\n `**Date**: ${date}`,\n '',\n `### Instructions`,\n `1. Set focus: \\`cleo focus set ${task.id}\\``,\n `2. Execute the ${protocol} protocol`,\n `3. Write output file`,\n `4. Append manifest entry to MANIFEST.jsonl`,\n `5. Complete: \\`cleo complete ${task.id}\\``,\n '',\n task.acceptance?.length ? `### Acceptance Criteria\\n${task.acceptance.map(a => `- ${a}`).join('\\n')}` : '',\n task.depends?.length ? `### Dependencies\\n${task.depends.map(d => `- ${d}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n');\n}\n\n/**\n * Find unresolved tokens in a prompt.\n * @task T4466\n */\nfunction findUnresolvedTokens(prompt: string): string[] {\n const tokens: string[] = [];\n const tokenRegex = /\\{\\{([A-Z_]+)\\}\\}/g;\n let match;\n while ((match = tokenRegex.exec(prompt)) !== null) {\n tokens.push(match[1]!);\n }\n\n const refRegex = /@([a-zA-Z0-9_./\\-]+\\.md)/g;\n while ((match = refRegex.exec(prompt)) !== null) {\n tokens.push(`@${match[1]}`);\n }\n\n return tokens;\n}\n\n/**\n * Resolve tokens in a prompt string.\n * @task T4466\n */\nexport function resolveTokens(\n prompt: string,\n context: Record<string, string>,\n): { resolved: string; unresolved: string[] } {\n let resolved = prompt;\n const unresolved: string[] = [];\n\n resolved = resolved.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (fullMatch, token: string) => {\n if (context[token] !== undefined) {\n return context[token]!;\n }\n unresolved.push(token);\n return fullMatch;\n });\n\n return { resolved, unresolved };\n}\n", "/**\n * Dependency graph resolution - topological sort, cycle detection, impact analysis.\n * @task T4464\n * @task T4659\n * @epic T4454\n * @epic T4654\n */\n\nimport { readJsonRequired, computeChecksum, saveJson } from '../../store/json.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { Task, TodoFile } from '../../types/task.js';\nimport { getTodoPath, getBackupDir } from '../paths.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/**\n * Cached TodoFile loader to avoid repeated file reads within a single operation.\n * Cache is keyed by resolved path and invalidated after 1 second.\n * @task T4659\n * @epic T4654\n */\nlet cachedTodoData: { path: string; data: TodoFile; timestamp: number } | null = null;\nconst CACHE_TTL_MS = 1000;\n\nasync function loadTodoData(cwd?: string, accessor?: DataAccessor): Promise<TodoFile> {\n if (accessor) {\n return accessor.loadTodoFile();\n }\n const todoPath = getTodoPath(cwd);\n const now = Date.now();\n if (cachedTodoData && cachedTodoData.path === todoPath && (now - cachedTodoData.timestamp) < CACHE_TTL_MS) {\n return cachedTodoData.data;\n }\n const data = await readJsonRequired<TodoFile>(todoPath);\n cachedTodoData = { path: todoPath, data, timestamp: now };\n return data;\n}\n\n/**\n * Invalidate the cached TodoFile (call after writes).\n * @task T4659\n * @epic T4654\n */\nexport function invalidateDepsCache(): void {\n cachedTodoData = null;\n}\n\n/** A node in the dependency graph. */\nexport interface DepNode {\n id: string;\n title: string;\n status: string;\n depends: string[];\n dependents: string[];\n}\n\n/** Dependency overview result. */\nexport interface DepsOverviewResult {\n nodes: DepNode[];\n totalTasks: number;\n withDependencies: number;\n withDependents: number;\n roots: string[];\n leaves: string[];\n}\n\n/** Single task dependency result. */\nexport interface TaskDepsResult {\n task: { id: string; title: string; status: string };\n upstream: Array<{ id: string; title: string; status: string }>;\n downstream: Array<{ id: string; title: string; status: string }>;\n blockedBy: Array<{ id: string; title: string; status: string }>;\n}\n\n/** Execution wave (group of parallelizable tasks). */\nexport interface ExecutionWave {\n wave: number;\n tasks: Array<{ id: string; title: string; status: string; depends: string[] }>;\n}\n\n/** Critical path result. */\nexport interface CriticalPathResult {\n path: Array<{ id: string; title: string; status: string }>;\n length: number;\n}\n\n/** Cycle detection result. */\nexport interface CycleResult {\n hasCycles: boolean;\n cycles: string[][];\n}\n\n/**\n * Build an adjacency graph from task dependencies.\n * @task T4464\n */\nexport function buildGraph(tasks: Task[]): Map<string, DepNode> {\n const graph = new Map<string, DepNode>();\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n\n // Initialize nodes\n for (const task of tasks) {\n graph.set(task.id, {\n id: task.id,\n title: task.title,\n status: task.status,\n depends: (task.depends ?? []).filter(d => taskMap.has(d)),\n dependents: [],\n });\n }\n\n // Build reverse edges (dependents)\n for (const [id, node] of graph) {\n for (const depId of node.depends) {\n const depNode = graph.get(depId);\n if (depNode) {\n depNode.dependents.push(id);\n }\n }\n }\n\n return graph;\n}\n\n/**\n * Get dependency overview for all tasks.\n * @task T4464\n */\nexport async function getDepsOverview(cwd?: string, accessor?: DataAccessor): Promise<DepsOverviewResult> {\n const data = await loadTodoData(cwd, accessor);\n const graph = buildGraph(data.tasks);\n const nodes = Array.from(graph.values());\n\n return {\n nodes,\n totalTasks: data.tasks.length,\n withDependencies: nodes.filter(n => n.depends.length > 0).length,\n withDependents: nodes.filter(n => n.dependents.length > 0).length,\n roots: nodes.filter(n => n.depends.length === 0).map(n => n.id),\n leaves: nodes.filter(n => n.dependents.length === 0).map(n => n.id),\n };\n}\n\n/**\n * Get dependencies for a specific task.\n * @task T4464\n */\nexport async function getTaskDeps(taskId: string, cwd?: string, accessor?: DataAccessor): Promise<TaskDepsResult> {\n const data = await loadTodoData(cwd, accessor);\n const task = data.tasks.find(t => t.id === taskId);\n\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n const graph = buildGraph(data.tasks);\n const node = graph.get(taskId)!;\n const taskMap = new Map(data.tasks.map(t => [t.id, t]));\n\n const toSummary = (id: string) => {\n const t = taskMap.get(id);\n return t ? { id: t.id, title: t.title, status: t.status } : { id, title: 'Unknown', status: 'unknown' };\n };\n\n // Find upstream dependencies that are not done (blocking this task)\n const blockedBy = node.depends\n .filter(depId => {\n const depTask = taskMap.get(depId);\n return depTask && depTask.status !== 'done';\n })\n .map(toSummary);\n\n return {\n task: { id: task.id, title: task.title, status: task.status },\n upstream: node.depends.map(toSummary),\n downstream: node.dependents.map(toSummary),\n blockedBy,\n };\n}\n\n/**\n * Topological sort of tasks respecting dependencies.\n * Returns tasks in execution order. Throws on cycles.\n * @task T4464\n */\nexport function topologicalSort(tasks: Task[]): Task[] {\n const graph = buildGraph(tasks);\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const result: string[] = [];\n\n function dfs(id: string): void {\n if (visited.has(id)) return;\n if (visiting.has(id)) {\n throw new CleoError(ExitCode.CIRCULAR_REFERENCE, `Circular dependency detected involving task: ${id}`);\n }\n\n visiting.add(id);\n const node = graph.get(id);\n if (node) {\n for (const dep of node.depends) {\n dfs(dep);\n }\n }\n visiting.delete(id);\n visited.add(id);\n result.push(id);\n }\n\n for (const task of tasks) {\n dfs(task.id);\n }\n\n return result.map(id => taskMap.get(id)!).filter(Boolean);\n}\n\n/**\n * Group tasks into parallelizable execution waves.\n * @task T4464\n */\nexport async function getExecutionWaves(epicId?: string, cwd?: string, accessor?: DataAccessor): Promise<ExecutionWave[]> {\n const data = await loadTodoData(cwd, accessor);\n let tasks = data.tasks.filter(t => t.status !== 'done' && t.status !== 'cancelled');\n\n // Scope to epic if provided\n if (epicId) {\n const epicTask = data.tasks.find(t => t.id === epicId);\n if (!epicTask) {\n throw new CleoError(ExitCode.NOT_FOUND, `Epic not found: ${epicId}`);\n }\n const childIds = new Set(data.tasks.filter(t => t.parentId === epicId).map(t => t.id));\n tasks = tasks.filter(t => childIds.has(t.id) || t.id === epicId);\n }\n\n const graph = buildGraph(tasks);\n const waves: ExecutionWave[] = [];\n const completed = new Set<string>();\n\n // Filter to only non-done tasks\n let remaining = new Set(tasks.map(t => t.id));\n\n let waveNum = 1;\n while (remaining.size > 0) {\n const wave: string[] = [];\n\n for (const id of remaining) {\n const node = graph.get(id);\n if (!node) continue;\n\n // Check if all dependencies are completed\n const allDepsComplete = node.depends.every(dep => completed.has(dep) || !remaining.has(dep));\n if (allDepsComplete) {\n wave.push(id);\n }\n }\n\n if (wave.length === 0) {\n // Remaining tasks have circular dependencies - add them all to last wave\n wave.push(...remaining);\n }\n\n waves.push({\n wave: waveNum,\n tasks: wave.map(id => {\n const node = graph.get(id)!;\n return {\n id,\n title: node.title,\n status: node.status,\n depends: node.depends,\n };\n }),\n });\n\n for (const id of wave) {\n completed.add(id);\n remaining.delete(id);\n }\n waveNum++;\n }\n\n return waves;\n}\n\n/**\n * Find the critical path (longest dependency chain) from a task.\n * @task T4464\n */\nexport async function getCriticalPath(taskId: string, cwd?: string, accessor?: DataAccessor): Promise<CriticalPathResult> {\n const data = await loadTodoData(cwd, accessor);\n const task = data.tasks.find(t => t.id === taskId);\n\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n const graph = buildGraph(data.tasks);\n const taskMap = new Map(data.tasks.map(t => [t.id, t]));\n\n // DFS to find longest path from this task through dependents\n function findLongestPath(id: string, visited: Set<string>): string[] {\n if (visited.has(id)) return [];\n visited.add(id);\n\n const node = graph.get(id);\n if (!node || node.dependents.length === 0) {\n return [id];\n }\n\n let longest: string[] = [];\n for (const depId of node.dependents) {\n const path = findLongestPath(depId, new Set(visited));\n if (path.length > longest.length) {\n longest = path;\n }\n }\n\n return [id, ...longest];\n }\n\n const path = findLongestPath(taskId, new Set<string>());\n\n return {\n path: path.map(id => {\n const t = taskMap.get(id);\n return t\n ? { id: t.id, title: t.title, status: t.status }\n : { id, title: 'Unknown', status: 'unknown' };\n }),\n length: path.length,\n };\n}\n\n/**\n * Find all tasks affected by changes to a given task.\n * @task T4464\n */\nexport async function getImpact(taskId: string, maxDepth: number = 10, cwd?: string, accessor?: DataAccessor): Promise<string[]> {\n const data = await loadTodoData(cwd, accessor);\n const task = data.tasks.find(t => t.id === taskId);\n\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n const graph = buildGraph(data.tasks);\n const impacted = new Set<string>();\n\n function traverse(id: string, depth: number): void {\n if (depth > maxDepth || impacted.has(id)) return;\n impacted.add(id);\n\n const node = graph.get(id);\n if (node) {\n for (const depId of node.dependents) {\n traverse(depId, depth + 1);\n }\n }\n }\n\n traverse(taskId, 0);\n impacted.delete(taskId); // Don't include the source task\n\n return Array.from(impacted);\n}\n\n/**\n * Detect circular dependencies in the task graph.\n * @task T4464\n */\nexport async function detectCycles(cwd?: string, accessor?: DataAccessor): Promise<CycleResult> {\n const data = await loadTodoData(cwd, accessor);\n const graph = buildGraph(data.tasks);\n const cycles: string[][] = [];\n const visited = new Set<string>();\n const stack = new Set<string>();\n const path: string[] = [];\n\n function dfs(id: string): void {\n if (visited.has(id)) return;\n if (stack.has(id)) {\n // Found a cycle\n const cycleStart = path.indexOf(id);\n if (cycleStart !== -1) {\n cycles.push([...path.slice(cycleStart), id]);\n }\n return;\n }\n\n stack.add(id);\n path.push(id);\n\n const node = graph.get(id);\n if (node) {\n for (const dep of node.depends) {\n if (graph.has(dep)) {\n dfs(dep);\n }\n }\n }\n\n path.pop();\n stack.delete(id);\n visited.add(id);\n }\n\n for (const id of graph.keys()) {\n if (!visited.has(id)) {\n dfs(id);\n }\n }\n\n return {\n hasCycles: cycles.length > 0,\n cycles,\n };\n}\n\n/**\n * Build task hierarchy tree.\n * @task T4464\n */\nexport async function getTaskTree(rootId?: string, cwd?: string, accessor?: DataAccessor): Promise<TreeNode[]> {\n const data = await loadTodoData(cwd, accessor);\n\n const taskMap = new Map(data.tasks.map(t => [t.id, t]));\n\n function buildChildren(parentId: string | null): TreeNode[] {\n const children = data.tasks\n .filter(t => (parentId ? t.parentId === parentId : !t.parentId))\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0));\n\n return children.map(t => ({\n id: t.id,\n title: t.title,\n status: t.status,\n type: t.type,\n children: buildChildren(t.id),\n }));\n }\n\n if (rootId) {\n const root = taskMap.get(rootId);\n if (!root) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${rootId}`);\n }\n return [{\n id: root.id,\n title: root.title,\n status: root.status,\n type: root.type,\n children: buildChildren(root.id),\n }];\n }\n\n return buildChildren(null);\n}\n\n/** Tree node representation. */\nexport interface TreeNode {\n id: string;\n title: string;\n status: string;\n type?: string;\n children: TreeNode[];\n}\n\n/**\n * Manage task relationships (relates/blocks).\n * @task T4464\n */\nexport async function addRelation(\n taskId: string,\n relatedId: string,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<{ taskId: string; relatedId: string }> {\n const todoPath = getTodoPath(cwd);\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJsonRequired<TodoFile>(todoPath);\n\n const task = data.tasks.find(t => t.id === taskId);\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n const related = data.tasks.find(t => t.id === relatedId);\n if (!related) {\n throw new CleoError(ExitCode.NOT_FOUND, `Related task not found: ${relatedId}`);\n }\n\n // Add dependency\n if (!task.depends) task.depends = [];\n if (!task.depends.includes(relatedId)) {\n task.depends.push(relatedId);\n }\n\n data.lastUpdated = new Date().toISOString();\n data._meta.checksum = computeChecksum(data.tasks);\n\n if (accessor) {\n await accessor.saveTodoFile(data);\n } else {\n await saveJson(todoPath, data, { backupDir: getBackupDir(cwd) });\n }\n invalidateDepsCache();\n\n return { taskId, relatedId };\n}\n\n", "/**\n * Wave computation and dependency graph operations.\n * @task T4784\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { Task, TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface Wave {\n waveNumber: number;\n tasks: string[];\n status: 'pending' | 'in_progress' | 'completed';\n}\n\nexport interface EnrichedWave {\n waveNumber: number;\n tasks: Array<{ id: string; title: string; status: string }>;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\n/** Build a dependency graph for tasks. */\nfunction buildDependencyGraph(tasks: Task[]): Map<string, Set<string>> {\n const graph = new Map<string, Set<string>>();\n for (const task of tasks) {\n if (!graph.has(task.id)) {\n graph.set(task.id, new Set());\n }\n if (task.depends) {\n for (const dep of task.depends) {\n graph.get(task.id)!.add(dep);\n }\n }\n }\n return graph;\n}\n\n/** Compute execution waves using topological sort. */\nexport function computeWaves(tasks: Task[]): Wave[] {\n const graph = buildDependencyGraph(tasks);\n const waves: Wave[] = [];\n const completed = new Set<string>();\n\n for (const task of tasks) {\n if (task.status === 'done' || task.status === 'cancelled') {\n completed.add(task.id);\n }\n }\n\n let remaining = tasks.filter(t => t.status !== 'done' && t.status !== 'cancelled');\n let waveNumber = 1;\n const maxWaves = 50;\n\n while (remaining.length > 0 && waveNumber <= maxWaves) {\n const waveTasks = remaining.filter(t => {\n const deps = graph.get(t.id) || new Set();\n return Array.from(deps).every(d => completed.has(d));\n });\n\n if (waveTasks.length === 0) break;\n\n waves.push({\n waveNumber,\n tasks: waveTasks.map(t => t.id),\n status: waveTasks.every(t => completed.has(t.id))\n ? 'completed'\n : waveTasks.some(t => t.status === 'active')\n ? 'in_progress'\n : 'pending',\n });\n\n for (const t of waveTasks) {\n completed.add(t.id);\n }\n\n remaining = remaining.filter(t => !waveTasks.some(wt => wt.id === t.id));\n waveNumber++;\n }\n\n if (remaining.length > 0) {\n waves.push({\n waveNumber,\n tasks: remaining.map(t => t.id),\n status: 'pending',\n });\n }\n\n return waves;\n}\n\n/** Get enriched wave data for an epic. */\nexport async function getEnrichedWaves(\n epicId: string,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<{ epicId: string; waves: EnrichedWave[]; totalWaves: number; totalTasks: number }> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n\n const tasks = data?.tasks ?? [];\n const children = tasks.filter(t => t.parentId === epicId);\n const waves = computeWaves(children);\n const taskMap = new Map(children.map(t => [t.id, t]));\n\n const enrichedWaves: EnrichedWave[] = waves.map(w => ({\n ...w,\n tasks: w.tasks.map(id => ({\n id,\n title: taskMap.get(id)?.title || id,\n status: taskMap.get(id)?.status || 'unknown',\n })),\n }));\n\n return {\n epicId,\n waves: enrichedWaves,\n totalWaves: waves.length,\n totalTasks: children.length,\n };\n}\n", "/**\n * Critical path analysis for task dependency graphs.\n * @task T4784\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface CriticalPathNode {\n taskId: string;\n title: string;\n status: string;\n size: string;\n blockerCount: number;\n}\n\nexport interface CriticalPathResult {\n path: CriticalPathNode[];\n length: number;\n totalEffort: number;\n completedInPath: number;\n remainingInPath: number;\n}\n\n/** Find the critical path (longest dependency chain) in the task graph. */\nexport async function getCriticalPath(\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<CriticalPathResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n\n const tasks = data?.tasks ?? [];\n\n if (tasks.length === 0) {\n return { path: [], length: 0, totalEffort: 0, completedInPath: 0, remainingInPath: 0 };\n }\n\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n\n // Build dependency maps\n const dependsOn = new Map<string, Set<string>>();\n const dependents = new Map<string, Set<string>>();\n\n for (const task of tasks) {\n if (!dependsOn.has(task.id)) dependsOn.set(task.id, new Set());\n if (!dependents.has(task.id)) dependents.set(task.id, new Set());\n if (task.depends) {\n for (const dep of task.depends) {\n dependsOn.get(task.id)!.add(dep);\n if (!dependents.has(dep)) dependents.set(dep, new Set());\n dependents.get(dep)!.add(task.id);\n }\n }\n }\n\n // Find longest path using DFS with memoization\n const memo = new Map<string, string[]>();\n\n function longestPathEndingAt(taskId: string, visited: Set<string>): string[] {\n if (memo.has(taskId)) return memo.get(taskId)!;\n if (visited.has(taskId)) return [taskId]; // circular\n\n visited.add(taskId);\n const deps = dependsOn.get(taskId) || new Set();\n let longest: string[] = [];\n\n for (const dep of deps) {\n if (taskMap.has(dep)) {\n const path = longestPathEndingAt(dep, visited);\n if (path.length > longest.length) longest = path;\n }\n }\n\n visited.delete(taskId);\n const result = [...longest, taskId];\n memo.set(taskId, result);\n return result;\n }\n\n // Find leaf nodes\n const leafNodes = tasks.filter(t => {\n const deps = dependents.get(t.id);\n return !deps || deps.size === 0;\n });\n\n let criticalPath: string[] = [];\n for (const leaf of leafNodes) {\n const path = longestPathEndingAt(leaf.id, new Set());\n if (path.length > criticalPath.length) criticalPath = path;\n }\n\n if (criticalPath.length === 0) {\n for (const task of tasks) {\n const path = longestPathEndingAt(task.id, new Set());\n if (path.length > criticalPath.length) criticalPath = path;\n }\n }\n\n const sizeWeights: Record<string, number> = { small: 1, medium: 3, large: 8 };\n\n const annotatedPath: CriticalPathNode[] = criticalPath.map(taskId => {\n const task = taskMap.get(taskId);\n const size = task?.size || 'medium';\n const incompleteDeps = (task?.depends || []).filter(dep => {\n const depTask = taskMap.get(dep);\n return depTask && depTask.status !== 'done' && depTask.status !== 'cancelled';\n });\n\n return {\n taskId,\n title: task?.title || taskId,\n status: task?.status || 'unknown',\n size,\n blockerCount: incompleteDeps.length,\n };\n });\n\n const completedInPath = annotatedPath.filter(t => t.status === 'done' || t.status === 'cancelled').length;\n const remainingInPath = annotatedPath.length - completedInPath;\n const totalEffort = annotatedPath\n .filter(t => t.status !== 'done' && t.status !== 'cancelled')\n .reduce((sum, t) => sum + (sizeWeights[t.size] ?? 3), 0);\n\n return { path: annotatedPath, length: criticalPath.length, totalEffort, completedInPath, remainingInPath };\n}\n", "/**\n * Unblock opportunities analysis.\n * @task T4784\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { Task, TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface HighImpactTask {\n taskId: string;\n title: string;\n wouldUnblock: number;\n dependents: string[];\n}\n\nexport interface SingleBlockerTask {\n taskId: string;\n title: string;\n remainingBlocker: { id: string; title: string };\n}\n\nexport interface CommonBlocker {\n taskId: string;\n title: string;\n blocksCount: number;\n blockedTasks: string[];\n}\n\nexport interface UnblockResult {\n highImpact: HighImpactTask[];\n singleBlocker: SingleBlockerTask[];\n commonBlockers: CommonBlocker[];\n}\n\n/** Build a reverse dependency map. */\nfunction buildReverseDependencyMap(tasks: Task[]): Map<string, string[]> {\n const reverseMap = new Map<string, string[]>();\n for (const task of tasks) {\n if (task.depends) {\n for (const dep of task.depends) {\n const existing = reverseMap.get(dep) || [];\n existing.push(task.id);\n reverseMap.set(dep, existing);\n }\n }\n }\n return reverseMap;\n}\n\n/** Count all transitive dependents. */\nfunction countTransitiveDependents(\n taskId: string,\n reverseMap: Map<string, string[]>,\n visited: Set<string> = new Set(),\n): string[] {\n if (visited.has(taskId)) return [];\n visited.add(taskId);\n\n const directDependents = reverseMap.get(taskId) || [];\n const allDependents: string[] = [...directDependents];\n\n for (const dep of directDependents) {\n const transitive = countTransitiveDependents(dep, reverseMap, visited);\n allDependents.push(...transitive);\n }\n\n return allDependents;\n}\n\n/** Analyze dependency graph for unblocking opportunities. */\nexport async function getUnblockOpportunities(\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<UnblockResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n\n const tasks = data?.tasks ?? [];\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n const completedIds = new Set(\n tasks.filter(t => t.status === 'done' || t.status === 'cancelled').map(t => t.id),\n );\n const nonDoneTasks = tasks.filter(t => t.status !== 'done' && t.status !== 'cancelled');\n const reverseMap = buildReverseDependencyMap(tasks);\n\n // 1. High-impact completions\n const highImpact: HighImpactTask[] = [];\n for (const task of nonDoneTasks) {\n const allDependents = countTransitiveDependents(task.id, reverseMap, new Set());\n const uniqueDependents = [...new Set(allDependents)];\n if (uniqueDependents.length > 0) {\n highImpact.push({\n taskId: task.id,\n title: task.title,\n wouldUnblock: uniqueDependents.length,\n dependents: uniqueDependents,\n });\n }\n }\n highImpact.sort((a, b) => b.wouldUnblock - a.wouldUnblock);\n\n // 2. Single-blocker tasks\n const singleBlocker: SingleBlockerTask[] = [];\n for (const task of tasks) {\n if (!task.depends || task.depends.length === 0) continue;\n const incompleteDeps = task.depends.filter(depId => !completedIds.has(depId));\n if (incompleteDeps.length === 1) {\n const blockerId = incompleteDeps[0]!;\n const blockerTask = taskMap.get(blockerId);\n singleBlocker.push({\n taskId: task.id,\n title: task.title,\n remainingBlocker: {\n id: blockerId,\n title: blockerTask?.title || blockerId,\n },\n });\n }\n }\n\n // 3. Common blockers\n const blockerCounts = new Map<string, string[]>();\n for (const task of tasks) {\n if (!task.depends) continue;\n for (const depId of task.depends) {\n if (!completedIds.has(depId)) {\n const existing = blockerCounts.get(depId) || [];\n existing.push(task.id);\n blockerCounts.set(depId, existing);\n }\n }\n }\n\n const commonBlockers: CommonBlocker[] = [];\n for (const [blockerId, blockedTasks] of blockerCounts) {\n if (blockedTasks.length > 1) {\n const blockerTask = taskMap.get(blockerId);\n commonBlockers.push({\n taskId: blockerId,\n title: blockerTask?.title || blockerId,\n blocksCount: blockedTasks.length,\n blockedTasks,\n });\n }\n }\n commonBlockers.sort((a, b) => b.blocksCount - a.blocksCount);\n\n return { highImpact, singleBlocker, commonBlockers };\n}\n", "/**\n * Parallel execution state management.\n * @task T4784\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport { computeWaves } from './waves.js';\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\ninterface ParallelState {\n active: boolean;\n epicId?: string;\n wave?: number;\n startedAt?: string;\n tasks?: string[];\n}\n\nfunction getParallelStatePath(projectRoot: string): string {\n return join(projectRoot, '.cleo', 'parallel-state.json');\n}\n\nfunction readParallelState(projectRoot: string): ParallelState {\n const statePath = getParallelStatePath(projectRoot);\n if (!existsSync(statePath)) return { active: false };\n try {\n return JSON.parse(readFileSync(statePath, 'utf-8'));\n } catch {\n return { active: false };\n }\n}\n\nfunction writeParallelState(state: ParallelState, projectRoot: string): void {\n const statePath = getParallelStatePath(projectRoot);\n const dir = dirname(statePath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf-8');\n}\n\n/** Start parallel execution for a wave. */\nexport async function startParallelExecution(\n epicId: string,\n wave: number,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<{\n epicId: string;\n wave: number;\n tasks: string[];\n taskCount: number;\n startedAt: string;\n}> {\n const projectRoot = cwd ?? process.cwd();\n\n const currentState = readParallelState(projectRoot);\n if (currentState.active) {\n throw new CleoError(\n ExitCode.GENERAL_ERROR,\n `Parallel execution already active for epic ${currentState.epicId}, wave ${currentState.wave}`,\n );\n }\n\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n\n const tasks = data?.tasks ?? [];\n const epic = tasks.find(t => t.id === epicId);\n if (!epic) {\n throw new CleoError(ExitCode.NOT_FOUND, `Epic ${epicId} not found`);\n }\n\n const children = tasks.filter(t => t.parentId === epicId);\n const waves = computeWaves(children);\n const targetWave = waves.find(w => w.waveNumber === wave);\n\n if (!targetWave) {\n throw new CleoError(ExitCode.INVALID_INPUT, `Wave ${wave} not found for epic ${epicId}`);\n }\n\n const startedAt = new Date().toISOString();\n const state: ParallelState = {\n active: true,\n epicId,\n wave,\n startedAt,\n tasks: targetWave.tasks,\n };\n\n writeParallelState(state, projectRoot);\n\n return {\n epicId,\n wave,\n tasks: targetWave.tasks,\n taskCount: targetWave.tasks.length,\n startedAt,\n };\n}\n\n/** End parallel execution for a wave. */\nexport function endParallelExecution(\n epicId: string,\n wave: number,\n cwd?: string,\n): {\n epicId: string;\n wave: number;\n tasks: string[];\n taskCount: number;\n startedAt: string | null;\n endedAt: string;\n durationMs: number;\n alreadyEnded?: boolean;\n} {\n const projectRoot = cwd ?? process.cwd();\n const currentState = readParallelState(projectRoot);\n\n if (!currentState.active) {\n return {\n epicId,\n wave,\n tasks: [],\n taskCount: 0,\n startedAt: null,\n endedAt: new Date().toISOString(),\n durationMs: 0,\n alreadyEnded: true,\n };\n }\n\n if (currentState.epicId !== epicId || currentState.wave !== wave) {\n throw new CleoError(\n ExitCode.INVALID_INPUT,\n `Active parallel is for epic ${currentState.epicId} wave ${currentState.wave}, not epic ${epicId} wave ${wave}`,\n );\n }\n\n const duration = currentState.startedAt\n ? Date.now() - new Date(currentState.startedAt).getTime()\n : 0;\n\n writeParallelState({ active: false }, projectRoot);\n\n return {\n epicId,\n wave,\n tasks: currentState.tasks || [],\n taskCount: currentState.tasks?.length || 0,\n startedAt: currentState.startedAt || null,\n endedAt: new Date().toISOString(),\n durationMs: duration,\n };\n}\n\n/** Get current parallel execution state. */\nexport function getParallelStatus(cwd?: string): ParallelState {\n return readParallelState(cwd ?? process.cwd());\n}\n", "/**\n * Skill listing and injection operations.\n * @task T4784\n */\n\nimport { readFileSync, existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\n\nexport interface SkillEntry {\n name: string;\n path: string;\n hasSkillFile: boolean;\n description: string;\n}\n\nexport interface SkillContent {\n skill: string;\n content: string;\n contentLength: number;\n estimatedTokens: number;\n references: Array<{ name: string; path: string }>;\n path: string;\n}\n\n/** List available skills. */\nexport function listSkills(projectRoot: string): { skills: SkillEntry[]; total: number } {\n const skillsDir = join(projectRoot, 'skills');\n\n if (!existsSync(skillsDir)) {\n return { skills: [], total: 0 };\n }\n\n const skillDirs = readdirSync(skillsDir, { withFileTypes: true })\n .filter(d => d.isDirectory() && !d.name.startsWith('_'))\n .map(d => {\n const skillPath = join(skillsDir, d.name, 'SKILL.md');\n let description = '';\n\n if (existsSync(skillPath)) {\n try {\n const content = readFileSync(skillPath, 'utf-8');\n const descMatch = content.match(/description:\\s*[|>]?\\s*\\n?\\s*(.+)/);\n if (descMatch) {\n description = descMatch[1]!.trim();\n }\n } catch {\n // ignore\n }\n }\n\n return {\n name: d.name,\n path: `skills/${d.name}`,\n hasSkillFile: existsSync(skillPath),\n description,\n };\n });\n\n return { skills: skillDirs, total: skillDirs.length };\n}\n\n/** Read skill content for injection into agent context. */\nexport function getSkillContent(skillName: string, projectRoot: string): SkillContent {\n if (!skillName) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'skill name is required');\n }\n\n const skillDir = join(projectRoot, 'skills', skillName);\n if (!existsSync(skillDir)) {\n throw new CleoError(ExitCode.NOT_FOUND, `Skill '${skillName}' not found at skills/${skillName}/`);\n }\n\n const skillFilePath = join(skillDir, 'SKILL.md');\n if (!existsSync(skillFilePath)) {\n throw new CleoError(ExitCode.NOT_FOUND, `Skill file not found: skills/${skillName}/SKILL.md`);\n }\n\n const content = readFileSync(skillFilePath, 'utf-8');\n\n // Check for reference files\n const refsDir = join(skillDir, 'references');\n let references: Array<{ name: string; path: string }> = [];\n if (existsSync(refsDir)) {\n try {\n references = readdirSync(refsDir)\n .filter(f => f.endsWith('.md') || f.endsWith('.txt'))\n .map(f => ({\n name: f,\n path: `skills/${skillName}/references/${f}`,\n }));\n } catch {\n // ignore\n }\n }\n\n return {\n skill: skillName,\n content,\n contentLength: content.length,\n estimatedTokens: Math.ceil(content.length / 4),\n references,\n path: `skills/${skillName}/SKILL.md`,\n };\n}\n", "/**\n * Spawn readiness validation.\n * @task T4784\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\nexport interface ValidationIssue {\n code: string;\n message: string;\n severity: string;\n}\n\nexport interface SpawnValidationResult {\n taskId: string;\n title: string;\n ready: boolean;\n issues: ValidationIssue[];\n}\n\n/** Validate spawn readiness for a task. */\nexport async function validateSpawnReadiness(\n taskId: string,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<SpawnValidationResult> {\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(cwd));\n\n const tasks = data?.tasks ?? [];\n const task = tasks.find(t => t.id === taskId);\n\n if (!task) {\n return {\n taskId,\n title: '',\n ready: false,\n issues: [{ code: 'V_NOT_FOUND', message: `Task ${taskId} not found`, severity: 'error' }],\n };\n }\n\n const issues: ValidationIssue[] = [];\n\n if (task.status === 'done') {\n issues.push({ code: 'V_ALREADY_DONE', message: 'Task is already completed', severity: 'error' });\n }\n if (task.status === 'cancelled') {\n issues.push({ code: 'V_CANCELLED', message: 'Task is cancelled', severity: 'error' });\n }\n\n if (task.depends) {\n for (const dep of task.depends) {\n const depTask = tasks.find(t => t.id === dep);\n if (!depTask) {\n issues.push({ code: 'V_MISSING_DEP', message: `Dependency ${dep} not found`, severity: 'error' });\n } else if (depTask.status !== 'done') {\n issues.push({\n code: 'V_UNMET_DEP',\n message: `Dependency ${dep} (${depTask.title}) is not complete (status: ${depTask.status})`,\n severity: 'error',\n });\n }\n }\n }\n\n if (!task.title) {\n issues.push({ code: 'V_MISSING_TITLE', message: 'Task title is missing', severity: 'error' });\n }\n if (!task.description) {\n issues.push({ code: 'V_MISSING_DESC', message: 'Task description is missing', severity: 'error' });\n }\n\n return {\n taskId,\n title: task.title,\n ready: issues.filter(i => i.severity === 'error').length === 0,\n issues,\n };\n}\n", "/**\n * Bootstrap brain state loading for agent startup.\n * Calls other core modules directly (not engine functions).\n * @task T4784\n */\n\nimport { readJson } from '../../store/json.js';\nimport { getTodoPath, getSessionsPath } from '../paths.js';\nimport type { TodoFile } from '../../types/task.js';\nimport type { DataAccessor } from '../../store/data-accessor.js';\nimport type { BrainState } from '../../types/operations/orchestrate.js';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Build brain state for agent bootstrapping. */\nexport async function buildBrainState(\n projectRoot: string,\n opts?: { speed?: 'fast' | 'full' | 'complete' },\n accessor?: DataAccessor,\n): Promise<BrainState> {\n const speed = opts?.speed || 'fast';\n const brain: BrainState = {\n _meta: {\n speed,\n generatedAt: new Date().toISOString(),\n version: '1.0.0',\n },\n };\n\n // --- Session (from sessions.json) ---\n try {\n const sessionsPath = getSessionsPath(projectRoot);\n if (existsSync(sessionsPath)) {\n const sessionsData = JSON.parse(readFileSync(sessionsPath, 'utf-8'));\n const activeSession = (sessionsData.sessions ?? []).find(\n (s: { status: string }) => s.status === 'active',\n );\n if (activeSession) {\n brain.session = {\n id: activeSession.id,\n name: activeSession.name || activeSession.id,\n status: activeSession.status,\n startedAt: activeSession.startedAt,\n };\n }\n }\n } catch {\n // skip\n }\n\n // --- Tasks & Progress ---\n const data = accessor\n ? await accessor.loadTodoFile()\n : await readJson<TodoFile>(getTodoPath(projectRoot));\n\n const tasks = data?.tasks ?? [];\n brain.progress = {\n total: tasks.length,\n done: tasks.filter(t => t.status === 'done').length,\n active: tasks.filter(t => t.status === 'active').length,\n blocked: tasks.filter(t => t.status === 'blocked').length,\n pending: tasks.filter(t => t.status === 'pending').length,\n };\n\n // --- Current Task (from focus or session) ---\n const focusTaskId = data?.focus?.currentTask ?? null;\n if (focusTaskId) {\n const task = tasks.find(t => t.id === focusTaskId);\n if (task) {\n brain.currentTask = { id: task.id, title: task.title, status: task.status };\n }\n }\n\n // --- Next Suggestion (simple: pick first pending task with all deps met) ---\n const completedIds = new Set(tasks.filter(t => t.status === 'done').map(t => t.id));\n const readyTasks = tasks.filter(t => {\n if (t.status !== 'pending') return false;\n const deps = t.depends ?? [];\n return deps.every(d => completedIds.has(d));\n });\n\n if (readyTasks.length > 0) {\n // Sort by priority\n const priorityOrder: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n readyTasks.sort((a, b) => {\n const aPri = priorityOrder[a.priority ?? 'medium'] ?? 2;\n const bPri = priorityOrder[b.priority ?? 'medium'] ?? 2;\n return aPri - bPri;\n });\n const next = readyTasks[0]!;\n brain.nextSuggestion = { id: next.id, title: next.title, score: 1 };\n }\n\n // --- Full tier: decisions, blockers, contextDrift ---\n if (speed === 'full' || speed === 'complete') {\n // Blockers\n const blockedTasks = tasks.filter(t => t.status === 'blocked' || (\n t.depends && t.depends.some(d => !completedIds.has(d))\n ));\n brain.blockers = blockedTasks.slice(0, 10).map(b => ({\n taskId: b.id,\n title: b.title,\n blockedBy: b.depends || [],\n }));\n\n // Recent decisions (from audit/decisions.jsonl in .cleo)\n try {\n const decisionLogPath = join(projectRoot, '.cleo', 'audit', 'decisions.jsonl');\n if (existsSync(decisionLogPath)) {\n const content = readFileSync(decisionLogPath, 'utf-8').trim();\n if (content) {\n const entries = content.split('\\n').filter(l => l.trim()).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n const recent = entries.slice(-5);\n brain.recentDecisions = recent.map((d: Record<string, unknown>) => ({\n id: (d.id as string) ?? '',\n decision: (d.decision as string) ?? '',\n timestamp: (d.timestamp as string) ?? '',\n }));\n }\n }\n } catch {\n // skip\n }\n\n // Context drift (from context state file)\n try {\n const contextStatePath = join(projectRoot, '.cleo', '.context-state.json');\n if (existsSync(contextStatePath)) {\n const state = JSON.parse(readFileSync(contextStatePath, 'utf-8'));\n const percentage = state.contextWindow?.percentage ?? 0;\n const factors: string[] = [];\n if (percentage > 80) factors.push('high_context_usage');\n if (percentage > 50) factors.push('moderate_context_usage');\n brain.contextDrift = { score: percentage, factors };\n }\n } catch {\n // skip\n }\n }\n\n return brain;\n}\n", "/**\n * Research Engine\n *\n * Thin wrapper over src/core/research/ for MCP engine layer.\n * Types and filter logic are defined in core; this file provides\n * synchronous EngineResult-wrapped access for MCP domain handlers.\n *\n * @task T4787\n */\n\nimport { readFileSync, writeFileSync, appendFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { resolveProjectRoot } from './store.js';\nimport { getManifestPath as getCentralManifestPath, getManifestArchivePath } from '../../core/paths.js';\nimport {\n filterManifestEntries,\n type ExtendedManifestEntry,\n type ResearchFilter,\n type ContradictionDetail,\n type SupersededDetail,\n} from '../../core/research/index.js';\n\n/**\n * Re-export types for consumers that import from engine.\n */\nexport type ManifestEntry = ExtendedManifestEntry;\nexport type { ResearchFilter, ContradictionDetail, SupersededDetail };\n\n/**\n * Engine result type\n */\ninterface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: { code: string; message: string; details?: unknown };\n}\n\n// ============================================================================\n// Internal I/O helpers (synchronous)\n// ============================================================================\n\nfunction getManifestPath(projectRoot?: string): string {\n return getCentralManifestPath(projectRoot);\n}\n\n/**\n * Read all manifest entries from MANIFEST.jsonl (synchronous).\n */\nexport function readManifestEntries(projectRoot?: string): ExtendedManifestEntry[] {\n const manifestPath = getManifestPath(projectRoot);\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n const entries: ExtendedManifestEntry[] = [];\n const lines = content.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n try {\n entries.push(JSON.parse(trimmed) as ExtendedManifestEntry);\n } catch {\n continue;\n }\n }\n\n return entries;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Filter manifest entries by criteria.\n * Delegates to core filterManifestEntries.\n */\nexport function filterEntries(entries: ExtendedManifestEntry[], filter: ResearchFilter): ExtendedManifestEntry[] {\n return filterManifestEntries(entries, filter);\n}\n\n// ============================================================================\n// Exported engine functions\n// ============================================================================\n\n/**\n * research.show - Get research entry details by ID\n * @task T4787\n */\nexport function researchShow(\n researchId: string,\n projectRoot?: string,\n): EngineResult {\n if (!researchId) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'researchId is required' } };\n }\n\n const entries = readManifestEntries(projectRoot);\n const entry = entries.find(e => e.id === researchId);\n\n if (!entry) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Research entry '${researchId}' not found`,\n },\n };\n }\n\n const root = projectRoot || resolveProjectRoot();\n let fileContent: string | null = null;\n try {\n const filePath = resolve(root, entry.file);\n if (existsSync(filePath)) {\n fileContent = readFileSync(filePath, 'utf-8');\n }\n } catch {\n // File may not exist or be unreadable\n }\n\n return {\n success: true,\n data: {\n ...entry,\n fileContent,\n fileExists: fileContent !== null,\n },\n };\n}\n\n/**\n * research.list - List research entries with filters\n * @task T4787\n */\nexport function researchList(\n params: ResearchFilter & { type?: string },\n projectRoot?: string,\n): EngineResult {\n const entries = readManifestEntries(projectRoot);\n\n const filter: ResearchFilter = { ...params };\n if (params.type) {\n filter.agent_type = params.type;\n }\n\n const filtered = filterManifestEntries(entries, filter);\n\n return {\n success: true,\n data: {\n entries: filtered,\n total: filtered.length,\n },\n };\n}\n\n/**\n * research.query / research.find - Find research entries by text\n * @task T4787\n */\nexport function researchQuery(\n query: string,\n options?: { confidence?: number; limit?: number },\n projectRoot?: string,\n): EngineResult {\n if (!query) {\n return { success: false, error: { code: 'E_INVALID_INPUT', message: 'query is required' } };\n }\n\n const entries = readManifestEntries(projectRoot);\n const queryLower = query.toLowerCase();\n\n const scored = entries.map(entry => {\n let score = 0;\n\n if (entry.title.toLowerCase().includes(queryLower)) {\n score += 0.5;\n }\n\n if (entry.topics.some(t => t.toLowerCase().includes(queryLower))) {\n score += 0.3;\n }\n\n if (entry.key_findings?.some(f => f.toLowerCase().includes(queryLower))) {\n score += 0.2;\n }\n\n if (entry.id.toLowerCase().includes(queryLower)) {\n score += 0.1;\n }\n\n return { entry, score };\n });\n\n const minConfidence = options?.confidence ?? 0.1;\n let results = scored\n .filter(s => s.score >= minConfidence)\n .sort((a, b) => b.score - a.score);\n\n if (options?.limit && options.limit > 0) {\n results = results.slice(0, options.limit);\n }\n\n return {\n success: true,\n data: {\n query,\n results: results.map(r => ({\n ...r.entry,\n relevanceScore: Math.round(r.score * 100) / 100,\n })),\n total: results.length,\n },\n };\n}\n\n/**\n * research.pending - Get pending research items\n * @task T4787\n */\nexport function researchPending(\n epicId?: string,\n projectRoot?: string,\n): EngineResult {\n const entries = readManifestEntries(projectRoot);\n\n let pending = entries.filter(\n e =>\n e.status === 'partial' ||\n e.status === 'blocked' ||\n (e.needs_followup && e.needs_followup.length > 0),\n );\n\n if (epicId) {\n pending = pending.filter(\n e => e.id.startsWith(epicId) || e.linked_tasks?.includes(epicId),\n );\n }\n\n return {\n success: true,\n data: {\n entries: pending,\n total: pending.length,\n byStatus: {\n partial: pending.filter(e => e.status === 'partial').length,\n blocked: pending.filter(e => e.status === 'blocked').length,\n needsFollowup: pending.filter(\n e => e.needs_followup && e.needs_followup.length > 0,\n ).length,\n },\n },\n };\n}\n\n/**\n * research.stats - Research statistics\n * @task T4787\n */\nexport function researchStats(\n epicId?: string,\n projectRoot?: string,\n): EngineResult {\n const entries = readManifestEntries(projectRoot);\n\n let filtered = entries;\n if (epicId) {\n filtered = entries.filter(\n e => e.id.startsWith(epicId) || e.linked_tasks?.includes(epicId),\n );\n }\n\n const byStatus: Record<string, number> = {};\n const byType: Record<string, number> = {};\n let actionable = 0;\n let needsFollowup = 0;\n let totalFindings = 0;\n\n for (const entry of filtered) {\n byStatus[entry.status] = (byStatus[entry.status] || 0) + 1;\n byType[entry.agent_type] = (byType[entry.agent_type] || 0) + 1;\n if (entry.actionable) actionable++;\n if (entry.needs_followup && entry.needs_followup.length > 0) needsFollowup++;\n if (entry.key_findings) totalFindings += entry.key_findings.length;\n }\n\n return {\n success: true,\n data: {\n total: filtered.length,\n byStatus,\n byType,\n actionable,\n needsFollowup,\n averageFindings:\n filtered.length > 0\n ? Math.round((totalFindings / filtered.length) * 10) / 10\n : 0,\n },\n };\n}\n\n/**\n * research.manifest.read - Read manifest entries with optional filter\n * @task T4787\n */\nexport function researchManifestRead(\n filter?: ResearchFilter,\n projectRoot?: string,\n): EngineResult {\n const entries = readManifestEntries(projectRoot);\n const filtered = filter ? filterManifestEntries(entries, filter) : entries;\n\n return {\n success: true,\n data: {\n entries: filtered,\n total: filtered.length,\n filter: filter || {},\n },\n };\n}\n\n/**\n * research.link - Link research entry to a task\n * @task T4787\n */\nexport function researchLink(\n taskId: string,\n researchId: string,\n notes?: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId || !researchId) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId and researchId are required' },\n };\n }\n\n const root = projectRoot || resolveProjectRoot();\n const manifestPath = getManifestPath(root);\n const entries = readManifestEntries(root);\n\n const entryIndex = entries.findIndex(e => e.id === researchId);\n if (entryIndex === -1) {\n return {\n success: false,\n error: { code: 'E_NOT_FOUND', message: `Research entry '${researchId}' not found` },\n };\n }\n\n const entry = entries[entryIndex];\n\n if (entry.linked_tasks?.includes(taskId)) {\n return {\n success: true,\n data: {\n taskId,\n researchId,\n linked: true,\n alreadyLinked: true,\n },\n };\n }\n\n if (!entry.linked_tasks) {\n entry.linked_tasks = [];\n }\n entry.linked_tasks.push(taskId);\n\n const content = entries.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n writeFileSync(manifestPath, content, 'utf-8');\n\n return {\n success: true,\n data: {\n taskId,\n researchId,\n linked: true,\n notes: notes || null,\n },\n };\n}\n\n/**\n * research.manifest.append - Append entry to MANIFEST.jsonl\n * @task T4787\n */\nexport function researchManifestAppend(\n entry: ExtendedManifestEntry,\n projectRoot?: string,\n): EngineResult {\n if (!entry) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'entry is required' },\n };\n }\n\n const errors: string[] = [];\n if (!entry.id) errors.push('id is required');\n if (!entry.file) errors.push('file is required');\n if (!entry.title) errors.push('title is required');\n if (!entry.date) errors.push('date is required');\n if (!entry.status) errors.push('status is required');\n if (!entry.agent_type) errors.push('agent_type is required');\n if (!entry.topics) errors.push('topics is required');\n if (entry.actionable === undefined) errors.push('actionable is required');\n\n if (errors.length > 0) {\n return {\n success: false,\n error: { code: 'E_VALIDATION_FAILED', message: `Invalid manifest entry: ${errors.join(', ')}` },\n };\n }\n\n const manifestPath = getManifestPath(projectRoot);\n const dir = dirname(manifestPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n const serialized = JSON.stringify(entry);\n appendFileSync(manifestPath, serialized + '\\n', 'utf-8');\n\n return {\n success: true,\n data: {\n appended: true,\n entryId: entry.id,\n file: getCentralManifestPath(),\n },\n };\n}\n\n/**\n * research.manifest.archive - Archive old manifest entries\n * @task T4787\n */\nexport function researchManifestArchive(\n beforeDate: string,\n projectRoot?: string,\n): EngineResult {\n if (!beforeDate) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'beforeDate is required (ISO-8601 format: YYYY-MM-DD)' },\n };\n }\n\n const root = projectRoot || resolveProjectRoot();\n const manifestPath = getManifestPath(root);\n const archivePath = getManifestArchivePath(root);\n const entries = readManifestEntries(root);\n\n const toArchive = entries.filter(e => e.date < beforeDate);\n const toKeep = entries.filter(e => e.date >= beforeDate);\n\n if (toArchive.length === 0) {\n return {\n success: true,\n data: {\n archived: 0,\n remaining: entries.length,\n message: 'No entries found before the specified date',\n },\n };\n }\n\n const archiveDir = dirname(archivePath);\n if (!existsSync(archiveDir)) {\n mkdirSync(archiveDir, { recursive: true });\n }\n const archiveContent = toArchive.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n appendFileSync(archivePath, archiveContent, 'utf-8');\n\n const remainingContent = toKeep.length > 0\n ? toKeep.map(e => JSON.stringify(e)).join('\\n') + '\\n'\n : '';\n writeFileSync(manifestPath, remainingContent, 'utf-8');\n\n return {\n success: true,\n data: {\n archived: toArchive.length,\n remaining: toKeep.length,\n archiveFile: getManifestArchivePath(),\n },\n };\n}\n\n/**\n * research.contradictions - Find entries with overlapping topics but conflicting key_findings\n * @task T4787\n */\nexport function researchContradictions(\n projectRoot?: string,\n params?: { topic?: string },\n): EngineResult<{ contradictions: ContradictionDetail[] }> {\n const entries = readManifestEntries(projectRoot);\n\n const byTopic = new Map<string, ExtendedManifestEntry[]>();\n for (const entry of entries) {\n if (!entry.key_findings || entry.key_findings.length === 0) continue;\n for (const topic of entry.topics) {\n if (params?.topic && topic !== params.topic) continue;\n if (!byTopic.has(topic)) {\n byTopic.set(topic, []);\n }\n byTopic.get(topic)!.push(entry);\n }\n }\n\n const contradictions: ContradictionDetail[] = [];\n\n const negationPairs: Array<[RegExp, RegExp]> = [\n [/\\bdoes NOT\\b/i, /\\bdoes\\b(?!.*\\bnot\\b)/i],\n [/\\bcannot\\b/i, /\\bcan\\b(?!.*\\bnot\\b)/i],\n [/\\bno\\s+\\w+\\s+required\\b/i, /\\brequired\\b(?!.*\\bno\\b)/i],\n [/\\bnot\\s+(?:available|supported|possible|recommended)\\b/i, /\\b(?:available|supported|possible|recommended)\\b(?!.*\\bnot\\b)/i],\n [/\\bwithout\\b/i, /\\brequires?\\b/i],\n [/\\bavoid\\b/i, /\\buse\\b/i],\n [/\\bdeprecated\\b/i, /\\brecommended\\b/i],\n [/\\banti-pattern\\b/i, /\\bbest practice\\b/i],\n ];\n\n for (const [topic, topicEntries] of byTopic) {\n if (topicEntries.length < 2) continue;\n\n for (let i = 0; i < topicEntries.length; i++) {\n for (let j = i + 1; j < topicEntries.length; j++) {\n const a = topicEntries[i];\n const b = topicEntries[j];\n const conflicts: string[] = [];\n\n for (const findingA of a.key_findings!) {\n for (const findingB of b.key_findings!) {\n for (const [patternNeg, patternPos] of negationPairs) {\n if (\n (patternNeg.test(findingA) && patternPos.test(findingB)) ||\n (patternPos.test(findingA) && patternNeg.test(findingB))\n ) {\n conflicts.push(`\"${findingA}\" vs \"${findingB}\"`);\n break;\n }\n }\n }\n }\n\n if (conflicts.length > 0) {\n contradictions.push({\n entryA: a,\n entryB: b,\n topic,\n conflictDetails: conflicts.join('; '),\n });\n }\n }\n }\n }\n\n return {\n success: true,\n data: { contradictions },\n };\n}\n\n/**\n * research.superseded - Identify research entries replaced by newer work on same topic\n * @task T4787\n */\nexport function researchSuperseded(\n projectRoot?: string,\n params?: { topic?: string },\n): EngineResult<{ superseded: SupersededDetail[] }> {\n const entries = readManifestEntries(projectRoot);\n\n const byTopicAndType = new Map<string, ExtendedManifestEntry[]>();\n for (const entry of entries) {\n for (const topic of entry.topics) {\n if (params?.topic && topic !== params.topic) continue;\n const key = `${topic}::${entry.agent_type}`;\n if (!byTopicAndType.has(key)) {\n byTopicAndType.set(key, []);\n }\n byTopicAndType.get(key)!.push(entry);\n }\n }\n\n const superseded: SupersededDetail[] = [];\n const seenPairs = new Set<string>();\n\n for (const [key, groupEntries] of byTopicAndType) {\n if (groupEntries.length < 2) continue;\n\n const topic = key.split('::')[0];\n const sorted = [...groupEntries].sort((a, b) => a.date.localeCompare(b.date));\n\n for (let i = 0; i < sorted.length - 1; i++) {\n const pairKey = `${sorted[i].id}::${sorted[sorted.length - 1].id}::${topic}`;\n if (seenPairs.has(pairKey)) continue;\n seenPairs.add(pairKey);\n\n superseded.push({\n old: sorted[i],\n replacement: sorted[sorted.length - 1],\n topic,\n });\n }\n }\n\n return {\n success: true,\n data: { superseded },\n };\n}\n\n/**\n * research.inject - Read protocol injection content for a given protocol type\n * @task T4787\n */\nexport function researchInject(\n protocolType: string,\n params?: { taskId?: string; variant?: string },\n projectRoot?: string,\n): EngineResult {\n if (!protocolType) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'protocolType is required' },\n };\n }\n\n const root = projectRoot || resolveProjectRoot();\n\n const protocolLocations = [\n resolve(root, 'protocols', `${protocolType}.md`),\n resolve(root, 'skills', '_shared', `${protocolType}.md`),\n resolve(root, 'agents', 'cleo-subagent', 'protocols', `${protocolType}.md`),\n ];\n\n let protocolContent: string | null = null;\n let protocolPath: string | null = null;\n\n for (const loc of protocolLocations) {\n if (existsSync(loc)) {\n try {\n protocolContent = readFileSync(loc, 'utf-8');\n protocolPath = loc.replace(root + '/', '');\n break;\n } catch {\n continue;\n }\n }\n }\n\n if (!protocolContent) {\n return {\n success: false,\n error: {\n code: 'E_NOT_FOUND',\n message: `Protocol '${protocolType}' not found in protocols/, skills/_shared/, or agents/cleo-subagent/protocols/`,\n },\n };\n }\n\n return {\n success: true,\n data: {\n protocolType,\n content: protocolContent,\n path: protocolPath,\n contentLength: protocolContent.length,\n estimatedTokens: Math.ceil(protocolContent.length / 4),\n taskId: params?.taskId || null,\n variant: params?.variant || null,\n },\n };\n}\n\n/**\n * research.compact - Compact MANIFEST.jsonl by removing duplicate/stale entries\n * @task T4787\n */\nexport function researchCompact(\n projectRoot?: string,\n): EngineResult {\n const manifestPath = getManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return {\n success: true,\n data: {\n compacted: false,\n message: 'No manifest file found',\n },\n };\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n const lines = content.split('\\n');\n\n const entries: ExtendedManifestEntry[] = [];\n let malformedCount = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n try {\n entries.push(JSON.parse(trimmed) as ExtendedManifestEntry);\n } catch {\n malformedCount++;\n }\n }\n\n const originalCount = entries.length + malformedCount;\n\n const idMap = new Map<string, ExtendedManifestEntry>();\n for (const entry of entries) {\n idMap.set(entry.id, entry);\n }\n\n const compacted = Array.from(idMap.values());\n const duplicatesRemoved = entries.length - compacted.length;\n\n const compactedContent = compacted.length > 0\n ? compacted.map(e => JSON.stringify(e)).join('\\n') + '\\n'\n : '';\n writeFileSync(manifestPath, compactedContent, 'utf-8');\n\n return {\n success: true,\n data: {\n compacted: true,\n originalLines: originalCount,\n malformedRemoved: malformedCount,\n duplicatesRemoved,\n remainingEntries: compacted.length,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'E_COMPACT_FAILED',\n message: error instanceof Error ? error.message : String(error),\n },\n };\n }\n}\n\n/**\n * research.validate - Validate research entries for a task\n * @task T4787\n */\nexport function researchValidate(\n taskId: string,\n projectRoot?: string,\n): EngineResult {\n if (!taskId) {\n return {\n success: false,\n error: { code: 'E_INVALID_INPUT', message: 'taskId is required' },\n };\n }\n\n const root = projectRoot || resolveProjectRoot();\n const entries = readManifestEntries(root);\n\n const linked = entries.filter(\n e => e.id.startsWith(taskId) || e.linked_tasks?.includes(taskId),\n );\n\n if (linked.length === 0) {\n return {\n success: true,\n data: {\n taskId,\n valid: true,\n entriesFound: 0,\n message: `No research entries found for task ${taskId}`,\n issues: [],\n },\n };\n }\n\n const issues: Array<{ entryId: string; issue: string; severity: 'error' | 'warning' }> = [];\n\n for (const entry of linked) {\n if (!entry.id) issues.push({ entryId: entry.id || '(unknown)', issue: 'Missing id', severity: 'error' });\n if (!entry.file) issues.push({ entryId: entry.id, issue: 'Missing file path', severity: 'error' });\n if (!entry.title) issues.push({ entryId: entry.id, issue: 'Missing title', severity: 'error' });\n if (!entry.date) issues.push({ entryId: entry.id, issue: 'Missing date', severity: 'error' });\n if (!entry.status) issues.push({ entryId: entry.id, issue: 'Missing status', severity: 'error' });\n if (!entry.agent_type) issues.push({ entryId: entry.id, issue: 'Missing agent_type', severity: 'error' });\n\n if (entry.status && !['complete', 'partial', 'blocked'].includes(entry.status)) {\n issues.push({ entryId: entry.id, issue: `Invalid status: ${entry.status}`, severity: 'error' });\n }\n\n if (entry.file) {\n const filePath = resolve(root, entry.file);\n if (!existsSync(filePath)) {\n issues.push({ entryId: entry.id, issue: `Output file not found: ${entry.file}`, severity: 'warning' });\n }\n }\n\n if (entry.agent_type === 'research' && (!entry.key_findings || entry.key_findings.length === 0)) {\n issues.push({ entryId: entry.id, issue: 'Research entry missing key_findings', severity: 'warning' });\n }\n }\n\n return {\n success: true,\n data: {\n taskId,\n valid: issues.filter(i => i.severity === 'error').length === 0,\n entriesFound: linked.length,\n issues,\n errorCount: issues.filter(i => i.severity === 'error').length,\n warningCount: issues.filter(i => i.severity === 'warning').length,\n },\n };\n}\n", "/**\n * Research commands and manifest operations.\n * @task T4465\n * @epic T4454\n */\n\nimport { readJsonRequired, saveJson, appendJsonl, readJson } from '../../store/json.js';\nimport { safeReadFile, atomicWrite } from '../../store/atomic.js';\nimport { CleoError } from '../errors.js';\nimport { ExitCode } from '../../types/exit-codes.js';\nimport type { TaskFile } from '../../types/task.js';\nimport { getTaskPath, getBackupDir, getLogPath, getCleoDirAbsolute, getManifestPath as getCentralManifestPath, getManifestArchivePath, getProjectRoot } from '../paths.js';\nimport { logOperation } from '../tasks/add.js';\nimport { join, resolve } from 'node:path';\nimport { existsSync, readFileSync } from 'node:fs';\nimport type { DataAccessor } from '../../store/data-accessor.js';\n\n/** Research entry attached to a task. */\nexport interface ResearchEntry {\n id: string;\n taskId: string;\n topic: string;\n findings: string[];\n sources: string[];\n status: 'pending' | 'complete' | 'partial';\n createdAt: string;\n updatedAt: string;\n}\n\n/** Manifest entry (JSONL line). */\nexport interface ManifestEntry {\n id: string;\n file: string;\n title: string;\n date: string;\n status: 'complete' | 'partial' | 'blocked';\n agent_type: string;\n topics: string[];\n key_findings: string[];\n actionable: boolean;\n needs_followup: string[];\n linked_tasks: string[];\n}\n\n/** Options for adding research. */\nexport interface AddResearchOptions {\n taskId: string;\n topic: string;\n findings?: string[];\n sources?: string[];\n}\n\n/** Options for listing research. */\nexport interface ListResearchOptions {\n taskId?: string;\n status?: 'pending' | 'complete' | 'partial';\n}\n\n/** Manifest query options. */\nexport interface ManifestQueryOptions {\n status?: string;\n agentType?: string;\n topic?: string;\n taskId?: string;\n limit?: number;\n}\n\n/**\n * Get the research file path.\n * @task T4465\n */\nfunction getResearchPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'research.json');\n}\n\n/**\n * Get the manifest file path.\n * @task T4465\n */\nfunction getManifestPath(cwd?: string): string {\n return getCentralManifestPath(cwd);\n}\n\n/**\n * Read or initialize the research file.\n * @task T4465\n */\nasync function readResearch(cwd?: string): Promise<{ entries: ResearchEntry[] }> {\n const path = getResearchPath(cwd);\n const data = await readJson<{ entries: ResearchEntry[] }>(path);\n return data ?? { entries: [] };\n}\n\n/**\n * Add a research entry.\n * @task T4465\n */\nexport async function addResearch(options: AddResearchOptions, cwd?: string, accessor?: DataAccessor): Promise<ResearchEntry> {\n const data = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(getTaskPath(cwd));\n\n // Validate task exists\n const task = data.tasks.find(t => t.id === options.taskId);\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${options.taskId}`);\n }\n\n if (!options.topic || options.topic.trim().length === 0) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Research topic is required');\n }\n\n const research = await readResearch(cwd);\n const now = new Date().toISOString();\n\n const entry: ResearchEntry = {\n id: `R${Date.now().toString(36)}`,\n taskId: options.taskId,\n topic: options.topic.trim(),\n findings: options.findings ?? [],\n sources: options.sources ?? [],\n status: (options.findings?.length ?? 0) > 0 ? 'complete' : 'pending',\n createdAt: now,\n updatedAt: now,\n };\n\n research.entries.push(entry);\n\n await saveJson(getResearchPath(cwd), research, { backupDir: getBackupDir(cwd) });\n await logOperation(getLogPath(cwd), 'research_added', entry.id, {\n taskId: options.taskId,\n topic: options.topic,\n }, accessor);\n\n return entry;\n}\n\n/**\n * Show a specific research entry.\n * @task T4465\n */\nexport async function showResearch(researchId: string, cwd?: string): Promise<ResearchEntry> {\n const research = await readResearch(cwd);\n const entry = research.entries.find(e => e.id === researchId);\n\n if (!entry) {\n throw new CleoError(ExitCode.NOT_FOUND, `Research entry not found: ${researchId}`);\n }\n\n return entry;\n}\n\n/**\n * List research entries with optional filtering.\n * @task T4465\n */\nexport async function listResearch(options: ListResearchOptions = {}, cwd?: string): Promise<ResearchEntry[]> {\n const research = await readResearch(cwd);\n let entries = research.entries;\n\n if (options.taskId) {\n entries = entries.filter(e => e.taskId === options.taskId);\n }\n if (options.status) {\n entries = entries.filter(e => e.status === options.status);\n }\n\n return entries;\n}\n\n/**\n * List pending research entries.\n * @task T4465\n */\nexport async function pendingResearch(cwd?: string): Promise<ResearchEntry[]> {\n return listResearch({ status: 'pending' }, cwd);\n}\n\n/**\n * Link a research entry to a task.\n * @task T4465\n */\nexport async function linkResearch(\n researchId: string,\n taskId: string,\n cwd?: string,\n accessor?: DataAccessor,\n): Promise<{ researchId: string; taskId: string }> {\n const research = await readResearch(cwd);\n const entry = research.entries.find(e => e.id === researchId);\n\n if (!entry) {\n throw new CleoError(ExitCode.NOT_FOUND, `Research entry not found: ${researchId}`);\n }\n\n // Validate task exists\n const todoData = accessor\n ? await accessor.loadTaskFile()\n : await readJsonRequired<TaskFile>(getTaskPath(cwd));\n const task = todoData.tasks.find(t => t.id === taskId);\n if (!task) {\n throw new CleoError(ExitCode.NOT_FOUND, `Task not found: ${taskId}`);\n }\n\n entry.taskId = taskId;\n entry.updatedAt = new Date().toISOString();\n\n await saveJson(getResearchPath(cwd), research, { backupDir: getBackupDir(cwd) });\n\n return { researchId, taskId };\n}\n\n/**\n * Update research findings.\n * @task T4465\n */\nexport async function updateResearch(\n researchId: string,\n updates: { findings?: string[]; sources?: string[]; status?: 'pending' | 'complete' | 'partial' },\n cwd?: string,\n): Promise<ResearchEntry> {\n const research = await readResearch(cwd);\n const entry = research.entries.find(e => e.id === researchId);\n\n if (!entry) {\n throw new CleoError(ExitCode.NOT_FOUND, `Research entry not found: ${researchId}`);\n }\n\n if (updates.findings) entry.findings = updates.findings;\n if (updates.sources) entry.sources = updates.sources;\n if (updates.status) entry.status = updates.status;\n entry.updatedAt = new Date().toISOString();\n\n await saveJson(getResearchPath(cwd), research, { backupDir: getBackupDir(cwd) });\n\n return entry;\n}\n\n/**\n * Get research statistics.\n * @task T4474\n */\nexport async function statsResearch(cwd?: string): Promise<{\n total: number;\n byStatus: Record<string, number>;\n byTopic: Record<string, number>;\n}> {\n const research = await readResearch(cwd);\n const byStatus: Record<string, number> = {};\n const byTopic: Record<string, number> = {};\n\n for (const entry of research.entries) {\n byStatus[entry.status] = (byStatus[entry.status] || 0) + 1;\n byTopic[entry.topic] = (byTopic[entry.topic] || 0) + 1;\n }\n\n return {\n total: research.entries.length,\n byStatus,\n byTopic,\n };\n}\n\n/**\n * Get research entries linked to a specific task.\n * @task T4474\n */\nexport async function linksResearch(taskId: string, cwd?: string): Promise<ResearchEntry[]> {\n if (!taskId) {\n throw new CleoError(ExitCode.INVALID_INPUT, 'Task ID is required');\n }\n const research = await readResearch(cwd);\n return research.entries.filter(e => e.taskId === taskId);\n}\n\n/**\n * Archive old research entries by status.\n * Moves 'complete' entries older than a threshold to an archive,\n * or returns summary of archivable entries.\n * @task T4474\n */\nexport async function archiveResearch(cwd?: string): Promise<{\n action: string;\n entriesArchived: number;\n entriesRemaining: number;\n}> {\n const research = await readResearch(cwd);\n const completed = research.entries.filter(e => e.status === 'complete');\n const remaining = research.entries.filter(e => e.status !== 'complete');\n\n // Write back only non-complete entries\n await saveJson(getResearchPath(cwd), { entries: remaining }, { backupDir: getBackupDir(cwd) });\n\n return {\n action: 'archive',\n entriesArchived: completed.length,\n entriesRemaining: remaining.length,\n };\n}\n\n// === MANIFEST OPERATIONS ===\n\n/**\n * Read manifest entries from MANIFEST.jsonl.\n * @task T4465\n */\nexport async function readManifest(cwd?: string): Promise<ManifestEntry[]> {\n const manifestPath = getManifestPath(cwd);\n const content = await safeReadFile(manifestPath);\n if (!content) return [];\n\n const entries: ManifestEntry[] = [];\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n entries.push(JSON.parse(trimmed) as ManifestEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n}\n\n/**\n * Append a manifest entry.\n * @task T4465\n */\nexport async function appendManifest(entry: ManifestEntry, cwd?: string): Promise<void> {\n const manifestPath = getManifestPath(cwd);\n await appendJsonl(manifestPath, entry);\n}\n\n/**\n * Query manifest entries.\n * @task T4465\n */\nexport async function queryManifest(\n options: ManifestQueryOptions = {},\n cwd?: string,\n): Promise<ManifestEntry[]> {\n let entries = await readManifest(cwd);\n\n if (options.status) {\n entries = entries.filter(e => e.status === options.status);\n }\n if (options.agentType) {\n entries = entries.filter(e => e.agent_type === options.agentType);\n }\n if (options.topic) {\n entries = entries.filter(e => e.topics.includes(options.topic!));\n }\n if (options.taskId) {\n entries = entries.filter(e => e.linked_tasks.includes(options.taskId!));\n }\n if (options.limit && options.limit > 0) {\n entries = entries.slice(0, options.limit);\n }\n\n return entries;\n}\n\n// ============================================================================\n// Engine-compatible manifest operations (extended fields)\n// These are used by the MCP engine layer for research domain support.\n// ============================================================================\n\n/** Extended manifest entry with optional fields used by the engine. */\nexport interface ExtendedManifestEntry extends ManifestEntry {\n confidence?: number;\n file_checksum?: string;\n duration_seconds?: number;\n}\n\n/** Research filter criteria used by the engine. */\nexport interface ResearchFilter {\n taskId?: string;\n status?: string;\n agent_type?: string;\n topic?: string;\n limit?: number;\n actionable?: boolean;\n dateAfter?: string;\n dateBefore?: string;\n}\n\n/**\n * Read all manifest entries as extended entries.\n * @task T4787\n */\nexport async function readExtendedManifest(cwd?: string): Promise<ExtendedManifestEntry[]> {\n const manifestPath = getManifestPath(cwd);\n const content = await safeReadFile(manifestPath);\n if (!content) return [];\n\n const entries: ExtendedManifestEntry[] = [];\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n entries.push(JSON.parse(trimmed) as ExtendedManifestEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n}\n\n/**\n * Filter manifest entries by criteria.\n * @task T4787\n */\nexport function filterManifestEntries(entries: ExtendedManifestEntry[], filter: ResearchFilter): ExtendedManifestEntry[] {\n let filtered = entries;\n\n if (filter.taskId) {\n const taskId = filter.taskId;\n filtered = filtered.filter(\n e => e.id.startsWith(taskId) || e.linked_tasks?.includes(taskId),\n );\n }\n\n if (filter.status) {\n filtered = filtered.filter(e => e.status === filter.status);\n }\n\n if (filter.agent_type) {\n filtered = filtered.filter(e => e.agent_type === filter.agent_type);\n }\n\n if (filter.topic) {\n filtered = filtered.filter(e => e.topics.includes(filter.topic!));\n }\n\n if (filter.actionable !== undefined) {\n filtered = filtered.filter(e => e.actionable === filter.actionable);\n }\n\n if (filter.dateAfter) {\n filtered = filtered.filter(e => e.date > filter.dateAfter!);\n }\n\n if (filter.dateBefore) {\n filtered = filtered.filter(e => e.date < filter.dateBefore!);\n }\n\n if (filter.limit && filter.limit > 0) {\n filtered = filtered.slice(0, filter.limit);\n }\n\n return filtered;\n}\n\n/**\n * Show a manifest entry by ID with optional file content.\n * @task T4787\n */\nexport async function showManifestEntry(\n researchId: string,\n cwd?: string,\n): Promise<ExtendedManifestEntry & { fileContent: string | null; fileExists: boolean }> {\n const entries = await readExtendedManifest(cwd);\n const entry = entries.find(e => e.id === researchId);\n\n if (!entry) {\n throw new CleoError(ExitCode.NOT_FOUND, `Research entry '${researchId}' not found`);\n }\n\n const root = getProjectRoot(cwd);\n let fileContent: string | null = null;\n try {\n const filePath = resolve(root, entry.file);\n if (existsSync(filePath)) {\n fileContent = readFileSync(filePath, 'utf-8');\n }\n } catch {\n // File may not exist or be unreadable\n }\n\n return {\n ...entry,\n fileContent,\n fileExists: fileContent !== null,\n };\n}\n\n/**\n * Search manifest entries by text with relevance scoring.\n * @task T4787\n */\nexport async function searchManifest(\n query: string,\n options?: { confidence?: number; limit?: number },\n cwd?: string,\n): Promise<Array<ExtendedManifestEntry & { relevanceScore: number }>> {\n const entries = await readExtendedManifest(cwd);\n const queryLower = query.toLowerCase();\n\n const scored = entries.map(entry => {\n let score = 0;\n\n if (entry.title.toLowerCase().includes(queryLower)) {\n score += 0.5;\n }\n\n if (entry.topics.some(t => t.toLowerCase().includes(queryLower))) {\n score += 0.3;\n }\n\n if (entry.key_findings?.some(f => f.toLowerCase().includes(queryLower))) {\n score += 0.2;\n }\n\n if (entry.id.toLowerCase().includes(queryLower)) {\n score += 0.1;\n }\n\n return { entry, score };\n });\n\n const minConfidence = options?.confidence ?? 0.1;\n let results = scored\n .filter(s => s.score >= minConfidence)\n .sort((a, b) => b.score - a.score);\n\n if (options?.limit && options.limit > 0) {\n results = results.slice(0, options.limit);\n }\n\n return results.map(r => ({\n ...r.entry,\n relevanceScore: Math.round(r.score * 100) / 100,\n }));\n}\n\n/**\n * Get pending manifest entries (partial, blocked, or needing followup).\n * @task T4787\n */\nexport async function pendingManifestEntries(\n epicId?: string,\n cwd?: string,\n): Promise<{\n entries: ExtendedManifestEntry[];\n total: number;\n byStatus: { partial: number; blocked: number; needsFollowup: number };\n}> {\n const entries = await readExtendedManifest(cwd);\n\n let pending = entries.filter(\n e =>\n e.status === 'partial' ||\n e.status === 'blocked' ||\n (e.needs_followup && e.needs_followup.length > 0),\n );\n\n if (epicId) {\n pending = pending.filter(\n e => e.id.startsWith(epicId) || e.linked_tasks?.includes(epicId),\n );\n }\n\n return {\n entries: pending,\n total: pending.length,\n byStatus: {\n partial: pending.filter(e => e.status === 'partial').length,\n blocked: pending.filter(e => e.status === 'blocked').length,\n needsFollowup: pending.filter(\n e => e.needs_followup && e.needs_followup.length > 0,\n ).length,\n },\n };\n}\n\n/**\n * Get manifest-based research statistics.\n * @task T4787\n */\nexport async function manifestStats(\n epicId?: string,\n cwd?: string,\n): Promise<{\n total: number;\n byStatus: Record<string, number>;\n byType: Record<string, number>;\n actionable: number;\n needsFollowup: number;\n averageFindings: number;\n}> {\n const entries = await readExtendedManifest(cwd);\n\n let filtered = entries;\n if (epicId) {\n filtered = entries.filter(\n e => e.id.startsWith(epicId) || e.linked_tasks?.includes(epicId),\n );\n }\n\n const byStatus: Record<string, number> = {};\n const byType: Record<string, number> = {};\n let actionable = 0;\n let needsFollowup = 0;\n let totalFindings = 0;\n\n for (const entry of filtered) {\n byStatus[entry.status] = (byStatus[entry.status] || 0) + 1;\n byType[entry.agent_type] = (byType[entry.agent_type] || 0) + 1;\n if (entry.actionable) actionable++;\n if (entry.needs_followup && entry.needs_followup.length > 0) needsFollowup++;\n if (entry.key_findings) totalFindings += entry.key_findings.length;\n }\n\n return {\n total: filtered.length,\n byStatus,\n byType,\n actionable,\n needsFollowup,\n averageFindings:\n filtered.length > 0\n ? Math.round((totalFindings / filtered.length) * 10) / 10\n : 0,\n };\n}\n\n/**\n * Link a manifest entry to a task (adds taskId to linked_tasks array).\n * @task T4787\n */\nexport async function linkManifestEntry(\n taskId: string,\n researchId: string,\n cwd?: string,\n): Promise<{ taskId: string; researchId: string; alreadyLinked: boolean }> {\n const manifestPath = getManifestPath(cwd);\n const entries = await readExtendedManifest(cwd);\n\n const entryIndex = entries.findIndex(e => e.id === researchId);\n if (entryIndex === -1) {\n throw new CleoError(ExitCode.NOT_FOUND, `Research entry '${researchId}' not found`);\n }\n\n const entry = entries[entryIndex];\n\n if (entry.linked_tasks?.includes(taskId)) {\n return { taskId, researchId, alreadyLinked: true };\n }\n\n if (!entry.linked_tasks) {\n entry.linked_tasks = [];\n }\n entry.linked_tasks.push(taskId);\n\n const content = entries.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n await atomicWrite(manifestPath, content);\n\n return { taskId, researchId, alreadyLinked: false };\n}\n\n/**\n * Append an extended manifest entry.\n * Validates required fields before appending.\n * @task T4787\n */\nexport async function appendExtendedManifest(\n entry: ExtendedManifestEntry,\n cwd?: string,\n): Promise<{ entryId: string; file: string }> {\n const errors: string[] = [];\n if (!entry.id) errors.push('id is required');\n if (!entry.file) errors.push('file is required');\n if (!entry.title) errors.push('title is required');\n if (!entry.date) errors.push('date is required');\n if (!entry.status) errors.push('status is required');\n if (!entry.agent_type) errors.push('agent_type is required');\n if (!entry.topics) errors.push('topics is required');\n if (entry.actionable === undefined) errors.push('actionable is required');\n\n if (errors.length > 0) {\n throw new CleoError(\n ExitCode.VALIDATION_ERROR,\n `Invalid manifest entry: ${errors.join(', ')}`,\n );\n }\n\n const manifestPath = getManifestPath(cwd);\n await appendJsonl(manifestPath, entry);\n\n return { entryId: entry.id, file: getManifestPath() };\n}\n\n/**\n * Archive manifest entries older than a date.\n * @task T4787\n */\nexport async function archiveManifestEntries(\n beforeDate: string,\n cwd?: string,\n): Promise<{ archived: number; remaining: number; archiveFile: string }> {\n const manifestPath = getManifestPath(cwd);\n const archivePath = getManifestArchivePath(cwd);\n const entries = await readExtendedManifest(cwd);\n\n const toArchive = entries.filter(e => e.date < beforeDate);\n const toKeep = entries.filter(e => e.date >= beforeDate);\n\n if (toArchive.length === 0) {\n return {\n archived: 0,\n remaining: entries.length,\n archiveFile: getManifestArchivePath(),\n };\n }\n\n // Append archived entries to archive file\n const existingArchive = await safeReadFile(archivePath);\n const archiveContent = toArchive.map(e => JSON.stringify(e)).join('\\n') + '\\n';\n const fullArchive = existingArchive\n ? existingArchive.trimEnd() + '\\n' + archiveContent\n : archiveContent;\n await atomicWrite(archivePath, fullArchive);\n\n // Rewrite main manifest with remaining entries\n const remainingContent = toKeep.length > 0\n ? toKeep.map(e => JSON.stringify(e)).join('\\n') + '\\n'\n : '';\n await atomicWrite(manifestPath, remainingContent);\n\n return {\n archived: toArchive.length,\n remaining: toKeep.length,\n archiveFile: getManifestArchivePath(),\n };\n}\n\n/** Contradiction detail between two manifest entries. */\nexport interface ContradictionDetail {\n entryA: ExtendedManifestEntry;\n entryB: ExtendedManifestEntry;\n topic: string;\n conflictDetails: string;\n}\n\n/**\n * Find manifest entries with overlapping topics but conflicting key_findings.\n * @task T4787\n */\nexport async function findContradictions(\n cwd?: string,\n params?: { topic?: string },\n): Promise<ContradictionDetail[]> {\n const entries = await readExtendedManifest(cwd);\n\n const byTopic = new Map<string, ExtendedManifestEntry[]>();\n for (const entry of entries) {\n if (!entry.key_findings || entry.key_findings.length === 0) continue;\n for (const topic of entry.topics) {\n if (params?.topic && topic !== params.topic) continue;\n if (!byTopic.has(topic)) {\n byTopic.set(topic, []);\n }\n byTopic.get(topic)!.push(entry);\n }\n }\n\n const contradictions: ContradictionDetail[] = [];\n\n const negationPairs: Array<[RegExp, RegExp]> = [\n [/\\bdoes NOT\\b/i, /\\bdoes\\b(?!.*\\bnot\\b)/i],\n [/\\bcannot\\b/i, /\\bcan\\b(?!.*\\bnot\\b)/i],\n [/\\bno\\s+\\w+\\s+required\\b/i, /\\brequired\\b(?!.*\\bno\\b)/i],\n [/\\bnot\\s+(?:available|supported|possible|recommended)\\b/i, /\\b(?:available|supported|possible|recommended)\\b(?!.*\\bnot\\b)/i],\n [/\\bwithout\\b/i, /\\brequires?\\b/i],\n [/\\bavoid\\b/i, /\\buse\\b/i],\n [/\\bdeprecated\\b/i, /\\brecommended\\b/i],\n [/\\banti-pattern\\b/i, /\\bbest practice\\b/i],\n ];\n\n for (const [topic, topicEntries] of byTopic) {\n if (topicEntries.length < 2) continue;\n\n for (let i = 0; i < topicEntries.length; i++) {\n for (let j = i + 1; j < topicEntries.length; j++) {\n const a = topicEntries[i];\n const b = topicEntries[j];\n const conflicts: string[] = [];\n\n for (const findingA of a.key_findings!) {\n for (const findingB of b.key_findings!) {\n for (const [patternNeg, patternPos] of negationPairs) {\n if (\n (patternNeg.test(findingA) && patternPos.test(findingB)) ||\n (patternPos.test(findingA) && patternNeg.test(findingB))\n ) {\n conflicts.push(`\"${findingA}\" vs \"${findingB}\"`);\n break;\n }\n }\n }\n }\n\n if (conflicts.length > 0) {\n contradictions.push({\n entryA: a,\n entryB: b,\n topic,\n conflictDetails: conflicts.join('; '),\n });\n }\n }\n }\n }\n\n return contradictions;\n}\n\n/** Superseded entry detail. */\nexport interface SupersededDetail {\n old: ExtendedManifestEntry;\n replacement: ExtendedManifestEntry;\n topic: string;\n}\n\n/**\n * Identify research entries replaced by newer work on same topic.\n * @task T4787\n */\nexport async function findSuperseded(\n cwd?: string,\n params?: { topic?: string },\n): Promise<SupersededDetail[]> {\n const entries = await readExtendedManifest(cwd);\n\n const byTopicAndType = new Map<string, ExtendedManifestEntry[]>();\n for (const entry of entries) {\n for (const topic of entry.topics) {\n if (params?.topic && topic !== params.topic) continue;\n const key = `${topic}::${entry.agent_type}`;\n if (!byTopicAndType.has(key)) {\n byTopicAndType.set(key, []);\n }\n byTopicAndType.get(key)!.push(entry);\n }\n }\n\n const superseded: SupersededDetail[] = [];\n const seenPairs = new Set<string>();\n\n for (const [key, groupEntries] of byTopicAndType) {\n if (groupEntries.length < 2) continue;\n\n const topic = key.split('::')[0];\n const sorted = [...groupEntries].sort((a, b) => a.date.localeCompare(b.date));\n\n for (let i = 0; i < sorted.length - 1; i++) {\n const pairKey = `${sorted[i].id}::${sorted[sorted.length - 1].id}::${topic}`;\n if (seenPairs.has(pairKey)) continue;\n seenPairs.add(pairKey);\n\n superseded.push({\n old: sorted[i],\n replacement: sorted[sorted.length - 1],\n topic,\n });\n }\n }\n\n return superseded;\n}\n\n/**\n * Read protocol injection content for a given protocol type.\n * @task T4787\n */\nexport async function readProtocolInjection(\n protocolType: string,\n params?: { taskId?: string; variant?: string },\n cwd?: string,\n): Promise<{\n protocolType: string;\n content: string;\n path: string;\n contentLength: number;\n estimatedTokens: number;\n taskId: string | null;\n variant: string | null;\n}> {\n const root = getProjectRoot(cwd);\n\n const protocolLocations = [\n resolve(root, 'protocols', `${protocolType}.md`),\n resolve(root, 'skills', '_shared', `${protocolType}.md`),\n resolve(root, 'agents', 'cleo-subagent', 'protocols', `${protocolType}.md`),\n ];\n\n let protocolContent: string | null = null;\n let protocolPath: string | null = null;\n\n for (const loc of protocolLocations) {\n if (existsSync(loc)) {\n try {\n protocolContent = readFileSync(loc, 'utf-8');\n protocolPath = loc.replace(root + '/', '');\n break;\n } catch {\n continue;\n }\n }\n }\n\n if (!protocolContent || !protocolPath) {\n throw new CleoError(\n ExitCode.NOT_FOUND,\n `Protocol '${protocolType}' not found in protocols/, skills/_shared/, or agents/cleo-subagent/protocols/`,\n );\n }\n\n return {\n protocolType,\n content: protocolContent,\n path: protocolPath,\n contentLength: protocolContent.length,\n estimatedTokens: Math.ceil(protocolContent.length / 4),\n taskId: params?.taskId || null,\n variant: params?.variant || null,\n };\n}\n\n/**\n * Compact MANIFEST.jsonl by removing duplicate/stale entries.\n * @task T4787\n */\nexport async function compactManifest(cwd?: string): Promise<{\n compacted: boolean;\n originalLines: number;\n malformedRemoved: number;\n duplicatesRemoved: number;\n remainingEntries: number;\n}> {\n const manifestPath = getManifestPath(cwd);\n const content = await safeReadFile(manifestPath);\n\n if (!content) {\n return {\n compacted: false,\n originalLines: 0,\n malformedRemoved: 0,\n duplicatesRemoved: 0,\n remainingEntries: 0,\n };\n }\n\n const lines = content.split('\\n');\n const entries: ExtendedManifestEntry[] = [];\n let malformedCount = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n entries.push(JSON.parse(trimmed) as ExtendedManifestEntry);\n } catch {\n malformedCount++;\n }\n }\n\n const originalCount = entries.length + malformedCount;\n\n const idMap = new Map<string, ExtendedManifestEntry>();\n for (const entry of entries) {\n idMap.set(entry.id, entry);\n }\n\n const compacted = Array.from(idMap.values());\n const duplicatesRemoved = entries.length - compacted.length;\n\n const compactedContent = compacted.length > 0\n ? compacted.map(e => JSON.stringify(e)).join('\\n') + '\\n'\n : '';\n await atomicWrite(manifestPath, compactedContent);\n\n return {\n compacted: true,\n originalLines: originalCount,\n malformedRemoved: malformedCount,\n duplicatesRemoved,\n remainingEntries: compacted.length,\n };\n}\n\n/**\n * Validate research entries for a task.\n * @task T4787\n */\nexport async function validateManifestEntries(\n taskId: string,\n cwd?: string,\n): Promise<{\n taskId: string;\n valid: boolean;\n entriesFound: number;\n issues: Array<{ entryId: string; issue: string; severity: 'error' | 'warning' }>;\n errorCount: number;\n warningCount: number;\n}> {\n const root = getProjectRoot(cwd);\n const entries = await readExtendedManifest(cwd);\n\n const linked = entries.filter(\n e => e.id.startsWith(taskId) || e.linked_tasks?.includes(taskId),\n );\n\n if (linked.length === 0) {\n return {\n taskId,\n valid: true,\n entriesFound: 0,\n issues: [],\n errorCount: 0,\n warningCount: 0,\n };\n }\n\n const issues: Array<{ entryId: string; issue: string; severity: 'error' | 'warning' }> = [];\n\n for (const entry of linked) {\n if (!entry.id) issues.push({ entryId: entry.id || '(unknown)', issue: 'Missing id', severity: 'error' });\n if (!entry.file) issues.push({ entryId: entry.id, issue: 'Missing file path', severity: 'error' });\n if (!entry.title) issues.push({ entryId: entry.id, issue: 'Missing title', severity: 'error' });\n if (!entry.date) issues.push({ entryId: entry.id, issue: 'Missing date', severity: 'error' });\n if (!entry.status) issues.push({ entryId: entry.id, issue: 'Missing status', severity: 'error' });\n if (!entry.agent_type) issues.push({ entryId: entry.id, issue: 'Missing agent_type', severity: 'error' });\n\n if (entry.status && !['complete', 'partial', 'blocked'].includes(entry.status)) {\n issues.push({ entryId: entry.id, issue: `Invalid status: ${entry.status}`, severity: 'error' });\n }\n\n if (entry.file) {\n const filePath = resolve(root, entry.file);\n if (!existsSync(filePath)) {\n issues.push({ entryId: entry.id, issue: `Output file not found: ${entry.file}`, severity: 'warning' });\n }\n }\n\n if (entry.agent_type === 'research' && (!entry.key_findings || entry.key_findings.length === 0)) {\n issues.push({ entryId: entry.id, issue: 'Research entry missing key_findings', severity: 'warning' });\n }\n }\n\n return {\n taskId,\n valid: issues.filter(i => i.severity === 'error').length === 0,\n entriesFound: linked.length,\n issues,\n errorCount: issues.filter(i => i.severity === 'error').length,\n warningCount: issues.filter(i => i.severity === 'warning').length,\n };\n}\n", "/**\n * Release manifest operations for the releases.json data model.\n *\n * These functions manage the separate .cleo/releases.json file used by\n * the MCP release domain. This is distinct from the todo.json-based\n * release tracking in index.ts.\n *\n * @task T4788\n */\n\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { execFileSync } from 'node:child_process';\nimport { dirname, join } from 'node:path';\nimport { readJson, saveJson } from '../../store/json.js';\nimport { getCleoDirAbsolute, getProjectRoot } from '../paths.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Release manifest structure. */\nexport interface ReleaseManifest {\n version: string;\n status: 'draft' | 'prepared' | 'committed' | 'tagged' | 'pushed' | 'rolled_back';\n createdAt: string;\n preparedAt?: string;\n committedAt?: string;\n taggedAt?: string;\n pushedAt?: string;\n tasks: string[];\n notes?: string;\n changelog?: string;\n previousVersion?: string;\n}\n\n/** Release index structure stored in .cleo/releases.json. */\nexport interface ReleasesIndex {\n releases: ReleaseManifest[];\n latest?: string;\n}\n\n/** Task record shape needed for release operations. */\nexport interface ReleaseTaskRecord {\n id: string;\n title: string;\n status: string;\n parentId?: string;\n completedAt?: string | null;\n labels?: string[];\n}\n\n// \u2500\u2500 Internal helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction getReleasesPath(cwd?: string): string {\n return join(getCleoDirAbsolute(cwd), 'releases.json');\n}\n\nasync function readReleases(cwd?: string): Promise<ReleasesIndex> {\n const data = await readJson<ReleasesIndex>(getReleasesPath(cwd));\n return data ?? { releases: [] };\n}\n\nasync function writeReleases(index: ReleasesIndex, cwd?: string): Promise<void> {\n const releasesPath = getReleasesPath(cwd);\n const dir = dirname(releasesPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n await saveJson(releasesPath, index);\n}\n\nfunction isValidVersion(version: string): boolean {\n return /^v?\\d+\\.\\d+\\.\\d+(-[\\w.]+)?(\\+[\\w.]+)?$/.test(version);\n}\n\nfunction normalizeVersion(version: string): string {\n return version.startsWith('v') ? version : `v${version}`;\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Prepare a release (create a release manifest entry).\n * @task T4788\n */\nexport async function prepareRelease(\n version: string,\n tasks: string[] | undefined,\n notes: string | undefined,\n loadTasksFn: () => Promise<ReleaseTaskRecord[]>,\n cwd?: string,\n): Promise<{\n version: string;\n status: string;\n tasks: string[];\n taskCount: number;\n}> {\n if (!version) {\n throw new Error('version is required');\n }\n if (!isValidVersion(version)) {\n throw new Error(`Invalid version format: ${version} (expected X.Y.Z or YYYY.M.patch)`);\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n\n const existing = index.releases.find((r) => r.version === normalizedVersion);\n if (existing) {\n throw new Error(`Release ${normalizedVersion} already exists (status: ${existing.status})`);\n }\n\n let releaseTasks = tasks ?? [];\n if (releaseTasks.length === 0) {\n const allTasks = await loadTasksFn();\n releaseTasks = allTasks\n .filter((t) => t.status === 'done' && t.completedAt)\n .map((t) => t.id);\n }\n\n // Filter out epic IDs\n const allTasks = await loadTasksFn();\n const epicIds = new Set(\n allTasks.filter((t) => allTasks.some((c) => c.parentId === t.id)).map((t) => t.id),\n );\n releaseTasks = releaseTasks.filter((id) => !epicIds.has(id));\n\n const release: ReleaseManifest = {\n version: normalizedVersion,\n status: 'prepared',\n createdAt: new Date().toISOString(),\n preparedAt: new Date().toISOString(),\n tasks: releaseTasks,\n notes,\n previousVersion: index.latest,\n };\n\n index.releases.push(release);\n await writeReleases(index, cwd);\n\n return {\n version: normalizedVersion,\n status: 'prepared',\n tasks: releaseTasks,\n taskCount: releaseTasks.length,\n };\n}\n\n/**\n * Generate changelog for a release.\n * @task T4788\n */\nexport async function generateReleaseChangelog(\n version: string,\n loadTasksFn: () => Promise<ReleaseTaskRecord[]>,\n cwd?: string,\n): Promise<{\n version: string;\n changelog: string;\n taskCount: number;\n sections: Record<string, number>;\n}> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n const allTasks = await loadTasksFn();\n const taskMap = new Map(allTasks.map((t) => [t.id, t]));\n\n const features: string[] = [];\n const fixes: string[] = [];\n const chores: string[] = [];\n const docs: string[] = [];\n const tests: string[] = [];\n const other: string[] = [];\n\n for (const taskId of release.tasks) {\n const task = taskMap.get(taskId);\n if (!task) continue;\n\n const titleLower = task.title.toLowerCase();\n const entry = `- ${task.title} (${task.id})`;\n\n if (titleLower.startsWith('feat') || titleLower.includes('add ') || titleLower.includes('implement')) {\n features.push(entry);\n } else if (titleLower.startsWith('fix') || titleLower.includes('bug')) {\n fixes.push(entry);\n } else if (titleLower.startsWith('doc') || titleLower.includes('documentation')) {\n docs.push(entry);\n } else if (titleLower.startsWith('test') || titleLower.includes('test')) {\n tests.push(entry);\n } else if (titleLower.startsWith('chore') || titleLower.includes('refactor')) {\n chores.push(entry);\n } else {\n other.push(entry);\n }\n }\n\n const sections: string[] = [];\n const date = new Date().toISOString().split('T')[0];\n sections.push(`## ${normalizedVersion} (${date})`);\n sections.push('');\n\n if (release.notes) {\n sections.push(release.notes);\n sections.push('');\n }\n\n if (features.length > 0) {\n sections.push('### Features');\n sections.push(...features);\n sections.push('');\n }\n if (fixes.length > 0) {\n sections.push('### Bug Fixes');\n sections.push(...fixes);\n sections.push('');\n }\n if (docs.length > 0) {\n sections.push('### Documentation');\n sections.push(...docs);\n sections.push('');\n }\n if (tests.length > 0) {\n sections.push('### Tests');\n sections.push(...tests);\n sections.push('');\n }\n if (chores.length > 0) {\n sections.push('### Chores');\n sections.push(...chores);\n sections.push('');\n }\n if (other.length > 0) {\n sections.push('### Other');\n sections.push(...other);\n sections.push('');\n }\n\n const changelog = sections.join('\\n');\n\n release.changelog = changelog;\n await writeReleases(index, cwd);\n\n return {\n version: normalizedVersion,\n changelog,\n taskCount: release.tasks.length,\n sections: {\n features: features.length,\n fixes: fixes.length,\n docs: docs.length,\n tests: tests.length,\n chores: chores.length,\n other: other.length,\n },\n };\n}\n\n/**\n * List all releases.\n * @task T4788\n */\nexport async function listManifestReleases(\n cwd?: string,\n): Promise<{\n releases: Array<{ version: string; status: string; createdAt: string; taskCount: number }>;\n total: number;\n latest?: string;\n}> {\n const index = await readReleases(cwd);\n\n return {\n releases: index.releases.map((r) => ({\n version: r.version,\n status: r.status,\n createdAt: r.createdAt,\n taskCount: r.tasks.length,\n })),\n total: index.releases.length,\n latest: index.latest,\n };\n}\n\n/**\n * Show release details.\n * @task T4788\n */\nexport async function showManifestRelease(\n version: string,\n cwd?: string,\n): Promise<ReleaseManifest> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n return release;\n}\n\n/**\n * Mark release as committed (metadata only).\n * @task T4788\n */\nexport async function commitRelease(\n version: string,\n cwd?: string,\n): Promise<{ version: string; status: string; committedAt: string }> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n if (release.status !== 'prepared') {\n throw new Error(`Release ${normalizedVersion} is in state '${release.status}', expected 'prepared'`);\n }\n\n release.status = 'committed';\n release.committedAt = new Date().toISOString();\n await writeReleases(index, cwd);\n\n return {\n version: normalizedVersion,\n status: 'committed',\n committedAt: release.committedAt,\n };\n}\n\n/**\n * Mark release as tagged (metadata only).\n * @task T4788\n */\nexport async function tagRelease(\n version: string,\n cwd?: string,\n): Promise<{ version: string; status: string; taggedAt: string }> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n release.status = 'tagged';\n release.taggedAt = new Date().toISOString();\n index.latest = normalizedVersion;\n await writeReleases(index, cwd);\n\n return {\n version: normalizedVersion,\n status: 'tagged',\n taggedAt: release.taggedAt,\n };\n}\n\n/**\n * Run release validation gates.\n * @task T4788\n */\nexport async function runReleaseGates(\n version: string,\n loadTasksFn: () => Promise<ReleaseTaskRecord[]>,\n cwd?: string,\n): Promise<{\n version: string;\n allPassed: boolean;\n gates: Array<{ name: string; status: 'passed' | 'failed'; message: string }>;\n passedCount: number;\n failedCount: number;\n}> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n const gates: Array<{ name: string; status: 'passed' | 'failed'; message: string }> = [];\n\n gates.push({\n name: 'version_valid',\n status: isValidVersion(normalizedVersion) ? 'passed' : 'failed',\n message: isValidVersion(normalizedVersion) ? 'Version format is valid' : 'Invalid version format',\n });\n\n gates.push({\n name: 'has_tasks',\n status: release.tasks.length > 0 ? 'passed' : 'failed',\n message: release.tasks.length > 0 ? `${release.tasks.length} tasks included` : 'No tasks in release',\n });\n\n gates.push({\n name: 'has_changelog',\n status: release.changelog ? 'passed' : 'failed',\n message: release.changelog ? 'Changelog generated' : 'No changelog generated. Run release.changelog first.',\n });\n\n const allTasks = await loadTasksFn();\n const incompleteTasks = release.tasks.filter((id) => {\n const task = allTasks.find((t) => t.id === id);\n return task && task.status !== 'done';\n });\n\n gates.push({\n name: 'tasks_complete',\n status: incompleteTasks.length === 0 ? 'passed' : 'failed',\n message: incompleteTasks.length === 0\n ? 'All tasks completed'\n : `${incompleteTasks.length} tasks not completed: ${incompleteTasks.join(', ')}`,\n });\n\n const allPassed = gates.every((g) => g.status === 'passed');\n\n return {\n version: normalizedVersion,\n allPassed,\n gates,\n passedCount: gates.filter((g) => g.status === 'passed').length,\n failedCount: gates.filter((g) => g.status === 'failed').length,\n };\n}\n\n/**\n * Rollback a release.\n * @task T4788\n */\nexport async function rollbackRelease(\n version: string,\n reason?: string,\n cwd?: string,\n): Promise<{\n version: string;\n previousStatus: string;\n status: string;\n reason: string;\n}> {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n\n if (!release) {\n throw new Error(`Release ${normalizedVersion} not found`);\n }\n\n const previousStatus = release.status;\n release.status = 'rolled_back';\n\n if (index.latest === normalizedVersion) {\n const otherReleases = index.releases\n .filter((r) => r.version !== normalizedVersion && r.status !== 'rolled_back')\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n index.latest = otherReleases[0]?.version;\n }\n\n await writeReleases(index, cwd);\n\n return {\n version: normalizedVersion,\n previousStatus,\n status: 'rolled_back',\n reason: reason ?? 'No reason provided',\n };\n}\n\n/**\n * Push release to remote via git.\n * @task T4788\n */\nexport function pushRelease(\n version: string,\n remote?: string,\n cwd?: string,\n): {\n version: string;\n status: string;\n remote: string;\n pushedAt: string;\n} {\n if (!version) {\n throw new Error('version is required');\n }\n\n const normalizedVersion = normalizeVersion(version);\n const projectRoot = getProjectRoot(cwd);\n const targetRemote = remote ?? 'origin';\n\n // Note: We don't update releases.json here synchronously since the\n // caller (engine) can handle status update after this returns.\n // The git push is the critical operation.\n execFileSync('git', ['push', targetRemote, '--follow-tags'], {\n cwd: projectRoot,\n timeout: 60000,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n return {\n version: normalizedVersion,\n status: 'pushed',\n remote: targetRemote,\n pushedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Update release status after push.\n * @task T4788\n */\nexport async function markReleasePushed(\n version: string,\n pushedAt: string,\n cwd?: string,\n): Promise<void> {\n const normalizedVersion = normalizeVersion(version);\n const index = await readReleases(cwd);\n const release = index.releases.find((r) => r.version === normalizedVersion);\n if (release) {\n release.status = 'pushed';\n release.pushedAt = pushedAt;\n await writeReleases(index, cwd);\n }\n}\n", "/**\n * Release Engine\n *\n * Thin wrapper around core release manifest operations.\n * Business logic lives in src/core/release/release-manifest.ts.\n *\n * Note: Some operations (push, rollback) inherently require git CLI.\n * Those are handled as hybrid operations - native for data, CLI for git.\n *\n * @task T4788\n */\n\nimport { resolveProjectRoot, readJsonFile, getDataPath } from './store.js';\nimport { getAccessor } from '../../store/data-accessor.js';\nimport {\n prepareRelease,\n generateReleaseChangelog,\n listManifestReleases,\n showManifestRelease,\n commitRelease,\n tagRelease,\n runReleaseGates,\n rollbackRelease,\n pushRelease,\n markReleasePushed,\n type ReleaseTaskRecord,\n} from '../../core/release/release-manifest.js';\n\n/**\n * Engine result type\n */\ninterface EngineResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: { code: string; message: string; details?: unknown };\n}\n\n/**\n * Load tasks via DataAccessor (SQLite or JSON depending on engine config).\n * When projectRoot is explicitly provided (e.g., in tests), uses direct\n * JSON read to avoid requiring full CLEO initialization.\n */\nasync function loadTasks(projectRoot?: string): Promise<ReleaseTaskRecord[]> {\n if (projectRoot) {\n const todoPath = getDataPath(projectRoot, 'todo.json');\n const todoData = readJsonFile<{ tasks: ReleaseTaskRecord[] }>(todoPath);\n return todoData?.tasks ?? [];\n }\n try {\n const accessor = await getAccessor();\n const todoFile = await accessor.loadTodoFile();\n return (todoFile?.tasks as ReleaseTaskRecord[]) ?? [];\n } catch {\n const root = resolveProjectRoot();\n const todoPath = getDataPath(root, 'todo.json');\n const todoData = readJsonFile<{ tasks: ReleaseTaskRecord[] }>(todoPath);\n return todoData?.tasks ?? [];\n }\n}\n\n/**\n * release.prepare - Prepare a release\n * @task T4788\n */\nexport async function releasePrepare(\n version: string,\n tasks?: string[],\n notes?: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await prepareRelease(\n version,\n tasks,\n notes,\n () => loadTasks(projectRoot),\n projectRoot,\n );\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n let code = 'E_RELEASE_PREPARE_FAILED';\n if (message.includes('required')) code = 'E_INVALID_INPUT';\n else if (message.includes('Invalid version')) code = 'E_INVALID_VERSION';\n else if (message.includes('already exists')) code = 'E_VERSION_EXISTS';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.changelog - Generate changelog\n * @task T4788\n */\nexport async function releaseChangelog(\n version: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await generateReleaseChangelog(\n version,\n () => loadTasks(projectRoot),\n projectRoot,\n );\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n let code = 'E_CHANGELOG_FAILED';\n if (message.includes('required')) code = 'E_INVALID_INPUT';\n else if (message.includes('not found')) code = 'E_NOT_FOUND';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.list - List all releases (query operation via data read)\n * @task T4788\n */\nexport async function releaseList(\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await listManifestReleases(projectRoot);\n return { success: true, data };\n } catch (err: unknown) {\n return {\n success: false,\n error: { code: 'E_LIST_FAILED', message: (err as Error).message },\n };\n }\n}\n\n/**\n * release.show - Show release details (query operation via data read)\n * @task T4788\n */\nexport async function releaseShow(\n version: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await showManifestRelease(version, projectRoot);\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_SHOW_FAILED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.commit - Mark release as committed (metadata only)\n * @task T4788\n */\nexport async function releaseCommit(\n version: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await commitRelease(version, projectRoot);\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n let code = 'E_COMMIT_FAILED';\n if (message.includes('not found')) code = 'E_NOT_FOUND';\n else if (message.includes('expected')) code = 'E_INVALID_STATE';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.tag - Mark release as tagged (metadata only)\n * @task T4788\n */\nexport async function releaseTag(\n version: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await tagRelease(version, projectRoot);\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_TAG_FAILED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.gates.run - Run release gates (validation checks)\n * @task T4788\n */\nexport async function releaseGatesRun(\n version: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await runReleaseGates(\n version,\n () => loadTasks(projectRoot),\n projectRoot,\n );\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_GATES_FAILED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.rollback - Rollback a release\n * @task T4788\n */\nexport async function releaseRollback(\n version: string,\n reason?: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const data = await rollbackRelease(version, reason, projectRoot);\n return { success: true, data };\n } catch (err: unknown) {\n const message = (err as Error).message;\n const code = message.includes('not found') ? 'E_NOT_FOUND' : 'E_ROLLBACK_FAILED';\n return { success: false, error: { code, message } };\n }\n}\n\n/**\n * release.push - Push release to remote via git\n * Uses execFileSync (no shell) for safety.\n * @task T4788\n */\nexport async function releasePush(\n version: string,\n remote?: string,\n projectRoot?: string\n): Promise<EngineResult> {\n try {\n const result = pushRelease(version, remote, projectRoot);\n // Update the manifest to record pushed status\n await markReleasePushed(result.version, result.pushedAt, projectRoot);\n return { success: true, data: result };\n } catch (err: unknown) {\n const execError = err as { status?: number; stderr?: string; message?: string };\n return {\n success: false,\n error: {\n code: 'E_PUSH_FAILED',\n message: `Git push failed: ${(execError.stderr ?? execError.message ?? '').slice(0, 500)}`,\n details: { exitCode: execError.status },\n },\n };\n }\n}\n", "/**\n * Capability Matrix\n *\n * Defines which operations can run natively in TypeScript vs requiring\n * the CLEO CLI (bash). Used by dual-mode routing to determine execution path.\n *\n * Each operation is tagged as:\n * - native: Runs in TypeScript, works cross-platform (no bash needed)\n * - cli: Requires CLEO CLI subprocess (Unix-only)\n * - hybrid: Can run either way (prefers CLI when available)\n */\n\n/**\n * Execution mode for an operation\n */\nexport type ExecutionMode = 'native' | 'cli' | 'hybrid';\n\n/**\n * Gateway type\n */\nexport type GatewayType = 'query' | 'mutate';\n\n/**\n * Single operation capability entry\n */\nexport interface OperationCapability {\n domain: string;\n operation: string;\n gateway: GatewayType;\n mode: ExecutionMode;\n}\n\n/**\n * Capability report returned by system.doctor\n */\nexport interface CapabilityReport {\n totalOperations: number;\n native: number;\n cli: number;\n hybrid: number;\n domains: Record<string, {\n native: string[];\n cli: string[];\n hybrid: string[];\n }>;\n}\n\n/**\n * The capability matrix - source of truth for operation routing.\n *\n * Gateway registries (query.ts + mutate.ts) define the canonical MCP API surface.\n * This matrix defines the full routing table including CLI-only paths.\n * All verb aliases have been removed \u2014 only canonical operation names remain.\n *\n * native: TypeScript engine handles directly (cross-platform)\n * cli: Requires CLEO CLI (bash, Unix-only)\n * hybrid: Can use either path (prefers CLI when available for richer output)\n */\nconst CAPABILITY_MATRIX: OperationCapability[] = [\n // === Tasks Domain ===\n // Native query operations (core CRUD reads)\n { domain: 'tasks', operation: 'show', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'list', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'find', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'exists', gateway: 'query', mode: 'native' },\n // Native query operations (analysis)\n { domain: 'tasks', operation: 'next', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'depends', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'stats', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'export', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'history', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'lint', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'batch.validate', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'manifest', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'tree', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'blockers', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'analyze', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'relates', gateway: 'query', mode: 'native' },\n { domain: 'tasks', operation: 'complexity.estimate', gateway: 'query', mode: 'native' },\n // Native mutate operations (core CRUD writes)\n { domain: 'tasks', operation: 'add', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'update', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'complete', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'delete', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'archive', gateway: 'mutate', mode: 'native' },\n // Native mutate operations (hierarchy, status, relations)\n { domain: 'tasks', operation: 'restore', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'import', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'reorder', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'reparent', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'promote', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'reopen', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'relates.add', gateway: 'mutate', mode: 'native' },\n // Native query operations (active task)\n { domain: 'tasks', operation: 'current', gateway: 'query', mode: 'native' },\n // Native mutate operations (active task)\n { domain: 'tasks', operation: 'start', gateway: 'mutate', mode: 'native' },\n { domain: 'tasks', operation: 'stop', gateway: 'mutate', mode: 'native' },\n\n // === Session Domain ===\n // Native query operations\n { domain: 'session', operation: 'status', gateway: 'query', mode: 'native' },\n { domain: 'session', operation: 'list', gateway: 'query', mode: 'native' },\n { domain: 'session', operation: 'show', gateway: 'query', mode: 'native' },\n // Native query operations\n { domain: 'session', operation: 'history', gateway: 'query', mode: 'native' },\n { domain: 'session', operation: 'stats', gateway: 'query', mode: 'native' },\n // Native mutate operations\n { domain: 'session', operation: 'start', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'end', gateway: 'mutate', mode: 'native' },\n // Native/CLI mutate operations\n { domain: 'session', operation: 'resume', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'switch', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'archive', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'cleanup', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'suspend', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'gc', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'record.decision', gateway: 'mutate', mode: 'native' },\n { domain: 'session', operation: 'decision.log', gateway: 'query', mode: 'native' },\n { domain: 'session', operation: 'context.drift', gateway: 'query', mode: 'native' },\n { domain: 'session', operation: 'record.assumption', gateway: 'mutate', mode: 'native' },\n\n // === System Domain ===\n { domain: 'system', operation: 'version', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'config.show', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'config.get', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'context', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'metrics', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'health', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'diagnostics', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'stats', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'help', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'dash', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'roadmap', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'labels', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'compliance', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'log', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'archive.stats', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'sequence', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'job.status', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'job.list', gateway: 'query', mode: 'native' },\n { domain: 'system', operation: 'init', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'config.set', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'backup', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'restore', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'migrate', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'cleanup', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'audit', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'sync', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'job.cancel', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'safestop', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'uncancel', gateway: 'mutate', mode: 'native' },\n { domain: 'system', operation: 'inject.generate', gateway: 'mutate', mode: 'native' },\n\n // === Validate Domain ===\n { domain: 'validate', operation: 'schema', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'protocol', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'task', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'manifest', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'output', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'compliance.summary', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'compliance.violations', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'compliance.record', gateway: 'mutate', mode: 'native' },\n { domain: 'validate', operation: 'test.run', gateway: 'mutate', mode: 'native' },\n { domain: 'validate', operation: 'test.status', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'test.coverage', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'coherence.check', gateway: 'query', mode: 'native' },\n { domain: 'validate', operation: 'batch.validate', gateway: 'mutate', mode: 'native' },\n\n // === Orchestrate Domain ===\n { domain: 'orchestrate', operation: 'status', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'next', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'ready', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'analyze', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'context', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'waves', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'skill.list', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'bootstrap', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'start', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'spawn', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'validate', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'parallel.start', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'parallel.end', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'check', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'skill.inject', gateway: 'mutate', mode: 'native' },\n { domain: 'orchestrate', operation: 'unblock.opportunities', gateway: 'query', mode: 'native' },\n { domain: 'orchestrate', operation: 'critical.path', gateway: 'query', mode: 'native' },\n\n // === Research Domain ===\n { domain: 'research', operation: 'show', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'list', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'find', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'pending', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'stats', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'manifest.read', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'contradictions', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'superseded', gateway: 'query', mode: 'native' },\n { domain: 'research', operation: 'inject', gateway: 'mutate', mode: 'native' },\n { domain: 'research', operation: 'link', gateway: 'mutate', mode: 'native' },\n { domain: 'research', operation: 'manifest.append', gateway: 'mutate', mode: 'native' },\n { domain: 'research', operation: 'manifest.archive', gateway: 'mutate', mode: 'native' },\n { domain: 'research', operation: 'compact', gateway: 'mutate', mode: 'native' },\n { domain: 'research', operation: 'validate', gateway: 'mutate', mode: 'native' },\n\n // === Lifecycle Domain ===\n { domain: 'lifecycle', operation: 'validate', gateway: 'query', mode: 'native' },\n { domain: 'lifecycle', operation: 'status', gateway: 'query', mode: 'native' },\n { domain: 'lifecycle', operation: 'history', gateway: 'query', mode: 'native' },\n { domain: 'lifecycle', operation: 'gates', gateway: 'query', mode: 'native' },\n { domain: 'lifecycle', operation: 'prerequisites', gateway: 'query', mode: 'native' },\n { domain: 'lifecycle', operation: 'record', gateway: 'mutate', mode: 'native' },\n { domain: 'lifecycle', operation: 'skip', gateway: 'mutate', mode: 'native' },\n { domain: 'lifecycle', operation: 'reset', gateway: 'mutate', mode: 'native' },\n { domain: 'lifecycle', operation: 'gate.pass', gateway: 'mutate', mode: 'native' },\n { domain: 'lifecycle', operation: 'gate.fail', gateway: 'mutate', mode: 'native' },\n\n // === Issues Domain ===\n // Native query operations (template parsing)\n { domain: 'issues', operation: 'templates', gateway: 'query', mode: 'native' },\n { domain: 'issues', operation: 'validate.labels', gateway: 'query', mode: 'native' },\n // Native mutate operations (config generation)\n { domain: 'issues', operation: 'generate.config', gateway: 'mutate', mode: 'native' },\n\n // === Release Domain ===\n { domain: 'release', operation: 'prepare', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'changelog', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'commit', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'tag', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'push', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'gates.run', gateway: 'mutate', mode: 'native' },\n { domain: 'release', operation: 'rollback', gateway: 'mutate', mode: 'native' },\n];\n\n/**\n * Lookup the execution mode for a specific operation\n */\nexport function getOperationMode(\n domain: string,\n operation: string,\n gateway: GatewayType\n): ExecutionMode | undefined {\n const entry = CAPABILITY_MATRIX.find(\n (cap) =>\n cap.domain === domain &&\n cap.operation === operation &&\n cap.gateway === gateway\n );\n return entry?.mode;\n}\n\n/**\n * Check if an operation can run natively (without CLI)\n */\nexport function canRunNatively(\n domain: string,\n operation: string,\n gateway: GatewayType\n): boolean {\n const mode = getOperationMode(domain, operation, gateway);\n return mode === 'native' || mode === 'hybrid';\n}\n\n/**\n * Check if an operation requires CLI\n */\nexport function requiresCLI(\n domain: string,\n operation: string,\n gateway: GatewayType\n): boolean {\n const mode = getOperationMode(domain, operation, gateway);\n return mode === 'cli';\n}\n\n/**\n * Get all native-capable operations for a domain\n */\nexport function getNativeOperations(domain: string): OperationCapability[] {\n return CAPABILITY_MATRIX.filter(\n (cap) => cap.domain === domain && (cap.mode === 'native' || cap.mode === 'hybrid')\n );\n}\n\n/**\n * Generate a capability report for system.doctor\n */\nexport function generateCapabilityReport(): CapabilityReport {\n const domains: CapabilityReport['domains'] = {};\n\n for (const cap of CAPABILITY_MATRIX) {\n if (!domains[cap.domain]) {\n domains[cap.domain] = { native: [], cli: [], hybrid: [] };\n }\n const key = `${cap.gateway}:${cap.operation}`;\n domains[cap.domain][cap.mode].push(key);\n }\n\n return {\n totalOperations: CAPABILITY_MATRIX.length,\n native: CAPABILITY_MATRIX.filter((c) => c.mode === 'native').length,\n cli: CAPABILITY_MATRIX.filter((c) => c.mode === 'cli').length,\n hybrid: CAPABILITY_MATRIX.filter((c) => c.mode === 'hybrid').length,\n domains,\n };\n}\n\n/**\n * Get the full capability matrix (for testing/introspection)\n */\nexport function getCapabilityMatrix(): ReadonlyArray<OperationCapability> {\n return CAPABILITY_MATRIX;\n}\n", "/**\n * Session Domain Handler (Dispatch Layer)\n *\n * Handles session lifecycle operations: status, list, show, start, end,\n * resume, suspend, gc, history, record.decision, decision.log,\n * context.drift, record.assumption.\n *\n * All operations delegate to native engine functions from session-engine.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n sessionStatus,\n sessionList,\n sessionShow,\n sessionStart,\n sessionEnd,\n sessionResume,\n sessionSuspend,\n sessionGc,\n sessionHistory,\n sessionRecordDecision,\n sessionDecisionLog,\n sessionContextDrift,\n sessionRecordAssumption,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// SessionHandler\n// ---------------------------------------------------------------------------\n\nexport class SessionHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'status': {\n const result = await sessionStatus(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n case 'list': {\n const result = await sessionList(this.projectRoot, params as { active?: boolean; limit?: number });\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n case 'show': {\n const sessionId = params?.sessionId as string;\n if (!sessionId) {\n return this.errorResponse('query', 'session', operation, 'E_INVALID_INPUT', 'sessionId is required', startTime);\n }\n const result = await sessionShow(this.projectRoot, sessionId);\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n case 'history': {\n const result = await sessionHistory(this.projectRoot, params as { sessionId?: string; limit?: number });\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n case 'decision.log': {\n const result = await sessionDecisionLog(this.projectRoot, params as { sessionId?: string; taskId?: string });\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n case 'context.drift': {\n const result = await sessionContextDrift(this.projectRoot, params as { sessionId?: string });\n return this.wrapEngineResult(result, 'query', 'session', operation, startTime);\n }\n\n default:\n return this.unsupported('query', 'session', operation, startTime);\n }\n } catch (error) {\n return this.handleError('query', 'session', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Mutate\n // -----------------------------------------------------------------------\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'start': {\n const scope = params?.scope as string;\n if (!scope) {\n return this.errorResponse('mutate', 'session', operation, 'E_INVALID_INPUT', 'scope is required', startTime);\n }\n const result = await sessionStart(this.projectRoot, {\n scope,\n name: params?.name as string | undefined,\n autoStart: params?.autoStart as boolean | undefined,\n focus: params?.focus as string | undefined,\n });\n // Enrich successful result with top-level sessionId for easy extraction\n if (result.success && result.data) {\n const session = result.data as unknown as Record<string, unknown>;\n result.data = { ...session, sessionId: session.id } as unknown as typeof result.data;\n }\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'end': {\n const result = await sessionEnd(this.projectRoot, params?.note as string | undefined);\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'resume': {\n const sessionId = params?.sessionId as string;\n if (!sessionId) {\n return this.errorResponse('mutate', 'session', operation, 'E_INVALID_INPUT', 'sessionId is required', startTime);\n }\n const result = await sessionResume(this.projectRoot, sessionId);\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'suspend': {\n const sessionId = params?.sessionId as string;\n if (!sessionId) {\n return this.errorResponse('mutate', 'session', operation, 'E_INVALID_INPUT', 'sessionId is required', startTime);\n }\n const result = await sessionSuspend(this.projectRoot, sessionId, params?.reason as string | undefined);\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'gc': {\n const result = await sessionGc(this.projectRoot, params?.maxAgeDays as number | undefined);\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'record.decision': {\n const result = await sessionRecordDecision(this.projectRoot, {\n sessionId: params?.sessionId as string,\n taskId: params?.taskId as string,\n decision: params?.decision as string,\n rationale: params?.rationale as string,\n alternatives: params?.alternatives as string[] | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n case 'record.assumption': {\n const result = await sessionRecordAssumption(this.projectRoot, {\n sessionId: params?.sessionId as string | undefined,\n taskId: params?.taskId as string | undefined,\n assumption: params?.assumption as string,\n confidence: params?.confidence as 'high' | 'medium' | 'low',\n });\n return this.wrapEngineResult(result, 'mutate', 'session', operation, startTime);\n }\n\n default:\n return this.unsupported('mutate', 'session', operation, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', 'session', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Supported operations\n // -----------------------------------------------------------------------\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: ['status', 'list', 'show', 'history', 'decision.log', 'context.drift'],\n mutate: ['start', 'end', 'resume', 'suspend', 'gc', 'record.decision', 'record.assumption'],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: result.success,\n ...(result.success ? { data: result.data } : {}),\n ...(result.error ? { error: { code: result.error.code, message: result.error.message, details: result.error.details as Record<string, unknown> | undefined } } : {}),\n };\n }\n\n private unsupported(gateway: string, domain: string, operation: string, startTime: number): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INVALID_OPERATION', message: `Unknown ${domain} ${gateway}: ${operation}` },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(gateway: string, domain: string, operation: string, error: unknown, startTime: number): DispatchResponse {\n const message = error instanceof Error ? error.message : String(error);\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INTERNAL', message },\n };\n }\n}\n", "/**\n * Check Domain Handler (Dispatch Layer)\n *\n * Consolidates MCP validate domain operations into the canonical \"check\"\n * domain. Handles schema validation, protocol compliance, task validation,\n * manifest checks, output validation, compliance tracking, test operations,\n * and coherence checks.\n *\n * All operations delegate to native engine functions from validate-engine.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n validateSchemaOp,\n validateTaskOp,\n validateProtocol,\n validateManifestOp,\n validateOutput,\n validateComplianceSummary,\n validateComplianceViolations,\n validateComplianceRecord,\n validateTestStatus,\n validateTestCoverage,\n validateCoherenceCheck,\n validateTestRun,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// CheckHandler\n// ---------------------------------------------------------------------------\n\nexport class CheckHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'schema': {\n const type = params?.type as string;\n if (!type) {\n return this.errorResponse('query', 'check', operation, 'E_INVALID_INPUT', 'type is required', startTime);\n }\n const result = validateSchemaOp(type, params?.data, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'protocol': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'check', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await validateProtocol(taskId, params?.protocolType as string | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'task': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'check', operation, 'E_INVALID_INPUT', 'taskId is required', startTime);\n }\n const result = await validateTaskOp(taskId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'manifest': {\n const result = validateManifestOp(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'output': {\n const filePath = params?.filePath as string;\n if (!filePath) {\n return this.errorResponse('query', 'check', operation, 'E_INVALID_INPUT', 'filePath is required', startTime);\n }\n const result = validateOutput(filePath, params?.taskId as string | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'compliance.summary': {\n const result = validateComplianceSummary(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'compliance.violations': {\n const result = validateComplianceViolations(params?.limit as number | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'test.status': {\n const result = validateTestStatus(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'test.coverage': {\n const result = validateTestCoverage(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n case 'coherence.check': {\n const result = await validateCoherenceCheck(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'check', operation, startTime);\n }\n\n default:\n return this.unsupported('query', 'check', operation, startTime);\n }\n } catch (error) {\n return this.handleError('query', 'check', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Mutate\n // -----------------------------------------------------------------------\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'compliance.record': {\n const taskId = params?.taskId as string;\n const result = params?.result as string;\n if (!taskId || !result) {\n return this.errorResponse('mutate', 'check', operation, 'E_INVALID_INPUT', 'taskId and result are required', startTime);\n }\n const engineResult = validateComplianceRecord(\n taskId,\n result,\n params?.protocol as string | undefined,\n params?.violations as Array<{ code: string; message: string; severity: string }> | undefined,\n this.projectRoot,\n );\n return this.wrapEngineResult(engineResult, 'mutate', 'check', operation, startTime);\n }\n\n case 'test.run': {\n const result = validateTestRun(\n params as { scope?: string; pattern?: string; parallel?: boolean } | undefined,\n this.projectRoot,\n );\n return this.wrapEngineResult(result, 'mutate', 'check', operation, startTime);\n }\n\n default:\n return this.unsupported('mutate', 'check', operation, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', 'check', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Supported operations\n // -----------------------------------------------------------------------\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n 'schema', 'protocol', 'task', 'manifest', 'output',\n 'compliance.summary', 'compliance.violations',\n 'test.status', 'test.coverage', 'coherence.check',\n ],\n mutate: ['compliance.record', 'test.run'],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: result.success,\n ...(result.success ? { data: result.data } : {}),\n ...(result.error ? { error: { code: result.error.code, message: result.error.message, details: result.error.details as Record<string, unknown> | undefined } } : {}),\n };\n }\n\n private unsupported(gateway: string, domain: string, operation: string, startTime: number): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INVALID_OPERATION', message: `Unknown ${domain} ${gateway}: ${operation}` },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(gateway: string, domain: string, operation: string, error: unknown, startTime: number): DispatchResponse {\n const message = error instanceof Error ? error.message : String(error);\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INTERNAL', message },\n };\n }\n}\n", "/**\n * Admin Domain Handler (Dispatch Layer)\n *\n * Consolidates MCP system domain operations into the canonical \"admin\"\n * domain. Handles version, health, config, stats, context, job management,\n * dashboard, log, sequence, init, backup, restore, migrate, sync, cleanup,\n * safestop, and inject.generate.\n *\n * All operations delegate to native engine functions from system-engine,\n * config-engine, and init-engine.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n systemDash,\n systemStats,\n systemLog,\n systemContext,\n systemSequence,\n systemHealth,\n systemInjectGenerate,\n systemBackup,\n systemRestore,\n systemMigrate,\n systemCleanup,\n systemSync,\n systemSafestop,\n configGet,\n configSet,\n getVersion,\n initProject,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// AdminHandler\n// ---------------------------------------------------------------------------\n\nexport class AdminHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'version': {\n const result = await getVersion(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'health': {\n const result = systemHealth(this.projectRoot, params as { detailed?: boolean } | undefined);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'config.get': {\n const result = await configGet(this.projectRoot, params?.key as string | undefined);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'stats': {\n const result = await systemStats(this.projectRoot, params as { period?: number } | undefined);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'context': {\n const result = systemContext(this.projectRoot, params as { session?: string } | undefined);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'job.status': {\n // TODO: Implement job status tracking when job system is available\n return this.errorResponse('query', 'admin', operation, 'E_NOT_IMPLEMENTED', 'Job status not yet available in dispatch layer', startTime);\n }\n\n case 'job.list': {\n // TODO: Implement job listing when job system is available\n return this.errorResponse('query', 'admin', operation, 'E_NOT_IMPLEMENTED', 'Job list not yet available in dispatch layer', startTime);\n }\n\n case 'dash': {\n const result = await systemDash(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'log': {\n const result = systemLog(this.projectRoot, params as {\n operation?: string;\n taskId?: string;\n since?: string;\n until?: string;\n limit?: number;\n offset?: number;\n } | undefined);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n case 'sequence': {\n const result = systemSequence(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'admin', operation, startTime);\n }\n\n default:\n return this.unsupported('query', 'admin', operation, startTime);\n }\n } catch (error) {\n return this.handleError('query', 'admin', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Mutate\n // -----------------------------------------------------------------------\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'init': {\n const result = await initProject(this.projectRoot, params as { projectName?: string; force?: boolean } | undefined);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'config.set': {\n const key = params?.key as string;\n if (!key) {\n return this.errorResponse('mutate', 'admin', operation, 'E_INVALID_INPUT', 'key is required', startTime);\n }\n const result = await configSet(this.projectRoot, key, params?.value);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'backup': {\n const result = systemBackup(this.projectRoot, params as { type?: string; note?: string } | undefined);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'restore': {\n const backupId = params?.backupId as string;\n if (!backupId) {\n return this.errorResponse('mutate', 'admin', operation, 'E_INVALID_INPUT', 'backupId is required', startTime);\n }\n const result = systemRestore(this.projectRoot, { backupId, force: params?.force as boolean | undefined });\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'migrate': {\n const result = systemMigrate(this.projectRoot, params as { target?: string; dryRun?: boolean } | undefined);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'sync': {\n const result = systemSync(this.projectRoot, params as { direction?: string } | undefined);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'cleanup': {\n const target = params?.target as string;\n if (!target) {\n return this.errorResponse('mutate', 'admin', operation, 'E_INVALID_INPUT', 'target is required', startTime);\n }\n const result = systemCleanup(this.projectRoot, {\n target,\n olderThan: params?.olderThan as string | undefined,\n dryRun: params?.dryRun as boolean | undefined,\n });\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'job.cancel': {\n // TODO: Implement job cancellation when job system is available\n return this.errorResponse('mutate', 'admin', operation, 'E_NOT_IMPLEMENTED', 'Job cancel not yet available in dispatch layer', startTime);\n }\n\n case 'safestop': {\n const result = systemSafestop(this.projectRoot, params as {\n reason?: string;\n commit?: boolean;\n handoff?: string;\n noSessionEnd?: boolean;\n dryRun?: boolean;\n } | undefined);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n case 'inject.generate': {\n const result = await systemInjectGenerate(this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'admin', operation, startTime);\n }\n\n default:\n return this.unsupported('mutate', 'admin', operation, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', 'admin', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Supported operations\n // -----------------------------------------------------------------------\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n 'version', 'health', 'config.get', 'stats', 'context',\n 'job.status', 'job.list', 'dash', 'log', 'sequence',\n ],\n mutate: [\n 'init', 'config.set', 'backup', 'restore', 'migrate',\n 'sync', 'cleanup', 'job.cancel', 'safestop', 'inject.generate',\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: result.success,\n ...(result.success ? { data: result.data } : {}),\n ...(result.error ? { error: { code: result.error.code, message: result.error.message, details: result.error.details as Record<string, unknown> | undefined } } : {}),\n };\n }\n\n private unsupported(gateway: string, domain: string, operation: string, startTime: number): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INVALID_OPERATION', message: `Unknown ${domain} ${gateway}: ${operation}` },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(gateway: string, domain: string, operation: string, error: unknown, startTime: number): DispatchResponse {\n const message = error instanceof Error ? error.message : String(error);\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INTERNAL', message },\n };\n }\n}\n", "/**\n * Memory Domain Handler (Dispatch Layer)\n *\n * Consolidates MCP research domain operations into the canonical \"memory\"\n * domain. Handles research manifest CRUD, research queries, contradiction\n * detection, supersession tracking, and protocol injection.\n *\n * All operations delegate to native engine functions from research-engine.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n researchShow,\n researchList,\n researchQuery,\n researchPending,\n researchStats,\n researchManifestRead,\n researchContradictions,\n researchSuperseded,\n researchInject,\n researchLink,\n researchManifestAppend,\n researchManifestArchive,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// MemoryHandler\n// ---------------------------------------------------------------------------\n\nexport class MemoryHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'show': {\n const entryId = params?.entryId as string;\n if (!entryId) {\n return this.errorResponse('query', 'memory', operation, 'E_INVALID_INPUT', 'entryId is required', startTime);\n }\n const result = researchShow(entryId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'list': {\n const result = researchList(\n (params ?? {}) as Parameters<typeof researchList>[0],\n this.projectRoot,\n );\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'find': {\n const query = params?.query as string;\n if (!query) {\n return this.errorResponse('query', 'memory', operation, 'E_INVALID_INPUT', 'query is required', startTime);\n }\n const result = researchQuery(\n query,\n { confidence: params?.confidence as number | undefined, limit: params?.limit as number | undefined },\n this.projectRoot,\n );\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'pending': {\n const result = researchPending(params?.epicId as string | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'stats': {\n const result = researchStats(params?.epicId as string | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'manifest.read': {\n const result = researchManifestRead(\n params as Parameters<typeof researchManifestRead>[0],\n this.projectRoot,\n );\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'contradictions': {\n const result = researchContradictions(this.projectRoot, params as { topic?: string } | undefined);\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n case 'superseded': {\n const result = researchSuperseded(this.projectRoot, params as { topic?: string } | undefined);\n return this.wrapEngineResult(result, 'query', 'memory', operation, startTime);\n }\n\n default:\n return this.unsupported('query', 'memory', operation, startTime);\n }\n } catch (error) {\n return this.handleError('query', 'memory', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Mutate\n // -----------------------------------------------------------------------\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'inject': {\n const protocolType = params?.protocolType as string;\n if (!protocolType) {\n return this.errorResponse('mutate', 'memory', operation, 'E_INVALID_INPUT', 'protocolType is required', startTime);\n }\n const result = researchInject(\n protocolType,\n { taskId: params?.taskId as string | undefined, variant: params?.variant as string | undefined },\n this.projectRoot,\n );\n return this.wrapEngineResult(result, 'mutate', 'memory', operation, startTime);\n }\n\n case 'link': {\n const taskId = params?.taskId as string;\n const entryId = params?.entryId as string;\n if (!taskId || !entryId) {\n return this.errorResponse('mutate', 'memory', operation, 'E_INVALID_INPUT', 'taskId and entryId are required', startTime);\n }\n const result = researchLink(taskId, entryId, params?.notes as string | undefined, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'memory', operation, startTime);\n }\n\n case 'manifest.append': {\n const entry = params?.entry as Parameters<typeof researchManifestAppend>[0];\n if (!entry) {\n return this.errorResponse('mutate', 'memory', operation, 'E_INVALID_INPUT', 'entry is required', startTime);\n }\n const result = researchManifestAppend(entry, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'memory', operation, startTime);\n }\n\n case 'manifest.archive': {\n const beforeDate = params?.beforeDate as string;\n if (!beforeDate) {\n return this.errorResponse('mutate', 'memory', operation, 'E_INVALID_INPUT', 'beforeDate is required (ISO-8601: YYYY-MM-DD)', startTime);\n }\n const result = researchManifestArchive(beforeDate, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'memory', operation, startTime);\n }\n\n default:\n return this.unsupported('mutate', 'memory', operation, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', 'memory', operation, error, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Supported operations\n // -----------------------------------------------------------------------\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: ['show', 'list', 'find', 'pending', 'stats', 'manifest.read', 'contradictions', 'superseded'],\n mutate: ['inject', 'link', 'manifest.append', 'manifest.archive'],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n domain: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: result.success,\n ...(result.success ? { data: result.data } : {}),\n ...(result.error ? { error: { code: result.error.code, message: result.error.message, details: result.error.details as Record<string, unknown> | undefined } } : {}),\n };\n }\n\n private unsupported(gateway: string, domain: string, operation: string, startTime: number): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INVALID_OPERATION', message: `Unknown ${domain} ${gateway}: ${operation}` },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(gateway: string, domain: string, operation: string, error: unknown, startTime: number): DispatchResponse {\n const message = error instanceof Error ? error.message : String(error);\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code: 'E_INTERNAL', message },\n };\n }\n}\n", "/**\n * Orchestrate Domain Handler (Dispatch Layer)\n *\n * Handles multi-agent orchestration: dependency analysis, wave computation,\n * spawn readiness, parallel coordination, and orchestration context.\n * All operations delegate to native engine functions.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n orchestrateStatus,\n orchestrateAnalyze,\n orchestrateReady,\n orchestrateNext,\n orchestrateWaves,\n orchestrateContext,\n orchestrateBootstrap,\n orchestrateUnblockOpportunities,\n orchestrateCriticalPath,\n orchestrateStartup,\n orchestrateSpawn,\n orchestrateValidate,\n orchestrateParallelStart,\n orchestrateParallelEnd,\n orchestrateCheck,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// OrchestrateHandler\n// ---------------------------------------------------------------------------\n\nexport class OrchestrateHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // DomainHandler interface\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'status': {\n const epicId = params?.epicId as string | undefined;\n const result = await orchestrateStatus(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'next': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('query', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = await orchestrateNext(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'ready': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('query', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = await orchestrateReady(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'analyze': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('query', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = await orchestrateAnalyze(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'context': {\n const epicId = params?.epicId as string | undefined;\n const result = await orchestrateContext(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'waves': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('query', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = await orchestrateWaves(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'bootstrap': {\n const speed = params?.speed as 'fast' | 'full' | 'complete' | undefined;\n const result = await orchestrateBootstrap(this.projectRoot, { speed });\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'unblock.opportunities': {\n const result = await orchestrateUnblockOpportunities(this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n case 'critical.path': {\n const result = await orchestrateCriticalPath(this.projectRoot);\n return this.wrapEngineResult(result, 'query', operation, startTime);\n }\n\n default:\n return this.errorResponse('query', operation, 'E_INVALID_OPERATION',\n `Unknown orchestrate query: ${operation}`, startTime);\n }\n } catch (error) {\n return this.handleError('query', operation, error, startTime);\n }\n }\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n switch (operation) {\n case 'start': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = await orchestrateStartup(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n case 'spawn': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'taskId is required', startTime);\n }\n const protocolType = params?.protocolType as string | undefined;\n const result = await orchestrateSpawn(taskId, protocolType, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n case 'validate': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'taskId is required', startTime);\n }\n const result = await orchestrateValidate(taskId, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n case 'parallel.start': {\n const epicId = params?.epicId as string;\n const wave = params?.wave as number;\n if (!epicId) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n if (wave === undefined || wave === null) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'wave number is required', startTime);\n }\n const result = await orchestrateParallelStart(epicId, wave, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n case 'parallel.end': {\n const epicId = params?.epicId as string;\n const wave = params?.wave as number;\n if (!epicId) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n if (wave === undefined || wave === null) {\n return this.errorResponse('mutate', operation, 'E_INVALID_INPUT',\n 'wave number is required', startTime);\n }\n const result = orchestrateParallelEnd(epicId, wave, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n case 'verify': {\n const result = await orchestrateCheck(this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', operation, startTime);\n }\n\n default:\n return this.errorResponse('mutate', operation, 'E_INVALID_OPERATION',\n `Unknown orchestrate mutation: ${operation}`, startTime);\n }\n } catch (error) {\n return this.handleError('mutate', operation, error, startTime);\n }\n }\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n 'status', 'next', 'ready', 'analyze', 'context',\n 'waves', 'bootstrap', 'unblock.opportunities', 'critical.path',\n ],\n mutate: [\n 'start', 'spawn', 'validate',\n 'parallel.start', 'parallel.end', 'verify',\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n if (result.success) {\n return {\n _meta: dispatchMeta(gateway, 'orchestrate', operation, startTime),\n success: true,\n data: result.data,\n };\n }\n return {\n _meta: dispatchMeta(gateway, 'orchestrate', operation, startTime),\n success: false,\n error: {\n code: result.error?.code || 'E_UNKNOWN',\n message: result.error?.message || 'Unknown error',\n },\n };\n }\n\n private errorResponse(\n gateway: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, 'orchestrate', operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(\n gateway: string,\n operation: string,\n error: unknown,\n startTime: number,\n ): DispatchResponse {\n return this.errorResponse(\n gateway, operation,\n 'E_INTERNAL_ERROR',\n error instanceof Error ? error.message : String(error),\n startTime,\n );\n }\n}\n", "/**\n * Pipeline Domain Handler (Dispatch Layer)\n *\n * Consolidates legacy lifecycle and release domains into a single \"pipeline\"\n * domain with dot-prefixed operation names. All operations delegate to\n * native engine functions.\n *\n * Sub-domains:\n * stage.* - RCSD-IVTR lifecycle stage management\n * release.* - Release lifecycle (prepare, changelog, commit, tag, push)\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n lifecycleStatus,\n lifecycleHistory,\n lifecycleGates,\n lifecyclePrerequisites,\n lifecycleCheck,\n lifecycleProgress,\n lifecycleSkip,\n lifecycleReset,\n lifecycleGatePass,\n lifecycleGateFail,\n releasePrepare,\n releaseChangelog,\n releaseCommit,\n releaseTag,\n releasePush,\n releaseGatesRun,\n releaseRollback,\n} from '../../mcp/engine/index.js';\n\n// ---------------------------------------------------------------------------\n// PipelineHandler\n// ---------------------------------------------------------------------------\n\nexport class PipelineHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // DomainHandler interface\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n // Stage sub-domain\n if (operation.startsWith('stage.')) {\n return this.queryStage(operation.slice('stage.'.length), params, startTime);\n }\n\n return this.errorResponse('query', operation, 'E_INVALID_OPERATION',\n `Unknown pipeline query: ${operation}`, startTime);\n } catch (error) {\n return this.handleError('query', operation, error, startTime);\n }\n }\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n // Stage sub-domain\n if (operation.startsWith('stage.')) {\n return this.mutateStage(operation.slice('stage.'.length), params, startTime);\n }\n\n // Release sub-domain\n if (operation.startsWith('release.')) {\n return this.mutateRelease(operation.slice('release.'.length), params, startTime);\n }\n\n return this.errorResponse('mutate', operation, 'E_INVALID_OPERATION',\n `Unknown pipeline mutation: ${operation}`, startTime);\n } catch (error) {\n return this.handleError('mutate', operation, error, startTime);\n }\n }\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n 'stage.validate', 'stage.status', 'stage.history',\n 'stage.gates', 'stage.prerequisites',\n ],\n mutate: [\n 'stage.record', 'stage.skip', 'stage.reset',\n 'stage.gate.pass', 'stage.gate.fail',\n 'release.prepare', 'release.changelog', 'release.commit',\n 'release.tag', 'release.push', 'release.gates.run',\n 'release.rollback',\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Stage queries\n // -----------------------------------------------------------------------\n\n private queryStage(\n sub: string,\n params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'validate': {\n const epicId = params?.epicId as string;\n const targetStage = params?.targetStage as string;\n if (!epicId || !targetStage) {\n return this.errorResponse('query', 'stage.validate', 'E_INVALID_INPUT',\n 'epicId and targetStage are required', startTime);\n }\n const result = lifecycleCheck(epicId, targetStage, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'stage.validate', startTime);\n }\n\n case 'status': {\n const epicId = params?.epicId as string;\n if (!epicId) {\n return this.errorResponse('query', 'stage.status', 'E_INVALID_INPUT',\n 'epicId is required', startTime);\n }\n const result = lifecycleStatus(epicId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'stage.status', startTime);\n }\n\n case 'history': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'stage.history', 'E_INVALID_INPUT',\n 'taskId is required', startTime);\n }\n const result = lifecycleHistory(taskId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'stage.history', startTime);\n }\n\n case 'gates': {\n const taskId = params?.taskId as string;\n if (!taskId) {\n return this.errorResponse('query', 'stage.gates', 'E_INVALID_INPUT',\n 'taskId is required', startTime);\n }\n const result = lifecycleGates(taskId, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'stage.gates', startTime);\n }\n\n case 'prerequisites': {\n const targetStage = params?.targetStage as string;\n if (!targetStage) {\n return this.errorResponse('query', 'stage.prerequisites', 'E_INVALID_INPUT',\n 'targetStage is required', startTime);\n }\n const result = lifecyclePrerequisites(targetStage, this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'stage.prerequisites', startTime);\n }\n\n default:\n return this.errorResponse('query', `stage.${sub}`, 'E_INVALID_OPERATION',\n `Unknown stage query: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Stage mutations\n // -----------------------------------------------------------------------\n\n private mutateStage(\n sub: string,\n params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'record': {\n const taskId = params?.taskId as string;\n const stage = params?.stage as string;\n const status = params?.status as string;\n const notes = params?.notes as string | undefined;\n if (!taskId || !stage || !status) {\n return this.errorResponse('mutate', 'stage.record', 'E_INVALID_INPUT',\n 'taskId, stage, and status are required', startTime);\n }\n const result = lifecycleProgress(taskId, stage, status, notes, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'stage.record', startTime);\n }\n\n case 'skip': {\n const taskId = params?.taskId as string;\n const stage = params?.stage as string;\n const reason = params?.reason as string;\n if (!taskId || !stage || !reason) {\n return this.errorResponse('mutate', 'stage.skip', 'E_INVALID_INPUT',\n 'taskId, stage, and reason are required', startTime);\n }\n const result = lifecycleSkip(taskId, stage, reason, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'stage.skip', startTime);\n }\n\n case 'reset': {\n const taskId = params?.taskId as string;\n const stage = params?.stage as string;\n const reason = params?.reason as string;\n if (!taskId || !stage || !reason) {\n return this.errorResponse('mutate', 'stage.reset', 'E_INVALID_INPUT',\n 'taskId, stage, and reason are required', startTime);\n }\n const result = lifecycleReset(taskId, stage, reason, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'stage.reset', startTime);\n }\n\n case 'gate.pass': {\n const taskId = params?.taskId as string;\n const gateName = params?.gateName as string;\n const agent = params?.agent as string | undefined;\n const notes = params?.notes as string | undefined;\n if (!taskId || !gateName) {\n return this.errorResponse('mutate', 'stage.gate.pass', 'E_INVALID_INPUT',\n 'taskId and gateName are required', startTime);\n }\n const result = lifecycleGatePass(taskId, gateName, agent, notes, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'stage.gate.pass', startTime);\n }\n\n case 'gate.fail': {\n const taskId = params?.taskId as string;\n const gateName = params?.gateName as string;\n const reason = params?.reason as string | undefined;\n if (!taskId || !gateName) {\n return this.errorResponse('mutate', 'stage.gate.fail', 'E_INVALID_INPUT',\n 'taskId and gateName are required', startTime);\n }\n const result = lifecycleGateFail(taskId, gateName, reason, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'stage.gate.fail', startTime);\n }\n\n default:\n return this.errorResponse('mutate', `stage.${sub}`, 'E_INVALID_OPERATION',\n `Unknown stage mutation: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Release mutations\n // -----------------------------------------------------------------------\n\n private async mutateRelease(\n sub: string,\n params: Record<string, unknown> | undefined,\n startTime: number,\n ): Promise<DispatchResponse> {\n switch (sub) {\n case 'prepare': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.prepare', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const tasks = params?.tasks as string[] | undefined;\n const notes = params?.notes as string | undefined;\n const result = await releasePrepare(version, tasks, notes, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.prepare', startTime);\n }\n\n case 'changelog': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.changelog', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const result = await releaseChangelog(version, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.changelog', startTime);\n }\n\n case 'commit': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.commit', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const result = await releaseCommit(version, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.commit', startTime);\n }\n\n case 'tag': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.tag', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const result = await releaseTag(version, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.tag', startTime);\n }\n\n case 'push': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.push', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const remote = params?.remote as string | undefined;\n const result = await releasePush(version, remote, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.push', startTime);\n }\n\n case 'gates.run': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.gates.run', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const result = await releaseGatesRun(version, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.gates.run', startTime);\n }\n\n case 'rollback': {\n const version = params?.version as string;\n if (!version) {\n return this.errorResponse('mutate', 'release.rollback', 'E_INVALID_INPUT',\n 'version is required', startTime);\n }\n const reason = params?.reason as string | undefined;\n const result = await releaseRollback(version, reason, this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'release.rollback', startTime);\n }\n\n default:\n return this.errorResponse('mutate', `release.${sub}`, 'E_INVALID_OPERATION',\n `Unknown release mutation: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n if (result.success) {\n return {\n _meta: dispatchMeta(gateway, 'pipeline', operation, startTime),\n success: true,\n data: result.data,\n };\n }\n return {\n _meta: dispatchMeta(gateway, 'pipeline', operation, startTime),\n success: false,\n error: {\n code: result.error?.code || 'E_UNKNOWN',\n message: result.error?.message || 'Unknown error',\n },\n };\n }\n\n private errorResponse(\n gateway: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, 'pipeline', operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(\n gateway: string,\n operation: string,\n error: unknown,\n startTime: number,\n ): DispatchResponse {\n return this.errorResponse(\n gateway, operation,\n 'E_INTERNAL_ERROR',\n error instanceof Error ? error.message : String(error),\n startTime,\n );\n }\n}\n", "/**\n * Tools Domain Handler (Dispatch Layer)\n *\n * Consolidates MCP domains issues, skills, and providers into a single\n * \"tools\" domain with dot-prefixed operation names. All operations delegate\n * to src/core/ or native engine functions -- no MCP coupling.\n *\n * Sub-domains:\n * issue.* - Issue templates, diagnostics, creation\n * skill.* - Skill discovery, dispatch, catalog\n * provider.* - CAAMP provider registry\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport {\n parseIssueTemplates,\n getTemplateForSubcommand,\n generateTemplateConfig,\n validateLabels,\n} from '../../mcp/engine/template-parser.js';\nimport { catalog } from '@cleocode/caamp';\n\n// ---------------------------------------------------------------------------\n// ToolsHandler\n// ---------------------------------------------------------------------------\n\nexport class ToolsHandler implements DomainHandler {\n private projectRoot: string;\n\n constructor() {\n this.projectRoot = getProjectRoot();\n }\n\n // -----------------------------------------------------------------------\n // DomainHandler interface\n // -----------------------------------------------------------------------\n\n async query(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n // Issue sub-domain\n if (operation.startsWith('issue.')) {\n return this.queryIssue(operation.slice('issue.'.length), params, startTime);\n }\n\n // Skill sub-domain\n if (operation.startsWith('skill.')) {\n return this.querySkill(operation.slice('skill.'.length), params, startTime);\n }\n\n // Provider sub-domain\n if (operation.startsWith('provider.')) {\n return this.queryProvider(operation.slice('provider.'.length), params, startTime);\n }\n\n return this.errorResponse('query', 'tools', operation, 'E_INVALID_OPERATION',\n `Unknown query operation: ${operation}`, startTime);\n } catch (error) {\n return this.handleError('query', 'tools', operation, error, startTime);\n }\n }\n\n async mutate(\n operation: string,\n params?: Record<string, unknown>,\n ): Promise<DispatchResponse> {\n const startTime = Date.now();\n\n try {\n // Issue sub-domain\n if (operation.startsWith('issue.')) {\n return this.mutateIssue(operation.slice('issue.'.length), params, startTime);\n }\n\n // Skill sub-domain\n if (operation.startsWith('skill.')) {\n return this.mutateSkill(operation.slice('skill.'.length), params, startTime);\n }\n\n // Provider sub-domain\n if (operation.startsWith('provider.')) {\n return this.mutateProvider(operation.slice('provider.'.length), params, startTime);\n }\n\n return this.errorResponse('mutate', 'tools', operation, 'E_INVALID_OPERATION',\n `Unknown mutate operation: ${operation}`, startTime);\n } catch (error) {\n return this.handleError('mutate', 'tools', operation, error, startTime);\n }\n }\n\n getSupportedOperations(): { query: string[]; mutate: string[] } {\n return {\n query: [\n // issue\n 'issue.diagnostics',\n 'issue.templates',\n 'issue.validate.labels',\n // skill\n 'skill.list', 'skill.show', 'skill.find',\n 'skill.dispatch', 'skill.verify', 'skill.dependencies',\n // skill.catalog\n 'skill.catalog.protocols', 'skill.catalog.profiles',\n 'skill.catalog.resources', 'skill.catalog.info',\n // provider\n 'provider.list', 'provider.detect', 'provider.inject.status',\n ],\n mutate: [\n // issue\n 'issue.add.bug', 'issue.add.feature', 'issue.add.help',\n 'issue.create.bug', 'issue.create.feature', 'issue.create.help',\n 'issue.generate.config',\n // skill\n 'skill.install', 'skill.uninstall', 'skill.enable',\n 'skill.disable', 'skill.configure', 'skill.refresh',\n // provider\n 'provider.inject',\n ],\n };\n }\n\n // -----------------------------------------------------------------------\n // Issue queries\n // -----------------------------------------------------------------------\n\n private queryIssue(\n sub: string,\n params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'diagnostics':\n // TODO: delegate to core diagnostics when available\n return this.errorResponse('query', 'tools', 'issue.diagnostics',\n 'E_NOT_IMPLEMENTED', 'Diagnostics not yet available in dispatch layer', startTime);\n\n case 'templates': {\n const subcommand = params?.subcommand as string | undefined;\n if (subcommand) {\n const result = getTemplateForSubcommand(this.projectRoot, subcommand);\n return this.wrapEngineResult(result, 'query', 'issue.templates', startTime);\n }\n const result = parseIssueTemplates(this.projectRoot);\n return this.wrapEngineResult(result, 'query', 'issue.templates', startTime);\n }\n\n case 'validate.labels': {\n const labels = params?.labels as string[] | undefined;\n const repoLabels = params?.repoLabels as string[] | undefined;\n if (!labels || !repoLabels) {\n return this.errorResponse('query', 'tools', 'issue.validate.labels',\n 'E_INVALID_INPUT',\n 'Missing required parameters: labels and repoLabels (both arrays of strings)',\n startTime);\n }\n const result = validateLabels(labels, repoLabels);\n return this.wrapEngineResult(result, 'query', 'issue.validate.labels', startTime);\n }\n\n default:\n return this.errorResponse('query', 'tools', `issue.${sub}`,\n 'E_INVALID_OPERATION', `Unknown issue query: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Issue mutations\n // -----------------------------------------------------------------------\n\n private async mutateIssue(\n sub: string,\n _params: Record<string, unknown> | undefined,\n startTime: number,\n ): Promise<DispatchResponse> {\n switch (sub) {\n case 'add.bug':\n case 'add.feature':\n case 'add.help':\n case 'create.bug':\n case 'create.feature':\n case 'create.help':\n // TODO: delegate to core issue creation when available\n return this.errorResponse('mutate', 'tools', `issue.${sub}`,\n 'E_NOT_IMPLEMENTED', 'Issue creation not yet available in dispatch layer', startTime);\n\n case 'generate.config': {\n const result = await generateTemplateConfig(this.projectRoot);\n return this.wrapEngineResult(result, 'mutate', 'issue.generate.config', startTime);\n }\n\n default:\n return this.errorResponse('mutate', 'tools', `issue.${sub}`,\n 'E_INVALID_OPERATION', `Unknown issue mutation: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Skill queries\n // -----------------------------------------------------------------------\n\n private querySkill(\n sub: string,\n _params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n // Catalog sub-sub-domain\n if (sub.startsWith('catalog.')) {\n return this.querySkillCatalog(sub.slice('catalog.'.length), startTime);\n }\n\n switch (sub) {\n case 'list':\n case 'show':\n case 'find':\n case 'dispatch':\n case 'verify':\n case 'dependencies':\n // TODO: delegate to core skill operations when dispatch migration completes\n return this.errorResponse('query', 'tools', `skill.${sub}`,\n 'E_NOT_IMPLEMENTED', `Skill query '${sub}' not yet available in dispatch layer`, startTime);\n\n default:\n return this.errorResponse('query', 'tools', `skill.${sub}`,\n 'E_INVALID_OPERATION', `Unknown skill query: ${sub}`, startTime);\n }\n }\n\n private querySkillCatalog(\n sub: string,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'protocols': {\n const protocols = catalog.listProtocols();\n const details = protocols.map((name) => ({\n name,\n path: catalog.getProtocolPath(name) ?? null,\n }));\n return {\n _meta: dispatchMeta('query', 'tools', 'skill.catalog.protocols', startTime),\n success: true,\n data: { protocols: details },\n };\n }\n\n case 'profiles': {\n const profileNames = catalog.listProfiles();\n const profiles = profileNames.map((name) => {\n const profile = catalog.getProfile(name);\n return {\n name,\n description: profile?.description ?? '',\n extends: profile?.extends,\n skillCount: profile?.skills.length ?? 0,\n skills: profile?.skills ?? [],\n };\n });\n return {\n _meta: dispatchMeta('query', 'tools', 'skill.catalog.profiles', startTime),\n success: true,\n data: { profiles },\n };\n }\n\n case 'resources': {\n const resources = catalog.listSharedResources();\n const details = resources.map((name) => ({\n name,\n path: catalog.getSharedResourcePath(name) ?? null,\n }));\n return {\n _meta: dispatchMeta('query', 'tools', 'skill.catalog.resources', startTime),\n success: true,\n data: { resources: details },\n };\n }\n\n case 'info': {\n const available = catalog.isCatalogAvailable();\n const version = available ? catalog.getVersion() : null;\n const libraryRoot = available ? catalog.getLibraryRoot() : null;\n const skillCount = available ? catalog.getSkills().length : 0;\n const protocolCount = available ? catalog.listProtocols().length : 0;\n const profileCount = available ? catalog.listProfiles().length : 0;\n\n return {\n _meta: dispatchMeta('query', 'tools', 'skill.catalog.info', startTime),\n success: true,\n data: {\n available,\n version,\n libraryRoot,\n skillCount,\n protocolCount,\n profileCount,\n },\n };\n }\n\n default:\n return this.errorResponse('query', 'tools', `skill.catalog.${sub}`,\n 'E_INVALID_OPERATION', `Unknown catalog query: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Skill mutations\n // -----------------------------------------------------------------------\n\n private mutateSkill(\n sub: string,\n _params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'install':\n case 'uninstall':\n case 'enable':\n case 'disable':\n case 'configure':\n case 'refresh':\n // TODO: delegate to core skill operations when dispatch migration completes\n return this.errorResponse('mutate', 'tools', `skill.${sub}`,\n 'E_NOT_IMPLEMENTED', `Skill mutation '${sub}' not yet available in dispatch layer`, startTime);\n\n default:\n return this.errorResponse('mutate', 'tools', `skill.${sub}`,\n 'E_INVALID_OPERATION', `Unknown skill mutation: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Provider queries\n // -----------------------------------------------------------------------\n\n private queryProvider(\n sub: string,\n _params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'list':\n case 'detect':\n case 'inject.status':\n // TODO: delegate to CAAMP adapter when dispatch migration completes\n return this.errorResponse('query', 'tools', `provider.${sub}`,\n 'E_NOT_IMPLEMENTED', `Provider query '${sub}' not yet available in dispatch layer`, startTime);\n\n default:\n return this.errorResponse('query', 'tools', `provider.${sub}`,\n 'E_INVALID_OPERATION', `Unknown provider query: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Provider mutations\n // -----------------------------------------------------------------------\n\n private mutateProvider(\n sub: string,\n _params: Record<string, unknown> | undefined,\n startTime: number,\n ): DispatchResponse {\n switch (sub) {\n case 'inject':\n // TODO: delegate to CAAMP adapter when dispatch migration completes\n return this.errorResponse('mutate', 'tools', `provider.${sub}`,\n 'E_NOT_IMPLEMENTED', `Provider mutation '${sub}' not yet available in dispatch layer`, startTime);\n\n default:\n return this.errorResponse('mutate', 'tools', `provider.${sub}`,\n 'E_INVALID_OPERATION', `Unknown provider mutation: ${sub}`, startTime);\n }\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /**\n * Wrap a native engine result (EngineResult pattern) into DispatchResponse.\n */\n private wrapEngineResult(\n result: { success: boolean; data?: unknown; error?: { code: string; message: string; details?: unknown } },\n gateway: string,\n operation: string,\n startTime: number,\n ): DispatchResponse {\n if (result.success) {\n return {\n _meta: dispatchMeta(gateway, 'tools', operation, startTime),\n success: true,\n data: result.data,\n };\n }\n return {\n _meta: dispatchMeta(gateway, 'tools', operation, startTime),\n success: false,\n error: {\n code: result.error?.code || 'E_UNKNOWN',\n message: result.error?.message || 'Unknown error',\n },\n };\n }\n\n private errorResponse(\n gateway: string,\n domain: string,\n operation: string,\n code: string,\n message: string,\n startTime: number,\n ): DispatchResponse {\n return {\n _meta: dispatchMeta(gateway, domain, operation, startTime),\n success: false,\n error: { code, message },\n };\n }\n\n private handleError(\n gateway: string,\n domain: string,\n operation: string,\n error: unknown,\n startTime: number,\n ): DispatchResponse {\n return this.errorResponse(\n gateway, domain, operation,\n 'E_INTERNAL_ERROR',\n error instanceof Error ? error.message : String(error),\n startTime,\n );\n }\n}\n", "/**\n * Nexus Domain Handler (Dispatch Layer)\n *\n * Placeholder handler for forward compatibility with BRAIN Network.\n * Currently implements 0 operations -- all requests return E_NOT_IMPLEMENTED.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler, DispatchResponse } from '../types.js';\nimport { dispatchMeta } from './_meta.js';\n\n// ---------------------------------------------------------------------------\n// NexusHandler\n// ---------------------------------------------------------------------------\n\nexport class NexusHandler implements DomainHandler {\n async query(operation: string, _params?: Record<string, unknown>): Promise<DispatchResponse> {\n const startTime = Date.now();\n return {\n _meta: dispatchMeta('query', 'nexus', operation, startTime),\n success: false,\n error: { code: 'E_NOT_IMPLEMENTED', message: `Nexus domain not yet implemented: ${operation}` },\n };\n }\n\n async mutate(operation: string, _params?: Record<string, unknown>): Promise<DispatchResponse> {\n const startTime = Date.now();\n return {\n _meta: dispatchMeta('mutate', 'nexus', operation, startTime),\n success: false,\n error: { code: 'E_NOT_IMPLEMENTED', message: `Nexus domain not yet implemented: ${operation}` },\n };\n }\n\n getSupportedOperations() {\n return { query: [] as string[], mutate: [] as string[] };\n }\n}\n", "/**\n * Domain Handler Registry -- Maps canonical domain names to handler instances.\n *\n * Uses static imports. Will produce compile errors until all handler files\n * are created by parallel agents -- that is expected.\n *\n * @epic T4820\n */\n\nimport type { DomainHandler } from '../types.js';\nimport { TasksHandler } from './tasks.js';\nimport { SessionHandler } from './session.js';\nimport { CheckHandler } from './check.js';\nimport { AdminHandler } from './admin.js';\nimport { MemoryHandler } from './memory.js';\nimport { OrchestrateHandler } from './orchestrate.js';\nimport { PipelineHandler } from './pipeline.js';\nimport { ToolsHandler } from './tools.js';\nimport { NexusHandler } from './nexus.js';\n\nexport {\n TasksHandler, SessionHandler, CheckHandler, AdminHandler, MemoryHandler,\n OrchestrateHandler, PipelineHandler, ToolsHandler, NexusHandler,\n};\n\n/**\n * Create a Map of all 9 canonical domain handlers.\n */\nexport function createDomainHandlers(): Map<string, DomainHandler> {\n const handlers = new Map<string, DomainHandler>();\n handlers.set('tasks', new TasksHandler());\n handlers.set('session', new SessionHandler());\n handlers.set('memory', new MemoryHandler());\n handlers.set('check', new CheckHandler());\n handlers.set('pipeline', new PipelineHandler());\n handlers.set('orchestrate', new OrchestrateHandler());\n handlers.set('tools', new ToolsHandler());\n handlers.set('admin', new AdminHandler());\n handlers.set('nexus', new NexusHandler());\n return handlers;\n}\n", "/**\n * Security Hardening and Input Sanitization for CLEO MCP Server\n *\n * Provides input validation, path sanitization, content filtering,\n * enum checking, and rate limiting for all MCP operations.\n *\n * @task T3144\n * @epic T3125\n */\n\nimport { resolve, normalize, relative, isAbsolute } from 'path';\n\n/**\n * Security validation error thrown when input fails sanitization\n */\nexport class SecurityError extends Error {\n constructor(\n message: string,\n public code: string = 'E_SECURITY_VIOLATION',\n public field?: string\n ) {\n super(message);\n this.name = 'SecurityError';\n }\n}\n\n/**\n * Task ID pattern: T followed by one or more digits\n */\nconst TASK_ID_PATTERN = /^T[0-9]+$/;\n\n/**\n * Maximum task ID numeric value (prevent absurdly large IDs)\n */\nconst MAX_TASK_ID_NUMBER = 999999;\n\n/**\n * Control character pattern (C0 and C1 control chars, excluding newline/tab/cr)\n */\nconst CONTROL_CHAR_PATTERN = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x9F]/g;\n\n/**\n * Default maximum content length (64KB)\n */\nconst DEFAULT_MAX_CONTENT_LENGTH = 64 * 1024;\n\n/**\n * Sanitize and validate a task ID\n *\n * Validates format: ^T[0-9]+$\n * Rejects empty, malformed, or excessively large IDs\n *\n * @param id - Raw task ID input\n * @returns Sanitized task ID\n * @throws SecurityError if ID is invalid\n */\nexport function sanitizeTaskId(id: string): string {\n if (typeof id !== 'string') {\n throw new SecurityError(\n 'Task ID must be a string',\n 'E_INVALID_TASK_ID',\n 'taskId'\n );\n }\n\n // Trim whitespace\n const trimmed = id.trim();\n\n if (trimmed.length === 0) {\n throw new SecurityError(\n 'Task ID cannot be empty',\n 'E_INVALID_TASK_ID',\n 'taskId'\n );\n }\n\n if (!TASK_ID_PATTERN.test(trimmed)) {\n throw new SecurityError(\n `Invalid task ID format: \"${trimmed}\". Must match pattern T[0-9]+ (e.g., T123)`,\n 'E_INVALID_TASK_ID',\n 'taskId'\n );\n }\n\n // Check numeric portion isn't absurdly large\n const numericPart = parseInt(trimmed.slice(1), 10);\n if (numericPart > MAX_TASK_ID_NUMBER) {\n throw new SecurityError(\n `Task ID numeric value exceeds maximum (${MAX_TASK_ID_NUMBER}): ${trimmed}`,\n 'E_INVALID_TASK_ID',\n 'taskId'\n );\n }\n\n return trimmed;\n}\n\n/**\n * Sanitize and validate a file path\n *\n * Prevents path traversal attacks by ensuring the resolved path\n * stays within the project root directory.\n *\n * @param path - Raw path input\n * @param projectRoot - Project root directory (absolute path)\n * @returns Sanitized absolute path within project root\n * @throws SecurityError if path escapes project root or is invalid\n */\nexport function sanitizePath(path: string, projectRoot: string): string {\n if (typeof path !== 'string') {\n throw new SecurityError(\n 'Path must be a string',\n 'E_INVALID_PATH',\n 'path'\n );\n }\n\n if (typeof projectRoot !== 'string' || projectRoot.length === 0) {\n throw new SecurityError(\n 'Project root must be a non-empty string',\n 'E_INVALID_PATH',\n 'projectRoot'\n );\n }\n\n const trimmedPath = path.trim();\n\n if (trimmedPath.length === 0) {\n throw new SecurityError(\n 'Path cannot be empty',\n 'E_INVALID_PATH',\n 'path'\n );\n }\n\n // Check for null bytes (common injection vector)\n if (trimmedPath.includes('\\0')) {\n throw new SecurityError(\n 'Path contains null bytes',\n 'E_PATH_TRAVERSAL',\n 'path'\n );\n }\n\n // Normalize the project root\n const normalizedRoot = resolve(projectRoot);\n\n // Resolve the path relative to project root\n let resolvedPath: string;\n if (isAbsolute(trimmedPath)) {\n resolvedPath = normalize(trimmedPath);\n } else {\n resolvedPath = resolve(normalizedRoot, trimmedPath);\n }\n\n // Ensure the resolved path is within the project root\n const relativePath = relative(normalizedRoot, resolvedPath);\n\n // If relative path starts with '..' or is absolute, it escapes the root\n if (relativePath.startsWith('..') || isAbsolute(relativePath)) {\n throw new SecurityError(\n `Path traversal detected: \"${path}\" resolves outside project root`,\n 'E_PATH_TRAVERSAL',\n 'path'\n );\n }\n\n return resolvedPath;\n}\n\n/**\n * Sanitize content string\n *\n * Enforces size limits and strips control characters (except newline, tab, CR).\n *\n * @param content - Raw content string\n * @param maxLength - Maximum allowed length (default: 64KB)\n * @returns Sanitized content string\n * @throws SecurityError if content exceeds size limit\n */\nexport function sanitizeContent(\n content: string,\n maxLength: number = DEFAULT_MAX_CONTENT_LENGTH\n): string {\n if (typeof content !== 'string') {\n throw new SecurityError(\n 'Content must be a string',\n 'E_INVALID_CONTENT',\n 'content'\n );\n }\n\n if (content.length > maxLength) {\n throw new SecurityError(\n `Content exceeds maximum length (${maxLength} characters): got ${content.length}`,\n 'E_CONTENT_TOO_LARGE',\n 'content'\n );\n }\n\n // Strip control characters (preserve \\n, \\t, \\r)\n return content.replace(CONTROL_CHAR_PATTERN, '');\n}\n\n/**\n * Validate that a value is in an allowed enum set\n *\n * @param value - Value to validate\n * @param allowed - Array of allowed values\n * @param fieldName - Name of the field (for error messages)\n * @returns The validated value\n * @throws SecurityError if value is not in allowed set\n */\nexport function validateEnum(\n value: string,\n allowed: string[],\n fieldName: string\n): string {\n if (typeof value !== 'string') {\n throw new SecurityError(\n `${fieldName} must be a string`,\n 'E_INVALID_ENUM',\n fieldName\n );\n }\n\n const trimmed = value.trim();\n\n if (!allowed.includes(trimmed)) {\n throw new SecurityError(\n `Invalid ${fieldName}: \"${trimmed}\". Allowed values: ${allowed.join(', ')}`,\n 'E_INVALID_ENUM',\n fieldName\n );\n }\n\n return trimmed;\n}\n\n/**\n * Known enum values for CLEO domains\n */\nexport const VALID_DOMAINS = [\n 'tasks', 'session', 'orchestrate', 'research',\n 'lifecycle', 'validate', 'release', 'system',\n] as const;\n\nexport const VALID_GATEWAYS = ['cleo_query', 'cleo_mutate'] as const;\n\nexport const VALID_STATUSES = ['pending', 'active', 'blocked', 'done'] as const;\n\nexport const VALID_MANIFEST_STATUSES = ['complete', 'partial', 'blocked'] as const;\n\nexport const ALL_VALID_STATUSES = [...VALID_STATUSES, 'complete', 'partial'] as const;\n\nexport const VALID_PRIORITIES = ['low', 'medium', 'high', 'critical'] as const;\n\n/**\n * Rate limiter configuration\n */\nexport interface RateLimitConfig {\n /** Maximum requests allowed in the window */\n maxRequests: number;\n /** Time window in milliseconds */\n windowMs: number;\n}\n\n/**\n * Rate limit check result\n */\nexport interface RateLimitResult {\n /** Whether the request is allowed */\n allowed: boolean;\n /** Remaining requests in current window */\n remaining: number;\n /** Milliseconds until window resets */\n resetMs: number;\n /** Total limit for the window */\n limit: number;\n}\n\n/**\n * Default rate limit configurations per operation type\n */\nexport const DEFAULT_RATE_LIMITS: Record<string, RateLimitConfig> = {\n query: { maxRequests: 100, windowMs: 60_000 },\n mutate: { maxRequests: 30, windowMs: 60_000 },\n spawn: { maxRequests: 10, windowMs: 60_000 },\n};\n\n/**\n * In-memory sliding window rate limiter\n *\n * Tracks request timestamps per key and enforces configurable limits.\n */\nexport class RateLimiter {\n private windows: Map<string, number[]> = new Map();\n private configs: Map<string, RateLimitConfig> = new Map();\n\n constructor(configs?: Record<string, RateLimitConfig>) {\n // Initialize with provided or default configs\n const effectiveConfigs = configs ?? DEFAULT_RATE_LIMITS;\n for (const [key, config] of Object.entries(effectiveConfigs)) {\n this.configs.set(key, config);\n }\n }\n\n /**\n * Check if a request is allowed under rate limits\n *\n * @param key - Rate limit bucket key (e.g., 'query', 'mutate', 'spawn')\n * @returns Rate limit check result\n */\n check(key: string): RateLimitResult {\n const config = this.configs.get(key);\n if (!config) {\n // No config for this key - allow by default\n return { allowed: true, remaining: Infinity, resetMs: 0, limit: Infinity };\n }\n\n const now = Date.now();\n const windowStart = now - config.windowMs;\n\n // Get or create window\n let timestamps = this.windows.get(key);\n if (!timestamps) {\n timestamps = [];\n this.windows.set(key, timestamps);\n }\n\n // Prune expired timestamps\n const validTimestamps = timestamps.filter(t => t > windowStart);\n this.windows.set(key, validTimestamps);\n\n const remaining = Math.max(0, config.maxRequests - validTimestamps.length);\n const oldestInWindow = validTimestamps.length > 0 ? validTimestamps[0] : now;\n const resetMs = Math.max(0, oldestInWindow + config.windowMs - now);\n\n return {\n allowed: validTimestamps.length < config.maxRequests,\n remaining,\n resetMs,\n limit: config.maxRequests,\n };\n }\n\n /**\n * Record a request (call after check returns allowed: true)\n *\n * @param key - Rate limit bucket key\n */\n record(key: string): void {\n const timestamps = this.windows.get(key) ?? [];\n timestamps.push(Date.now());\n this.windows.set(key, timestamps);\n }\n\n /**\n * Check and record in one step\n *\n * @param key - Rate limit bucket key\n * @returns Rate limit check result (recorded if allowed)\n */\n consume(key: string): RateLimitResult {\n const result = this.check(key);\n if (result.allowed) {\n this.record(key);\n // Adjust remaining after recording\n result.remaining = Math.max(0, result.remaining - 1);\n }\n return result;\n }\n\n /**\n * Reset rate limit state for a specific key or all keys\n *\n * @param key - Optional key to reset (resets all if omitted)\n */\n reset(key?: string): void {\n if (key) {\n this.windows.delete(key);\n } else {\n this.windows.clear();\n }\n }\n\n /**\n * Get current configuration for a key\n */\n getConfig(key: string): RateLimitConfig | undefined {\n return this.configs.get(key);\n }\n\n /**\n * Update configuration for a key\n */\n setConfig(key: string, config: RateLimitConfig): void {\n this.configs.set(key, config);\n }\n}\n\n/**\n * Sanitize all params in a DomainRequest before routing\n *\n * Applies appropriate sanitization based on known field names:\n * - taskId, parent, epicId -> sanitizeTaskId\n * - path, file -> sanitizePath (if projectRoot provided)\n * - title, description, notes, content -> sanitizeContent\n * - status -> validateEnum(VALID_STATUSES)\n * - priority -> validateEnum(VALID_PRIORITIES)\n * - domain -> validateEnum(VALID_DOMAINS)\n *\n * @param params - Raw request parameters\n * @param projectRoot - Project root for path sanitization\n * @returns Sanitized parameters\n * @throws SecurityError on validation failure\n */\nexport function sanitizeParams(\n params: Record<string, unknown> | undefined,\n projectRoot?: string\n): Record<string, unknown> | undefined {\n if (!params) {\n return params;\n }\n\n const sanitized: Record<string, unknown> = { ...params };\n\n for (const [key, value] of Object.entries(sanitized)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n // Task ID fields\n if (\n typeof value === 'string' &&\n (key === 'taskId' || key === 'parent' || key === 'epicId')\n ) {\n // Allow empty string for 'parent' field (means \"promote to root\" / remove parent)\n if (key === 'parent' && value === '') {\n continue;\n }\n sanitized[key] = sanitizeTaskId(value);\n continue;\n }\n\n // Task ID arrays (depends)\n if (key === 'depends' && Array.isArray(value)) {\n sanitized[key] = value.map((v) => {\n if (typeof v === 'string') {\n return sanitizeTaskId(v);\n }\n return v;\n });\n continue;\n }\n\n // Path fields\n if (\n typeof value === 'string' &&\n (key === 'path' || key === 'file') &&\n projectRoot\n ) {\n sanitized[key] = sanitizePath(value, projectRoot);\n continue;\n }\n\n // Content fields (with size limits)\n if (\n typeof value === 'string' &&\n (key === 'title' || key === 'description' || key === 'content')\n ) {\n const maxLen = key === 'title' ? 200 : DEFAULT_MAX_CONTENT_LENGTH;\n sanitized[key] = sanitizeContent(value, maxLen);\n continue;\n }\n\n // Notes can be string or array of strings\n if (key === 'notes') {\n if (typeof value === 'string') {\n sanitized[key] = sanitizeContent(value);\n } else if (Array.isArray(value)) {\n sanitized[key] = value.map((v) =>\n typeof v === 'string' ? sanitizeContent(v) : v\n );\n }\n continue;\n }\n\n // Status enum - accept both task statuses and manifest statuses\n if (typeof value === 'string' && key === 'status') {\n sanitized[key] = validateEnum(value, [...ALL_VALID_STATUSES], 'status');\n continue;\n }\n\n // Priority enum\n if (typeof value === 'string' && key === 'priority') {\n sanitized[key] = validateEnum(value, [...VALID_PRIORITIES], 'priority');\n continue;\n }\n }\n\n return sanitized;\n}\n", "import { DispatchRequest, DispatchResponse, Middleware, DispatchNext } from '../types.js';\nimport { sanitizeParams as legacySanitizeParams } from '../../mcp/lib/security.js';\n\n/**\n * Creates a middleware that sanitizes incoming request parameters.\n * Uses the canonical sanitization logic from security.ts to handle\n * Task IDs, paths, string lengths, and enum validation.\n *\n * @param getProjectRoot - Optional function to resolve the current project root for path sanitization\n */\nexport function createSanitizer(getProjectRoot?: () => string): Middleware {\n return async (req: DispatchRequest, next: DispatchNext): Promise<DispatchResponse> => {\n if (req.params) {\n try {\n const root = getProjectRoot ? getProjectRoot() : undefined;\n req.params = legacySanitizeParams(req.params, root);\n } catch (error) {\n return {\n _meta: {\n gateway: req.gateway,\n domain: req.domain,\n operation: req.operation,\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n source: req.source,\n requestId: req.requestId,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6, // VALIDATION_ERROR\n message: error instanceof Error ? error.message : String(error),\n }\n };\n }\n }\n \n return next();\n };\n}\n", "import { DispatchRequest, DispatchResponse, Middleware, DispatchNext, RateLimitMeta } from '../types.js';\n\n/**\n * Rate Limit Configuration\n */\nexport interface RateLimitConfig {\n maxRequests: number;\n windowMs: number;\n}\n\nexport interface RateLimitingConfig {\n enabled: boolean;\n query: RateLimitConfig;\n mutate: RateLimitConfig;\n spawn: RateLimitConfig;\n}\n\nexport const DEFAULT_RATE_LIMITING: RateLimitingConfig = {\n enabled: true,\n query: { maxRequests: 100, windowMs: 60_000 },\n mutate: { maxRequests: 30, windowMs: 60_000 },\n spawn: { maxRequests: 10, windowMs: 60_000 },\n};\n\n/**\n * Internal bucket tracking timestamps of requests in the sliding window\n */\ninterface SlidingWindowBucket {\n timestamps: number[];\n}\n\nexport class RateLimiter {\n private buckets: Map<string, SlidingWindowBucket> = new Map();\n private config: RateLimitingConfig;\n\n constructor(config?: Partial<RateLimitingConfig>) {\n this.config = {\n ...DEFAULT_RATE_LIMITING,\n ...config,\n query: { ...DEFAULT_RATE_LIMITING.query, ...config?.query },\n mutate: { ...DEFAULT_RATE_LIMITING.mutate, ...config?.mutate },\n spawn: { ...DEFAULT_RATE_LIMITING.spawn, ...config?.spawn },\n };\n }\n\n check(req: DispatchRequest): RateLimitMeta & { allowed: boolean } {\n if (!this.config.enabled) {\n return {\n allowed: true,\n remaining: Infinity,\n limit: Infinity,\n resetMs: 0,\n category: 'disabled',\n };\n }\n\n const category = this.resolveCategory(req.gateway, req.domain, req.operation);\n const limitConfig = this.getLimitConfig(category);\n\n const now = Date.now();\n const windowStart = now - limitConfig.windowMs;\n\n let bucket = this.buckets.get(category);\n if (!bucket) {\n bucket = { timestamps: [] };\n this.buckets.set(category, bucket);\n }\n\n // Clean up old timestamps\n bucket.timestamps = bucket.timestamps.filter(t => t > windowStart);\n\n const allowed = bucket.timestamps.length < limitConfig.maxRequests;\n if (allowed) {\n bucket.timestamps.push(now);\n }\n\n const oldest = bucket.timestamps[0] || now;\n const resetMs = Math.max(0, oldest + limitConfig.windowMs - now);\n\n return {\n allowed,\n remaining: Math.max(0, limitConfig.maxRequests - bucket.timestamps.length),\n limit: limitConfig.maxRequests,\n resetMs,\n category,\n };\n }\n\n private resolveCategory(gateway: string, domain: string, operation: string): 'query' | 'mutate' | 'spawn' {\n if (domain === 'orchestrate' && operation === 'spawn') {\n return 'spawn';\n }\n return gateway === 'query' ? 'query' : 'mutate';\n }\n\n private getLimitConfig(category: 'query' | 'mutate' | 'spawn'): RateLimitConfig {\n return this.config[category];\n }\n}\n\n/**\n * Creates a rate limiting middleware.\n */\nexport function createRateLimiter(config?: Partial<RateLimitingConfig>): Middleware {\n const limiter = new RateLimiter(config);\n\n return async (req: DispatchRequest, next: DispatchNext): Promise<DispatchResponse> => {\n const check = limiter.check(req);\n\n if (!check.allowed) {\n return {\n _meta: {\n gateway: req.gateway,\n domain: req.domain,\n operation: req.operation,\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n source: req.source,\n requestId: req.requestId,\n rateLimit: check,\n },\n success: false,\n error: {\n code: 'E_RATE_LIMIT_EXCEEDED',\n exitCode: 429, // Too Many Requests\n message: `Rate limit exceeded for category: ${check.category}. Please wait ${Math.ceil(check.resetMs / 1000)} seconds.`,\n }\n };\n }\n\n const response = await next();\n response._meta.rateLimit = {\n limit: check.limit,\n remaining: check.remaining,\n resetMs: check.resetMs,\n category: check.category,\n };\n \n return response;\n };\n}\n", "/**\n * Protocol Rule Definitions for CLEO MCP Server\n *\n * @task T2918\n * @epic T2908\n *\n * Defines validation rules for all 7 RCSD-IVTR protocols.\n *\n * Reference: lib/protocol-validation.sh, protocols/*.md\n */\n\n/**\n * RFC 2119 requirement levels\n */\nexport type RequirementLevel = 'MUST' | 'SHOULD' | 'MAY';\n\n/**\n * Violation severity\n */\nexport type ViolationSeverity = 'error' | 'warning';\n\n/**\n * Protocol rule definition\n */\nexport interface ProtocolRule {\n /** Rule identifier (e.g., RSCH-001) */\n id: string;\n /** RFC 2119 level */\n level: RequirementLevel;\n /** Rule description */\n message: string;\n /** Suggested fix command */\n fix: string;\n /** Validation function */\n validate: (\n manifestEntry: Record<string, unknown>,\n additionalData?: Record<string, unknown>\n ) => Promise<boolean> | boolean;\n}\n\n/**\n * Protocol violation result\n */\nexport interface ProtocolViolation {\n requirement: string;\n severity: ViolationSeverity;\n message: string;\n fix: string;\n}\n\n/**\n * Protocol validation result\n */\nexport interface ProtocolValidationResult {\n valid: boolean;\n violations: ProtocolViolation[];\n score: number;\n}\n\n/**\n * Helper: Check if field exists and is non-empty\n */\nfunction hasField(obj: Record<string, unknown>, field: string): boolean {\n const value = obj[field];\n return value !== null && value !== undefined && value !== '';\n}\n\n/**\n * Helper: Check array field length\n */\nfunction arrayLengthInRange(\n obj: Record<string, unknown>,\n field: string,\n min: number,\n max: number\n): boolean {\n const value = obj[field];\n if (!Array.isArray(value)) {\n return false;\n }\n return value.length >= min && value.length <= max;\n}\n\n/**\n * Helper: Check enum value\n */\nfunction hasEnumValue(obj: Record<string, unknown>, field: string, values: string[]): boolean {\n const value = obj[field];\n return typeof value === 'string' && values.includes(value);\n}\n\n/**\n * Research Protocol Rules (RSCH-*)\n */\nconst RESEARCH_RULES: ProtocolRule[] = [\n {\n id: 'RSCH-001',\n level: 'MUST',\n message: 'Research task must not modify code',\n fix: 'Revert code changes, research is read-only',\n validate: (_entry, data) => {\n return !data?.hasCodeChanges;\n },\n },\n {\n id: 'RSCH-002',\n level: 'SHOULD',\n message: 'Should document sources',\n fix: 'Add sources array to manifest',\n validate: (entry) => {\n return hasField(entry, 'sources');\n },\n },\n {\n id: 'RSCH-003',\n level: 'MUST',\n message: 'Must link research to task via linked_tasks',\n fix: 'Add linked_tasks array referencing the task and epic IDs',\n validate: (entry) => {\n const linkedTasks = entry.linked_tasks;\n return Array.isArray(linkedTasks) && linkedTasks.length > 0;\n },\n },\n {\n id: 'RSCH-004',\n level: 'MUST',\n message: 'Must append entry to MANIFEST.jsonl',\n fix: 'Append manifest entry with correct format',\n validate: (entry) => {\n return hasField(entry, 'id') && hasField(entry, 'file') && hasField(entry, 'date');\n },\n },\n {\n id: 'RSCH-005',\n level: 'MUST',\n message: 'Must write output file with required structure (title, summary, content)',\n fix: 'Ensure output file contains title, summary, and content sections',\n validate: (entry) => {\n return hasField(entry, 'file') && hasField(entry, 'title') && hasField(entry, 'status');\n },\n },\n {\n id: 'RSCH-006',\n level: 'MUST',\n message: 'Must include 3-7 key findings',\n fix: 'Add/remove findings in manifest entry',\n validate: (entry) => {\n return arrayLengthInRange(entry, 'key_findings', 3, 7);\n },\n },\n {\n id: 'RSCH-007',\n level: 'MUST',\n message: 'Must set agent_type: research',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['research']);\n },\n },\n];\n\n/**\n * Consensus Protocol Rules (CONS-*)\n */\nconst CONSENSUS_RULES: ProtocolRule[] = [\n {\n id: 'CONS-001',\n level: 'MUST',\n message: 'Must have voting matrix with \u22652 options',\n fix: 'Add more options to voting matrix',\n validate: (_entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return false;\n const options = votingMatrix.options as unknown[];\n return Array.isArray(options) && options.length >= 2;\n },\n },\n {\n id: 'CONS-002',\n level: 'MUST',\n message: 'Must include rationale for each voting option',\n fix: 'Add rationale string to each option in voting matrix',\n validate: (_entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return false;\n const options = votingMatrix.options as Array<{ rationale?: string }>;\n if (!Array.isArray(options)) return false;\n return options.every((opt) => typeof opt.rationale === 'string' && opt.rationale.length > 0);\n },\n },\n {\n id: 'CONS-003',\n level: 'MUST',\n message: 'Must include confidence scores (0.0-1.0)',\n fix: 'Fix confidence values in voting matrix',\n validate: (_entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return false;\n const options = votingMatrix.options as Array<{ confidence?: number }>;\n if (!Array.isArray(options)) return false;\n return options.every((opt) => {\n const conf = opt.confidence;\n return typeof conf === 'number' && conf >= 0.0 && conf <= 1.0;\n });\n },\n },\n {\n id: 'CONS-004',\n level: 'MUST',\n message: 'Must meet threshold (50% required)',\n fix: 'Increase confidence or add more supporting rationale',\n validate: (_entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return false;\n const options = votingMatrix.options as Array<{ confidence?: number }>;\n if (!Array.isArray(options)) return false;\n const maxConfidence = Math.max(...options.map((o) => o.confidence || 0));\n return maxConfidence >= 0.5;\n },\n },\n {\n id: 'CONS-005',\n level: 'SHOULD',\n message: 'Should record dissenting opinions',\n fix: 'Add dissent field to voting matrix for minority options',\n validate: (_entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return true; // Optional: SHOULD level\n return hasField(votingMatrix as Record<string, unknown>, 'dissent') ||\n hasField(votingMatrix as Record<string, unknown>, 'notes');\n },\n },\n {\n id: 'CONS-006',\n level: 'MUST',\n message: 'Must escalate to HITL when threshold not reached',\n fix: 'Set needs_followup with HITL escalation when no option meets threshold',\n validate: (entry, data) => {\n const votingMatrix = data?.votingMatrix as Record<string, unknown> | undefined;\n if (!votingMatrix) return false;\n const options = votingMatrix.options as Array<{ confidence?: number }>;\n if (!Array.isArray(options)) return false;\n const maxConfidence = Math.max(...options.map((o) => o.confidence || 0));\n // If threshold met, rule passes (no escalation needed)\n if (maxConfidence >= 0.5) return true;\n // If threshold not met, must have escalation flag\n const needsFollowup = entry.needs_followup;\n return Array.isArray(needsFollowup) && needsFollowup.length > 0;\n },\n },\n {\n id: 'CONS-007',\n level: 'MUST',\n message: 'Must set agent_type: analysis',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['analysis']);\n },\n },\n];\n\n/**\n * Specification Protocol Rules (SPEC-*)\n */\nconst SPECIFICATION_RULES: ProtocolRule[] = [\n {\n id: 'SPEC-001',\n level: 'MUST',\n message: 'Must include RFC 2119 keywords',\n fix: 'Add MUST/SHOULD/MAY requirements to specification',\n validate: (_entry, data) => {\n const fileContent = data?.fileContent as string | undefined;\n if (!fileContent) return false;\n return /\\b(MUST|SHOULD|MAY|MUST NOT|SHOULD NOT|MAY NOT)\\b/.test(fileContent);\n },\n },\n {\n id: 'SPEC-002',\n level: 'MUST',\n message: 'Must have version field',\n fix: 'Add version field to manifest entry',\n validate: (entry) => {\n return hasField(entry, 'version');\n },\n },\n {\n id: 'SPEC-003',\n level: 'SHOULD',\n message: 'Should include authority/scope section',\n fix: 'Add authority section defining specification scope',\n validate: (_entry, data) => {\n const fileContent = data?.fileContent as string | undefined;\n if (!fileContent) return true; // Optional\n return /\\b(authority|scope)\\b/i.test(fileContent);\n },\n },\n {\n id: 'SPEC-004',\n level: 'SHOULD',\n message: 'Should include conformance criteria',\n fix: 'Add conformance section defining how to verify compliance',\n validate: (_entry, data) => {\n const fileContent = data?.fileContent as string | undefined;\n if (!fileContent) return true; // SHOULD level, pass when no content\n return /\\b(conformance|compliance|verification)\\b/i.test(fileContent);\n },\n },\n {\n id: 'SPEC-005',\n level: 'SHOULD',\n message: 'Should include change log section',\n fix: 'Add change log tracking version history',\n validate: (_entry, data) => {\n const fileContent = data?.fileContent as string | undefined;\n if (!fileContent) return true; // SHOULD level\n return /\\b(change\\s*log|revision\\s*history|version\\s*history)\\b/i.test(fileContent);\n },\n },\n {\n id: 'SPEC-006',\n level: 'SHOULD',\n message: 'Should include references section',\n fix: 'Add references to related specifications and documents',\n validate: (_entry, data) => {\n const fileContent = data?.fileContent as string | undefined;\n if (!fileContent) return true; // SHOULD level\n return /\\b(references|see also|related)\\b/i.test(fileContent);\n },\n },\n {\n id: 'SPEC-007',\n level: 'MUST',\n message: 'Must set agent_type: specification',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['specification']);\n },\n },\n];\n\n/**\n * Decomposition Protocol Rules (DCMP-*)\n */\nconst DECOMPOSITION_RULES: ProtocolRule[] = [\n {\n id: 'DCMP-001',\n level: 'MUST',\n message: 'Must follow MECE principle (mutually exclusive, collectively exhaustive)',\n fix: 'Ensure tasks do not overlap and cover all requirements',\n validate: (_entry, data) => {\n // Check for duplicate task titles in sibling list (overlap detection)\n const siblingTitles = data?.siblingTitles as string[] | undefined;\n if (!siblingTitles) return true; // No sibling data available, pass\n const uniqueTitles = new Set(siblingTitles.map((t) => t.toLowerCase().trim()));\n return uniqueTitles.size === siblingTitles.length;\n },\n },\n {\n id: 'DCMP-002',\n level: 'MUST',\n message: 'Must map dependencies (no cycles allowed)',\n fix: 'Add depends field to tasks and verify no circular references',\n validate: (_entry, data) => {\n const hasCycles = data?.hasCycles as boolean | undefined;\n return hasCycles !== true; // Pass if no cycle data or no cycles\n },\n },\n {\n id: 'DCMP-003',\n level: 'MUST',\n message: 'Must respect max depth 3 (epic\u2192task\u2192subtask)',\n fix: 'Flatten hierarchy to max 3 levels',\n validate: (_entry, data) => {\n const depth = data?.hierarchyDepth as number | undefined;\n return depth === undefined || depth <= 3;\n },\n },\n {\n id: 'DCMP-004',\n level: 'MUST',\n message: 'Must verify atomicity for leaf tasks',\n fix: 'Ensure leaf tasks are atomic and independently completable',\n validate: (entry, data) => {\n const isLeaf = data?.isLeafTask as boolean | undefined;\n if (!isLeaf) return true; // Not a leaf task, pass\n // Leaf tasks must have a clear description\n return hasField(entry, 'description') &&\n typeof entry.description === 'string' &&\n (entry.description as string).length >= 10;\n },\n },\n {\n id: 'DCMP-005',\n level: 'MUST',\n message: 'Must not include time estimates',\n fix: 'Remove time estimates, use relative sizing',\n validate: (entry) => {\n const title = entry.title as string | undefined;\n const description = entry.description as string | undefined;\n const text = `${title} ${description}`;\n return !/\\b\\d+\\s*(hour|day|week|minute|hr|min)s?\\b/i.test(text);\n },\n },\n {\n id: 'DCMP-006',\n level: 'MUST',\n message: 'Must enforce max 7 siblings per parent',\n fix: 'Break epic into smaller sub-epics or reduce task count',\n validate: (_entry, data) => {\n const siblingCount = data?.siblingCount as number | undefined;\n return siblingCount === undefined || siblingCount <= 7;\n },\n },\n {\n id: 'DCMP-007',\n level: 'MUST',\n message: 'Must set agent_type: specification',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['specification']);\n },\n },\n];\n\n/**\n * Implementation Protocol Rules (IMPL-*)\n */\nconst IMPLEMENTATION_RULES: ProtocolRule[] = [\n {\n id: 'IMPL-003',\n level: 'MUST',\n message: 'Must include @task provenance tags',\n fix: 'Add @task T#### comment above new functions',\n validate: (_entry, data) => {\n const hasNewFunctions = data?.hasNewFunctions as boolean | undefined;\n const hasProvenanceTags = data?.hasProvenanceTags as boolean | undefined;\n\n // If no new functions, rule passes\n if (!hasNewFunctions) return true;\n\n // If new functions exist, must have provenance tags\n return hasProvenanceTags === true;\n },\n },\n {\n id: 'IMPL-004',\n level: 'SHOULD',\n message: 'Should pass all tests after implementation',\n fix: 'Run test suite and fix failing tests before completion',\n validate: (_entry, data) => {\n const testsPassed = data?.testsPassed as boolean | undefined;\n if (testsPassed === undefined) return true; // SHOULD level, pass when no data\n return testsPassed === true;\n },\n },\n {\n id: 'IMPL-005',\n level: 'MUST',\n message: 'Must use atomic file operations for all writes',\n fix: 'Use temp file \u2192 validate \u2192 backup \u2192 rename pattern for writes',\n validate: (_entry, data) => {\n const usesAtomicOps = data?.usesAtomicOperations as boolean | undefined;\n if (usesAtomicOps === undefined) return true; // No data available, pass\n return usesAtomicOps === true;\n },\n },\n {\n id: 'IMPL-006',\n level: 'SHOULD',\n message: 'Should follow project code style',\n fix: 'Run linter and fix style violations',\n validate: (_entry, data) => {\n const lintPassed = data?.lintPassed as boolean | undefined;\n if (lintPassed === undefined) return true; // SHOULD level, pass when no data\n return lintPassed === true;\n },\n },\n {\n id: 'IMPL-007',\n level: 'MUST',\n message: 'Must set agent_type: implementation',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['implementation']);\n },\n },\n];\n\n/**\n * Contribution Protocol Rules (CONT-*)\n */\nconst CONTRIBUTION_RULES: ProtocolRule[] = [\n {\n id: 'CONT-001',\n level: 'MUST',\n message: 'Must follow commit message conventions (<type>: <summary>)',\n fix: 'Use commit format: feat|fix|docs|test|refactor|chore: summary',\n validate: (_entry, data) => {\n const commitMessage = data?.commitMessage as string | undefined;\n if (!commitMessage) return true; // No commit data available, pass\n return /^(feat|fix|docs|test|refactor|chore)(\\(.+\\))?:\\s/.test(commitMessage);\n },\n },\n {\n id: 'CONT-002',\n level: 'MUST',\n message: 'Must include provenance tags (@task/@session)',\n fix: 'Add @task and @session tags to code',\n validate: (_entry, data) => {\n const hasNewFunctions = data?.hasNewFunctions as boolean | undefined;\n const hasProvenanceTags = data?.hasProvenanceTags as boolean | undefined;\n\n if (!hasNewFunctions) return true;\n return hasProvenanceTags === true;\n },\n },\n {\n id: 'CONT-003',\n level: 'MUST',\n message: 'Must pass validation gates before merge',\n fix: 'Run cleo --validate and fix all violations before merging',\n validate: (_entry, data) => {\n const validationPassed = data?.validationPassed as boolean | undefined;\n if (validationPassed === undefined) return true; // No data, pass\n return validationPassed === true;\n },\n },\n {\n id: 'CONT-005',\n level: 'SHOULD',\n message: 'Should flag conflicts with other sessions',\n fix: 'Check for conflicting sessions: cleo session list --active',\n validate: (_entry, data) => {\n const hasConflicts = data?.hasConflicts as boolean | undefined;\n if (hasConflicts === undefined) return true; // SHOULD level, pass when no data\n return hasConflicts === false;\n },\n },\n {\n id: 'CONT-007',\n level: 'MUST',\n message: 'Must set agent_type: implementation',\n fix: 'Update manifest entry agent_type field',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['implementation']);\n },\n },\n];\n\n/**\n * Release Protocol Rules (RLSE-*)\n */\nconst RELEASE_RULES: ProtocolRule[] = [\n {\n id: 'RLSE-001',\n level: 'MUST',\n message: 'Must follow version format (X.Y.Z or YYYY.M.patch)',\n fix: 'Use format X.Y.Z or YYYY.M.patch (e.g., 2026.2.0)',\n validate: (_entry, data) => {\n const version = data?.version as string | undefined;\n if (!version) return false;\n return /^\\d+\\.\\d+\\.\\d+$/.test(version);\n },\n },\n {\n id: 'RLSE-002',\n level: 'MUST',\n message: 'Must have changelog entry',\n fix: 'Add entry to CHANGELOG.md',\n validate: (_entry, data) => {\n const changelogEntry = data?.changelogEntry as string | undefined;\n return !!changelogEntry;\n },\n },\n {\n id: 'RLSE-003',\n level: 'SHOULD',\n message: 'Should pass all tests before release',\n fix: 'Run test suite: ./tests/run-all-tests.sh',\n validate: (_entry, data) => {\n const testsPassed = data?.testsPassed as boolean | undefined;\n if (testsPassed === undefined) return true; // SHOULD level, pass when no data\n return testsPassed === true;\n },\n },\n {\n id: 'RLSE-004',\n level: 'MUST',\n message: 'Must have git tag matching version',\n fix: 'Create git tag: git tag v{version}',\n validate: (_entry, data) => {\n const gitTag = data?.gitTag as string | undefined;\n const version = data?.version as string | undefined;\n if (!gitTag || !version) return true; // No git data available, pass\n // Tag should match version (with or without 'v' prefix)\n return gitTag === version || gitTag === `v${version}`;\n },\n },\n {\n id: 'RLSE-005',\n level: 'MUST',\n message: 'Must have consistent version across VERSION file, README, and package.json',\n fix: 'Run dev/validate-version.sh to check version consistency',\n validate: (_entry, data) => {\n const versionConsistent = data?.versionConsistent as boolean | undefined;\n if (versionConsistent === undefined) return true; // No data available, pass\n return versionConsistent === true;\n },\n },\n {\n id: 'RLSE-006',\n level: 'SHOULD',\n message: 'Should include rollback plan',\n fix: 'Document rollback procedure in release notes',\n validate: (_entry, data) => {\n const hasRollbackPlan = data?.hasRollbackPlan as boolean | undefined;\n if (hasRollbackPlan === undefined) return true; // SHOULD level, pass when no data\n return hasRollbackPlan === true;\n },\n },\n {\n id: 'RLSE-007',\n level: 'MUST',\n message: 'Must set agent_type: documentation or release',\n fix: 'Set agent_type appropriately',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['documentation', 'release']);\n },\n },\n];\n\n/**\n * Validation Protocol Rules (VALID-*)\n */\nconst VALIDATION_RULES: ProtocolRule[] = [\n {\n id: 'VALID-001',\n level: 'MUST',\n message: 'Must verify output matches spec',\n fix: 'Add validation_result field with pass/fail',\n validate: (entry) => {\n return hasField(entry, 'validation_result');\n },\n },\n {\n id: 'VALID-002',\n level: 'MUST',\n message: 'Must execute test suite during validation',\n fix: 'Run test suite and record results in manifest',\n validate: (_entry, data) => {\n const testResults = data?.testResults as Record<string, unknown> | undefined;\n if (!testResults) return true; // No test data, pass (tests may not apply)\n return hasField(testResults as Record<string, unknown>, 'pass_rate');\n },\n },\n {\n id: 'VALID-003',\n level: 'MUST',\n message: 'Must check protocol compliance',\n fix: 'Set status to complete/partial/blocked',\n validate: (entry) => {\n return hasEnumValue(entry, 'status', ['complete', 'partial', 'blocked']);\n },\n },\n {\n id: 'VALID-004',\n level: 'SHOULD',\n message: 'Should generate validation report',\n fix: 'Add key_findings array with validation details',\n validate: (entry) => {\n return hasField(entry, 'key_findings');\n },\n },\n {\n id: 'VALID-005',\n level: 'SHOULD',\n message: 'Should classify violation severity (error/warning)',\n fix: 'Include severity classification in validation results',\n validate: (_entry, data) => {\n const violations = data?.violations as Array<{ severity?: string }> | undefined;\n if (!violations || violations.length === 0) return true; // No violations, pass\n return violations.every(\n (v) => v.severity === 'error' || v.severity === 'warning'\n );\n },\n },\n {\n id: 'VALID-006',\n level: 'MUST',\n message: 'Must set agent_type: validation',\n fix: 'Set agent_type to validation',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['validation']);\n },\n },\n];\n\n/**\n * Testing Protocol Rules (TEST-*)\n */\nconst TESTING_RULES: ProtocolRule[] = [\n {\n id: 'TEST-001',\n level: 'MUST',\n message: 'Must use configured test framework',\n fix: 'Use project test framework (BATS for shell, Jest for TS)',\n validate: (_entry, data) => {\n const testFramework = data?.testFramework as string | undefined;\n if (!testFramework) return true; // No framework specified, pass\n const validFrameworks = ['bats', 'jest', 'vitest', 'mocha', 'pytest'];\n return validFrameworks.includes(testFramework.toLowerCase());\n },\n },\n {\n id: 'TEST-002',\n level: 'SHOULD',\n message: 'Should follow test file naming conventions',\n fix: 'Name test files: feature-name.bats or feature-name.test.ts',\n validate: (_entry, data) => {\n const testFiles = data?.testFiles as string[] | undefined;\n if (!testFiles || testFiles.length === 0) return true; // SHOULD level, pass\n return testFiles.every((f) =>\n /\\.(test|spec)\\.(ts|js|tsx|jsx)$/.test(f) || /\\.bats$/.test(f)\n );\n },\n },\n {\n id: 'TEST-003',\n level: 'SHOULD',\n message: 'Should meet coverage thresholds',\n fix: 'Increase test coverage to meet project thresholds',\n validate: (_entry, data) => {\n const coveragePercent = data?.coveragePercent as number | undefined;\n if (coveragePercent === undefined) return true; // SHOULD level, pass when no data\n return coveragePercent >= 80; // Default threshold\n },\n },\n {\n id: 'TEST-004',\n level: 'MUST',\n message: 'Must achieve 100% pass rate',\n fix: 'Fix failing tests before completion',\n validate: (_entry, data) => {\n const testResults = data?.testResults as Record<string, unknown> | undefined;\n if (!testResults) return false;\n const passRate = testResults.pass_rate as number | undefined;\n return passRate === 1.0 || passRate === 1;\n },\n },\n {\n id: 'TEST-005',\n level: 'MUST',\n message: 'Must cover all MUST requirements from specification',\n fix: 'Add tests for each MUST requirement in the spec',\n validate: (_entry, data) => {\n const mustRequirementsCovered = data?.mustRequirementsCovered as boolean | undefined;\n if (mustRequirementsCovered === undefined) return true; // No data, pass\n return mustRequirementsCovered === true;\n },\n },\n {\n id: 'TEST-006',\n level: 'MUST',\n message: 'Must include test summary in manifest',\n fix: 'Add key_findings array with test results',\n validate: (entry) => {\n return hasField(entry, 'key_findings');\n },\n },\n {\n id: 'TEST-007',\n level: 'MUST',\n message: 'Must set agent_type: testing',\n fix: 'Set agent_type to testing',\n validate: (entry) => {\n return hasEnumValue(entry, 'agent_type', ['testing']);\n },\n },\n];\n\n/**\n * Protocol rule registry\n */\nexport const PROTOCOL_RULES: Record<string, ProtocolRule[]> = {\n research: RESEARCH_RULES,\n consensus: CONSENSUS_RULES,\n specification: SPECIFICATION_RULES,\n decomposition: DECOMPOSITION_RULES,\n implementation: IMPLEMENTATION_RULES,\n contribution: CONTRIBUTION_RULES,\n release: RELEASE_RULES,\n validation: VALIDATION_RULES,\n testing: TESTING_RULES,\n};\n", "/**\n * Protocol Enforcement Middleware for CLEO MCP Server\n *\n * @task T2918\n * @epic T2908\n *\n * Validates RCSD-IVTR lifecycle compliance with exit codes 60-70.\n * Intercepts domain operations to enforce protocol requirements before execution.\n *\n * Reference: lib/protocol-validation.sh, docs/specs/MCP-SERVER-SPECIFICATION.md\n */\n\nimport { ProtocolRule, ProtocolViolation, ProtocolValidationResult } from './protocol-rules.js';\nimport { PROTOCOL_RULES } from './protocol-rules.js';\nimport { DomainRequest, DomainResponse } from './router.js';\nimport { ExitCode } from './exit-codes.js';\n\n/**\n * Protocol types aligned with RCSD-IVTR lifecycle\n */\nexport enum ProtocolType {\n RESEARCH = 'research',\n CONSENSUS = 'consensus',\n SPECIFICATION = 'specification',\n DECOMPOSITION = 'decomposition',\n IMPLEMENTATION = 'implementation',\n CONTRIBUTION = 'contribution',\n RELEASE = 'release',\n VALIDATION = 'validation',\n TESTING = 'testing',\n}\n\n/**\n * Exit code mapping for protocol violations\n */\nconst PROTOCOL_EXIT_CODES: Record<ProtocolType, ExitCode> = {\n [ProtocolType.RESEARCH]: ExitCode.E_PROTOCOL_RESEARCH,\n [ProtocolType.CONSENSUS]: ExitCode.E_PROTOCOL_CONSENSUS,\n [ProtocolType.SPECIFICATION]: ExitCode.E_PROTOCOL_SPECIFICATION,\n [ProtocolType.DECOMPOSITION]: ExitCode.E_PROTOCOL_DECOMPOSITION,\n [ProtocolType.IMPLEMENTATION]: ExitCode.E_PROTOCOL_IMPLEMENTATION,\n [ProtocolType.CONTRIBUTION]: ExitCode.E_PROTOCOL_CONTRIBUTION,\n [ProtocolType.RELEASE]: ExitCode.E_PROTOCOL_RELEASE,\n [ProtocolType.VALIDATION]: ExitCode.E_PROTOCOL_VALIDATION,\n [ProtocolType.TESTING]: ExitCode.E_TESTS_SKIPPED,\n};\n\n/**\n * Lifecycle stage dependencies\n */\nconst LIFECYCLE_GATES: Record<string, string[]> = {\n research: [],\n consensus: ['research'],\n specification: ['research', 'consensus'],\n decomposition: ['research', 'consensus', 'specification'],\n implementation: ['research', 'consensus', 'specification', 'decomposition'],\n contribution: [], // Cross-cutting: no strict prerequisites\n validation: ['implementation'],\n testing: ['implementation', 'validation'],\n release: ['implementation', 'validation', 'testing'],\n};\n\n/**\n * Violation log entry\n */\nexport interface ViolationLogEntry {\n timestamp: string;\n taskId?: string;\n protocol: ProtocolType;\n violations: ProtocolViolation[];\n score: number;\n blocked: boolean;\n}\n\n/**\n * Main protocol enforcement class\n */\nexport class ProtocolEnforcer {\n private violations: ViolationLogEntry[] = [];\n private strictMode: boolean;\n\n constructor(strictMode: boolean = true) {\n this.strictMode = strictMode;\n }\n\n /**\n * Validate protocol compliance for a manifest entry\n */\n async validateProtocol(\n protocol: ProtocolType,\n manifestEntry: Record<string, unknown>,\n additionalData?: Record<string, unknown>\n ): Promise<ProtocolValidationResult> {\n const rules = PROTOCOL_RULES[protocol];\n if (!rules) {\n return {\n valid: false,\n violations: [\n {\n requirement: 'UNKNOWN',\n severity: 'error',\n message: `Unknown protocol type: ${protocol}`,\n fix: 'Use valid protocol type',\n },\n ],\n score: 0,\n };\n }\n\n const violations: ProtocolViolation[] = [];\n let score = 100;\n\n // Validate each rule\n for (const rule of rules) {\n const violation = await this.validateRule(rule, manifestEntry, additionalData);\n if (violation) {\n violations.push(violation);\n score -= this.calculatePenalty(violation.severity);\n }\n }\n\n return {\n valid: violations.filter((v) => v.severity === 'error').length === 0,\n violations,\n score,\n };\n }\n\n /**\n * Validate a single rule\n */\n private async validateRule(\n rule: ProtocolRule,\n manifestEntry: Record<string, unknown>,\n additionalData?: Record<string, unknown>\n ): Promise<ProtocolViolation | null> {\n try {\n const isValid = await rule.validate(manifestEntry, additionalData);\n if (!isValid) {\n return {\n requirement: rule.id,\n severity: rule.level === 'MUST' ? 'error' : 'warning',\n message: rule.message,\n fix: rule.fix,\n };\n }\n return null;\n } catch (error) {\n return {\n requirement: rule.id,\n severity: 'error',\n message: `Validation error: ${error instanceof Error ? error.message : String(error)}`,\n fix: rule.fix,\n };\n }\n }\n\n /**\n * Check lifecycle gate prerequisites\n */\n async checkLifecycleGate(\n _taskId: string,\n targetStage: string,\n rcsdManifest?: Record<string, unknown>\n ): Promise<{\n passed: boolean;\n missingPrerequisites: string[];\n message: string;\n }> {\n const prerequisites = LIFECYCLE_GATES[targetStage] || [];\n\n if (!rcsdManifest) {\n // No manifest available - warn but allow\n return {\n passed: true,\n missingPrerequisites: [],\n message: 'No RCSD manifest found - skipping gate check',\n };\n }\n\n const missingPrerequisites: string[] = [];\n\n for (const prereq of prerequisites) {\n const stageStatus = rcsdManifest[prereq];\n if (stageStatus !== 'completed' && stageStatus !== 'skipped') {\n missingPrerequisites.push(prereq);\n }\n }\n\n if (missingPrerequisites.length > 0) {\n return {\n passed: false,\n missingPrerequisites,\n message: `Lifecycle gate failed: missing prerequisites [${missingPrerequisites.join(', ')}]`,\n };\n }\n\n return {\n passed: true,\n missingPrerequisites: [],\n message: 'All prerequisites met',\n };\n }\n\n /**\n * Record a protocol violation\n */\n recordViolation(\n protocol: ProtocolType,\n violations: ProtocolViolation[],\n score: number,\n taskId?: string\n ): void {\n const entry: ViolationLogEntry = {\n timestamp: new Date().toISOString(),\n taskId,\n protocol,\n violations,\n score,\n blocked: this.strictMode && violations.some((v) => v.severity === 'error'),\n };\n\n this.violations.push(entry);\n\n // Keep last 1000 violations\n if (this.violations.length > 1000) {\n this.violations.shift();\n }\n }\n\n /**\n * Get recent violations\n */\n getViolations(limit?: number): ViolationLogEntry[] {\n return limit ? this.violations.slice(-limit) : this.violations;\n }\n\n /**\n * Calculate penalty for violation severity\n */\n private calculatePenalty(severity: 'error' | 'warning'): number {\n return severity === 'error' ? 20 : 5;\n }\n\n /**\n * Middleware function for domain router\n *\n * Intercepts operations and validates protocol compliance before execution.\n */\n async enforceProtocol(\n request: DomainRequest,\n next: () => Promise<DomainResponse>\n ): Promise<DomainResponse> {\n // Only enforce on mutate operations that may create outputs\n if (request.gateway !== 'cleo_mutate') {\n return next();\n }\n\n // Check if operation requires protocol validation\n const requiresValidation = this.requiresProtocolValidation(request);\n if (!requiresValidation) {\n return next();\n }\n\n // Execute the operation\n const response = await next();\n\n // Skip validation if operation failed\n if (!response.success) {\n return response;\n }\n\n // Extract protocol type from request/response\n const protocol = this.detectProtocol(request, response);\n if (!protocol) {\n return response;\n }\n\n // Validate protocol compliance\n const manifestEntry = this.extractManifestEntry(response);\n if (!manifestEntry) {\n return response; // No manifest to validate\n }\n\n const result = await this.validateProtocol(protocol, manifestEntry, request.params);\n\n // Record violation\n const taskId = request.params?.taskId as string | undefined;\n this.recordViolation(protocol, result.violations, result.score, taskId);\n\n // If strict mode and errors found, block the operation\n if (this.strictMode && !result.valid) {\n return {\n _meta: response._meta,\n success: false,\n error: {\n code: `E_PROTOCOL_${protocol.toUpperCase()}`,\n exitCode: PROTOCOL_EXIT_CODES[protocol],\n message: `Protocol violation: ${protocol}`,\n details: {\n violations: result.violations,\n score: result.score,\n },\n fix: result.violations[0]?.fix || 'Fix protocol violations',\n alternatives: result.violations.map((v) => ({\n action: v.requirement,\n command: v.fix,\n })),\n },\n };\n }\n\n return response;\n }\n\n /**\n * Determine if operation requires protocol validation\n */\n private requiresProtocolValidation(request: DomainRequest): boolean {\n // Operations that create outputs requiring validation\n const validatedOperations = [\n 'research.inject',\n 'research.manifest.append',\n 'orchestrate.spawn',\n 'tasks.complete',\n 'release.prepare',\n 'release.commit',\n 'validate.compliance.record',\n ];\n\n const key = `${request.domain}.${request.operation}`;\n return validatedOperations.includes(key);\n }\n\n /**\n * Detect protocol type from request/response\n */\n private detectProtocol(request: DomainRequest, _response: DomainResponse): ProtocolType | null {\n // Check params for explicit protocol\n if (request.params?.protocolType) {\n return request.params.protocolType as ProtocolType;\n }\n\n // Infer from domain\n const domainProtocolMap: Record<string, ProtocolType> = {\n research: ProtocolType.RESEARCH,\n orchestrate: ProtocolType.DECOMPOSITION,\n release: ProtocolType.RELEASE,\n validate: ProtocolType.VALIDATION,\n testing: ProtocolType.TESTING,\n contribution: ProtocolType.CONTRIBUTION,\n };\n\n // Infer from operation name\n if (request.operation) {\n const opProtocolMap: Record<string, ProtocolType> = {\n 'consensus.record': ProtocolType.CONSENSUS,\n 'specification.validate': ProtocolType.SPECIFICATION,\n 'implementation.complete': ProtocolType.IMPLEMENTATION,\n 'contribution.merge': ProtocolType.CONTRIBUTION,\n };\n const opKey = `${request.domain}.${request.operation}`;\n if (opProtocolMap[opKey]) {\n return opProtocolMap[opKey];\n }\n }\n\n return domainProtocolMap[request.domain] || null;\n }\n\n /**\n * Extract manifest entry from response\n */\n private extractManifestEntry(response: DomainResponse): Record<string, unknown> | null {\n const data = response.data as Record<string, unknown> | undefined;\n if (!data) {\n return null;\n }\n\n // Check for manifest entry in response\n if (data.manifestEntry) {\n return data.manifestEntry as Record<string, unknown>;\n }\n\n // Check for entry field\n if (data.entry) {\n return data.entry as Record<string, unknown>;\n }\n\n return null;\n }\n\n /**\n * Set strict mode\n */\n setStrictMode(strict: boolean): void {\n this.strictMode = strict;\n }\n\n /**\n * Get strict mode status\n */\n isStrictMode(): boolean {\n return this.strictMode;\n }\n}\n\n/**\n * Default protocol enforcer instance\n */\nexport const protocolEnforcer = new ProtocolEnforcer();\n", "/**\n * Gate Validators for 4-Layer Verification System\n *\n * @task T2936\n * @task T3138\n * @epic T2908\n *\n * Individual validator functions for each gate layer:\n * - Layer 1: Schema validation (JSON Schema, format constraints)\n * - Layer 2: Semantic validation (business rules, anti-hallucination)\n * - Layer 3: Referential validation (cross-entity integrity)\n * - Layer 4: Protocol validation (RCSD-IVTR lifecycle)\n *\n * Reference: docs/specs/MCP-SERVER-SPECIFICATION.md Section 8\n */\n\nimport {\n GateLayer,\n GateStatus,\n GateViolation,\n LayerResult,\n OperationContext,\n WorkflowGateName,\n WorkflowGateTracker,\n WORKFLOW_GATE_SEQUENCE,\n isValidWorkflowGateName,\n} from './verification-gates.js';\nimport { ErrorSeverity } from './exit-codes.js';\nimport { ProtocolEnforcer } from './protocol-enforcement.js';\n\n/**\n * Layer 1: Schema Validation\n *\n * Validates operation parameters against JSON Schema definitions.\n * Checks required fields, data types, and format constraints.\n */\nexport async function validateLayer1Schema(\n context: OperationContext\n): Promise<LayerResult> {\n const violations: GateViolation[] = [];\n\n // Task ID validation (if present)\n if (context.params?.taskId) {\n const taskId = context.params.taskId as string;\n if (!taskId.match(/^T[0-9]+$/)) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_TASK_ID',\n message: `Invalid task ID format: ${taskId}`,\n field: 'taskId',\n value: taskId,\n constraint: 'Must match pattern ^T[0-9]+$',\n fix: 'Use format T followed by digits (e.g., T1234)',\n });\n }\n }\n\n // Title validation (for create/update operations)\n if (context.params?.title !== undefined) {\n const title = context.params.title as string;\n if (typeof title !== 'string' || title.length < 5 || title.length > 100) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_TITLE',\n message: 'Title must be 5-100 characters',\n field: 'title',\n value: title,\n constraint: 'length: 5-100',\n fix: 'Provide a title between 5 and 100 characters',\n });\n }\n }\n\n // Description validation (Section 8.1: 10-1000 characters)\n if (context.params?.description !== undefined) {\n const description = context.params.description as string;\n if (typeof description !== 'string' || description.length < 10 || description.length > 1000) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_DESCRIPTION',\n message: 'Description must be 10-1000 characters',\n field: 'description',\n value: typeof description === 'string' ? `${description.substring(0, 50)}...` : description,\n constraint: 'length: 10-1000',\n fix: 'Provide a description between 10 and 1000 characters',\n });\n }\n }\n\n // Manifest ID format validation (Section 8.2: ^T\\d{3,}-[a-z0-9-]+$)\n if (context.params?.manifestEntry) {\n const entry = context.params.manifestEntry as Record<string, unknown>;\n if (entry.id) {\n const manifestId = entry.id as string;\n if (!manifestId.match(/^T\\d{3,}-[a-z0-9-]+$/)) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_MANIFEST_ID',\n message: `Invalid manifest ID format: ${manifestId}`,\n field: 'manifestEntry.id',\n value: manifestId,\n constraint: 'Must match ^T\\\\d{3,}-[a-z0-9-]+$',\n fix: 'Use format T####-slug (e.g., T1234-research-output)',\n });\n }\n }\n\n // Date format validation (Section 8.2: ISO 8601 YYYY-MM-DD)\n if (entry.date) {\n const date = entry.date as string;\n if (!date.match(/^\\d{4}-\\d{2}-\\d{2}$/)) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_DATE_FORMAT',\n message: `Invalid date format: ${date}`,\n field: 'manifestEntry.date',\n value: date,\n constraint: 'Must be ISO 8601 YYYY-MM-DD',\n fix: 'Use date format YYYY-MM-DD (e.g., 2026-02-06)',\n });\n }\n }\n\n // Agent type validation (Section 8.2: known protocol type)\n if (entry.agent_type) {\n const agentType = entry.agent_type as string;\n const validAgentTypes = [\n 'research', 'analysis', 'specification', 'implementation',\n 'testing', 'validation', 'documentation', 'release',\n ];\n if (!validAgentTypes.includes(agentType)) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_AGENT_TYPE',\n message: `Invalid agent type: ${agentType}`,\n field: 'manifestEntry.agent_type',\n value: agentType,\n constraint: `Must be one of: ${validAgentTypes.join(', ')}`,\n fix: `Use one of: ${validAgentTypes.join(', ')}`,\n });\n }\n }\n }\n\n // Status validation\n if (context.params?.status) {\n const status = context.params.status as string;\n const validStatuses = ['pending', 'active', 'blocked', 'done'];\n if (!validStatuses.includes(status)) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_STATUS',\n message: `Invalid status: ${status}`,\n field: 'status',\n value: status,\n constraint: `Must be one of: ${validStatuses.join(', ')}`,\n fix: `Use one of: ${validStatuses.join(', ')}`,\n });\n }\n }\n\n // Priority validation - accepts both string names and numeric 1-9\n // @task T4572 - Fixed to accept canonical string format per todo.schema.json\n if (context.params?.priority !== undefined) {\n const priority = context.params.priority;\n const validStringPriorities = ['critical', 'high', 'medium', 'low'];\n let isValid = false;\n\n if (typeof priority === 'string') {\n // Accept canonical string values\n if (validStringPriorities.includes(priority.toLowerCase())) {\n isValid = true;\n }\n // Accept numeric strings \"1\"-\"9\"\n const asNum = Number(priority);\n if (!Number.isNaN(asNum) && Number.isInteger(asNum) && asNum >= 1 && asNum <= 9) {\n isValid = true;\n }\n } else if (typeof priority === 'number') {\n // Accept numeric 1-9\n if (Number.isInteger(priority) && priority >= 1 && priority <= 9) {\n isValid = true;\n }\n }\n\n if (!isValid) {\n violations.push({\n layer: GateLayer.SCHEMA,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_PRIORITY',\n message: `Invalid priority: ${priority}. Must be critical|high|medium|low or numeric 1-9`,\n field: 'priority',\n value: priority,\n constraint: 'critical|high|medium|low or 1-9',\n fix: 'Set priority to critical, high, medium, low, or a number 1-9',\n });\n }\n }\n\n return {\n layer: GateLayer.SCHEMA,\n status: violations.length > 0 ? GateStatus.FAILED : GateStatus.PASSED,\n passed: violations.length === 0,\n violations,\n duration_ms: 0,\n };\n}\n\n/**\n * Layer 2: Semantic Validation\n *\n * Validates business rules and logical constraints.\n * Checks hierarchy depth, sibling limits, title/description uniqueness.\n */\nexport async function validateLayer2Semantic(\n context: OperationContext\n): Promise<LayerResult> {\n const violations: GateViolation[] = [];\n\n // Title and description must be different (anti-hallucination)\n if (context.params?.title && context.params?.description) {\n const title = context.params.title as string;\n const description = context.params.description as string;\n if (title === description) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.ERROR,\n code: 'E_TITLE_DESCRIPTION_SAME',\n message: 'Title and description must be different',\n field: 'description',\n constraint: 'must differ from title',\n fix: 'Provide a unique description that explains the task',\n });\n }\n }\n\n // No future timestamps (Section 8.1: created/updated <= now)\n if (context.params?.created || context.params?.updated) {\n const now = new Date();\n for (const field of ['created', 'updated'] as const) {\n const value = context.params?.[field] as string | undefined;\n if (value) {\n const timestamp = new Date(value);\n if (!isNaN(timestamp.getTime()) && timestamp > now) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.ERROR,\n code: 'E_FUTURE_TIMESTAMP',\n message: `Timestamp ${field} cannot be in the future: ${value}`,\n field,\n value,\n constraint: `${field} <= current time`,\n fix: `Set ${field} to current or past timestamp`,\n });\n }\n }\n }\n }\n\n // Manifest date must not be future (Section 8.1)\n if (context.params?.manifestEntry) {\n const entry = context.params.manifestEntry as Record<string, unknown>;\n if (entry.date) {\n const dateStr = entry.date as string;\n const today = new Date().toISOString().split('T')[0];\n if (dateStr > today) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.ERROR,\n code: 'E_FUTURE_TIMESTAMP',\n message: `Manifest date cannot be in the future: ${dateStr}`,\n field: 'manifestEntry.date',\n value: dateStr,\n constraint: 'date <= today',\n fix: 'Set date to today or earlier',\n });\n }\n }\n }\n\n // Circular dependency check (if depends specified)\n if (context.params?.depends) {\n const depends = context.params.depends as string[];\n const taskId = context.params?.taskId as string | undefined;\n if (taskId && depends.includes(taskId)) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.ERROR,\n code: 'E_CIRCULAR_DEPENDENCY',\n message: 'Task cannot depend on itself',\n field: 'depends',\n constraint: 'no self-reference',\n fix: 'Remove self-reference from dependencies',\n });\n }\n }\n\n // Session scope validation\n if (context.domain === 'session' && context.operation === 'start') {\n const scope = context.params?.scope as string | undefined;\n if (scope && !scope.match(/^(epic|task|global):/)) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_SCOPE',\n message: `Invalid session scope format: ${scope}`,\n field: 'scope',\n constraint: 'Must be epic:<id>, task:<id>, or global',\n fix: 'Use format: epic:T1234, task:T5678, or global',\n });\n }\n }\n\n // Notes required for completion (if configured)\n if (context.operation === 'complete' && context.params?.notes === undefined) {\n violations.push({\n layer: GateLayer.SEMANTIC,\n severity: ErrorSeverity.WARNING,\n code: 'E_NOTES_RECOMMENDED',\n message: 'Completion notes are recommended',\n field: 'notes',\n constraint: 'should be present',\n fix: 'Add --notes \"...\" to document completion',\n });\n }\n\n return {\n layer: GateLayer.SEMANTIC,\n status: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length > 0\n ? GateStatus.FAILED\n : GateStatus.PASSED,\n passed: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length === 0,\n violations,\n duration_ms: 0,\n };\n}\n\n/**\n * Layer 3: Referential Validation\n *\n * Validates cross-entity references and relationships.\n * Checks task existence, parent/child relationships, dependencies.\n */\nexport async function validateLayer3Referential(\n context: OperationContext\n): Promise<LayerResult> {\n const violations: GateViolation[] = [];\n\n // Parent task validation (if specified)\n if (context.params?.parent) {\n const parent = context.params.parent as string;\n // Note: In production, this would call CLIExecutor to check existence\n // For now, we validate format\n if (!parent.match(/^T[0-9]+$/)) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_PARENT_REF',\n message: `Invalid parent reference: ${parent}`,\n field: 'parent',\n value: parent,\n constraint: 'Must be valid task ID',\n fix: 'Verify parent task exists with: cleo exists <id>',\n });\n }\n }\n\n // Dependency validation\n if (context.params?.depends) {\n const depends = context.params.depends as string[];\n for (const depId of depends) {\n if (!depId.match(/^T[0-9]+$/)) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_DEPENDENCY_REF',\n message: `Invalid dependency reference: ${depId}`,\n field: 'depends',\n value: depId,\n constraint: 'Must be valid task ID',\n fix: 'Verify dependency exists with: cleo find --id <id>',\n });\n }\n }\n }\n\n // Task existence validation (for update/complete/delete operations)\n if (['update', 'complete', 'delete', 'archive', 'reopen'].includes(context.operation)) {\n const taskId = context.params?.taskId as string | undefined;\n if (!taskId) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_TASK_ID_REQUIRED',\n message: 'Task ID is required for this operation',\n field: 'taskId',\n constraint: 'required',\n fix: 'Provide task ID with --taskId T####',\n });\n }\n }\n\n // Task start validation\n if (context.domain === 'tasks' && context.operation === 'start') {\n const taskId = context.params?.taskId as string | undefined;\n if (taskId && !taskId.match(/^T[0-9]+$/)) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_TASK_REF',\n message: `Invalid task reference: ${taskId}`,\n field: 'taskId',\n value: taskId,\n constraint: 'Must be valid task ID',\n fix: 'Use valid task ID format: T####',\n });\n }\n }\n\n // Hierarchy depth validation (Section 8.1: max 3 levels)\n if (context.params?.depth !== undefined) {\n const depth = context.params.depth as number;\n if (typeof depth === 'number' && depth > VALIDATION_RULES.MAX_DEPTH) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_DEPTH_EXCEEDED',\n message: `Hierarchy depth ${depth} exceeds maximum of ${VALIDATION_RULES.MAX_DEPTH}`,\n field: 'depth',\n value: depth,\n constraint: `max depth: ${VALIDATION_RULES.MAX_DEPTH}`,\n fix: 'Flatten hierarchy to max 3 levels (epic -> task -> subtask)',\n });\n }\n }\n\n // Sibling limit validation (Section 8.1: max 7 per parent)\n if (context.params?.siblingCount !== undefined) {\n const siblingCount = context.params.siblingCount as number;\n if (typeof siblingCount === 'number' && siblingCount >= VALIDATION_RULES.MAX_SIBLINGS) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_SIBLING_LIMIT',\n message: `Parent already has ${siblingCount} children (max ${VALIDATION_RULES.MAX_SIBLINGS})`,\n field: 'siblingCount',\n value: siblingCount,\n constraint: `max siblings: ${VALIDATION_RULES.MAX_SIBLINGS}`,\n fix: 'Create a new parent to group related tasks',\n });\n }\n }\n\n // Manifest file reference validation (Section 8.2: referenced file readable)\n if (context.params?.manifestEntry) {\n const entry = context.params.manifestEntry as Record<string, unknown>;\n if (typeof entry.file === 'string' && entry.file.length === 0) {\n violations.push({\n layer: GateLayer.REFERENTIAL,\n severity: ErrorSeverity.ERROR,\n code: 'E_EMPTY_FILE_REF',\n message: 'Manifest entry file reference cannot be empty',\n field: 'manifestEntry.file',\n value: entry.file,\n constraint: 'must be non-empty file path',\n fix: 'Provide a valid file path in manifest entry',\n });\n }\n }\n\n return {\n layer: GateLayer.REFERENTIAL,\n status: violations.length > 0 ? GateStatus.FAILED : GateStatus.PASSED,\n passed: violations.length === 0,\n violations,\n duration_ms: 0,\n };\n}\n\n/**\n * Layer 4: Protocol Validation\n *\n * Validates RCSD-IVTR lifecycle compliance and protocol requirements.\n * Checks lifecycle gates, protocol-specific rules, provenance tags.\n */\nexport async function validateLayer4Protocol(\n context: OperationContext,\n _enforcer: ProtocolEnforcer\n): Promise<LayerResult> {\n const violations: GateViolation[] = [];\n\n // Skip protocol validation for non-protocol operations\n if (!context.protocolType) {\n return {\n layer: GateLayer.PROTOCOL,\n status: GateStatus.SKIPPED,\n passed: true,\n violations: [],\n duration_ms: 0,\n };\n }\n\n // Lifecycle gate validation (for spawn/complete operations)\n if (context.operation === 'spawn' || context.operation === 'complete') {\n const protocolType = context.protocolType;\n\n // Check lifecycle prerequisites\n const lifecycleGates: Record<string, string[]> = {\n research: [],\n consensus: ['research'],\n specification: ['research', 'consensus'],\n decomposition: ['research', 'consensus', 'specification'],\n implementation: ['research', 'consensus', 'specification', 'decomposition'],\n validation: ['implementation'],\n testing: ['implementation', 'validation'],\n release: ['implementation', 'validation', 'testing'],\n };\n\n const requiredGates = lifecycleGates[protocolType] || [];\n if (requiredGates.length > 0) {\n // Note: In production, check actual gate status via CLIExecutor\n // For now, we document the requirement\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.INFO,\n code: 'E_LIFECYCLE_PREREQUISITES',\n message: `This operation requires prior stages: ${requiredGates.join(', ')}`,\n field: 'lifecycle',\n constraint: `prerequisites: ${requiredGates.join(', ')}`,\n fix: 'Ensure prior lifecycle stages are complete',\n });\n }\n }\n\n // Manifest validation (for complete operations)\n if (context.operation === 'complete') {\n const manifestEntry = context.params?.manifestEntry as Record<string, unknown> | undefined;\n if (manifestEntry) {\n // Required manifest fields\n const requiredFields = ['id', 'file', 'title', 'date', 'status', 'agent_type'];\n for (const field of requiredFields) {\n if (!manifestEntry[field]) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_MANIFEST_FIELD_MISSING',\n message: `Manifest entry missing required field: ${field}`,\n field: `manifestEntry.${field}`,\n constraint: 'required',\n fix: `Add ${field} to manifest entry`,\n });\n }\n }\n\n // Status enum validation\n const status = manifestEntry.status as string;\n if (!['complete', 'partial', 'blocked'].includes(status)) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_MANIFEST_STATUS',\n message: `Invalid manifest status: ${status}`,\n field: 'manifestEntry.status',\n value: status,\n constraint: 'Must be: complete, partial, or blocked',\n fix: 'Set status to complete, partial, or blocked',\n });\n }\n }\n }\n\n // Key findings validation for research protocol (Section 8.2: 3-7 items)\n if (context.protocolType === 'research' && context.operation === 'complete') {\n const manifestEntry = context.params?.manifestEntry as Record<string, unknown> | undefined;\n if (manifestEntry?.key_findings) {\n const findings = manifestEntry.key_findings;\n if (!Array.isArray(findings) || findings.length < VALIDATION_RULES.KEY_FINDINGS_MIN || findings.length > VALIDATION_RULES.KEY_FINDINGS_MAX) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_KEY_FINDINGS_COUNT',\n message: `Research must have ${VALIDATION_RULES.KEY_FINDINGS_MIN}-${VALIDATION_RULES.KEY_FINDINGS_MAX} key findings, got ${Array.isArray(findings) ? findings.length : 0}`,\n field: 'manifestEntry.key_findings',\n value: Array.isArray(findings) ? findings.length : findings,\n constraint: `count: ${VALIDATION_RULES.KEY_FINDINGS_MIN}-${VALIDATION_RULES.KEY_FINDINGS_MAX}`,\n fix: 'Adjust key findings to have 3-7 items',\n });\n }\n }\n }\n\n // Provenance validation (for implementation protocol)\n if (context.protocolType === 'implementation') {\n const files = context.params?.files as string[] | undefined;\n if (files && files.length > 0) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.WARNING,\n code: 'E_PROVENANCE_CHECK',\n message: 'Implementation files should include @task provenance tags',\n field: 'files',\n constraint: 'should include @task comments',\n fix: 'Add @task T#### comments to new functions/classes',\n });\n }\n }\n\n return {\n layer: GateLayer.PROTOCOL,\n status: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length > 0\n ? GateStatus.FAILED\n : GateStatus.PASSED,\n passed: violations.filter((v) => v.severity === ErrorSeverity.ERROR).length === 0,\n violations,\n duration_ms: 0,\n };\n}\n\n/**\n * Validation rule definitions for reuse\n */\nexport const VALIDATION_RULES = {\n TASK_ID_PATTERN: /^T[0-9]+$/,\n MANIFEST_ID_PATTERN: /^T\\d{3,}-[a-z0-9-]+$/,\n DATE_FORMAT_PATTERN: /^\\d{4}-\\d{2}-\\d{2}$/,\n TITLE_MIN_LENGTH: 5,\n TITLE_MAX_LENGTH: 100,\n DESCRIPTION_MIN_LENGTH: 10,\n DESCRIPTION_MAX_LENGTH: 1000,\n VALID_STATUSES: ['pending', 'active', 'blocked', 'done'] as const,\n VALID_MANIFEST_STATUSES: ['complete', 'partial', 'blocked'] as const,\n VALID_AGENT_TYPES: [\n 'research', 'analysis', 'specification', 'implementation',\n 'testing', 'validation', 'documentation', 'release',\n ] as const,\n VALID_PRIORITIES: ['critical', 'high', 'medium', 'low'] as const,\n PRIORITY_NUMERIC_MIN: 1,\n PRIORITY_NUMERIC_MAX: 9,\n MAX_DEPTH: 3,\n MAX_SIBLINGS: 7,\n KEY_FINDINGS_MIN: 3,\n KEY_FINDINGS_MAX: 7,\n};\n\n/**\n * Helper to check if a field is required for an operation\n */\nexport function isFieldRequired(\n domain: string,\n operation: string,\n field: string\n): boolean {\n const requirements: Record<string, Record<string, string[]>> = {\n tasks: {\n add: ['title', 'description'],\n update: ['taskId'],\n complete: ['taskId'],\n delete: ['taskId'],\n start: ['taskId'],\n },\n session: {\n start: ['scope'],\n },\n };\n\n return requirements[domain]?.[operation]?.includes(field) ?? false;\n}\n\n// ============================================================================\n// Section 7: Workflow Gate Validators\n// ============================================================================\n\n/**\n * Valid workflow gate agent names per Section 7.2\n */\nexport const VALID_WORKFLOW_AGENTS = ['coder', 'testing', 'qa', 'cleanup', 'security', 'docs'] as const;\n\n/**\n * Valid workflow gate status values per Section 7.3\n */\nexport const VALID_WORKFLOW_GATE_STATUSES = [null, 'passed', 'failed', 'blocked'] as const;\n\n/**\n * Validate a workflow gate name\n *\n * @task T3141\n */\nexport function validateWorkflowGateName(name: string): boolean {\n return isValidWorkflowGateName(name);\n}\n\n/**\n * Validate a workflow gate status value per Section 7.3\n *\n * @task T3141\n */\nexport function validateWorkflowGateStatus(\n status: unknown\n): status is null | 'passed' | 'failed' | 'blocked' {\n return status === null || status === 'passed' || status === 'failed' || status === 'blocked';\n}\n\n/**\n * Validate a gate update operation.\n *\n * Checks that:\n * - Gate name is valid\n * - Status value is valid\n * - Agent matches expected agent for the gate\n * - Dependencies are met for pass operations\n *\n * @task T3141\n */\nexport function validateWorkflowGateUpdate(\n gateName: string,\n status: string,\n agent?: string,\n tracker?: WorkflowGateTracker\n): GateViolation[] {\n const violations: GateViolation[] = [];\n\n // Validate gate name\n if (!isValidWorkflowGateName(gateName)) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_GATE',\n message: `Invalid workflow gate name: ${gateName}`,\n field: 'gateName',\n value: gateName,\n constraint: `Must be one of: ${WORKFLOW_GATE_SEQUENCE.join(', ')}`,\n fix: `Use a valid gate name: ${WORKFLOW_GATE_SEQUENCE.join(', ')}`,\n });\n return violations;\n }\n\n // Validate status\n if (status !== 'passed' && status !== 'failed') {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_GATE_STATUS',\n message: `Invalid gate status for update: ${status}`,\n field: 'status',\n value: status,\n constraint: 'Must be \"passed\" or \"failed\" for update operations',\n fix: 'Use status \"passed\" or \"failed\"',\n });\n }\n\n // Validate agent match (if tracker provided for context)\n if (agent && tracker) {\n const gateState = tracker.getGateState(gateName as WorkflowGateName);\n if (gateState && agent !== gateState.agent) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_INVALID_AGENT',\n message: `Agent \"${agent}\" is not authorized for gate \"${gateName}\" (expected: ${gateState.agent})`,\n field: 'agent',\n value: agent,\n constraint: `Must be agent: ${gateState.agent}`,\n fix: `Use the correct agent: ${gateState.agent}`,\n });\n }\n }\n\n // Validate dependencies are met for pass operations\n if (status === 'passed' && tracker) {\n if (!tracker.canAttempt(gateName as WorkflowGateName)) {\n violations.push({\n layer: GateLayer.PROTOCOL,\n severity: ErrorSeverity.ERROR,\n code: 'E_GATE_DEPENDENCY',\n message: `Cannot pass gate \"${gateName}\": dependencies not met`,\n field: 'gateName',\n value: gateName,\n constraint: 'All dependency gates must be passed first',\n fix: 'Pass all prerequisite gates first',\n });\n }\n }\n\n return violations;\n}\n", "/**\n * Verification Gate System for CLEO MCP Server\n *\n * @task T2936\n * @epic T2908\n *\n * Implements 4-layer validation gate system:\n * Layer 1: Schema Validation (JSON Schema compliance)\n * Layer 2: Semantic Validation (Business rules)\n * Layer 3: Referential Validation (Cross-entity integrity)\n * Layer 4: Protocol Validation (RCSD-IVTR lifecycle)\n *\n * Reference: docs/specs/MCP-SERVER-SPECIFICATION.md Section 7\n */\n\nimport { ExitCode, ErrorCategory, ErrorSeverity } from './exit-codes.js';\nimport { ProtocolEnforcer, ProtocolType } from './protocol-enforcement.js';\n\nimport {\n validateLayer1Schema,\n validateLayer2Semantic,\n validateLayer3Referential,\n validateLayer4Protocol,\n} from './gate-validators.js';\n\n/**\n * Gate layer enumeration\n */\nexport enum GateLayer {\n SCHEMA = 1,\n SEMANTIC = 2,\n REFERENTIAL = 3,\n PROTOCOL = 4,\n}\n\n/**\n * Gate status for each layer\n */\nexport enum GateStatus {\n PENDING = 'pending',\n PASSED = 'passed',\n FAILED = 'failed',\n BLOCKED = 'blocked',\n SKIPPED = 'skipped',\n}\n\n/**\n * Violation detail for a specific gate layer\n */\nexport interface GateViolation {\n layer: GateLayer;\n severity: ErrorSeverity;\n code: string;\n message: string;\n field?: string;\n value?: unknown;\n constraint?: string;\n fix?: string;\n}\n\n/**\n * Result from a single gate layer validation\n */\nexport interface LayerResult {\n layer: GateLayer;\n status: GateStatus;\n passed: boolean;\n violations: GateViolation[];\n duration_ms: number;\n}\n\n/**\n * Complete verification result across all 4 layers\n */\nexport interface VerificationResult {\n passed: boolean;\n layers: Record<GateLayer, LayerResult>;\n totalViolations: number;\n exitCode: ExitCode;\n category: ErrorCategory;\n summary: string;\n blockedAt?: GateLayer;\n}\n\n/**\n * Operation context for gate validation\n */\nexport interface OperationContext {\n domain: string;\n operation: string;\n gateway: 'cleo_query' | 'cleo_mutate';\n params?: Record<string, unknown>;\n taskId?: string;\n protocolType?: ProtocolType;\n}\n\n/**\n * Main Verification Gate class\n *\n * Orchestrates 4-layer validation and determines pass/fail status.\n * Each layer must pass before proceeding to the next.\n */\nexport class VerificationGate {\n private protocolEnforcer: ProtocolEnforcer;\n private strictMode: boolean;\n\n constructor(strictMode: boolean = true) {\n this.protocolEnforcer = new ProtocolEnforcer(strictMode);\n this.strictMode = strictMode;\n }\n\n /**\n * Execute all 4 gate layers sequentially\n *\n * Stops at first failure unless in advisory mode.\n */\n async verifyOperation(context: OperationContext): Promise<VerificationResult> {\n const layers: Record<GateLayer, LayerResult> = {} as Record<GateLayer, LayerResult>;\n\n // Layer 1: Schema Validation\n const schemaResult = await this.runLayer(\n GateLayer.SCHEMA,\n () => validateLayer1Schema(context)\n );\n layers[GateLayer.SCHEMA] = schemaResult;\n\n if (!schemaResult.passed && this.strictMode) {\n return this.buildFailureResult(layers, GateLayer.SCHEMA);\n }\n\n // Layer 2: Semantic Validation\n const semanticResult = await this.runLayer(\n GateLayer.SEMANTIC,\n () => validateLayer2Semantic(context)\n );\n layers[GateLayer.SEMANTIC] = semanticResult;\n\n if (!semanticResult.passed && this.strictMode) {\n return this.buildFailureResult(layers, GateLayer.SEMANTIC);\n }\n\n // Layer 3: Referential Validation\n const referentialResult = await this.runLayer(\n GateLayer.REFERENTIAL,\n () => validateLayer3Referential(context)\n );\n layers[GateLayer.REFERENTIAL] = referentialResult;\n\n if (!referentialResult.passed && this.strictMode) {\n return this.buildFailureResult(layers, GateLayer.REFERENTIAL);\n }\n\n // Layer 4: Protocol Validation\n const protocolResult = await this.runLayer(\n GateLayer.PROTOCOL,\n () => validateLayer4Protocol(context, this.protocolEnforcer)\n );\n layers[GateLayer.PROTOCOL] = protocolResult;\n\n if (!protocolResult.passed && this.strictMode) {\n return this.buildFailureResult(layers, GateLayer.PROTOCOL);\n }\n\n // All gates passed\n return this.buildSuccessResult(layers);\n }\n\n /**\n * Run a single validation layer with timing\n */\n private async runLayer(\n layer: GateLayer,\n validator: () => Promise<LayerResult>\n ): Promise<LayerResult> {\n const startTime = Date.now();\n\n try {\n const result = await validator();\n result.duration_ms = Date.now() - startTime;\n return result;\n } catch (error) {\n // Convert exceptions to layer failures\n return {\n layer,\n status: GateStatus.FAILED,\n passed: false,\n violations: [\n {\n layer,\n severity: ErrorSeverity.ERROR,\n code: 'E_VALIDATION_ERROR',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n duration_ms: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Build success result when all gates pass\n */\n private buildSuccessResult(layers: Record<GateLayer, LayerResult>): VerificationResult {\n return {\n passed: true,\n layers,\n totalViolations: 0,\n exitCode: ExitCode.SUCCESS,\n category: ErrorCategory.GENERAL,\n summary: 'All verification gates passed',\n };\n }\n\n /**\n * Build failure result when a gate fails\n */\n private buildFailureResult(\n layers: Record<GateLayer, LayerResult>,\n blockedAt: GateLayer\n ): VerificationResult {\n const failedLayer = layers[blockedAt];\n const totalViolations = Object.values(layers).reduce(\n (sum, layer) => sum + layer.violations.length,\n 0\n );\n\n // Determine exit code based on layer and violation type\n let exitCode = ExitCode.E_VALIDATION_ERROR;\n let category = ErrorCategory.GENERAL;\n\n if (blockedAt === GateLayer.SCHEMA) {\n exitCode = ExitCode.E_VALIDATION_ERROR;\n category = ErrorCategory.GENERAL;\n } else if (blockedAt === GateLayer.SEMANTIC) {\n exitCode = this.determineSemanticExitCode(failedLayer.violations);\n category = ErrorCategory.HIERARCHY;\n } else if (blockedAt === GateLayer.REFERENTIAL) {\n exitCode = this.determineReferentialExitCode(failedLayer.violations);\n category = ErrorCategory.HIERARCHY;\n } else if (blockedAt === GateLayer.PROTOCOL) {\n exitCode = this.determineProtocolExitCode(failedLayer.violations);\n category = ErrorCategory.PROTOCOL;\n }\n\n return {\n passed: false,\n layers,\n totalViolations,\n exitCode,\n category,\n summary: `Verification failed at layer ${blockedAt}: ${failedLayer.violations[0]?.message || 'Unknown error'}`,\n blockedAt,\n };\n }\n\n /**\n * Determine semantic layer exit code from violations\n */\n private determineSemanticExitCode(violations: GateViolation[]): ExitCode {\n // Check for specific semantic errors\n for (const v of violations) {\n if (v.code.includes('PARENT')) return ExitCode.E_PARENT_NOT_FOUND;\n if (v.code.includes('DEPTH')) return ExitCode.E_DEPTH_EXCEEDED;\n if (v.code.includes('SIBLING')) return ExitCode.E_SIBLING_LIMIT;\n if (v.code.includes('CIRCULAR')) return ExitCode.E_CIRCULAR_REFERENCE;\n if (v.code.includes('SESSION')) return ExitCode.E_SESSION_REQUIRED;\n }\n return ExitCode.E_VALIDATION_ERROR;\n }\n\n /**\n * Determine referential layer exit code from violations\n */\n private determineReferentialExitCode(violations: GateViolation[]): ExitCode {\n for (const v of violations) {\n if (v.code.includes('NOT_FOUND')) return ExitCode.E_NOT_FOUND;\n if (v.code.includes('PARENT')) return ExitCode.E_PARENT_NOT_FOUND;\n if (v.code.includes('DEPENDENCY')) return ExitCode.E_DEPENDENCY_ERROR;\n }\n return ExitCode.E_NOT_FOUND;\n }\n\n /**\n * Determine protocol layer exit code from violations\n */\n private determineProtocolExitCode(violations: GateViolation[]): ExitCode {\n // Protocol violations map directly to 60-70 range\n for (const v of violations) {\n if (v.code.includes('RESEARCH')) return ExitCode.E_PROTOCOL_RESEARCH;\n if (v.code.includes('CONSENSUS')) return ExitCode.E_PROTOCOL_CONSENSUS;\n if (v.code.includes('SPECIFICATION')) return ExitCode.E_PROTOCOL_SPECIFICATION;\n if (v.code.includes('DECOMPOSITION')) return ExitCode.E_PROTOCOL_DECOMPOSITION;\n if (v.code.includes('IMPLEMENTATION')) return ExitCode.E_PROTOCOL_IMPLEMENTATION;\n if (v.code.includes('CONTRIBUTION')) return ExitCode.E_PROTOCOL_CONTRIBUTION;\n if (v.code.includes('RELEASE')) return ExitCode.E_PROTOCOL_RELEASE;\n if (v.code.includes('VALIDATION')) return ExitCode.E_PROTOCOL_VALIDATION;\n if (v.code.includes('TESTING')) return ExitCode.E_TESTS_SKIPPED;\n if (v.code.includes('LIFECYCLE')) return ExitCode.E_LIFECYCLE_GATE_FAILED;\n }\n return ExitCode.E_PROTOCOL_GENERIC;\n }\n\n /**\n * Check if an operation requires gate validation\n *\n * All mutate operations require validation.\n * Query operations skip validation for performance.\n */\n static requiresValidation(context: OperationContext): boolean {\n // All mutate operations require validation\n if (context.gateway === 'cleo_mutate') {\n return true;\n }\n\n // Query operations are read-only, skip validation\n return false;\n }\n\n /**\n * Get human-readable layer name\n */\n static getLayerName(layer: GateLayer): string {\n const names: Record<GateLayer, string> = {\n [GateLayer.SCHEMA]: 'Schema Validation',\n [GateLayer.SEMANTIC]: 'Semantic Validation',\n [GateLayer.REFERENTIAL]: 'Referential Validation',\n [GateLayer.PROTOCOL]: 'Protocol Validation',\n };\n return names[layer];\n }\n}\n\n/**\n * Factory function for creating verification gates\n */\nexport function createVerificationGate(strictMode: boolean = true): VerificationGate {\n return new VerificationGate(strictMode);\n}\n\n/**\n * Export gate layer sequence for external use\n */\nexport const GATE_SEQUENCE = [\n GateLayer.SCHEMA,\n GateLayer.SEMANTIC,\n GateLayer.REFERENTIAL,\n GateLayer.PROTOCOL,\n] as const;\n\n// ============================================================================\n// Section 7: Workflow Verification Gates\n// ============================================================================\n\n/**\n * Workflow gate names per MCP-SERVER-SPECIFICATION.md Section 7.1\n *\n * Sequence: implemented \u2192 testsPassed \u2192 qaPassed \u2192 cleanupDone \u2192 securityPassed \u2192 documented\n *\n * @task T3141\n */\nexport enum WorkflowGateName {\n IMPLEMENTED = 'implemented',\n TESTS_PASSED = 'testsPassed',\n QA_PASSED = 'qaPassed',\n CLEANUP_DONE = 'cleanupDone',\n SECURITY_PASSED = 'securityPassed',\n DOCUMENTED = 'documented',\n}\n\n/**\n * Workflow gate status values per Section 7.3\n *\n * - null: Not yet attempted\n * - passed: Gate passed successfully\n * - failed: Gate failed (blocks downstream)\n * - blocked: Cannot attempt (dependencies not met)\n */\nexport type WorkflowGateStatus = null | 'passed' | 'failed' | 'blocked';\n\n/**\n * Agent responsible for each gate per Section 7.2\n */\nexport type WorkflowGateAgent = 'coder' | 'testing' | 'qa' | 'cleanup' | 'security' | 'docs';\n\n/**\n * Individual workflow gate definition per Section 7.2\n */\nexport interface WorkflowGateDefinition {\n name: WorkflowGateName;\n agent: WorkflowGateAgent;\n dependsOn: WorkflowGateName[];\n description: string;\n}\n\n/**\n * State of a single workflow gate\n */\nexport interface WorkflowGateState {\n name: WorkflowGateName;\n status: WorkflowGateStatus;\n agent: WorkflowGateAgent;\n updatedAt: string | null;\n failureReason?: string;\n}\n\n/**\n * Complete workflow gate definitions per Section 7.2\n */\nexport const WORKFLOW_GATE_DEFINITIONS: WorkflowGateDefinition[] = [\n {\n name: WorkflowGateName.IMPLEMENTED,\n agent: 'coder',\n dependsOn: [],\n description: 'Code implementation complete',\n },\n {\n name: WorkflowGateName.TESTS_PASSED,\n agent: 'testing',\n dependsOn: [WorkflowGateName.IMPLEMENTED],\n description: 'All tests passing',\n },\n {\n name: WorkflowGateName.QA_PASSED,\n agent: 'qa',\n dependsOn: [WorkflowGateName.TESTS_PASSED],\n description: 'QA review approved',\n },\n {\n name: WorkflowGateName.CLEANUP_DONE,\n agent: 'cleanup',\n dependsOn: [WorkflowGateName.QA_PASSED],\n description: 'Code cleanup finished',\n },\n {\n name: WorkflowGateName.SECURITY_PASSED,\n agent: 'security',\n dependsOn: [WorkflowGateName.CLEANUP_DONE],\n description: 'Security audit passed',\n },\n {\n name: WorkflowGateName.DOCUMENTED,\n agent: 'docs',\n dependsOn: [WorkflowGateName.SECURITY_PASSED],\n description: 'Documentation complete',\n },\n];\n\n/**\n * Ordered workflow gate sequence per Section 7.1\n */\nexport const WORKFLOW_GATE_SEQUENCE: WorkflowGateName[] = [\n WorkflowGateName.IMPLEMENTED,\n WorkflowGateName.TESTS_PASSED,\n WorkflowGateName.QA_PASSED,\n WorkflowGateName.CLEANUP_DONE,\n WorkflowGateName.SECURITY_PASSED,\n WorkflowGateName.DOCUMENTED,\n];\n\n/**\n * Map from gate name to definition for fast lookup\n */\nconst GATE_DEF_MAP: Record<WorkflowGateName, WorkflowGateDefinition> =\n Object.fromEntries(WORKFLOW_GATE_DEFINITIONS.map((d) => [d.name, d])) as Record<\n WorkflowGateName,\n WorkflowGateDefinition\n >;\n\n/**\n * WorkflowGateTracker\n *\n * Tracks the status of all 6 workflow verification gates for a task.\n * Implements Section 7.4 failure cascade behavior: when a gate fails,\n * all downstream gates reset to null.\n *\n * @task T3141\n */\nexport class WorkflowGateTracker {\n private gates: Map<WorkflowGateName, WorkflowGateState>;\n\n constructor() {\n this.gates = new Map();\n for (const def of WORKFLOW_GATE_DEFINITIONS) {\n this.gates.set(def.name, {\n name: def.name,\n status: null,\n agent: def.agent,\n updatedAt: null,\n });\n }\n }\n\n /**\n * Get the status of a specific gate\n */\n getGateStatus(gateName: WorkflowGateName): WorkflowGateStatus {\n const gate = this.gates.get(gateName);\n return gate ? gate.status : null;\n }\n\n /**\n * Get the full state of a specific gate\n */\n getGateState(gateName: WorkflowGateName): WorkflowGateState | undefined {\n return this.gates.get(gateName);\n }\n\n /**\n * Get all gate states\n */\n getAllGates(): WorkflowGateState[] {\n return WORKFLOW_GATE_SEQUENCE.map((name) => this.gates.get(name)!);\n }\n\n /**\n * Check if a gate can be attempted (all dependencies passed)\n */\n canAttempt(gateName: WorkflowGateName): boolean {\n const def = GATE_DEF_MAP[gateName];\n if (!def) return false;\n\n for (const dep of def.dependsOn) {\n const depState = this.gates.get(dep);\n if (!depState || depState.status !== 'passed') {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Mark a gate as passed.\n *\n * Returns false if the gate cannot be attempted (dependencies not met).\n */\n passGate(gateName: WorkflowGateName, agent?: string): boolean {\n if (!this.isValidGate(gateName)) return false;\n\n if (!this.canAttempt(gateName)) return false;\n\n const gate = this.gates.get(gateName)!;\n const expectedAgent = GATE_DEF_MAP[gateName].agent;\n if (agent && agent !== expectedAgent) return false;\n\n gate.status = 'passed';\n gate.updatedAt = new Date().toISOString();\n delete gate.failureReason;\n return true;\n }\n\n /**\n * Mark a gate as failed.\n *\n * Per Section 7.4: When a gate fails, all downstream gates reset to null.\n */\n failGate(gateName: WorkflowGateName, reason?: string): boolean {\n if (!this.isValidGate(gateName)) return false;\n\n const gate = this.gates.get(gateName)!;\n gate.status = 'failed';\n gate.updatedAt = new Date().toISOString();\n if (reason) gate.failureReason = reason;\n\n // Section 7.4 failure cascade: reset all downstream gates to null\n this.cascadeReset(gateName);\n\n return true;\n }\n\n /**\n * Reset a gate and all downstream gates to null.\n *\n * Used for failure cascade per Section 7.4.\n */\n private cascadeReset(failedGateName: WorkflowGateName): void {\n const failedIndex = WORKFLOW_GATE_SEQUENCE.indexOf(failedGateName);\n if (failedIndex === -1) return;\n\n // Reset all gates downstream of the failed gate\n for (let i = failedIndex + 1; i < WORKFLOW_GATE_SEQUENCE.length; i++) {\n const downstreamName = WORKFLOW_GATE_SEQUENCE[i];\n const downstreamGate = this.gates.get(downstreamName)!;\n downstreamGate.status = null;\n downstreamGate.updatedAt = null;\n delete downstreamGate.failureReason;\n }\n }\n\n /**\n * Update blocked status for all gates based on current state.\n *\n * A gate is blocked if it hasn't been attempted (null) and its\n * dependencies are not all passed.\n */\n updateBlockedStatus(): void {\n for (const name of WORKFLOW_GATE_SEQUENCE) {\n const gate = this.gates.get(name)!;\n // Only update gates that are null (not yet attempted)\n if (gate.status === null && !this.canAttempt(name)) {\n gate.status = 'blocked';\n }\n // If a gate was blocked but can now be attempted, reset to null\n if (gate.status === 'blocked' && this.canAttempt(name)) {\n gate.status = null;\n }\n }\n }\n\n /**\n * Check if all gates have passed\n */\n allPassed(): boolean {\n for (const name of WORKFLOW_GATE_SEQUENCE) {\n if (this.gates.get(name)!.status !== 'passed') return false;\n }\n return true;\n }\n\n /**\n * Get all gates that are currently blocked or have null status\n */\n getPendingGates(): WorkflowGateState[] {\n return this.getAllGates().filter(\n (g) => g.status === null || g.status === 'blocked'\n );\n }\n\n /**\n * Get the next gate that can be attempted\n */\n getNextAttemptable(): WorkflowGateName | null {\n for (const name of WORKFLOW_GATE_SEQUENCE) {\n const gate = this.gates.get(name)!;\n if (gate.status !== 'passed' && this.canAttempt(name)) {\n return name;\n }\n }\n return null;\n }\n\n /**\n * Get downstream gates of a given gate (not including the gate itself)\n */\n getDownstreamGates(gateName: WorkflowGateName): WorkflowGateName[] {\n const index = WORKFLOW_GATE_SEQUENCE.indexOf(gateName);\n if (index === -1) return [];\n return WORKFLOW_GATE_SEQUENCE.slice(index + 1);\n }\n\n /**\n * Serialize gate states to a plain record\n */\n toRecord(): Record<string, WorkflowGateStatus> {\n const record: Record<string, WorkflowGateStatus> = {};\n for (const name of WORKFLOW_GATE_SEQUENCE) {\n record[name] = this.gates.get(name)!.status;\n }\n return record;\n }\n\n /**\n * Restore gate states from a record\n */\n fromRecord(record: Record<string, WorkflowGateStatus>): void {\n for (const [name, status] of Object.entries(record)) {\n const gate = this.gates.get(name as WorkflowGateName);\n if (gate) {\n gate.status = status;\n }\n }\n }\n\n /**\n * Check if a gate name is valid\n */\n private isValidGate(gateName: WorkflowGateName): boolean {\n return this.gates.has(gateName);\n }\n}\n\n/**\n * Validate a workflow gate name string\n */\nexport function isValidWorkflowGateName(name: string): name is WorkflowGateName {\n return WORKFLOW_GATE_SEQUENCE.includes(name as WorkflowGateName);\n}\n\n/**\n * Get the definition for a workflow gate\n */\nexport function getWorkflowGateDefinition(\n name: WorkflowGateName\n): WorkflowGateDefinition | undefined {\n return GATE_DEF_MAP[name];\n}\n", "import { DispatchRequest, DispatchResponse, Middleware, DispatchNext } from '../types.js';\nimport { createVerificationGate as legacyCreateGate } from '../../mcp/lib/verification-gates.js';\n\nexport function createVerificationGates(strictMode: boolean = true): Middleware {\n const gate = legacyCreateGate(strictMode);\n\n return async (req: DispatchRequest, next: DispatchNext): Promise<DispatchResponse> => {\n // Map DispatchRequest to legacy OperationContext\n const context = {\n domain: req.domain,\n operation: req.operation,\n gateway: req.gateway === 'query' ? 'cleo_query' as const : 'cleo_mutate' as const,\n params: req.params,\n taskId: (req.params?.taskId as string) || (req.params?.parent as string),\n };\n\n const result = await gate.verifyOperation(context);\n\n if (!result.passed) {\n return {\n _meta: {\n gateway: req.gateway,\n domain: req.domain,\n operation: req.operation,\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n source: req.source,\n requestId: req.requestId,\n verification: result,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 80, // LIFECYCLE_GATE_FAILED\n message: `Verification gate failed at layer ${result.blockedAt}: ${result.summary}`,\n details: { verification: result },\n }\n };\n }\n\n const response = await next();\n response._meta.verification = result;\n return response;\n };\n}\n", "import { DispatchResponse, Middleware, DispatchNext } from '../types.js';\nimport { ProtocolEnforcer } from '../../mcp/lib/protocol-enforcement.js';\n\n/**\n * Creates a middleware that enforces protocol compliance.\n */\nexport function createProtocolEnforcement(strictMode: boolean = true): Middleware {\n void new ProtocolEnforcer(strictMode);\n\n return async (_req, next: DispatchNext): Promise<DispatchResponse> => {\n const response = await next();\n return response;\n };\n}\n", "/**\n * Audit Trail for MCP Server Mutations\n *\n * Logs all write operations to .cleo/audit-log.json for compliance\n * and debugging purposes.\n *\n * @task T2920\n * @task T2929\n */\n\nimport { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { getConfig } from '../../mcp/lib/config.js';\n\n/**\n * Audit entry interface\n */\nexport interface AuditEntry {\n timestamp: string; // ISO-8601\n sessionId: string | null; // Current session\n domain: string; // Domain name\n operation: string; // Operation name\n params: Record<string, unknown>; // Operation parameters\n result: {\n success: boolean;\n exitCode: number;\n duration: number; // Milliseconds\n };\n metadata: {\n taskId?: string; // Affected task\n userId?: string; // User identifier\n source: \"mcp\"; // Always \"mcp\" for MCP server\n gateway?: 'cleo_mutate' | 'cleo_query';\n };\n error?: string; // Error message if failed\n}\n\n/**\n * Maximum audit log size in bytes before rotation (default: 10MB)\n */\nconst MAX_AUDIT_LOG_SIZE = 10 * 1024 * 1024;\n\n/**\n * Get audit log file path\n */\nfunction getAuditLogPath(): string {\n // Default to .cleo/audit-log.json in project root\n return join(process.cwd(), '.cleo', 'audit-log.json');\n}\n\n/**\n * Get current session ID from environment or config\n */\nfunction getCurrentSessionId(): string | null {\n // TODO: Integrate with session system when available\n return process.env.CLEO_SESSION_ID || null;\n}\n\n/**\n * Ensure .cleo directory exists\n */\nasync function ensureCleoDir(): Promise<void> {\n const cleoDir = join(process.cwd(), '.cleo');\n try {\n await fs.mkdir(cleoDir, { recursive: true });\n } catch (error) {\n // Ignore if already exists\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\n/**\n * Log mutation to audit trail\n *\n * Appends a single-line JSON entry to .cleo/audit-log.json\n * Non-blocking - errors are logged but not thrown\n * Automatically rotates log if size exceeds limit\n *\n * @param entry Audit entry to log\n */\nexport async function logMutation(entry: AuditEntry): Promise<void> {\n try {\n // Check if audit logging is enabled\n const config = getConfig();\n if (!config.auditLog) {\n return; // Audit logging disabled\n }\n\n // Ensure .cleo directory exists\n await ensureCleoDir();\n\n // Get audit log path\n const logPath = getAuditLogPath();\n\n // Check if rotation is needed\n await checkAndRotateLog(logPath);\n\n // Serialize entry as single-line JSON\n const line = JSON.stringify(entry) + '\\n';\n\n // Append to log file\n await fs.appendFile(logPath, line, 'utf8');\n } catch (error) {\n // Log error but don't throw - audit logging should not block operations\n console.error('Failed to write audit log entry:', error);\n }\n}\n\n/**\n * Log error to audit trail\n *\n * Convenience function for logging errors with full context\n *\n * @param domain Domain where error occurred\n * @param operation Operation that failed\n * @param error Error object or message\n * @param params Operation parameters\n * @param exitCode Exit code (default: 1)\n */\nexport async function logError(\n domain: string,\n operation: string,\n error: Error | string,\n params: Record<string, unknown> = {},\n exitCode: number = 1\n): Promise<void> {\n // Check if audit logging is enabled\n const config = getConfig();\n if (!config.auditLog) {\n return; // Audit logging disabled\n }\n\n const errorMessage = error instanceof Error ? error.message : error;\n const taskId = typeof params.taskId === 'string' ? params.taskId : undefined;\n\n const entry: AuditEntry = {\n timestamp: new Date().toISOString(),\n sessionId: getCurrentSessionId(),\n domain,\n operation,\n params,\n result: {\n success: false,\n exitCode,\n duration: 0,\n },\n metadata: {\n taskId,\n source: 'mcp',\n },\n error: errorMessage,\n };\n\n await logMutation(entry);\n}\n\n/**\n * Read audit log entries\n *\n * @param options Filter options\n * @returns Array of audit entries\n */\nexport async function readAuditLog(options?: {\n since?: string;\n domain?: string;\n operation?: string;\n success?: boolean;\n limit?: number;\n}): Promise<AuditEntry[]> {\n try {\n const logPath = getAuditLogPath();\n\n // Read log file\n const content = await fs.readFile(logPath, 'utf8');\n\n // Parse JSONL\n const entries = content\n .split('\\n')\n .filter((line) => line.trim())\n .map((line) => JSON.parse(line) as AuditEntry);\n\n // Apply filters\n let filtered = entries;\n\n if (options?.since) {\n filtered = filtered.filter((e) => e.timestamp >= options.since!);\n }\n\n if (options?.domain) {\n filtered = filtered.filter((e) => e.domain === options.domain);\n }\n\n if (options?.operation) {\n filtered = filtered.filter((e) => e.operation === options.operation);\n }\n\n if (options?.success !== undefined) {\n filtered = filtered.filter((e) => e.result.success === options.success);\n }\n\n // Apply limit\n if (options?.limit) {\n filtered = filtered.slice(-options.limit);\n }\n\n return filtered;\n } catch (error) {\n // If file doesn't exist, return empty array\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Get audit statistics\n *\n * @returns Audit statistics\n */\nexport async function getAuditStats(): Promise<{\n totalEntries: number;\n successCount: number;\n failureCount: number;\n byDomain: Record<string, number>;\n byOperation: Record<string, number>;\n avgDuration: number;\n}> {\n const entries = await readAuditLog();\n\n const stats = {\n totalEntries: entries.length,\n successCount: entries.filter((e) => e.result.success).length,\n failureCount: entries.filter((e) => !e.result.success).length,\n byDomain: {} as Record<string, number>,\n byOperation: {} as Record<string, number>,\n avgDuration: 0,\n };\n\n // Count by domain\n for (const entry of entries) {\n stats.byDomain[entry.domain] = (stats.byDomain[entry.domain] || 0) + 1;\n const opKey = `${entry.domain}.${entry.operation}`;\n stats.byOperation[opKey] = (stats.byOperation[opKey] || 0) + 1;\n }\n\n // Calculate average duration\n const durations = entries.filter((e) => e.result.duration).map((e) => e.result.duration);\n if (durations.length > 0) {\n stats.avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;\n }\n\n return stats;\n}\n\n/**\n * Clear audit log (use with caution)\n *\n * @returns Number of entries cleared\n */\nexport async function clearAuditLog(): Promise<number> {\n try {\n const entries = await readAuditLog();\n const count = entries.length;\n\n const logPath = getAuditLogPath();\n await fs.unlink(logPath);\n\n return count;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return 0;\n }\n throw error;\n }\n}\n\n/**\n * Check and rotate audit log if size exceeds limit\n *\n * Rotates log to timestamped archive file when size exceeds MAX_AUDIT_LOG_SIZE\n *\n * @param logPath Path to audit log file\n */\nasync function checkAndRotateLog(logPath: string): Promise<void> {\n try {\n const stats = await fs.stat(logPath);\n\n if (stats.size >= MAX_AUDIT_LOG_SIZE) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-${timestamp}.json`\n );\n\n // Move current log to archive\n await fs.rename(logPath, archivePath);\n\n console.log(`Rotated audit log: ${archivePath} (${stats.size} bytes)`);\n }\n } catch (error) {\n // If file doesn't exist, no rotation needed\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.error('Failed to check/rotate audit log:', error);\n }\n }\n}\n\n/**\n * Manually rotate audit log\n *\n * Forces rotation regardless of size\n *\n * @returns Path to rotated log file\n */\nexport async function rotateLog(): Promise<string | null> {\n try {\n const logPath = getAuditLogPath();\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-${timestamp}.json`\n );\n\n // Check if log exists\n try {\n await fs.access(logPath);\n } catch {\n return null; // No log to rotate\n }\n\n // Move current log to archive\n await fs.rename(logPath, archivePath);\n\n return archivePath;\n } catch (error) {\n console.error('Failed to rotate audit log:', error);\n return null;\n }\n}\n\n/**\n * Archive old audit entries\n *\n * Moves entries older than specified date to archive file\n *\n * @param beforeDate ISO date string\n * @returns Number of entries archived\n */\nexport async function archiveAuditLog(beforeDate: string): Promise<number> {\n try {\n const entries = await readAuditLog();\n\n const toArchive = entries.filter((e) => e.timestamp < beforeDate);\n const toKeep = entries.filter((e) => e.timestamp >= beforeDate);\n\n if (toArchive.length === 0) {\n return 0;\n }\n\n // Write archive file\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-archive-${beforeDate}.json`\n );\n const archiveContent = toArchive.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n await fs.writeFile(archivePath, archiveContent, 'utf8');\n\n // Write remaining entries back to log\n const logPath = getAuditLogPath();\n const logContent = toKeep.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n await fs.writeFile(logPath, logContent, 'utf8');\n\n return toArchive.length;\n } catch (error) {\n console.error('Failed to archive audit log:', error);\n return 0;\n }\n}\n\n/**\n * Query audit log entries with filters\n *\n * @param options Query options\n * @returns Filtered audit entries\n */\nexport async function queryAudit(options?: {\n since?: string;\n domain?: string;\n operation?: string;\n success?: boolean;\n taskId?: string;\n sessionId?: string;\n limit?: number;\n}): Promise<AuditEntry[]> {\n const entries = await readAuditLog(options);\n\n // Additional filters for new fields\n let filtered = entries;\n\n if (options?.taskId) {\n filtered = filtered.filter((e) => e.metadata?.taskId === options.taskId);\n }\n\n if (options?.sessionId) {\n filtered = filtered.filter((e) => e.sessionId === options.sessionId);\n }\n\n return filtered;\n}\n\nimport { DispatchRequest, DispatchResponse, Middleware, DispatchNext } from '../types.js';\n\n/**\n * Creates an audit middleware that logs all mutate operations.\n */\nexport function createAudit(): Middleware {\n return async (req: DispatchRequest, next: DispatchNext): Promise<DispatchResponse> => {\n const startTime = Date.now();\n const response = await next();\n \n // Only audit mutations\n if (req.gateway === 'mutate') {\n const entry: AuditEntry = {\n timestamp: new Date().toISOString(),\n sessionId: req.sessionId || null,\n domain: req.domain,\n operation: req.operation,\n params: req.params || {},\n result: {\n success: response.success,\n exitCode: response.error?.exitCode || 0,\n duration: Date.now() - startTime,\n },\n metadata: {\n taskId: (req.params?.taskId as string) || (req.params?.parent as string),\n source: req.source as any,\n gateway: req.gateway as any,\n },\n error: response.error?.message,\n };\n\n // Fire and forget\n logMutation(entry).catch(err => {\n console.error(`[Audit] Failed to log mutation: ${err}`);\n });\n }\n\n return response;\n };\n}\n", "/**\n * MCP Adapter for the CQRS Dispatch Layer.\n *\n * Provides handleMcpToolCall() \u2014 the single entry point for MCP requests\n * that route through the dispatch pipeline.\n *\n * @epic T4820\n * @task T4819\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { Gateway, DispatchRequest, DispatchResponse } from '../types.js';\nimport { Dispatcher } from '../dispatcher.js';\nimport { createDomainHandlers } from '../domains/index.js';\nimport { createSanitizer } from '../middleware/sanitizer.js';\nimport { createRateLimiter } from '../middleware/rate-limiter.js';\nimport { createVerificationGates } from '../middleware/verification-gates.js';\nimport { createProtocolEnforcement } from '../middleware/protocol-enforcement.js';\nimport { createAudit } from '../middleware/audit.js';\nimport { getProjectRoot } from '../../core/paths.js';\nimport type { RateLimitingConfig } from '../../mcp/lib/rate-limiter.js';\n\nexport interface McpDispatcherConfig {\n rateLimiting?: Partial<RateLimitingConfig>;\n strictMode?: boolean;\n}\n\nlet _dispatcher: Dispatcher | null = null;\n\n/**\n * Initialize and get the singleton MCP dispatcher.\n */\nexport function initMcpDispatcher(config: McpDispatcherConfig = {}): Dispatcher {\n if (_dispatcher) return _dispatcher;\n\n const handlers = createDomainHandlers();\n const strictMode = config.strictMode ?? true;\n\n _dispatcher = new Dispatcher({\n handlers,\n middlewares: [\n createSanitizer(() => getProjectRoot()),\n createRateLimiter(config.rateLimiting),\n createVerificationGates(strictMode),\n createProtocolEnforcement(strictMode),\n createAudit(),\n ],\n });\n\n return _dispatcher;\n}\n\n/**\n * Get the initialized singleton MCP dispatcher.\n */\nexport function getMcpDispatcher(): Dispatcher {\n if (!_dispatcher) {\n return initMcpDispatcher();\n }\n return _dispatcher;\n}\n\n/**\n * Reset the singleton dispatcher (for testing).\n */\nexport function resetMcpDispatcher(): void {\n _dispatcher = null;\n}\n\n/**\n * Handle an MCP tool call (cleo_query or cleo_mutate).\n *\n * Translates the MCP parameters into a DispatchRequest, executes it\n * through the dispatcher, and formats the response back to the standard\n * MCP SDK format.\n */\nexport async function handleMcpToolCall(\n gateway: string,\n domain: string,\n operation: string,\n params?: Record<string, unknown>,\n requestId?: string\n): Promise<DispatchResponse> {\n const dispatcher = getMcpDispatcher();\n\n // Validate gateway\n if (gateway !== 'cleo_query' && gateway !== 'cleo_mutate') {\n return {\n _meta: {\n gateway: gateway as Gateway,\n domain: domain || 'system',\n operation: operation || 'unknown',\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n },\n success: false,\n error: {\n code: 'E_INVALID_GATEWAY',\n exitCode: 2,\n message: `Unknown gateway: ${gateway}. Use 'cleo_query' or 'cleo_mutate'.`,\n },\n } as DispatchResponse;\n }\n\n // Validate required parameters\n if (!domain || !operation) {\n return {\n _meta: {\n gateway: gateway as Gateway,\n domain: domain || 'system',\n operation: operation || 'unknown',\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n },\n success: false,\n error: {\n code: 'E_INVALID_INPUT',\n exitCode: 2,\n message: 'Missing required parameters: domain and operation',\n },\n } as DispatchResponse;\n }\n\n const req: DispatchRequest = {\n gateway: gateway as Gateway,\n domain,\n operation,\n params,\n source: 'mcp',\n requestId: requestId || randomUUID(),\n };\n\n return dispatcher.dispatch(req);\n}\n", "/**\n * CLI Executor Wrapper\n *\n * Executes CLEO CLI commands safely with timeout handling, retry logic,\n * and proper error parsing. Captures stdout, stderr, and exit codes.\n *\n * @task T2914\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { buildCLICommand } from './command-builder.js';\nimport { isRetryableError, ErrorCode, ERROR_CODE_NAMES } from '../types/index.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Execution options\n */\nexport interface ExecutorOptions {\n /** CLI command domain */\n domain: string;\n\n /** Operation to perform */\n operation: string;\n\n /** Positional arguments */\n args?: Array<string | number>;\n\n /** Named flags/options */\n flags?: Record<string, unknown>;\n\n /** Timeout in milliseconds (default: 30000) */\n timeout?: number;\n\n /** Maximum retry attempts (default: 3) */\n maxRetries?: number;\n\n /** Session ID to bind to */\n sessionId?: string;\n\n /** Working directory (default: process.cwd()) */\n cwd?: string;\n\n /** Custom command to execute instead of building from domain/operation */\n customCommand?: string;\n}\n\n/**\n * Execution result\n */\nexport interface ExecutorResult<T = unknown> {\n /** Whether execution succeeded */\n success: boolean;\n\n /** Parsed JSON data (if success=true) */\n data?: T;\n\n /** Error details (if success=false) */\n error?: {\n code: string;\n exitCode?: number;\n message: string;\n details?: unknown;\n fix?: string;\n alternatives?: Array<{\n action: string;\n command: string;\n }>;\n };\n\n /** Exit code from CLI */\n exitCode: number;\n\n /** Raw stdout */\n stdout: string;\n\n /** Raw stderr */\n stderr: string;\n\n /** Execution duration in milliseconds */\n duration: number;\n}\n\n/**\n * CLI executor class\n */\nexport class CLIExecutor {\n constructor(\n private cliPath: string,\n private defaultTimeout: number = 30000,\n private defaultMaxRetries: number = 3\n ) {}\n\n /**\n * Execute CLI command with retry logic\n */\n async execute<T = unknown>(options: ExecutorOptions): Promise<ExecutorResult<T>> {\n const maxRetries = options.maxRetries ?? this.defaultMaxRetries;\n let lastError: ExecutorResult<T> | null = null;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n const result = await this.executeOnce<T>(options, attempt);\n\n // Success - return immediately\n if (result.success) {\n return result;\n }\n\n // Non-retryable error - return immediately\n if (!this.shouldRetry(result.exitCode, attempt, maxRetries)) {\n return result;\n }\n\n // Store error for potential final return\n lastError = result;\n\n // Exponential backoff: 2^attempt seconds\n const backoffMs = Math.pow(2, attempt) * 1000;\n await this.sleep(backoffMs);\n }\n\n // All retries exhausted\n return lastError!;\n }\n\n /**\n * Execute CLI command once (no retry)\n */\n private async executeOnce<T = unknown>(\n options: ExecutorOptions,\n _attempt: number\n ): Promise<ExecutorResult<T>> {\n const startTime = Date.now();\n const timeout = options.timeout ?? this.defaultTimeout;\n\n try {\n // Build command\n const command = this.buildCommand(options);\n\n // Prepare environment\n const env = this.buildEnvironment(options);\n\n // Execute with timeout\n const { stdout, stderr } = await execAsync(command, {\n timeout,\n cwd: options.cwd || process.cwd(),\n env: { ...process.env, ...env },\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n });\n\n const duration = Date.now() - startTime;\n\n // Parse output\n return this.parseOutput<T>(stdout, stderr, 0, duration);\n } catch (error: any) {\n const duration = Date.now() - startTime;\n\n // Handle exec errors (exit code, timeout, etc.)\n if (error.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') {\n return {\n success: false,\n error: {\n code: 'E_OUTPUT_TOO_LARGE',\n message: 'Command output exceeded buffer size',\n fix: 'Add --limit flag to reduce output size',\n },\n exitCode: 1,\n stdout: error.stdout || '',\n stderr: error.stderr || '',\n duration,\n };\n }\n\n if (error.killed) {\n return {\n success: false,\n error: {\n code: 'E_TIMEOUT',\n message: `Command timed out after ${timeout}ms`,\n fix: `Increase timeout or optimize query`,\n },\n exitCode: 124,\n stdout: error.stdout || '',\n stderr: error.stderr || '',\n duration,\n };\n }\n\n // Command executed but returned non-zero exit code\n const exitCode = error.code || 1;\n return this.parseOutput<T>(\n error.stdout || '',\n error.stderr || '',\n exitCode,\n duration\n );\n }\n }\n\n /**\n * Build CLI command string\n */\n private buildCommand(options: ExecutorOptions): string {\n // If customCommand is provided, use it directly\n if (options.customCommand) {\n return options.customCommand;\n }\n\n // Otherwise build from domain/operation\n return buildCLICommand(\n this.cliPath,\n options.domain,\n options.operation,\n options.args || [],\n options.flags || {}\n );\n }\n\n /**\n * Build environment variables\n */\n private buildEnvironment(options: ExecutorOptions): Record<string, string> {\n const env: Record<string, string> = {};\n\n // Bind to session if specified\n if (options.sessionId) {\n env.CLEO_SESSION = options.sessionId;\n }\n\n return env;\n }\n\n /**\n * Parse command output\n */\n private parseOutput<T = unknown>(\n stdout: string,\n stderr: string,\n exitCode: number,\n duration: number\n ): ExecutorResult<T> {\n // Try to parse stdout as JSON, fall back to stderr if stdout is empty\n // Some CLI commands (e.g., orchestrator context) output JSON to stderr\n // with non-zero exit codes that still contain success:true\n const rawOutput = stdout.trim() || stderr.trim();\n try {\n const trimmed = rawOutput;\n if (!trimmed) {\n // Empty output with zero exit = success\n if (exitCode === 0) {\n return {\n success: true,\n data: undefined as T,\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n // Empty output with non-zero exit = error\n return {\n success: false,\n error: {\n code: 'E_UNKNOWN',\n exitCode,\n message: stderr.trim() || 'Command failed with no output',\n },\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n const parsed = JSON.parse(trimmed);\n\n // CLI returned structured JSON response\n if (typeof parsed === 'object' && parsed !== null) {\n // Check for success field\n if ('success' in parsed) {\n if (parsed.success === true) {\n // Extract payload data from CLI response.\n // CLEO CLI returns payload fields directly on the response object\n // (e.g., \"task\", \"tasks\", \"session\", \"sessionId\") rather than\n // wrapping them in a \"data\" field. Extract by removing envelope fields.\n // Extract payload data from CLI response.\n // V2 CLI wraps in {\"success\":true,\"data\":{...}}, V1 puts fields at top level.\n // In both cases, unwrap well-known primary payload fields for convenience.\n const primaryPayloadFields = [\n 'task', 'tasks', 'session', 'sessions', 'matches', 'results',\n 'result', 'focus', 'entries', 'stages', 'summary',\n ];\n\n let data: T;\n\n // Determine raw payload: V2 wraps in .data, LAFS wraps in .result, V1 puts fields at top\n const rawPayload: Record<string, unknown> =\n parsed.data !== undefined ? (parsed.data as Record<string, unknown>) :\n parsed.result !== undefined ? (parsed.result as Record<string, unknown>) : parsed;\n\n // V2 and V1 both need primary field unwrapping\n if (rawPayload && typeof rawPayload === 'object' && !Array.isArray(rawPayload)) {\n const found = primaryPayloadFields.find(\n (f) => (rawPayload as Record<string, unknown>)[f] !== undefined,\n );\n if (found && Array.isArray((rawPayload as Record<string, unknown>)[found])) {\n // Primary field is an array (list/find/entries) - unwrap it\n data = (rawPayload as Record<string, unknown>)[found] as T;\n } else if (found) {\n // Primary field is an object - check for companion fields\n const metaKeys = new Set([\n 'total', 'filtered', 'count', 'query', 'searchType',\n 'message', 'mode', 'initialized', 'directory', 'created',\n 'skipped', 'duplicate',\n ]);\n const companions = Object.keys(rawPayload).filter(\n (k) => k !== found && !metaKeys.has(k),\n );\n if (companions.length === 0) {\n data = (rawPayload as Record<string, unknown>)[found] as T;\n } else {\n // Has companion fields (upstream, downstream) - keep full payload\n data = rawPayload as T;\n }\n } else {\n // No primary field found - use full payload\n data = rawPayload as T;\n }\n } else {\n data = rawPayload as T;\n }\n\n\n return {\n success: true,\n data,\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n // Structured error response\n // V2 CLI uses numeric codes with a 'name' field (e.g., {code: 4, name: \"NOT_FOUND\"}).\n // Normalize to string error codes (E_NOT_FOUND) for compatibility.\n // LAFS format uses string codes directly (e.g., \"E_NOT_FOUND_NOT_FOUND\").\n let errorCode = parsed.error?.code;\n if (typeof errorCode === 'number') {\n // Use the name field if available\n const name = parsed.error?.name as string | undefined;\n if (name) {\n // Name may already have E_ prefix (from dispatch adapter) or not (from V2 CLI)\n errorCode = name.startsWith('E_') ? name : `E_${name}`;\n } else {\n // Fall back to ERROR_CODE_NAMES mapping from exit-codes\n const mappedName = ERROR_CODE_NAMES[errorCode];\n errorCode = mappedName || `E_EXIT_${errorCode}`;\n }\n } else if (typeof errorCode === 'string' && errorCode.startsWith('E_')) {\n // LAFS format already has the right code (e.g., \"E_NOT_FOUND_NOT_FOUND\").\n // Simplify multi-segment codes to match test expectations.\n // E.g., \"E_INTERNAL_NOT_FOUND\" -> \"E_NOT_FOUND\", \"E_VALIDATION_PARENT_NOT_FOUND\" -> \"E_PARENT_NOT_FOUND\"\n // Extract the meaningful suffix after the category segment.\n const lafsDetails = parsed.error?.details;\n if (lafsDetails?.name && typeof lafsDetails.name === 'string') {\n errorCode = `E_${lafsDetails.name}`;\n }\n }\n const errorExitCode = typeof parsed.error?.code === 'number'\n ? parsed.error.code\n : (parsed.error?.exitCode || parsed.error?.details?.exitCode || exitCode);\n return {\n success: false,\n error: {\n code: errorCode || 'E_UNKNOWN',\n exitCode: errorExitCode,\n message: parsed.error?.message || 'Command failed',\n details: parsed.error?.details,\n fix: parsed.error?.fix || parsed.error?.details?.fix,\n alternatives: parsed.error?.alternatives || parsed.error?.details?.alternatives,\n },\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n // JSON without success field - treat as data\n return {\n success: exitCode === 0,\n data: parsed as T,\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n } catch (parseError) {\n // Not valid JSON - treat as plain text\n if (exitCode === 0) {\n // Success with non-JSON output\n return {\n success: true,\n data: stdout.trim() as T,\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n // Error with non-JSON output\n return {\n success: false,\n error: {\n code: 'E_UNKNOWN',\n exitCode,\n message: stderr.trim() || stdout.trim() || 'Command failed',\n },\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n // Shouldn't reach here, but TypeScript needs it\n return {\n success: false,\n error: {\n code: 'E_UNKNOWN',\n exitCode,\n message: 'Unexpected execution result',\n },\n exitCode,\n stdout,\n stderr,\n duration,\n };\n }\n\n /**\n * Determine if error is retryable\n */\n private shouldRetry(exitCode: number, attempt: number, maxRetries: number): boolean {\n // Max retries exhausted\n if (attempt >= maxRetries) {\n return false;\n }\n\n // Check if error code is retryable\n return isRetryableError(exitCode as ErrorCode);\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Get CLI version\n */\n async getVersion(): Promise<string> {\n const result = await this.execute<{ version: string }>({\n domain: 'system',\n operation: 'version',\n customCommand: `${this.cliPath} version`,\n maxRetries: 1,\n });\n\n if (result.success) {\n // Try data field first (already parsed by execute)\n if (result.data && typeof result.data === 'object' && 'version' in result.data) {\n return (result.data as { version: string }).version;\n }\n\n // Fallback: parse version from raw stdout JSON\n try {\n const parsed = JSON.parse(result.stdout.trim());\n if (parsed.version) {\n return parsed.version;\n }\n if (parsed.data?.version) {\n return parsed.data.version;\n }\n } catch (e) {\n // Not valid JSON, continue to error\n }\n }\n\n throw new Error(`Failed to get CLI version: ${result.error?.message || 'Unknown error'}`);\n }\n\n /**\n * Test CLI connection\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.getVersion();\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Check if CLI is available (non-blocking check)\n */\n isAvailable(): boolean {\n return this._available;\n }\n\n /**\n * Set CLI availability status\n */\n setAvailable(available: boolean): void {\n this._available = available;\n }\n\n /**\n * Internal availability flag\n */\n private _available: boolean = true;\n}\n\n/**\n * Create executor instance from config\n */\nexport function createExecutor(\n cliPath: string,\n timeout?: number,\n maxRetries?: number\n): CLIExecutor {\n return new CLIExecutor(cliPath, timeout, maxRetries);\n}\n", "/**\n * CLI Command Builder\n *\n * Constructs safe CLI commands with proper argument escaping and flag formatting.\n * Prevents shell injection attacks by properly escaping all arguments.\n *\n * @task T2914\n */\n\n/**\n * Escape shell argument to prevent injection\n *\n * Wraps argument in single quotes and escapes any embedded single quotes.\n * This is safe for all shell interpreters (bash, sh, zsh).\n */\nexport function escapeArg(arg: string | number | boolean): string {\n // Convert to string\n const str = String(arg);\n\n // Escape single quotes by replacing ' with '\\''\n // This closes the quote, adds an escaped quote, and reopens the quote\n const escaped = str.replace(/'/g, \"'\\\\''\");\n\n // Wrap in single quotes\n return `'${escaped}'`;\n}\n\n/**\n * Format CLI flags from key-value object\n *\n * Converts {json: true, parent: \"T001\"} to [\"--json\", \"--parent\", \"T001\"]\n */\nexport function formatFlags(flags: Record<string, unknown>): string[] {\n const result: string[] = [];\n\n for (const [key, value] of Object.entries(flags)) {\n // Skip undefined/null values\n if (value === undefined || value === null) {\n continue;\n }\n\n // Boolean flags\n if (typeof value === 'boolean') {\n if (value === true) {\n result.push(`--${key}`);\n }\n // Skip false boolean flags (don't add anything)\n continue;\n }\n\n // Array flags (multiple values)\n if (Array.isArray(value)) {\n for (const item of value) {\n result.push(`--${key}`, escapeArg(item as string | number | boolean));\n }\n continue;\n }\n\n // Object flags (JSON stringify)\n if (typeof value === 'object') {\n result.push(`--${key}`, escapeArg(JSON.stringify(value)));\n continue;\n }\n\n // Regular flags (string/number)\n result.push(`--${key}`, escapeArg(value as string | number | boolean));\n }\n\n return result;\n}\n\n/**\n * Map domain+operation to CLI command\n *\n * Maps MCP domain/operation pairs to the actual CLI command structure.\n * For example: domain='tasks', operation='add' -> command='add', addOperationAsSubcommand=false\n */\nexport function mapDomainToCommand(domain: string, operation: string): { command: string; addOperationAsSubcommand: boolean } {\n // Domain aliases used by legacy handlers/comments that should resolve to\n // canonical CLI commands.\n const domainAliases: Record<string, { command: string; addOperationAsSubcommand: boolean }> = {\n depends: { command: 'deps', addOperationAsSubcommand: true },\n import: { command: 'import-tasks', addOperationAsSubcommand: true },\n lint: { command: 'validate', addOperationAsSubcommand: true },\n skill: { command: 'skills', addOperationAsSubcommand: true },\n version: { command: 'version', addOperationAsSubcommand: false },\n };\n\n if (domainAliases[domain]) {\n return domainAliases[domain];\n }\n\n // For tasks domain, the operation IS the command\n // For session/lifecycle domains, we need both (e.g., 'session start')\n const domainOperationMap: Record<string, Record<string, { command: string; addOperationAsSubcommand: boolean }>> = {\n tasks: {\n show: { command: 'show', addOperationAsSubcommand: false },\n list: { command: 'list', addOperationAsSubcommand: false },\n find: { command: 'find', addOperationAsSubcommand: false },\n add: { command: 'add', addOperationAsSubcommand: false },\n update: { command: 'update', addOperationAsSubcommand: false },\n complete: { command: 'complete', addOperationAsSubcommand: false },\n delete: { command: 'delete', addOperationAsSubcommand: false },\n archive: { command: 'archive', addOperationAsSubcommand: false },\n restore: { command: 'restore task', addOperationAsSubcommand: false },\n reopen: { command: 'restore task', addOperationAsSubcommand: false },\n exists: { command: 'exists', addOperationAsSubcommand: false },\n next: { command: 'next', addOperationAsSubcommand: false },\n current: { command: 'current', addOperationAsSubcommand: false },\n start: { command: 'start', addOperationAsSubcommand: false },\n stop: { command: 'stop', addOperationAsSubcommand: false },\n depends: { command: 'deps show', addOperationAsSubcommand: false },\n blockers: { command: 'blockers', addOperationAsSubcommand: false },\n tree: { command: 'tree', addOperationAsSubcommand: false },\n analyze: { command: 'analyze', addOperationAsSubcommand: false },\n },\n session: {\n start: { command: 'session', addOperationAsSubcommand: true },\n end: { command: 'session', addOperationAsSubcommand: true },\n status: { command: 'session', addOperationAsSubcommand: true },\n list: { command: 'session', addOperationAsSubcommand: true },\n show: { command: 'session', addOperationAsSubcommand: true },\n suspend: { command: 'session', addOperationAsSubcommand: true },\n resume: { command: 'session', addOperationAsSubcommand: true },\n history: { command: 'session', addOperationAsSubcommand: true },\n archive: { command: 'session', addOperationAsSubcommand: true },\n cleanup: { command: 'session', addOperationAsSubcommand: true },\n switch: { command: 'session', addOperationAsSubcommand: true },\n focus: { command: 'focus', addOperationAsSubcommand: false },\n },\n lifecycle: {\n status: { command: 'lifecycle show', addOperationAsSubcommand: false },\n show: { command: 'lifecycle show', addOperationAsSubcommand: false },\n stages: { command: 'lifecycle show', addOperationAsSubcommand: false },\n validate: { command: 'lifecycle gate', addOperationAsSubcommand: false },\n record: { command: 'lifecycle complete', addOperationAsSubcommand: false },\n start: { command: 'lifecycle start', addOperationAsSubcommand: false },\n complete: { command: 'lifecycle complete', addOperationAsSubcommand: false },\n enforce: { command: 'lifecycle gate', addOperationAsSubcommand: false },\n skip: { command: 'lifecycle skip', addOperationAsSubcommand: false },\n unskip: { command: 'lifecycle', addOperationAsSubcommand: true },\n report: { command: 'lifecycle show', addOperationAsSubcommand: false },\n export: { command: 'lifecycle', addOperationAsSubcommand: true },\n import: { command: 'lifecycle', addOperationAsSubcommand: true },\n gate: { command: 'lifecycle gate', addOperationAsSubcommand: false },\n gates: { command: 'lifecycle show', addOperationAsSubcommand: false },\n prerequisites: { command: 'lifecycle show', addOperationAsSubcommand: false },\n history: { command: 'lifecycle show', addOperationAsSubcommand: false },\n reset: { command: 'lifecycle start', addOperationAsSubcommand: false },\n 'gate.pass': { command: 'lifecycle gate', addOperationAsSubcommand: false },\n 'gate.fail': { command: 'lifecycle gate', addOperationAsSubcommand: false },\n },\n // Orchestrate domain maps to 'cleo orchestrate <subcommand>'\n orchestrate: {\n analyze: { command: 'orchestrate', addOperationAsSubcommand: true },\n start: { command: 'orchestrate', addOperationAsSubcommand: true },\n status: { command: 'orchestrate context', addOperationAsSubcommand: false },\n next: { command: 'orchestrate', addOperationAsSubcommand: true },\n ready: { command: 'orchestrate', addOperationAsSubcommand: true },\n spawn: { command: 'orchestrate', addOperationAsSubcommand: true },\n waves: { command: 'orchestrate analyze', addOperationAsSubcommand: false },\n parallel: { command: 'orchestrate ready', addOperationAsSubcommand: false },\n check: { command: 'orchestrate validate', addOperationAsSubcommand: false },\n validate: { command: 'orchestrate', addOperationAsSubcommand: true },\n context: { command: 'orchestrate', addOperationAsSubcommand: true },\n skill: { command: 'orchestrate', addOperationAsSubcommand: true },\n },\n // Research domain maps to 'cleo research <subcommand>'\n research: {\n link: { command: 'research', addOperationAsSubcommand: true },\n links: { command: 'research', addOperationAsSubcommand: true },\n unlink: { command: 'research', addOperationAsSubcommand: true },\n list: { command: 'research', addOperationAsSubcommand: true },\n show: { command: 'research', addOperationAsSubcommand: true },\n get: { command: 'research', addOperationAsSubcommand: true },\n add: { command: 'research', addOperationAsSubcommand: true },\n search: { command: 'research', addOperationAsSubcommand: true },\n stats: { command: 'research manifest', addOperationAsSubcommand: false },\n pending: { command: 'research', addOperationAsSubcommand: true },\n inject: { command: 'research', addOperationAsSubcommand: true },\n archive: { command: 'research', addOperationAsSubcommand: true },\n 'archive-list': { command: 'research', addOperationAsSubcommand: true },\n status: { command: 'research', addOperationAsSubcommand: true },\n compact: { command: 'research', addOperationAsSubcommand: true },\n validate: { command: 'research', addOperationAsSubcommand: true },\n // Manifest sub-operations map to actual CLI subcommands\n 'manifest.append': { command: 'research add', addOperationAsSubcommand: false },\n 'manifest.read': { command: 'research list', addOperationAsSubcommand: false },\n 'manifest.archive': { command: 'research archive', addOperationAsSubcommand: false },\n },\n system: {\n version: { command: 'version', addOperationAsSubcommand: false },\n config: { command: 'config', addOperationAsSubcommand: false },\n 'config.show': { command: 'config', addOperationAsSubcommand: false },\n 'config.get': { command: 'config', addOperationAsSubcommand: false },\n 'config.set': { command: 'config', addOperationAsSubcommand: false },\n backup: { command: 'backup', addOperationAsSubcommand: false },\n cleanup: { command: 'cleanup', addOperationAsSubcommand: false },\n health: { command: 'doctor', addOperationAsSubcommand: false },\n stats: { command: 'stats', addOperationAsSubcommand: false },\n context: { command: 'context', addOperationAsSubcommand: false },\n },\n validate: {\n schema: { command: 'validate', addOperationAsSubcommand: false },\n task: { command: 'validate', addOperationAsSubcommand: false },\n compliance: { command: 'compliance', addOperationAsSubcommand: false },\n test: { command: 'test', addOperationAsSubcommand: false },\n },\n };\n\n const mapping = domainOperationMap[domain]?.[operation];\n\n if (mapping) {\n return mapping;\n }\n\n // Handle compound operations (e.g., 'config.get' in 'system' domain)\n // Split on first dot and try to resolve via a sub-domain\n if (operation.includes('.')) {\n const dotIndex = operation.indexOf('.');\n const subDomain = operation.substring(0, dotIndex);\n const subOp = operation.substring(dotIndex + 1);\n // Check if there's a dedicated domain for the sub-operation\n const subMapping = domainOperationMap[subDomain]?.[subOp];\n if (subMapping) {\n return subMapping;\n }\n }\n\n // Default: use domain as command, operation as subcommand\n return { command: domain, addOperationAsSubcommand: true };\n}\n\n/**\n * Build complete CLI command\n *\n * @param cliPath - Path to CLEO CLI executable\n * @param domain - Domain name (e.g., 'tasks', 'session') OR direct command (e.g., 'show', 'add')\n * @param operation - Operation name (e.g., 'show', 'list') OR first argument\n * @param args - Positional arguments\n * @param flags - Named flags/options\n * @returns Complete command string ready for execution\n *\n * @example\n * ```typescript\n * buildCLICommand('cleo', 'tasks', 'show', ['T2914'], {json: true})\n * // Returns: \"cleo show 'T2914' --json\"\n *\n * buildCLICommand('cleo', 'show', 'T2914', [], {json: true})\n * // Returns: \"cleo show 'T2914' --json\"\n * ```\n */\nexport function buildCLICommand(\n cliPath: string,\n domain: string,\n operation: string,\n args: Array<string | number> = [],\n flags: Record<string, unknown> = {}\n): string {\n const parts: string[] = [cliPath];\n\n // Check if we need to map domain+operation to CLI command\n // This handles E2E tests that use domain='tasks', operation='add'\n // versus domain handlers that use domain='add', operation=title\n // Valid CLI commands that can be used directly as the first command word.\n // These are commands where domain IS the command itself (e.g., domain='add', operation='My Task Title').\n // Do NOT include domain names that need mapDomainToCommand lookup (like 'session', 'lifecycle',\n // 'orchestrate', 'research', 'tasks', 'focus', 'system', 'validate').\n const validCliCommands = [\n 'add', 'list', 'show', 'find', 'update', 'complete', 'delete', 'archive',\n 'exists', 'next', 'current', 'start', 'stop',\n 'version', 'dash', 'analyze', 'config',\n 'backup', 'init', 'blockers', 'deps', 'tree',\n ];\n\n if (!validCliCommands.includes(domain)) {\n // This looks like domain='tasks', operation='add' pattern from E2E tests\n // Map it to the proper CLI command\n const mapping = mapDomainToCommand(domain, operation);\n parts.push(mapping.command);\n\n // For commands that need the operation as a subcommand (session, lifecycle)\n if (mapping.addOperationAsSubcommand) {\n parts.push(escapeArg(operation));\n }\n // For tasks domain, the operation IS already the command, so don't add it again\n } else {\n // This is already a direct CLI command (domain='add', operation=title)\n parts.push(domain);\n\n // Add operation (may be user-controlled, e.g., task title, so escape it)\n if (operation) {\n parts.push(escapeArg(operation));\n }\n }\n\n // Add positional arguments (escaped)\n for (const arg of args) {\n parts.push(escapeArg(arg));\n }\n\n // Add flags (escaped)\n const flagParts = formatFlags(flags);\n parts.push(...flagParts);\n\n return parts.join(' ');\n}\n", "/**\n * Error Code Definitions\n *\n * All CLEO exit codes and their corresponding error constants.\n */\n\n/**\n * General errors (1-9)\n */\nexport const enum GeneralErrorCode {\n SUCCESS = 0,\n E_GENERAL = 1,\n E_INVALID_INPUT = 2,\n E_FILE_ERROR = 3,\n E_NOT_FOUND = 4,\n E_DEPENDENCY = 5,\n E_VALIDATION = 6,\n E_RETRYABLE = 7,\n}\n\n/**\n * Hierarchy errors (10-19)\n */\nexport const enum HierarchyErrorCode {\n E_PARENT_NOT_FOUND = 10,\n E_DEPTH_EXCEEDED = 11,\n E_SIBLING_LIMIT = 12,\n E_CIRCULAR_DEP = 13,\n}\n\n/**\n * Session errors (30-39)\n */\nexport const enum SessionErrorCode {\n E_FOCUS_REQUIRED = 38,\n E_SESSION_DISCOVERY = 100, // Special: not an error\n}\n\n/**\n * Gate errors (40-49)\n */\nexport const enum GateErrorCode {\n E_GATE_UPDATE_FAILED = 40,\n E_VERIFICATION_LOCKED = 41,\n E_INVALID_GATE = 42,\n E_INVALID_AGENT = 43,\n}\n\n/**\n * Context errors (50-59)\n */\nexport const enum ContextErrorCode {\n E_CONTEXT_CRITICAL = 50,\n E_CONTEXT_HIGH = 51,\n E_CONTEXT_MEDIUM = 52,\n}\n\n/**\n * Protocol violations (60-70)\n */\nexport const enum ProtocolErrorCode {\n E_PROTOCOL_RESEARCH = 60,\n E_PROTOCOL_CONSENSUS = 61,\n E_PROTOCOL_SPECIFICATION = 62,\n E_PROTOCOL_DECOMPOSITION = 63,\n E_PROTOCOL_IMPLEMENTATION = 64,\n E_PROTOCOL_CONTRIBUTION = 65,\n E_PROTOCOL_RELEASE = 66,\n E_PROTOCOL_GENERIC = 67,\n E_PROTOCOL_VALIDATION = 68,\n E_TESTS_SKIPPED = 69,\n E_COVERAGE_INSUFFICIENT = 70,\n}\n\n/**\n * Lifecycle errors (75-79)\n */\nexport const enum LifecycleErrorCode {\n E_LIFECYCLE_GATE_FAILED = 75,\n E_AUDIT_MISSING = 76,\n E_CIRCULAR_VALIDATION = 77,\n E_LIFECYCLE_TRANSITION_INVALID = 78,\n E_PROVENANCE_REQUIRED = 79,\n}\n\n/**\n * Special codes (100+)\n */\nexport const enum SpecialCode {\n E_SESSION_DISCOVERY_MODE = 100,\n E_DUPLICATE_ID = 101,\n}\n\n/**\n * All error codes union\n */\nexport type ErrorCode =\n | GeneralErrorCode\n | HierarchyErrorCode\n | SessionErrorCode\n | GateErrorCode\n | ContextErrorCode\n | ProtocolErrorCode\n | LifecycleErrorCode\n | SpecialCode;\n\n/**\n * Error code to constant name mapping\n */\nexport const ERROR_CODE_NAMES: Record<number, string> = {\n 0: 'SUCCESS',\n 1: 'E_GENERAL',\n 2: 'E_INVALID_INPUT',\n 3: 'E_FILE_ERROR',\n 4: 'E_NOT_FOUND',\n 5: 'E_DEPENDENCY',\n 6: 'E_VALIDATION',\n 7: 'E_RETRYABLE',\n 10: 'E_PARENT_NOT_FOUND',\n 11: 'E_DEPTH_EXCEEDED',\n 12: 'E_SIBLING_LIMIT',\n 13: 'E_CIRCULAR_DEP',\n 38: 'E_FOCUS_REQUIRED',\n 40: 'E_GATE_UPDATE_FAILED',\n 41: 'E_VERIFICATION_LOCKED',\n 42: 'E_INVALID_GATE',\n 43: 'E_INVALID_AGENT',\n 50: 'E_CONTEXT_CRITICAL',\n 51: 'E_CONTEXT_HIGH',\n 52: 'E_CONTEXT_MEDIUM',\n 60: 'E_PROTOCOL_RESEARCH',\n 61: 'E_PROTOCOL_CONSENSUS',\n 62: 'E_PROTOCOL_SPECIFICATION',\n 63: 'E_PROTOCOL_DECOMPOSITION',\n 64: 'E_PROTOCOL_IMPLEMENTATION',\n 65: 'E_PROTOCOL_CONTRIBUTION',\n 66: 'E_PROTOCOL_RELEASE',\n 67: 'E_PROTOCOL_GENERIC',\n 68: 'E_PROTOCOL_VALIDATION',\n 69: 'E_TESTS_SKIPPED',\n 70: 'E_COVERAGE_INSUFFICIENT',\n 75: 'E_LIFECYCLE_GATE_FAILED',\n 76: 'E_AUDIT_MISSING',\n 77: 'E_CIRCULAR_VALIDATION',\n 78: 'E_LIFECYCLE_TRANSITION_INVALID',\n 79: 'E_PROVENANCE_REQUIRED',\n 100: 'E_SESSION_DISCOVERY_MODE',\n 101: 'E_DUPLICATE_ID',\n};\n\n/**\n * Retryable error codes\n */\nexport const RETRYABLE_ERROR_CODES: number[] = [\n 7, 20, 21, 22, 60, 61, 62, 63,\n];\n\n/**\n * Check if error code is retryable\n */\nexport function isRetryableError(code: number): boolean {\n return RETRYABLE_ERROR_CODES.includes(code);\n}\n", "/**\n * cleo_query Gateway - Read Operations\n *\n * Handles all read-only operations for discovery, status, analysis,\n * and validation checks. Never modifies state.\n *\n * Domains: tasks, session, orchestrate, research, lifecycle, validate, system, issues, skills\n * Total operations: 75\n *\n * @task T2915\n */\n\nimport { DomainRequest, DomainResponse } from '../lib/router.js';\n\n/**\n * Query request interface\n */\nexport interface QueryRequest {\n domain: 'tasks' | 'session' | 'orchestrate' | 'research' | 'lifecycle' | 'validate' | 'system' | 'issues' | 'skills' | 'providers';\n operation: string;\n params?: Record<string, unknown>;\n}\n\n/**\n * Query response interface (aliases DomainResponse)\n */\nexport type QueryResponse = DomainResponse;\n\n/**\n * Query operation matrix - all read operations by domain\n * Reference: MCP-SERVER-SPECIFICATION.md Section 2.1.2\n */\nexport const QUERY_OPERATIONS: Record<string, string[]> = {\n tasks: [\n 'show', // Get single task details\n 'list', // List tasks with filters\n 'find', // Fuzzy search tasks\n 'exists', // Check task existence\n 'tree', // Hierarchical task view\n 'blockers', // Get blocking tasks\n 'depends', // Get dependencies\n 'analyze', // Triage analysis\n 'next', // Next task suggestion\n 'relates', // Query task relationships\n 'complexity.estimate', // Deterministic complexity scoring\n 'current', // Get currently active task\n ],\n session: [\n 'status', // Current session status\n 'list', // List all sessions\n 'show', // Session details\n 'history', // Session history\n 'decision.log', // Decision audit log\n 'context.drift', // Session context drift analysis\n ],\n orchestrate: [\n 'status', // Orchestrator status\n 'next', // Next task to spawn\n 'ready', // Parallel-safe tasks\n 'analyze', // Dependency analysis\n 'context', // Context usage check\n 'waves', // Wave computation\n 'skill.list', // Available skills\n 'bootstrap', // Brain state bootstrap\n 'unblock.opportunities', // Unblocking opportunities analysis\n 'critical.path', // Longest dependency chain analysis\n ],\n research: [\n 'show', // Research entry details\n 'list', // List research entries\n 'find', // Find research\n 'pending', // Pending research\n 'stats', // Research statistics\n 'manifest.read', // Read manifest entries\n 'contradictions', // Find conflicting research findings\n 'superseded', // Find superseded research entries\n ],\n lifecycle: [\n 'validate', // Check stage prerequisites\n 'status', // Current lifecycle state\n 'history', // Stage transition history\n 'gates', // All gate statuses\n 'prerequisites', // Required prior stages\n ],\n validate: [\n 'schema', // JSON Schema validation\n 'protocol', // Protocol compliance\n 'task', // Anti-hallucination check\n 'manifest', // Manifest entry check\n 'output', // Output file validation\n 'compliance.summary', // Aggregated compliance\n 'compliance.violations', // List violations\n 'test.status', // Test suite status\n 'test.coverage', // Coverage metrics\n 'coherence.check', // Task graph consistency\n ],\n system: [\n 'version', // CLEO version\n 'health', // Health check\n 'config.show', // Show config value\n 'config.get', // Alias (backward compat)\n 'stats', // Project statistics\n 'context', // Context window info\n 'job.status', // Get background job status\n 'job.list', // List background jobs\n 'dash', // Project overview dashboard\n 'roadmap', // Roadmap generation\n 'labels', // Label listing and stats\n 'compliance', // Compliance metrics\n 'log', // Audit log entries\n 'archive.stats', // Archive analytics\n 'sequence', // ID sequence inspection\n ],\n issues: [\n 'diagnostics', // System diagnostics for bug reports\n ],\n skills: [\n 'list', // List available skills\n 'show', // Skill details\n 'find', // Find skills\n 'dispatch', // Simulate skill dispatch\n 'verify', // Validate skill frontmatter\n 'dependencies', // Skill dependency tree\n ],\n providers: [\n 'list', // List all registered providers\n 'detect', // Detect installed providers\n 'inject.status', // Check injection status\n ],\n};\n\n/**\n * Total operation count check\n */\nconst EXPECTED_QUERY_COUNT = 76;\nconst actualQueryCount = Object.values(QUERY_OPERATIONS).flat().length;\nif (actualQueryCount !== EXPECTED_QUERY_COUNT) {\n console.error(\n `Warning: Query operation count mismatch. Expected ${EXPECTED_QUERY_COUNT}, got ${actualQueryCount}`\n );\n}\n\n/**\n * Validate query request parameters\n */\nexport function validateQueryParams(request: QueryRequest): {\n valid: boolean;\n error?: DomainResponse;\n} {\n const { domain, operation } = request;\n\n // Check if domain is valid\n if (!QUERY_OPERATIONS[domain]) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_query',\n domain,\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_INVALID_DOMAIN',\n exitCode: 2,\n message: `Unknown query domain: ${domain}`,\n fix: `Use one of: ${Object.keys(QUERY_OPERATIONS).join(', ')}`,\n alternatives: Object.keys(QUERY_OPERATIONS).map((d) => ({\n action: `List ${d} operations`,\n command: `Available: ${QUERY_OPERATIONS[d].join(', ')}`,\n })),\n },\n },\n };\n }\n\n // Check if operation is valid for this domain\n const validOps = QUERY_OPERATIONS[domain];\n if (!validOps.includes(operation)) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_query',\n domain,\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_INVALID_OPERATION',\n exitCode: 2,\n message: `Operation '${operation}' not supported for cleo_query in domain '${domain}'`,\n fix: `Use one of: ${validOps.join(', ')}`,\n alternatives: validOps.map((op) => ({\n action: `Use ${op}`,\n command: `cleo_query ${domain} ${op}`,\n })),\n },\n },\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Register cleo_query tool with MCP server\n *\n * Returns tool definition for ListToolsRequestSchema handler\n */\nexport function registerQueryTool() {\n return {\n name: 'cleo_query',\n description:\n 'CLEO read operations: task discovery, status checks, analysis, validation, and compliance metrics. Never modifies state.',\n inputSchema: {\n type: 'object',\n required: ['domain', 'operation'],\n properties: {\n domain: {\n type: 'string',\n enum: Object.keys(QUERY_OPERATIONS),\n description: 'Functional domain to query',\n },\n operation: {\n type: 'string',\n description: 'Domain-specific read operation (see operation matrix)',\n },\n params: {\n type: 'object',\n description: 'Operation-specific parameters',\n additionalProperties: true,\n },\n },\n },\n };\n}\n\n/**\n * Handle cleo_query request\n *\n * Validates parameters and routes to domain handler via DomainRouter\n *\n * @param request Query request with domain, operation, and params\n * @returns Promise resolving to query response\n */\nexport async function handleQueryRequest(\n request: QueryRequest\n): Promise<QueryResponse> {\n // Validate request parameters\n const validation = validateQueryParams(request);\n if (!validation.valid) {\n return validation.error!;\n }\n\n // Build domain request (will be routed by DomainRouter)\n const domainRequest: DomainRequest = {\n gateway: 'cleo_query',\n domain: request.domain,\n operation: request.operation,\n params: request.params,\n };\n\n // Return domain request for router to handle\n // (This function is called by the router via index.ts)\n // The actual routing happens in DomainRouter.routeOperation()\n return {\n _meta: {\n gateway: 'cleo_query',\n domain: request.domain,\n operation: request.operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: true,\n data: domainRequest,\n };\n}\n\n/**\n * Get query operation count for specific domain or all domains\n */\nexport function getQueryOperationCount(domain?: string): number {\n if (domain) {\n return QUERY_OPERATIONS[domain]?.length || 0;\n }\n return actualQueryCount;\n}\n\n/**\n * Check if operation is read-only (query)\n */\nexport function isQueryOperation(domain: string, operation: string): boolean {\n return QUERY_OPERATIONS[domain]?.includes(operation) || false;\n}\n\n/**\n * Get all query domains\n */\nexport function getQueryDomains(): string[] {\n return Object.keys(QUERY_OPERATIONS);\n}\n\n/**\n * Get operations for specific query domain\n */\nexport function getQueryOperations(domain: string): string[] {\n return QUERY_OPERATIONS[domain] || [];\n}\n", "/**\n * Audit Trail for MCP Server Mutations\n *\n * Logs all write operations to .cleo/audit-log.json for compliance\n * and debugging purposes.\n *\n * @task T2920\n * @task T2929\n */\n\nimport { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { getConfig } from './config.js';\n\n/**\n * Audit entry interface\n */\nexport interface AuditEntry {\n timestamp: string; // ISO-8601\n sessionId: string | null; // Current session\n domain: string; // Domain name\n operation: string; // Operation name\n params: Record<string, unknown>; // Operation parameters\n result: {\n success: boolean;\n exitCode: number;\n duration: number; // Milliseconds\n };\n metadata: {\n taskId?: string; // Affected task\n userId?: string; // User identifier\n source: \"mcp\"; // Always \"mcp\" for MCP server\n gateway?: 'cleo_mutate' | 'cleo_query';\n };\n error?: string; // Error message if failed\n}\n\n/**\n * Maximum audit log size in bytes before rotation (default: 10MB)\n */\nconst MAX_AUDIT_LOG_SIZE = 10 * 1024 * 1024;\n\n/**\n * Get audit log file path\n */\nfunction getAuditLogPath(): string {\n // Default to .cleo/audit-log.json in project root\n return join(process.cwd(), '.cleo', 'audit-log.json');\n}\n\n/**\n * Get current session ID from environment or config\n */\nfunction getCurrentSessionId(): string | null {\n // TODO: Integrate with session system when available\n return process.env.CLEO_SESSION_ID || null;\n}\n\n/**\n * Ensure .cleo directory exists\n */\nasync function ensureCleoDir(): Promise<void> {\n const cleoDir = join(process.cwd(), '.cleo');\n try {\n await fs.mkdir(cleoDir, { recursive: true });\n } catch (error) {\n // Ignore if already exists\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\n/**\n * Log mutation to audit trail\n *\n * Appends a single-line JSON entry to .cleo/audit-log.json\n * Non-blocking - errors are logged but not thrown\n * Automatically rotates log if size exceeds limit\n *\n * @param entry Audit entry to log\n */\nexport async function logMutation(entry: AuditEntry): Promise<void> {\n try {\n // Check if audit logging is enabled\n const config = getConfig();\n if (!config.auditLog) {\n return; // Audit logging disabled\n }\n\n // Ensure .cleo directory exists\n await ensureCleoDir();\n\n // Get audit log path\n const logPath = getAuditLogPath();\n\n // Check if rotation is needed\n await checkAndRotateLog(logPath);\n\n // Serialize entry as single-line JSON\n const line = JSON.stringify(entry) + '\\n';\n\n // Append to log file\n await fs.appendFile(logPath, line, 'utf8');\n } catch (error) {\n // Log error but don't throw - audit logging should not block operations\n console.error('Failed to write audit log entry:', error);\n }\n}\n\n/**\n * Log error to audit trail\n *\n * Convenience function for logging errors with full context\n *\n * @param domain Domain where error occurred\n * @param operation Operation that failed\n * @param error Error object or message\n * @param params Operation parameters\n * @param exitCode Exit code (default: 1)\n */\nexport async function logError(\n domain: string,\n operation: string,\n error: Error | string,\n params: Record<string, unknown> = {},\n exitCode: number = 1\n): Promise<void> {\n // Check if audit logging is enabled\n const config = getConfig();\n if (!config.auditLog) {\n return; // Audit logging disabled\n }\n\n const errorMessage = error instanceof Error ? error.message : error;\n const taskId = typeof params.taskId === 'string' ? params.taskId : undefined;\n\n const entry: AuditEntry = {\n timestamp: new Date().toISOString(),\n sessionId: getCurrentSessionId(),\n domain,\n operation,\n params,\n result: {\n success: false,\n exitCode,\n duration: 0,\n },\n metadata: {\n taskId,\n source: 'mcp',\n },\n error: errorMessage,\n };\n\n await logMutation(entry);\n}\n\n/**\n * Read audit log entries\n *\n * @param options Filter options\n * @returns Array of audit entries\n */\nexport async function readAuditLog(options?: {\n since?: string;\n domain?: string;\n operation?: string;\n success?: boolean;\n limit?: number;\n}): Promise<AuditEntry[]> {\n try {\n const logPath = getAuditLogPath();\n\n // Read log file\n const content = await fs.readFile(logPath, 'utf8');\n\n // Parse JSONL\n const entries = content\n .split('\\n')\n .filter((line) => line.trim())\n .map((line) => JSON.parse(line) as AuditEntry);\n\n // Apply filters\n let filtered = entries;\n\n if (options?.since) {\n filtered = filtered.filter((e) => e.timestamp >= options.since!);\n }\n\n if (options?.domain) {\n filtered = filtered.filter((e) => e.domain === options.domain);\n }\n\n if (options?.operation) {\n filtered = filtered.filter((e) => e.operation === options.operation);\n }\n\n if (options?.success !== undefined) {\n filtered = filtered.filter((e) => e.result.success === options.success);\n }\n\n // Apply limit\n if (options?.limit) {\n filtered = filtered.slice(-options.limit);\n }\n\n return filtered;\n } catch (error) {\n // If file doesn't exist, return empty array\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Get audit statistics\n *\n * @returns Audit statistics\n */\nexport async function getAuditStats(): Promise<{\n totalEntries: number;\n successCount: number;\n failureCount: number;\n byDomain: Record<string, number>;\n byOperation: Record<string, number>;\n avgDuration: number;\n}> {\n const entries = await readAuditLog();\n\n const stats = {\n totalEntries: entries.length,\n successCount: entries.filter((e) => e.result.success).length,\n failureCount: entries.filter((e) => !e.result.success).length,\n byDomain: {} as Record<string, number>,\n byOperation: {} as Record<string, number>,\n avgDuration: 0,\n };\n\n // Count by domain\n for (const entry of entries) {\n stats.byDomain[entry.domain] = (stats.byDomain[entry.domain] || 0) + 1;\n const opKey = `${entry.domain}.${entry.operation}`;\n stats.byOperation[opKey] = (stats.byOperation[opKey] || 0) + 1;\n }\n\n // Calculate average duration\n const durations = entries.filter((e) => e.result.duration).map((e) => e.result.duration);\n if (durations.length > 0) {\n stats.avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;\n }\n\n return stats;\n}\n\n/**\n * Clear audit log (use with caution)\n *\n * @returns Number of entries cleared\n */\nexport async function clearAuditLog(): Promise<number> {\n try {\n const entries = await readAuditLog();\n const count = entries.length;\n\n const logPath = getAuditLogPath();\n await fs.unlink(logPath);\n\n return count;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return 0;\n }\n throw error;\n }\n}\n\n/**\n * Check and rotate audit log if size exceeds limit\n *\n * Rotates log to timestamped archive file when size exceeds MAX_AUDIT_LOG_SIZE\n *\n * @param logPath Path to audit log file\n */\nasync function checkAndRotateLog(logPath: string): Promise<void> {\n try {\n const stats = await fs.stat(logPath);\n\n if (stats.size >= MAX_AUDIT_LOG_SIZE) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-${timestamp}.json`\n );\n\n // Move current log to archive\n await fs.rename(logPath, archivePath);\n\n console.log(`Rotated audit log: ${archivePath} (${stats.size} bytes)`);\n }\n } catch (error) {\n // If file doesn't exist, no rotation needed\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.error('Failed to check/rotate audit log:', error);\n }\n }\n}\n\n/**\n * Manually rotate audit log\n *\n * Forces rotation regardless of size\n *\n * @returns Path to rotated log file\n */\nexport async function rotateLog(): Promise<string | null> {\n try {\n const logPath = getAuditLogPath();\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-${timestamp}.json`\n );\n\n // Check if log exists\n try {\n await fs.access(logPath);\n } catch {\n return null; // No log to rotate\n }\n\n // Move current log to archive\n await fs.rename(logPath, archivePath);\n\n return archivePath;\n } catch (error) {\n console.error('Failed to rotate audit log:', error);\n return null;\n }\n}\n\n/**\n * Archive old audit entries\n *\n * Moves entries older than specified date to archive file\n *\n * @param beforeDate ISO date string\n * @returns Number of entries archived\n */\nexport async function archiveAuditLog(beforeDate: string): Promise<number> {\n try {\n const entries = await readAuditLog();\n\n const toArchive = entries.filter((e) => e.timestamp < beforeDate);\n const toKeep = entries.filter((e) => e.timestamp >= beforeDate);\n\n if (toArchive.length === 0) {\n return 0;\n }\n\n // Write archive file\n const archivePath = join(\n process.cwd(),\n '.cleo',\n `audit-log-archive-${beforeDate}.json`\n );\n const archiveContent = toArchive.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n await fs.writeFile(archivePath, archiveContent, 'utf8');\n\n // Write remaining entries back to log\n const logPath = getAuditLogPath();\n const logContent = toKeep.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n await fs.writeFile(logPath, logContent, 'utf8');\n\n return toArchive.length;\n } catch (error) {\n console.error('Failed to archive audit log:', error);\n return 0;\n }\n}\n\n/**\n * Query audit log entries with filters\n *\n * @param options Query options\n * @returns Filtered audit entries\n */\nexport async function queryAudit(options?: {\n since?: string;\n domain?: string;\n operation?: string;\n success?: boolean;\n taskId?: string;\n sessionId?: string;\n limit?: number;\n}): Promise<AuditEntry[]> {\n const entries = await readAuditLog(options);\n\n // Additional filters for new fields\n let filtered = entries;\n\n if (options?.taskId) {\n filtered = filtered.filter((e) => e.metadata?.taskId === options.taskId);\n }\n\n if (options?.sessionId) {\n filtered = filtered.filter((e) => e.sessionId === options.sessionId);\n }\n\n return filtered;\n}\n", "/**\n * cleo_mutate Gateway - Write Operations\n *\n * Handles all state-modifying operations with strict validation,\n * audit logging, and rollback support.\n *\n * Domains: tasks, session, orchestrate, research, lifecycle, validate, release, system, issues, skills\n * Total operations: 65\n *\n * @task T2929\n */\n\nimport { DomainRequest, DomainResponse } from '../lib/router.js';\n\nimport { logMutation, AuditEntry } from '../lib/audit.js';\n\n/**\n * Mutate request interface\n */\nexport interface MutateRequest {\n domain: 'tasks' | 'session' | 'orchestrate' | 'research' | 'lifecycle' | 'validate' | 'release' | 'system' | 'issues' | 'skills' | 'providers';\n operation: string;\n params?: Record<string, unknown>;\n}\n\n/**\n * Mutate response interface (aliases DomainResponse)\n */\nexport type MutateResponse = DomainResponse;\n\n/**\n * Mutate operation matrix - all write operations by domain\n * Reference: MCP-SERVER-SPECIFICATION.md Section 2.2.2\n */\nexport const MUTATE_OPERATIONS: Record<string, string[]> = {\n tasks: [\n 'add', // Create new task\n 'update', // Update task fields\n 'complete', // Mark task done\n 'delete', // Delete task\n 'archive', // Archive done tasks\n 'restore', // Restore from archive\n 'reparent', // Change task parent\n 'promote', // Promote subtask to task\n 'reorder', // Reorder siblings\n 'reopen', // Alias for restore (completed tasks)\n 'relates.add', // Add task relationship\n 'uncancel', // Alias for restore (cancelled tasks)\n 'start', // Start working on task\n 'stop', // Stop working on task\n ],\n session: [\n 'start', // Start new session\n 'end', // End current session\n 'resume', // Resume existing session\n 'suspend', // Suspend session\n 'gc', // Garbage collect sessions\n 'record.decision', // Record a decision\n 'record.assumption', // Record an assumption\n ],\n orchestrate: [\n 'start', // Initialize orchestration\n 'spawn', // Generate spawn prompt\n 'validate', // Validate spawn readiness\n 'parallel.start', // Start parallel wave\n 'parallel.end', // End parallel wave\n ],\n research: [\n 'inject', // Get protocol injection\n 'link', // Link research to task\n 'manifest.append', // Append manifest entry\n 'manifest.archive', // Archive old entries\n ],\n lifecycle: [\n 'record', // Record stage completion\n 'skip', // Skip optional stage\n 'reset', // Reset stage (emergency)\n 'gate.pass', // Mark gate as passed\n 'gate.fail', // Mark gate as failed\n ],\n validate: [\n 'compliance.record', // Record compliance check\n 'test.run', // Execute test suite\n ],\n release: [\n 'prepare', // Prepare release\n 'changelog', // Generate changelog\n 'commit', // Create release commit\n 'tag', // Create git tag\n 'push', // Push to remote\n 'gates.run', // Run release gates\n 'rollback', // Rollback release\n ],\n system: [\n 'init', // Initialize CLEO\n 'config.set', // Set config value\n 'backup', // Create backup\n 'restore', // Restore from backup\n 'migrate', // Run migrations\n 'sync', // Sync with TodoWrite\n 'cleanup', // Cleanup stale data\n 'job.cancel', // Cancel background job\n 'safestop', // Graceful agent shutdown\n 'uncancel', // Alias for restore (cancelled tasks)\n 'inject.generate', // Generate MVI injection\n ],\n issues: [\n 'add.bug', // File a bug report\n 'add.feature', // Request a feature\n 'add.help', // Ask a question\n 'create.bug', // Alias (backward compat)\n 'create.feature', // Alias (backward compat)\n 'create.help', // Alias (backward compat)\n ],\n skills: [\n 'install', // Install a skill\n 'uninstall', // Uninstall a skill\n 'enable', // Enable a skill\n 'disable', // Disable a skill\n 'configure', // Configure a skill\n 'refresh', // Refresh skill registry\n ],\n providers: [\n 'inject', // Inject content into provider instruction files\n ],\n};\n\n/**\n * Total operation count check\n */\nconst EXPECTED_MUTATE_COUNT = 68;\nconst actualMutateCount = Object.values(MUTATE_OPERATIONS).flat().length;\nif (actualMutateCount !== EXPECTED_MUTATE_COUNT) {\n console.error(\n `Warning: Mutate operation count mismatch. Expected ${EXPECTED_MUTATE_COUNT}, got ${actualMutateCount}`\n );\n}\n\n/**\n * Idempotent operations that may return success for already-completed actions\n * These operations use exit codes 100+ to signal \"already done\" vs \"just completed\"\n */\nconst IDEMPOTENT_OPERATIONS: Record<string, string[]> = {\n tasks: ['complete', 'archive'],\n session: ['end', 'gc'],\n lifecycle: ['record', 'skip', 'gate.pass'],\n validate: ['compliance.record'],\n release: ['tag', 'push'],\n system: ['init', 'migrate', 'cleanup'],\n};\n\n/**\n * Operations that require session binding\n */\nconst SESSION_REQUIRED_OPERATIONS: Record<string, string[]> = {\n tasks: ['add', 'update', 'complete'],\n session: ['start'],\n orchestrate: ['start', 'spawn'],\n};\n\n/**\n * Validate mutate request parameters\n */\nexport function validateMutateParams(request: MutateRequest): {\n valid: boolean;\n error?: DomainResponse;\n} {\n const { domain, operation, params } = request;\n\n // Check if domain is valid\n if (!MUTATE_OPERATIONS[domain]) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain,\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_INVALID_DOMAIN',\n exitCode: 2,\n message: `Unknown mutate domain: ${domain}`,\n fix: `Use one of: ${Object.keys(MUTATE_OPERATIONS).join(', ')}`,\n alternatives: Object.keys(MUTATE_OPERATIONS).map((d) => ({\n action: `List ${d} operations`,\n command: `Available: ${MUTATE_OPERATIONS[d].join(', ')}`,\n })),\n },\n },\n };\n }\n\n // Check if operation is valid for this domain\n const validOps = MUTATE_OPERATIONS[domain];\n if (!validOps.includes(operation)) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain,\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_INVALID_OPERATION',\n exitCode: 2,\n message: `Operation '${operation}' not supported for cleo_mutate in domain '${domain}'`,\n fix: `Use one of: ${validOps.join(', ')}`,\n alternatives: validOps.map((op) => ({\n action: `Use ${op}`,\n command: `cleo_mutate ${domain} ${op}`,\n })),\n },\n },\n };\n }\n\n // Perform operation-specific parameter validation\n const paramValidation = validateOperationParams(domain, operation, params);\n if (!paramValidation.valid) {\n return paramValidation;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate operation-specific parameters\n */\nfunction validateOperationParams(\n domain: string,\n operation: string,\n params?: Record<string, unknown>\n): {\n valid: boolean;\n error?: DomainResponse;\n} {\n // Domain-specific parameter validation\n switch (domain) {\n case 'tasks':\n return validateTasksParams(operation, params);\n case 'session':\n return validateSessionParams(operation, params);\n case 'orchestrate':\n return validateOrchestrateParams(operation, params);\n case 'research':\n return validateResearchParams(operation, params);\n case 'lifecycle':\n return validateLifecycleParams(operation, params);\n case 'validate':\n return validateValidateParams(operation, params);\n case 'release':\n return validateReleaseParams(operation, params);\n case 'system':\n return validateSystemParams(operation, params);\n case 'skills':\n return validateSkillsParams(operation, params);\n default:\n return { valid: true };\n }\n}\n\n/**\n * Validate tasks domain parameters\n */\nfunction validateTasksParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'add':\n if (!params?.title || !params?.description) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'tasks',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: title and description',\n fix: 'Provide both title and description fields',\n },\n },\n };\n }\n if (params.title === params.description) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'tasks',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Title and description must be different (anti-hallucination requirement)',\n fix: 'Provide a unique description that differs from the title',\n },\n },\n };\n }\n break;\n\n case 'update':\n case 'complete':\n case 'delete':\n case 'restore':\n case 'reparent':\n case 'promote':\n case 'reorder':\n case 'reopen':\n case 'start':\n case 'uncancel':\n if (!params?.taskId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'tasks',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: taskId',\n fix: 'Provide taskId parameter',\n },\n },\n };\n }\n break;\n\n case 'relates.add':\n if (!params?.taskId || !params?.targetId || !params?.type || !params?.reason) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'tasks',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: taskId, targetId, type, and reason',\n fix: 'Provide taskId, targetId, type, and reason parameters',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate session domain parameters\n */\nfunction validateSessionParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'start':\n if (!params?.scope) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'session',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: scope',\n fix: 'Provide scope parameter (e.g., \"epic:T1234\")',\n },\n },\n };\n }\n break;\n\n case 'resume':\n if (!params?.sessionId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'session',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: sessionId',\n fix: 'Provide sessionId parameter',\n },\n },\n };\n }\n break;\n\n case 'record.decision':\n if (!params?.sessionId || !params?.taskId || !params?.decision || !params?.rationale) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'session',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: sessionId, taskId, decision, and rationale',\n fix: 'Provide sessionId, taskId, decision, and rationale parameters',\n },\n },\n };\n }\n break;\n\n case 'record.assumption':\n if (!params?.assumption || !params?.confidence) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'session',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: assumption and confidence',\n fix: 'Provide assumption (string) and confidence (high|medium|low) parameters',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate orchestrate domain parameters\n */\nfunction validateOrchestrateParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'start':\n if (!params?.epicId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'orchestrate',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: epicId',\n fix: 'Provide epicId parameter',\n },\n },\n };\n }\n break;\n\n case 'spawn':\n case 'validate':\n if (!params?.taskId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'orchestrate',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: taskId',\n fix: 'Provide taskId parameter',\n },\n },\n };\n }\n break;\n\n case 'parallel.start':\n case 'parallel.end':\n if (!params?.epicId || params?.wave === undefined) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'orchestrate',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: epicId and wave',\n fix: 'Provide both epicId and wave parameters',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate research domain parameters\n */\nfunction validateResearchParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'inject':\n if (!params?.protocolType) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'research',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: protocolType',\n fix: 'Provide protocolType parameter (e.g., \"research\", \"implementation\")',\n },\n },\n };\n }\n break;\n\n case 'link':\n if (!params?.researchId || !params?.taskId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'research',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: researchId and taskId',\n fix: 'Provide both researchId and taskId parameters',\n },\n },\n };\n }\n break;\n\n case 'manifest.append':\n if (!params?.entry) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'research',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: entry',\n fix: 'Provide entry parameter with manifest entry object',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate lifecycle domain parameters\n */\nfunction validateLifecycleParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'record':\n if (!params?.taskId || !params?.stage || !params?.status) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'lifecycle',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: taskId, stage, and status',\n fix: 'Provide taskId, stage, and status parameters',\n },\n },\n };\n }\n break;\n\n case 'skip':\n case 'reset':\n if (!params?.taskId || !params?.stage || !params?.reason) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'lifecycle',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: taskId, stage, and reason',\n fix: 'Provide taskId, stage, and reason parameters',\n },\n },\n };\n }\n break;\n\n case 'gate.pass':\n case 'gate.fail':\n if (!params?.taskId || !params?.gateName) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'lifecycle',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: taskId and gateName',\n fix: 'Provide taskId and gateName parameters',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate validate domain parameters\n */\nfunction validateValidateParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'compliance.record':\n if (!params?.taskId || !params?.result) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'validate',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: taskId and result',\n fix: 'Provide taskId and result parameters',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate release domain parameters\n */\nfunction validateReleaseParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'prepare':\n case 'changelog':\n case 'commit':\n case 'tag':\n case 'push':\n case 'rollback':\n if (!params?.version) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'release',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: version',\n fix: 'Provide version parameter (X.Y.Z or YYYY.M.patch format)',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate system domain parameters\n */\nfunction validateSystemParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'config.set':\n if (!params?.key || params?.value === undefined) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'system',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameters: key and value',\n fix: 'Provide key and value parameters',\n },\n },\n };\n }\n break;\n\n case 'restore':\n if (!params?.backupId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'system',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: backupId',\n fix: 'Provide backupId parameter',\n },\n },\n };\n }\n break;\n\n case 'job.cancel':\n if (!params?.jobId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'system',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: jobId',\n fix: 'Provide jobId parameter',\n },\n },\n };\n }\n break;\n\n case 'cleanup':\n if (!params?.type) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'system',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: type',\n fix: 'Provide type parameter (e.g., \"sessions\", \"backups\")',\n },\n },\n };\n }\n break;\n\n case 'uncancel':\n if (!params?.taskId) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'system',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: taskId',\n fix: 'Provide taskId parameter for the cancelled task to restore',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Validate skills domain parameters\n */\nfunction validateSkillsParams(\n operation: string,\n params?: Record<string, unknown>\n): { valid: boolean; error?: DomainResponse } {\n switch (operation) {\n case 'install':\n case 'uninstall':\n case 'enable':\n case 'disable':\n case 'configure':\n if (!params?.name) {\n return {\n valid: false,\n error: {\n _meta: {\n gateway: 'cleo_mutate',\n domain: 'skills',\n operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: 0,\n },\n success: false,\n error: {\n code: 'E_VALIDATION_FAILED',\n exitCode: 6,\n message: 'Missing required parameter: name',\n fix: 'Provide name parameter for the skill',\n },\n },\n };\n }\n break;\n }\n\n return { valid: true };\n}\n\n/**\n * Register cleo_mutate tool with MCP server\n *\n * Returns tool definition for ListToolsRequestSchema handler\n */\nexport function registerMutateTool() {\n return {\n name: 'cleo_mutate',\n description:\n 'CLEO write operations: create, update, complete tasks; manage sessions; spawn agents; progress lifecycle; execute releases. Modifies state with validation.',\n inputSchema: {\n type: 'object',\n required: ['domain', 'operation'],\n properties: {\n domain: {\n type: 'string',\n enum: Object.keys(MUTATE_OPERATIONS),\n description: 'Functional domain to mutate',\n },\n operation: {\n type: 'string',\n description: 'Domain-specific write operation (see operation matrix)',\n },\n params: {\n type: 'object',\n description: 'Operation-specific parameters',\n additionalProperties: true,\n },\n },\n },\n };\n}\n\n/**\n * Handle cleo_mutate request\n *\n * Validates parameters, logs to audit trail, routes to domain handler,\n * and handles idempotency\n *\n * @param request Mutate request with domain, operation, and params\n * @returns Promise resolving to mutate response\n */\nexport async function handleMutateRequest(\n request: MutateRequest\n): Promise<MutateResponse> {\n const startTime = Date.now();\n\n // Validate request parameters\n const validation = validateMutateParams(request);\n if (!validation.valid) {\n return validation.error!;\n }\n\n // Extract task ID from params if present\n const taskId = typeof request.params?.taskId === 'string' ? request.params.taskId : undefined;\n const sessionId = process.env.CLEO_SESSION_ID || null;\n\n // Log mutation attempt to audit trail\n const auditEntry: AuditEntry = {\n timestamp: new Date().toISOString(),\n sessionId,\n domain: request.domain,\n operation: request.operation,\n params: request.params || {},\n result: {\n success: false,\n exitCode: 0,\n duration: 0,\n },\n metadata: {\n taskId,\n source: 'mcp',\n gateway: 'cleo_mutate',\n },\n };\n\n try {\n // Build domain request (will be routed by DomainRouter)\n const domainRequest: DomainRequest = {\n gateway: 'cleo_mutate',\n domain: request.domain,\n operation: request.operation,\n params: request.params,\n };\n\n // Create response (this function is called by the router)\n const response: MutateResponse = {\n _meta: {\n gateway: 'cleo_mutate',\n domain: request.domain,\n operation: request.operation,\n version: '1.0.0',\n timestamp: new Date().toISOString(),\n duration_ms: Date.now() - startTime,\n },\n success: true,\n data: domainRequest,\n };\n\n // Update audit entry with success\n auditEntry.result.success = true;\n auditEntry.result.exitCode = 0;\n auditEntry.result.duration = Date.now() - startTime;\n\n // Log to audit trail (async, non-blocking)\n logMutation(auditEntry).catch((err) => {\n console.error('Failed to log mutation to audit trail:', err);\n });\n\n return response;\n } catch (error) {\n // Update audit entry with failure\n auditEntry.result.success = false;\n auditEntry.result.exitCode = 1; // TODO: Extract actual exit code from CLI response\n auditEntry.result.duration = Date.now() - startTime;\n auditEntry.error = error instanceof Error ? error.message : String(error);\n\n // Log to audit trail (async, non-blocking)\n logMutation(auditEntry).catch((err) => {\n console.error('Failed to log mutation error to audit trail:', err);\n });\n\n throw error;\n }\n}\n\n/**\n * Check if operation is idempotent\n */\nexport function isIdempotentOperation(domain: string, operation: string): boolean {\n return IDEMPOTENT_OPERATIONS[domain]?.includes(operation) || false;\n}\n\n/**\n * Check if operation requires session binding\n */\nexport function requiresSession(domain: string, operation: string): boolean {\n return SESSION_REQUIRED_OPERATIONS[domain]?.includes(operation) || false;\n}\n\n/**\n * Get mutate operation count for specific domain or all domains\n */\nexport function getMutateOperationCount(domain?: string): number {\n if (domain) {\n return MUTATE_OPERATIONS[domain]?.length || 0;\n }\n return actualMutateCount;\n}\n\n/**\n * Check if operation is write (mutate)\n */\nexport function isMutateOperation(domain: string, operation: string): boolean {\n return MUTATE_OPERATIONS[domain]?.includes(operation) || false;\n}\n\n/**\n * Get all mutate domains\n */\nexport function getMutateDomains(): string[] {\n return Object.keys(MUTATE_OPERATIONS);\n}\n\n/**\n * Get operations for specific mutate domain\n */\nexport function getMutateOperations(domain: string): string[] {\n return MUTATE_OPERATIONS[domain] || [];\n}\n", "/**\n * In-memory query cache for CLEO MCP Server\n *\n * Caches cleo_query responses with configurable TTL.\n * Cache key = domain + operation + hash(params).\n * Invalidated on any cleo_mutate operation for the relevant domain.\n *\n * @task T3145\n */\n\nimport { createHash } from 'crypto';\n\n/**\n * Single cache entry with expiration tracking\n */\ninterface CacheEntry<T = unknown> {\n value: T;\n expiresAt: number;\n createdAt: number;\n}\n\n/**\n * Cache statistics\n */\nexport interface CacheStats {\n hits: number;\n misses: number;\n evictions: number;\n size: number;\n domains: Record<string, number>;\n}\n\n/**\n * Query cache with per-domain invalidation\n */\nexport class QueryCache {\n private store: Map<string, CacheEntry> = new Map();\n private domainKeys: Map<string, Set<string>> = new Map();\n private stats: CacheStats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: 0,\n domains: {},\n };\n private ttl: number;\n private enabled: boolean;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(ttlMs: number = 30000, enabled: boolean = true) {\n this.ttl = ttlMs;\n this.enabled = enabled;\n\n // Periodic cleanup of expired entries every TTL interval\n if (enabled && ttlMs > 0) {\n this.cleanupTimer = setInterval(() => this.evictExpired(), ttlMs);\n // Allow Node to exit even if timer is running\n if (this.cleanupTimer.unref) {\n this.cleanupTimer.unref();\n }\n }\n }\n\n /**\n * Build cache key from domain, operation, and params\n */\n buildKey(domain: string, operation: string, params?: Record<string, unknown>): string {\n const paramsHash = params\n ? createHash('md5').update(JSON.stringify(sortObject(params))).digest('hex').slice(0, 12)\n : 'no-params';\n return `${domain}:${operation}:${paramsHash}`;\n }\n\n /**\n * Get cached value, or undefined if not found/expired\n */\n get<T = unknown>(domain: string, operation: string, params?: Record<string, unknown>): T | undefined {\n if (!this.enabled) {\n this.stats.misses++;\n return undefined;\n }\n\n const key = this.buildKey(domain, operation, params);\n const entry = this.store.get(key);\n\n if (!entry) {\n this.stats.misses++;\n return undefined;\n }\n\n // Check TTL expiration\n if (Date.now() > entry.expiresAt) {\n this.delete(key, domain);\n this.stats.misses++;\n this.stats.evictions++;\n return undefined;\n }\n\n this.stats.hits++;\n return entry.value as T;\n }\n\n /**\n * Store a value in the cache\n */\n set<T = unknown>(domain: string, operation: string, params: Record<string, unknown> | undefined, value: T): void {\n if (!this.enabled || this.ttl <= 0) {\n return;\n }\n\n const key = this.buildKey(domain, operation, params);\n const now = Date.now();\n\n this.store.set(key, {\n value,\n expiresAt: now + this.ttl,\n createdAt: now,\n });\n\n // Track key under its domain for bulk invalidation\n if (!this.domainKeys.has(domain)) {\n this.domainKeys.set(domain, new Set());\n }\n this.domainKeys.get(domain)!.add(key);\n\n // Update stats\n this.stats.size = this.store.size;\n this.stats.domains[domain] = this.domainKeys.get(domain)!.size;\n }\n\n /**\n * Invalidate all cached entries for a domain\n *\n * Called on any cleo_mutate operation to ensure consistency.\n */\n invalidateDomain(domain: string): number {\n const keys = this.domainKeys.get(domain);\n if (!keys || keys.size === 0) {\n return 0;\n }\n\n const count = keys.size;\n for (const key of keys) {\n this.store.delete(key);\n }\n keys.clear();\n\n this.stats.evictions += count;\n this.stats.size = this.store.size;\n this.stats.domains[domain] = 0;\n\n return count;\n }\n\n /**\n * Clear entire cache\n */\n clear(): void {\n const count = this.store.size;\n this.store.clear();\n this.domainKeys.clear();\n this.stats.evictions += count;\n this.stats.size = 0;\n this.stats.domains = {};\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n return { ...this.stats, size: this.store.size };\n }\n\n /**\n * Reset statistics counters\n */\n resetStats(): void {\n this.stats.hits = 0;\n this.stats.misses = 0;\n this.stats.evictions = 0;\n }\n\n /**\n * Evict all expired entries\n */\n evictExpired(): number {\n const now = Date.now();\n let count = 0;\n\n for (const [key, entry] of this.store) {\n if (now > entry.expiresAt) {\n // Find the domain for this key\n const domain = key.split(':')[0];\n this.delete(key, domain);\n count++;\n }\n }\n\n if (count > 0) {\n this.stats.evictions += count;\n }\n\n return count;\n }\n\n /**\n * Stop the cleanup timer (call on shutdown)\n */\n destroy(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n this.clear();\n }\n\n /**\n * Check if cache is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /**\n * Delete a single key and update domain tracking\n */\n private delete(key: string, domain: string): void {\n this.store.delete(key);\n const keys = this.domainKeys.get(domain);\n if (keys) {\n keys.delete(key);\n this.stats.domains[domain] = keys.size;\n }\n this.stats.size = this.store.size;\n }\n}\n\n/**\n * Sort object keys recursively for deterministic hashing\n */\nfunction sortObject(obj: Record<string, unknown>): Record<string, unknown> {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n const val = obj[key];\n if (val !== null && typeof val === 'object' && !Array.isArray(val)) {\n sorted[key] = sortObject(val as Record<string, unknown>);\n } else {\n sorted[key] = val;\n }\n }\n return sorted;\n}\n", "/**\n * Background Job Manager for Long-Running Operations\n *\n * Per MCP-SERVER-SPECIFICATION.md Section 10, operations that may take >30s\n * should support async execution. This module provides a job manager that\n * tracks background operations with status, progress, and auto-cleanup.\n *\n * @task T3080\n */\n\nimport { randomUUID } from 'crypto';\n\n/**\n * Background job status\n */\nexport type JobStatus = 'running' | 'completed' | 'failed' | 'cancelled';\n\n/**\n * Background job representation\n */\nexport interface BackgroundJob {\n id: string;\n operation: string;\n status: JobStatus;\n startedAt: string;\n completedAt?: string;\n result?: unknown;\n error?: string;\n progress?: number;\n}\n\n/**\n * Configuration for BackgroundJobManager\n */\nexport interface BackgroundJobManagerConfig {\n maxJobs?: number;\n retentionMs?: number;\n}\n\n/**\n * Manages background jobs for long-running operations\n */\nexport class BackgroundJobManager {\n private jobs: Map<string, BackgroundJob>;\n private abortControllers: Map<string, AbortController>;\n private maxJobs: number;\n private retentionMs: number;\n private cleanupTimer: ReturnType<typeof setInterval> | null;\n\n constructor(config?: BackgroundJobManagerConfig) {\n this.jobs = new Map();\n this.abortControllers = new Map();\n this.maxJobs = config?.maxJobs ?? 10;\n this.retentionMs = config?.retentionMs ?? 3600000; // 1 hour default\n this.cleanupTimer = null;\n\n // Start periodic cleanup every 5 minutes\n this.cleanupTimer = setInterval(() => this.cleanup(), 300000);\n // Don't prevent process exit\n if (this.cleanupTimer.unref) {\n this.cleanupTimer.unref();\n }\n }\n\n /**\n * Start a new background job\n *\n * @param operation - The operation identifier (e.g. \"validate.test.run\")\n * @param executor - Async function to execute in the background\n * @returns The job ID\n * @throws Error if max concurrent jobs reached\n */\n async startJob(operation: string, executor: () => Promise<unknown>): Promise<string> {\n // Check concurrent job limit (only count running jobs)\n const runningCount = this.listJobs('running').length;\n if (runningCount >= this.maxJobs) {\n throw new Error(\n `Maximum concurrent jobs reached (${this.maxJobs}). Cancel or wait for existing jobs to complete.`\n );\n }\n\n const jobId = randomUUID();\n const abortController = new AbortController();\n\n const job: BackgroundJob = {\n id: jobId,\n operation,\n status: 'running',\n startedAt: new Date().toISOString(),\n };\n\n this.jobs.set(jobId, job);\n this.abortControllers.set(jobId, abortController);\n\n // Execute async - don't await\n this.executeJob(jobId, executor, abortController.signal);\n\n return jobId;\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): BackgroundJob | undefined {\n return this.jobs.get(jobId);\n }\n\n /**\n * List all jobs, optionally filtered by status\n */\n listJobs(status?: string): BackgroundJob[] {\n const all = Array.from(this.jobs.values());\n if (!status) {\n return all;\n }\n return all.filter((job) => job.status === status);\n }\n\n /**\n * Cancel a running job\n *\n * @returns true if the job was cancelled, false if not found or not running\n */\n cancelJob(jobId: string): boolean {\n const job = this.jobs.get(jobId);\n if (!job || job.status !== 'running') {\n return false;\n }\n\n const controller = this.abortControllers.get(jobId);\n if (controller) {\n controller.abort();\n this.abortControllers.delete(jobId);\n }\n\n job.status = 'cancelled';\n job.completedAt = new Date().toISOString();\n\n return true;\n }\n\n /**\n * Update job progress (0-100)\n */\n updateProgress(jobId: string, progress: number): boolean {\n const job = this.jobs.get(jobId);\n if (!job || job.status !== 'running') {\n return false;\n }\n job.progress = Math.max(0, Math.min(100, progress));\n return true;\n }\n\n /**\n * Cleanup old completed/failed/cancelled jobs past retention period\n *\n * @returns Number of jobs cleaned up\n */\n cleanup(): number {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [id, job] of this.jobs.entries()) {\n if (job.status === 'running') {\n continue;\n }\n if (job.completedAt) {\n const completedTime = new Date(job.completedAt).getTime();\n if (now - completedTime > this.retentionMs) {\n this.jobs.delete(id);\n this.abortControllers.delete(id);\n cleaned++;\n }\n }\n }\n\n return cleaned;\n }\n\n /**\n * Destroy the manager: cancel all running jobs and clear state\n */\n destroy(): void {\n // Cancel all running jobs\n for (const [id, job] of this.jobs.entries()) {\n if (job.status === 'running') {\n const controller = this.abortControllers.get(id);\n if (controller) {\n controller.abort();\n }\n }\n }\n\n this.jobs.clear();\n this.abortControllers.clear();\n\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n\n /**\n * Execute a job's executor function and update status on completion/failure\n */\n private async executeJob(\n jobId: string,\n executor: () => Promise<unknown>,\n signal: AbortSignal\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n return;\n }\n\n try {\n const result = await executor();\n\n // Check if cancelled during execution\n if (signal.aborted) {\n return;\n }\n\n job.status = 'completed';\n job.completedAt = new Date().toISOString();\n job.result = result;\n job.progress = 100;\n } catch (error) {\n // Check if this was a cancellation\n if (signal.aborted) {\n return;\n }\n\n job.status = 'failed';\n job.completedAt = new Date().toISOString();\n job.error = error instanceof Error ? error.message : String(error);\n } finally {\n this.abortControllers.delete(jobId);\n }\n }\n}\n", "/**\n * Execution Mode Detector\n *\n * Detects whether the CLEO CLI is available and determines the execution mode\n * for the MCP server. Supports three modes:\n *\n * - native: TypeScript engine only (cross-platform, no bash needed)\n * - cli: CLI subprocess only (Unix, requires bash + jq)\n * - auto: Detect CLI availability; prefer CLI when found, fallback to native\n *\n * Controlled by MCP_EXECUTION_MODE environment variable.\n */\n\nimport { execFileSync } from 'child_process';\n\n/**\n * Execution mode for the MCP server\n */\nexport type ServerExecutionMode = 'native' | 'cli' | 'auto';\n\n/**\n * Resolved execution mode after detection\n */\nexport type ResolvedMode = 'native' | 'cli';\n\n/**\n * Detection result with metadata\n */\nexport interface ModeDetectionResult {\n /** The resolved execution mode */\n mode: ResolvedMode;\n /** The configured mode (from env) */\n configuredMode: ServerExecutionMode;\n /** Whether CLI was detected as available */\n cliAvailable: boolean;\n /** Path to CLI binary (if found) */\n cliPath: string | null;\n /** CLI version (if available) */\n cliVersion: string | null;\n /** Reason for mode selection */\n reason: string;\n}\n\n/**\n * Detect CLI availability and determine execution mode.\n *\n * Priority:\n * 1. MCP_EXECUTION_MODE env: 'cli' (force CLI), 'native' (force native), 'auto' (default)\n * 2. If auto: check CLEO_MCP_CLI_PATH env -> if set and executable, prefer CLI\n * 3. If auto: check which/where cleo -> if found, prefer CLI\n * 4. If auto: no CLI found -> native mode\n */\nexport function detectExecutionMode(): ModeDetectionResult {\n const configuredMode = getConfiguredMode();\n\n // Force native mode\n if (configuredMode === 'native') {\n return {\n mode: 'native',\n configuredMode,\n cliAvailable: false,\n cliPath: null,\n cliVersion: null,\n reason: 'MCP_EXECUTION_MODE=native (forced)',\n };\n }\n\n // Check CLI availability\n const cliCheck = checkCLIAvailability();\n\n // Force CLI mode\n if (configuredMode === 'cli') {\n if (!cliCheck.available) {\n return {\n mode: 'cli',\n configuredMode,\n cliAvailable: false,\n cliPath: null,\n cliVersion: null,\n reason: 'MCP_EXECUTION_MODE=cli (forced, but CLI not found - operations will fail)',\n };\n }\n return {\n mode: 'cli',\n configuredMode,\n cliAvailable: true,\n cliPath: cliCheck.path,\n cliVersion: cliCheck.version,\n reason: 'MCP_EXECUTION_MODE=cli (forced)',\n };\n }\n\n // Auto mode: detect CLI\n if (cliCheck.available) {\n return {\n mode: 'cli',\n configuredMode: 'auto',\n cliAvailable: true,\n cliPath: cliCheck.path,\n cliVersion: cliCheck.version,\n reason: `CLI detected at ${cliCheck.path} (auto mode, preferring CLI)`,\n };\n }\n\n return {\n mode: 'native',\n configuredMode: 'auto',\n cliAvailable: false,\n cliPath: null,\n cliVersion: null,\n reason: 'CLI not found (auto mode, using native TypeScript engine)',\n };\n}\n\n/**\n * Get configured mode from environment\n */\nfunction getConfiguredMode(): ServerExecutionMode {\n const env = process.env.MCP_EXECUTION_MODE?.toLowerCase();\n if (env === 'native' || env === 'cli' || env === 'auto') {\n return env;\n }\n return 'auto';\n}\n\n/**\n * Check if CLEO CLI is available\n */\nfunction checkCLIAvailability(): {\n available: boolean;\n path: string | null;\n version: string | null;\n} {\n // 1. Check CLEO_MCP_CLI_PATH env\n const envPath = process.env.CLEO_MCP_CLI_PATH;\n if (envPath) {\n const result = testCLIPath(envPath);\n if (result.available) {\n return result;\n }\n }\n\n // 2. Check standard CLI path from config\n const configPath = process.env.CLEO_CLI_PATH;\n if (configPath) {\n const result = testCLIPath(configPath);\n if (result.available) {\n return result;\n }\n }\n\n // 3. Try which/where command to find cleo in PATH\n const isWindows = process.platform === 'win32';\n const whichCmd = isWindows ? 'where' : 'which';\n\n for (const binary of ['cleo', 'ct']) {\n try {\n const cliPath = execFileSync(whichCmd, [binary], {\n encoding: 'utf-8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim().split('\\n')[0];\n\n if (cliPath) {\n const result = testCLIPath(cliPath);\n if (result.available) {\n return result;\n }\n }\n } catch {\n // Binary not found in PATH\n }\n }\n\n return { available: false, path: null, version: null };\n}\n\n/**\n * Test if a CLI path is executable and returns a version.\n * Uses execFileSync (no shell) to prevent command injection.\n */\nfunction testCLIPath(cliPath: string): {\n available: boolean;\n path: string | null;\n version: string | null;\n} {\n try {\n const output = execFileSync(cliPath, ['version', '--json'], {\n encoding: 'utf-8',\n timeout: 10000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n try {\n const parsed = JSON.parse(output);\n const version = parsed.version || parsed.data?.version || null;\n return { available: true, path: cliPath, version };\n } catch {\n // Non-JSON output but command succeeded\n return { available: true, path: cliPath, version: null };\n }\n } catch {\n return { available: false, path: null, version: null };\n }\n}\n\n/**\n * Create the E_CLI_REQUIRED error response\n */\nexport function createCLIRequiredError(domain: string, operation: string): {\n success: false;\n error: {\n code: string;\n message: string;\n availableInStandaloneMode: boolean;\n nativeAlternatives: string[];\n };\n} {\n return {\n success: false,\n error: {\n code: 'E_CLI_REQUIRED',\n message: `Operation '${domain}.${operation}' requires the CLEO CLI (bash). Install with: ./install.sh`,\n availableInStandaloneMode: false,\n nativeAlternatives: [],\n },\n };\n}\n\n/**\n * Create the E_NOT_INITIALIZED error response\n */\nexport function createNotInitializedError(): {\n success: false;\n error: {\n code: string;\n message: string;\n fix: string;\n };\n} {\n return {\n success: false,\n error: {\n code: 'E_NOT_INITIALIZED',\n message: 'CLEO project not initialized. Run system.init or set CLEO_AUTO_INIT=true',\n fix: \"cleo_mutate({domain: 'system', operation: 'init'})\",\n },\n };\n}\n", "/**\n * LAFS token budget enforcement for MCP responses.\n *\n * Wraps the LAFS protocol's applyBudgetEnforcement() to limit MCP\n * response sizes for context-constrained agents.\n *\n * @task T4701\n * @epic T4663\n */\n\nimport {\n applyBudgetEnforcement,\n checkBudget,\n} from '@cleocode/lafs-protocol';\nimport type { LAFSEnvelope, BudgetEnforcementResult } from '@cleocode/lafs-protocol';\n\n/**\n * Default token budget when no explicit budget is provided.\n * Standard MVI level allows up to 4000 tokens per response.\n *\n * @task T4701\n */\nconst DEFAULT_BUDGET = 4000;\n\n/**\n * Apply budget enforcement to an MCP response envelope.\n *\n * Converts the DomainResponse into an LAFSEnvelope shape for budget checking,\n * then applies truncation if the response exceeds the budget.\n *\n * @param response - The MCP domain response object\n * @param budget - Maximum allowed tokens (defaults to DEFAULT_BUDGET)\n * @returns The response, potentially truncated, with budget metadata\n *\n * @task T4701\n * @epic T4663\n */\nexport function enforceBudget(\n response: Record<string, unknown>,\n budget?: number,\n): { response: Record<string, unknown>; enforcement: BudgetEnforcementResult } {\n const effectiveBudget = budget ?? DEFAULT_BUDGET;\n\n // Build an LAFSEnvelope-shaped object for the budget checker\n const envelope: LAFSEnvelope = {\n $schema: 'https://lafs.dev/schemas/v1/envelope.schema.json',\n _meta: (response['_meta'] as LAFSEnvelope['_meta']) ?? {\n specVersion: '1.2.3',\n schemaVersion: '2026.2.1',\n timestamp: new Date().toISOString(),\n operation: 'mcp.response',\n requestId: 'budget-check',\n transport: 'sdk',\n strict: true,\n mvi: 'standard',\n contextVersion: 1,\n },\n success: (response['success'] as boolean) ?? true,\n result: (response['data'] as Record<string, unknown>) ?? null,\n ...(response['error'] ? { error: response['error'] as LAFSEnvelope['error'] } : {}),\n };\n\n const enforcement = applyBudgetEnforcement(envelope, effectiveBudget, {\n truncateOnExceed: true,\n });\n\n // Merge budget info back into the response _meta\n const meta = (response['_meta'] ?? {}) as Record<string, unknown>;\n meta['_budgetEnforcement'] = {\n budget: effectiveBudget,\n estimatedTokens: enforcement.estimatedTokens,\n withinBudget: enforcement.withinBudget,\n truncated: enforcement.truncated,\n };\n\n return {\n response: {\n ...response,\n _meta: meta,\n // Replace data with potentially truncated result\n ...(enforcement.truncated && enforcement.envelope.result !== undefined && {\n data: enforcement.envelope.result,\n }),\n },\n enforcement,\n };\n}\n\n/**\n * Quick check whether a response exceeds a token budget without modifying it.\n *\n * @task T4701\n * @epic T4663\n */\nexport function isWithinBudget(response: Record<string, unknown>, budget?: number): boolean {\n const effectiveBudget = budget ?? DEFAULT_BUDGET;\n const envelope: LAFSEnvelope = {\n $schema: 'https://lafs.dev/schemas/v1/envelope.schema.json',\n _meta: (response['_meta'] as LAFSEnvelope['_meta']) ?? {\n specVersion: '1.2.3',\n schemaVersion: '2026.2.1',\n timestamp: new Date().toISOString(),\n operation: 'mcp.response',\n requestId: 'budget-check',\n transport: 'sdk',\n strict: true,\n mvi: 'standard',\n contextVersion: 1,\n },\n success: true,\n result: (response['data'] as Record<string, unknown>) ?? null,\n };\n const { exceeded } = checkBudget(envelope, effectiveBudget);\n return !exceeded;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["resolve", "join", "existsSync", "readFileSync", "existsSync", "readFileSync", "join", "ExitCode", "existsSync", "readFileSync", "writeFileSync", "mkdirSync", "dirname", "join", "result", "dirname", "unlink", "mkdir", "join", "basename", "lockfile", "readFile", "existsSync", "join", "result", "readFileSync", "writeFileSync", "existsSync", "join", "tasks", "eq", "DEFAULT_CONFIG", "result", "eq", "sql", "tasks", "taskDeps", "result", "eq", "and", "isNull", "parseJson", "existsSync", "readFileSync", "writeFileSync", "join", "dirname", "mkdirSync", "initSqlJs", "drizzle", "tasks", "sessions", "result", "closeDb", "resetDbState", "statSync", "ne", "eq", "db", "listTasks", "listSessions", "eq", "ne", "rowToTask", "taskToRow", "rowToSession", "tasks", "sessions", "readFileSync", "join", "homedir", "createHash", "join", "mkdir", "readFile", "tasks", "existsSync", "readdirSync", "join", "result", "index", "readFileSync", "renameSync", "existsSync", "join", "dirname", "readFileSync", "dirname", "join", "existsSync", "renameSync", "dirname", "join", "existsSync", "renameSync", "readFileSync", "join", "readFileSync", "existsSync", "join", "tasks", "checkStorageMigration", "migrateJsonToSqlite", "result", "CleoError", "ExitCode", "createSqliteDataAccessor", "createJsonDataAccessor", "existsSync", "readFileSync", "getCleoDirAbsolute", "join", "mkdirSync", "renameSync", "readdirSync", "randomBytes", "existsSync", "writeFile", "mkdir", "dirname", "result", "parseEnvValue", "loadConfig", "globalConfig", "existsSync", "dirname", "mkdir", "writeFile", "tasks", "randomBytes", "readJson", "loadConfig", "getChildren", "tasks", "tasks", "result", "getChildren", "tasks", "validateHierarchy", "tasks", "getChildren", "validateHierarchy", "updateTask", "result", "deleteTask", "listTasks", "text", "findTasks", "tasks", "oldParent", "tasks", "result", "listTasks", "findTasks", "updateTask", "deleteTask", "result", "result", "sessions", "sessions", "result", "tasks", "result", "rootTaskId", "inScopeIds", "inScopeTasks", "completedInScope", "totalInScope", "score", "randomBytes", "readFileSync", "mkdirSync", "existsSync", "join", "randomBytes", "appendFileSync", "mkdirSync", "existsSync", "join", "randomBytes", "join", "existsSync", "mkdirSync", "appendFileSync", "eq", "and", "inArray", "desc", "asc", "startTask", "stopTask", "sessions", "result", "startTask", "stopTask", "randomBytes", "result", "readFileSync", "existsSync", "readdirSync", "join", "basename", "tasks", "readFileSync", "existsSync", "join", "existsSync", "readFileSync", "statSync", "join", "execFile", "promisify", "promisify", "execFile", "join", "existsSync", "readFileSync", "readFileSync", "writeFileSync", "existsSync", "mkdirSync", "join", "createBackup", "readFileSync", "existsSync", "join", "readFileSync", "writeFileSync", "existsSync", "readdirSync", "unlinkSync", "join", "sessions", "readFileSync", "writeFileSync", "existsSync", "join", "sessions", "result", "tasks", "join", "existsSync", "readFileSync", "sessions", "readdirSync", "basename", "result", "result", "result", "createBackup", "result", "result", "mkdir", "access", "writeFile", "readFile", "copyFile", "unlink", "existsSync", "readFileSync", "readdirSync", "join", "resolve", "basename", "dirname", "createHash", "homedir", "generateProjectHash", "getInstalledProviders", "injectAll", "stat", "detectEnvMode", "generateMcpServerEntry", "catalog", "result", "nexusInit", "nexusRegister", "detectProjectType", "join", "readFile", "initProject", "result", "getVersion", "result", "readFileSync", "readdirSync", "existsSync", "join", "join", "readFileSync", "existsSync", "readdirSync", "result", "validateLabels", "existsSync", "mkdirSync", "readdirSync", "join", "STAGE_DEFINITIONS", "join", "existsSync", "mkdirSync", "STAGE_DEFINITIONS", "readFileSync", "existsSync", "appendFileSync", "mkdirSync", "join", "dirname", "resolve", "tasks", "readJsonFile", "readFileSync", "join", "existsSync", "result", "resolve", "dirname", "mkdirSync", "appendFileSync", "tasks", "join", "existsSync", "readJsonFile", "result", "result", "readFileSync", "existsSync", "tasks", "tasks", "text", "tasks", "tasks", "result", "tasks", "readFileSync", "writeFileSync", "existsSync", "mkdirSync", "join", "dirname", "join", "existsSync", "readFileSync", "dirname", "mkdirSync", "writeFileSync", "tasks", "tasks", "readFileSync", "existsSync", "join", "tasks", "tasks", "dfs", "result", "existsSync", "readFileSync", "result", "tasks", "readFileSync", "writeFileSync", "appendFileSync", "existsSync", "mkdirSync", "resolve", "dirname", "getManifestPath", "readFileSync", "resolve", "existsSync", "readFileSync", "getManifestPath", "writeFileSync", "dirname", "mkdirSync", "appendFileSync", "existsSync", "mkdirSync", "execFileSync", "dirname", "join", "index", "tasks", "allTasks", "index", "execFileSync", "loadTasks", "tasks", "loadTasks", "result", "result", "result", "result", "result", "getVersion", "initProject", "result", "result", "result", "tasks", "result", "validateLabels", "resolve", "VALID_PRIORITIES", "VALID_PRIORITIES", "getProjectRoot", "DEFAULT_RATE_LIMITING", "text", "result", "VALIDATION_RULES", "lifecycleGates", "result", "result", "join", "join", "join", "join", "promisify", "result", "execAsync", "promisify", "result", "resolve", "MAX_AUDIT_LOG_SIZE", "createHash", "randomUUID", "result", "execFileSync", "result"]
|
|
7
|
+
}
|