@cleocode/core 2026.4.13 → 2026.4.15

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.
Files changed (918) hide show
  1. package/dist/hooks/payload-schemas.d.ts +1 -1
  2. package/dist/hooks/payload-schemas.d.ts.map +1 -1
  3. package/dist/index.js +71866 -175
  4. package/dist/index.js.map +7 -1
  5. package/dist/init.d.ts.map +1 -1
  6. package/dist/internal.d.ts +16 -5
  7. package/dist/internal.d.ts.map +1 -1
  8. package/dist/memory/brain-embedding.d.ts +1 -1
  9. package/dist/memory/embedding-local.d.ts +8 -3
  10. package/dist/memory/embedding-local.d.ts.map +1 -1
  11. package/dist/memory/embedding-worker.d.ts +1 -1
  12. package/dist/memory/learnings.d.ts +2 -2
  13. package/dist/memory/patterns.d.ts +6 -6
  14. package/dist/store/agent-registry-accessor.d.ts +54 -1
  15. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  16. package/dist/store/backup-crypto.d.ts +89 -0
  17. package/dist/store/backup-crypto.d.ts.map +1 -0
  18. package/dist/store/backup-pack.d.ts +91 -0
  19. package/dist/store/backup-pack.d.ts.map +1 -0
  20. package/dist/store/backup-unpack.d.ts +140 -0
  21. package/dist/store/backup-unpack.d.ts.map +1 -0
  22. package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -1
  23. package/dist/store/nexus-validation-schemas.d.ts +1 -1
  24. package/dist/store/nexus-validation-schemas.d.ts.map +1 -1
  25. package/dist/store/regenerators.d.ts +126 -0
  26. package/dist/store/regenerators.d.ts.map +1 -0
  27. package/dist/store/restore-conflict-report.d.ts +118 -0
  28. package/dist/store/restore-conflict-report.d.ts.map +1 -0
  29. package/dist/store/restore-json-merge.d.ts +187 -0
  30. package/dist/store/restore-json-merge.d.ts.map +1 -0
  31. package/dist/store/sqlite-backup.d.ts +60 -5
  32. package/dist/store/sqlite-backup.d.ts.map +1 -1
  33. package/dist/store/t310-readiness.d.ts +83 -0
  34. package/dist/store/t310-readiness.d.ts.map +1 -0
  35. package/dist/store/validation-schemas.d.ts +1 -1
  36. package/dist/store/validation-schemas.d.ts.map +1 -1
  37. package/package.json +11 -11
  38. package/src/__tests__/cli-parity.test.ts +19 -14
  39. package/src/__tests__/human-output.test.ts +13 -11
  40. package/src/hooks/payload-schemas.ts +1 -1
  41. package/src/init.ts +18 -8
  42. package/src/internal.ts +4 -1
  43. package/src/memory/__tests__/brain-automation.test.ts +2 -2
  44. package/src/memory/brain-embedding.ts +1 -1
  45. package/src/memory/embedding-local.ts +10 -5
  46. package/src/memory/embedding-worker.ts +1 -1
  47. package/src/skills/__tests__/discovery.test.ts +22 -7
  48. package/src/store/__tests__/performance-safety.test.ts +11 -5
  49. package/src/store/migrate-signaldock-to-conduit.ts +14 -7
  50. package/src/store/nexus-validation-schemas.ts +3 -3
  51. package/src/store/validation-schemas.ts +3 -3
  52. package/src/validation/protocols/_shared.ts +1 -1
  53. package/dist/adapters/adapter-registry.js +0 -64
  54. package/dist/adapters/adapter-registry.js.map +0 -1
  55. package/dist/adapters/discovery.js +0 -83
  56. package/dist/adapters/discovery.js.map +0 -1
  57. package/dist/adapters/index.js +0 -9
  58. package/dist/adapters/index.js.map +0 -1
  59. package/dist/adapters/manager.js +0 -260
  60. package/dist/adapters/manager.js.map +0 -1
  61. package/dist/admin/export-tasks.js +0 -171
  62. package/dist/admin/export-tasks.js.map +0 -1
  63. package/dist/admin/export.js +0 -103
  64. package/dist/admin/export.js.map +0 -1
  65. package/dist/admin/help.js +0 -106
  66. package/dist/admin/help.js.map +0 -1
  67. package/dist/admin/import-tasks.js +0 -182
  68. package/dist/admin/import-tasks.js.map +0 -1
  69. package/dist/admin/import.js +0 -129
  70. package/dist/admin/import.js.map +0 -1
  71. package/dist/admin/index.js +0 -13
  72. package/dist/admin/index.js.map +0 -1
  73. package/dist/adrs/find.js +0 -134
  74. package/dist/adrs/find.js.map +0 -1
  75. package/dist/adrs/index.js +0 -15
  76. package/dist/adrs/index.js.map +0 -1
  77. package/dist/adrs/link-pipeline.js +0 -160
  78. package/dist/adrs/link-pipeline.js.map +0 -1
  79. package/dist/adrs/list.js +0 -43
  80. package/dist/adrs/list.js.map +0 -1
  81. package/dist/adrs/parse.js +0 -51
  82. package/dist/adrs/parse.js.map +0 -1
  83. package/dist/adrs/show.js +0 -22
  84. package/dist/adrs/show.js.map +0 -1
  85. package/dist/adrs/sync.js +0 -188
  86. package/dist/adrs/sync.js.map +0 -1
  87. package/dist/adrs/types.js +0 -9
  88. package/dist/adrs/types.js.map +0 -1
  89. package/dist/adrs/validate.js +0 -57
  90. package/dist/adrs/validate.js.map +0 -1
  91. package/dist/agents/agent-registry.js +0 -288
  92. package/dist/agents/agent-registry.js.map +0 -1
  93. package/dist/agents/agent-schema.js +0 -82
  94. package/dist/agents/agent-schema.js.map +0 -1
  95. package/dist/agents/capacity.js +0 -116
  96. package/dist/agents/capacity.js.map +0 -1
  97. package/dist/agents/execution-learning.js +0 -474
  98. package/dist/agents/execution-learning.js.map +0 -1
  99. package/dist/agents/health-monitor.js +0 -217
  100. package/dist/agents/health-monitor.js.map +0 -1
  101. package/dist/agents/index.js +0 -29
  102. package/dist/agents/index.js.map +0 -1
  103. package/dist/agents/registry.js +0 -314
  104. package/dist/agents/registry.js.map +0 -1
  105. package/dist/agents/retry.js +0 -215
  106. package/dist/agents/retry.js.map +0 -1
  107. package/dist/audit-prune.js +0 -94
  108. package/dist/audit-prune.js.map +0 -1
  109. package/dist/audit.js +0 -68
  110. package/dist/audit.js.map +0 -1
  111. package/dist/backfill/index.js +0 -229
  112. package/dist/backfill/index.js.map +0 -1
  113. package/dist/bootstrap.js +0 -344
  114. package/dist/bootstrap.js.map +0 -1
  115. package/dist/caamp/adapter.js +0 -259
  116. package/dist/caamp/adapter.js.map +0 -1
  117. package/dist/caamp/capability-check.js +0 -38
  118. package/dist/caamp/capability-check.js.map +0 -1
  119. package/dist/caamp/index.js +0 -21
  120. package/dist/caamp/index.js.map +0 -1
  121. package/dist/caamp-init.js +0 -16
  122. package/dist/caamp-init.js.map +0 -1
  123. package/dist/cleo.js +0 -322
  124. package/dist/cleo.js.map +0 -1
  125. package/dist/code/index.js +0 -10
  126. package/dist/code/index.js.map +0 -1
  127. package/dist/code/outline.js +0 -165
  128. package/dist/code/outline.js.map +0 -1
  129. package/dist/code/parser.js +0 -295
  130. package/dist/code/parser.js.map +0 -1
  131. package/dist/code/search.js +0 -135
  132. package/dist/code/search.js.map +0 -1
  133. package/dist/code/unfold.js +0 -155
  134. package/dist/code/unfold.js.map +0 -1
  135. package/dist/codebase-map/analyzers/architecture.js +0 -129
  136. package/dist/codebase-map/analyzers/architecture.js.map +0 -1
  137. package/dist/codebase-map/analyzers/concerns.js +0 -122
  138. package/dist/codebase-map/analyzers/concerns.js.map +0 -1
  139. package/dist/codebase-map/analyzers/conventions.js +0 -149
  140. package/dist/codebase-map/analyzers/conventions.js.map +0 -1
  141. package/dist/codebase-map/analyzers/integrations.js +0 -108
  142. package/dist/codebase-map/analyzers/integrations.js.map +0 -1
  143. package/dist/codebase-map/analyzers/stack.js +0 -117
  144. package/dist/codebase-map/analyzers/stack.js.map +0 -1
  145. package/dist/codebase-map/analyzers/structure.js +0 -137
  146. package/dist/codebase-map/analyzers/structure.js.map +0 -1
  147. package/dist/codebase-map/analyzers/testing.js +0 -118
  148. package/dist/codebase-map/analyzers/testing.js.map +0 -1
  149. package/dist/codebase-map/index.js +0 -57
  150. package/dist/codebase-map/index.js.map +0 -1
  151. package/dist/codebase-map/store.js +0 -122
  152. package/dist/codebase-map/store.js.map +0 -1
  153. package/dist/codebase-map/summary.js +0 -152
  154. package/dist/codebase-map/summary.js.map +0 -1
  155. package/dist/compliance/index.js +0 -288
  156. package/dist/compliance/index.js.map +0 -1
  157. package/dist/compliance/protocol-enforcement.js +0 -332
  158. package/dist/compliance/protocol-enforcement.js.map +0 -1
  159. package/dist/compliance/protocol-rules.js +0 -786
  160. package/dist/compliance/protocol-rules.js.map +0 -1
  161. package/dist/compliance/protocol-types.js +0 -79
  162. package/dist/compliance/protocol-types.js.map +0 -1
  163. package/dist/compliance/store.js +0 -53
  164. package/dist/compliance/store.js.map +0 -1
  165. package/dist/conduit/conduit-client.js +0 -107
  166. package/dist/conduit/conduit-client.js.map +0 -1
  167. package/dist/conduit/factory.js +0 -52
  168. package/dist/conduit/factory.js.map +0 -1
  169. package/dist/conduit/http-transport.js +0 -155
  170. package/dist/conduit/http-transport.js.map +0 -1
  171. package/dist/conduit/index.js +0 -15
  172. package/dist/conduit/index.js.map +0 -1
  173. package/dist/conduit/local-transport.js +0 -255
  174. package/dist/conduit/local-transport.js.map +0 -1
  175. package/dist/conduit/sse-transport.js +0 -299
  176. package/dist/conduit/sse-transport.js.map +0 -1
  177. package/dist/config/build-config.js +0 -29
  178. package/dist/config/build-config.js.map +0 -1
  179. package/dist/config.js +0 -400
  180. package/dist/config.js.map +0 -1
  181. package/dist/constants.js +0 -18
  182. package/dist/constants.js.map +0 -1
  183. package/dist/context/index.js +0 -137
  184. package/dist/context/index.js.map +0 -1
  185. package/dist/crypto/credentials.js +0 -191
  186. package/dist/crypto/credentials.js.map +0 -1
  187. package/dist/discovery.js +0 -182
  188. package/dist/discovery.js.map +0 -1
  189. package/dist/engine-result.js +0 -12
  190. package/dist/engine-result.js.map +0 -1
  191. package/dist/error-catalog.js +0 -404
  192. package/dist/error-catalog.js.map +0 -1
  193. package/dist/error-registry.js +0 -393
  194. package/dist/error-registry.js.map +0 -1
  195. package/dist/errors.js +0 -173
  196. package/dist/errors.js.map +0 -1
  197. package/dist/hooks/handlers/agent-hooks.js +0 -106
  198. package/dist/hooks/handlers/agent-hooks.js.map +0 -1
  199. package/dist/hooks/handlers/context-hooks.js +0 -111
  200. package/dist/hooks/handlers/context-hooks.js.map +0 -1
  201. package/dist/hooks/handlers/error-hooks.js +0 -52
  202. package/dist/hooks/handlers/error-hooks.js.map +0 -1
  203. package/dist/hooks/handlers/file-hooks.js +0 -104
  204. package/dist/hooks/handlers/file-hooks.js.map +0 -1
  205. package/dist/hooks/handlers/handler-helpers.js +0 -61
  206. package/dist/hooks/handlers/handler-helpers.js.map +0 -1
  207. package/dist/hooks/handlers/index.js +0 -28
  208. package/dist/hooks/handlers/index.js.map +0 -1
  209. package/dist/hooks/handlers/memory-bridge-refresh.js +0 -42
  210. package/dist/hooks/handlers/memory-bridge-refresh.js.map +0 -1
  211. package/dist/hooks/handlers/notification-hooks.js +0 -62
  212. package/dist/hooks/handlers/notification-hooks.js.map +0 -1
  213. package/dist/hooks/handlers/session-hooks.js +0 -142
  214. package/dist/hooks/handlers/session-hooks.js.map +0 -1
  215. package/dist/hooks/handlers/task-hooks.js +0 -65
  216. package/dist/hooks/handlers/task-hooks.js.map +0 -1
  217. package/dist/hooks/handlers/work-capture-hooks.js +0 -165
  218. package/dist/hooks/handlers/work-capture-hooks.js.map +0 -1
  219. package/dist/hooks/index.js +0 -13
  220. package/dist/hooks/index.js.map +0 -1
  221. package/dist/hooks/payload-schemas.js +0 -220
  222. package/dist/hooks/payload-schemas.js.map +0 -1
  223. package/dist/hooks/provider-hooks.js +0 -66
  224. package/dist/hooks/provider-hooks.js.map +0 -1
  225. package/dist/hooks/registry.js +0 -229
  226. package/dist/hooks/registry.js.map +0 -1
  227. package/dist/hooks/types.js +0 -66
  228. package/dist/hooks/types.js.map +0 -1
  229. package/dist/hooks.js +0 -136
  230. package/dist/hooks.js.map +0 -1
  231. package/dist/init.js +0 -851
  232. package/dist/init.js.map +0 -1
  233. package/dist/inject/index.js +0 -82
  234. package/dist/inject/index.js.map +0 -1
  235. package/dist/injection.js +0 -343
  236. package/dist/injection.js.map +0 -1
  237. package/dist/intelligence/adaptive-validation.js +0 -497
  238. package/dist/intelligence/adaptive-validation.js.map +0 -1
  239. package/dist/intelligence/impact.js +0 -675
  240. package/dist/intelligence/impact.js.map +0 -1
  241. package/dist/intelligence/index.js +0 -22
  242. package/dist/intelligence/index.js.map +0 -1
  243. package/dist/intelligence/patterns.js +0 -492
  244. package/dist/intelligence/patterns.js.map +0 -1
  245. package/dist/intelligence/prediction.js +0 -499
  246. package/dist/intelligence/prediction.js.map +0 -1
  247. package/dist/intelligence/types.js +0 -13
  248. package/dist/intelligence/types.js.map +0 -1
  249. package/dist/internal.js +0 -306
  250. package/dist/internal.js.map +0 -1
  251. package/dist/issue/create.js +0 -121
  252. package/dist/issue/create.js.map +0 -1
  253. package/dist/issue/diagnostics.js +0 -59
  254. package/dist/issue/diagnostics.js.map +0 -1
  255. package/dist/issue/index.js +0 -10
  256. package/dist/issue/index.js.map +0 -1
  257. package/dist/issue/template-parser.js +0 -267
  258. package/dist/issue/template-parser.js.map +0 -1
  259. package/dist/json-schema-validator.js +0 -76
  260. package/dist/json-schema-validator.js.map +0 -1
  261. package/dist/lib/index.js +0 -11
  262. package/dist/lib/index.js.map +0 -1
  263. package/dist/lib/retry.js +0 -152
  264. package/dist/lib/retry.js.map +0 -1
  265. package/dist/lib/tree-sitter-languages.js +0 -71
  266. package/dist/lib/tree-sitter-languages.js.map +0 -1
  267. package/dist/lifecycle/chain-composition.js +0 -152
  268. package/dist/lifecycle/chain-composition.js.map +0 -1
  269. package/dist/lifecycle/chain-store.js +0 -246
  270. package/dist/lifecycle/chain-store.js.map +0 -1
  271. package/dist/lifecycle/consolidate-rcasd.js +0 -352
  272. package/dist/lifecycle/consolidate-rcasd.js.map +0 -1
  273. package/dist/lifecycle/default-chain.js +0 -176
  274. package/dist/lifecycle/default-chain.js.map +0 -1
  275. package/dist/lifecycle/evidence.js +0 -180
  276. package/dist/lifecycle/evidence.js.map +0 -1
  277. package/dist/lifecycle/frontmatter.js +0 -363
  278. package/dist/lifecycle/frontmatter.js.map +0 -1
  279. package/dist/lifecycle/index.js +0 -756
  280. package/dist/lifecycle/index.js.map +0 -1
  281. package/dist/lifecycle/pipeline.js +0 -656
  282. package/dist/lifecycle/pipeline.js.map +0 -1
  283. package/dist/lifecycle/rcasd-index.js +0 -326
  284. package/dist/lifecycle/rcasd-index.js.map +0 -1
  285. package/dist/lifecycle/rcasd-paths.js +0 -220
  286. package/dist/lifecycle/rcasd-paths.js.map +0 -1
  287. package/dist/lifecycle/resume.js +0 -864
  288. package/dist/lifecycle/resume.js.map +0 -1
  289. package/dist/lifecycle/stage-artifacts.js +0 -94
  290. package/dist/lifecycle/stage-artifacts.js.map +0 -1
  291. package/dist/lifecycle/stage-guidance.js +0 -234
  292. package/dist/lifecycle/stage-guidance.js.map +0 -1
  293. package/dist/lifecycle/stages.js +0 -534
  294. package/dist/lifecycle/stages.js.map +0 -1
  295. package/dist/lifecycle/state-machine.js +0 -516
  296. package/dist/lifecycle/state-machine.js.map +0 -1
  297. package/dist/lifecycle/tessera-engine.js +0 -249
  298. package/dist/lifecycle/tessera-engine.js.map +0 -1
  299. package/dist/logger.js +0 -140
  300. package/dist/logger.js.map +0 -1
  301. package/dist/memory/auto-extract.js +0 -177
  302. package/dist/memory/auto-extract.js.map +0 -1
  303. package/dist/memory/brain-embedding.js +0 -66
  304. package/dist/memory/brain-embedding.js.map +0 -1
  305. package/dist/memory/brain-lifecycle.js +0 -298
  306. package/dist/memory/brain-lifecycle.js.map +0 -1
  307. package/dist/memory/brain-links.js +0 -161
  308. package/dist/memory/brain-links.js.map +0 -1
  309. package/dist/memory/brain-maintenance.js +0 -114
  310. package/dist/memory/brain-maintenance.js.map +0 -1
  311. package/dist/memory/brain-migration.js +0 -149
  312. package/dist/memory/brain-migration.js.map +0 -1
  313. package/dist/memory/brain-reasoning.js +0 -215
  314. package/dist/memory/brain-reasoning.js.map +0 -1
  315. package/dist/memory/brain-retrieval.js +0 -542
  316. package/dist/memory/brain-retrieval.js.map +0 -1
  317. package/dist/memory/brain-row-types.js +0 -10
  318. package/dist/memory/brain-row-types.js.map +0 -1
  319. package/dist/memory/brain-search.js +0 -519
  320. package/dist/memory/brain-search.js.map +0 -1
  321. package/dist/memory/brain-similarity.js +0 -145
  322. package/dist/memory/brain-similarity.js.map +0 -1
  323. package/dist/memory/claude-mem-migration.js +0 -277
  324. package/dist/memory/claude-mem-migration.js.map +0 -1
  325. package/dist/memory/decisions.js +0 -162
  326. package/dist/memory/decisions.js.map +0 -1
  327. package/dist/memory/embedding-local.js +0 -97
  328. package/dist/memory/embedding-local.js.map +0 -1
  329. package/dist/memory/embedding-queue.js +0 -271
  330. package/dist/memory/embedding-queue.js.map +0 -1
  331. package/dist/memory/embedding-worker.js +0 -58
  332. package/dist/memory/embedding-worker.js.map +0 -1
  333. package/dist/memory/engine-compat.js +0 -1397
  334. package/dist/memory/engine-compat.js.map +0 -1
  335. package/dist/memory/index.js +0 -1140
  336. package/dist/memory/index.js.map +0 -1
  337. package/dist/memory/learnings.js +0 -121
  338. package/dist/memory/learnings.js.map +0 -1
  339. package/dist/memory/memory-bridge.js +0 -370
  340. package/dist/memory/memory-bridge.js.map +0 -1
  341. package/dist/memory/patterns.js +0 -122
  342. package/dist/memory/patterns.js.map +0 -1
  343. package/dist/memory/pipeline-manifest-sqlite.js +0 -975
  344. package/dist/memory/pipeline-manifest-sqlite.js.map +0 -1
  345. package/dist/memory/session-memory.js +0 -331
  346. package/dist/memory/session-memory.js.map +0 -1
  347. package/dist/metrics/ab-test.js +0 -260
  348. package/dist/metrics/ab-test.js.map +0 -1
  349. package/dist/metrics/aggregation.js +0 -363
  350. package/dist/metrics/aggregation.js.map +0 -1
  351. package/dist/metrics/common.js +0 -64
  352. package/dist/metrics/common.js.map +0 -1
  353. package/dist/metrics/enums.js +0 -78
  354. package/dist/metrics/enums.js.map +0 -1
  355. package/dist/metrics/index.js +0 -19
  356. package/dist/metrics/index.js.map +0 -1
  357. package/dist/metrics/model-provider-registry.js +0 -88
  358. package/dist/metrics/model-provider-registry.js.map +0 -1
  359. package/dist/metrics/otel-integration.js +0 -263
  360. package/dist/metrics/otel-integration.js.map +0 -1
  361. package/dist/metrics/provider-detection.js +0 -103
  362. package/dist/metrics/provider-detection.js.map +0 -1
  363. package/dist/metrics/token-estimation.js +0 -253
  364. package/dist/metrics/token-estimation.js.map +0 -1
  365. package/dist/metrics/token-service.js +0 -450
  366. package/dist/metrics/token-service.js.map +0 -1
  367. package/dist/migration/agent-outputs.js +0 -316
  368. package/dist/migration/agent-outputs.js.map +0 -1
  369. package/dist/migration/checksum.js +0 -92
  370. package/dist/migration/checksum.js.map +0 -1
  371. package/dist/migration/index.js +0 -282
  372. package/dist/migration/index.js.map +0 -1
  373. package/dist/migration/logger.js +0 -360
  374. package/dist/migration/logger.js.map +0 -1
  375. package/dist/migration/preflight.js +0 -9
  376. package/dist/migration/preflight.js.map +0 -1
  377. package/dist/migration/state.js +0 -421
  378. package/dist/migration/state.js.map +0 -1
  379. package/dist/migration/validate.js +0 -241
  380. package/dist/migration/validate.js.map +0 -1
  381. package/dist/mvi-helpers.js +0 -74
  382. package/dist/mvi-helpers.js.map +0 -1
  383. package/dist/nexus/deps.js +0 -375
  384. package/dist/nexus/deps.js.map +0 -1
  385. package/dist/nexus/discover.js +0 -288
  386. package/dist/nexus/discover.js.map +0 -1
  387. package/dist/nexus/hash.js +0 -10
  388. package/dist/nexus/hash.js.map +0 -1
  389. package/dist/nexus/index.js +0 -40
  390. package/dist/nexus/index.js.map +0 -1
  391. package/dist/nexus/migrate-json-to-sqlite.js +0 -115
  392. package/dist/nexus/migrate-json-to-sqlite.js.map +0 -1
  393. package/dist/nexus/permissions.js +0 -105
  394. package/dist/nexus/permissions.js.map +0 -1
  395. package/dist/nexus/query.js +0 -175
  396. package/dist/nexus/query.js.map +0 -1
  397. package/dist/nexus/registry.js +0 -584
  398. package/dist/nexus/registry.js.map +0 -1
  399. package/dist/nexus/sharing/index.js +0 -288
  400. package/dist/nexus/sharing/index.js.map +0 -1
  401. package/dist/nexus/transfer-types.js +0 -8
  402. package/dist/nexus/transfer-types.js.map +0 -1
  403. package/dist/nexus/transfer.js +0 -263
  404. package/dist/nexus/transfer.js.map +0 -1
  405. package/dist/nexus/workspace.js +0 -355
  406. package/dist/nexus/workspace.js.map +0 -1
  407. package/dist/observability/index.js +0 -103
  408. package/dist/observability/index.js.map +0 -1
  409. package/dist/observability/log-filter.js +0 -63
  410. package/dist/observability/log-filter.js.map +0 -1
  411. package/dist/observability/log-parser.js +0 -99
  412. package/dist/observability/log-parser.js.map +0 -1
  413. package/dist/observability/log-reader.js +0 -139
  414. package/dist/observability/log-reader.js.map +0 -1
  415. package/dist/observability/types.js +0 -19
  416. package/dist/observability/types.js.map +0 -1
  417. package/dist/orchestration/analyze.js +0 -107
  418. package/dist/orchestration/analyze.js.map +0 -1
  419. package/dist/orchestration/bootstrap.js +0 -132
  420. package/dist/orchestration/bootstrap.js.map +0 -1
  421. package/dist/orchestration/context.js +0 -56
  422. package/dist/orchestration/context.js.map +0 -1
  423. package/dist/orchestration/critical-path.js +0 -100
  424. package/dist/orchestration/critical-path.js.map +0 -1
  425. package/dist/orchestration/hierarchy.js +0 -183
  426. package/dist/orchestration/hierarchy.js.map +0 -1
  427. package/dist/orchestration/index.js +0 -287
  428. package/dist/orchestration/index.js.map +0 -1
  429. package/dist/orchestration/parallel.js +0 -89
  430. package/dist/orchestration/parallel.js.map +0 -1
  431. package/dist/orchestration/protocol-validators.js +0 -815
  432. package/dist/orchestration/protocol-validators.js.map +0 -1
  433. package/dist/orchestration/skill-ops.js +0 -98
  434. package/dist/orchestration/skill-ops.js.map +0 -1
  435. package/dist/orchestration/status.js +0 -107
  436. package/dist/orchestration/status.js.map +0 -1
  437. package/dist/orchestration/unblock.js +0 -103
  438. package/dist/orchestration/unblock.js.map +0 -1
  439. package/dist/orchestration/validate-spawn.js +0 -67
  440. package/dist/orchestration/validate-spawn.js.map +0 -1
  441. package/dist/orchestration/waves.js +0 -86
  442. package/dist/orchestration/waves.js.map +0 -1
  443. package/dist/otel/index.js +0 -163
  444. package/dist/otel/index.js.map +0 -1
  445. package/dist/output.js +0 -164
  446. package/dist/output.js.map +0 -1
  447. package/dist/pagination.js +0 -64
  448. package/dist/pagination.js.map +0 -1
  449. package/dist/paths.js +0 -842
  450. package/dist/paths.js.map +0 -1
  451. package/dist/phases/deps.js +0 -372
  452. package/dist/phases/deps.js.map +0 -1
  453. package/dist/phases/index.js +0 -349
  454. package/dist/phases/index.js.map +0 -1
  455. package/dist/pipeline/index.js +0 -10
  456. package/dist/pipeline/index.js.map +0 -1
  457. package/dist/pipeline/phase.js +0 -45
  458. package/dist/pipeline/phase.js.map +0 -1
  459. package/dist/platform.js +0 -211
  460. package/dist/platform.js.map +0 -1
  461. package/dist/project-info.js +0 -84
  462. package/dist/project-info.js.map +0 -1
  463. package/dist/reconciliation/index.js +0 -10
  464. package/dist/reconciliation/index.js.map +0 -1
  465. package/dist/reconciliation/link-store.js +0 -129
  466. package/dist/reconciliation/link-store.js.map +0 -1
  467. package/dist/reconciliation/reconciliation-engine.js +0 -298
  468. package/dist/reconciliation/reconciliation-engine.js.map +0 -1
  469. package/dist/release/artifacts.js +0 -427
  470. package/dist/release/artifacts.js.map +0 -1
  471. package/dist/release/changelog-writer.js +0 -151
  472. package/dist/release/changelog-writer.js.map +0 -1
  473. package/dist/release/channel.js +0 -144
  474. package/dist/release/channel.js.map +0 -1
  475. package/dist/release/ci.js +0 -166
  476. package/dist/release/ci.js.map +0 -1
  477. package/dist/release/github-pr.js +0 -225
  478. package/dist/release/github-pr.js.map +0 -1
  479. package/dist/release/guards.js +0 -116
  480. package/dist/release/guards.js.map +0 -1
  481. package/dist/release/index.js +0 -22
  482. package/dist/release/index.js.map +0 -1
  483. package/dist/release/release-config.js +0 -158
  484. package/dist/release/release-config.js.map +0 -1
  485. package/dist/release/release-manifest.js +0 -1019
  486. package/dist/release/release-manifest.js.map +0 -1
  487. package/dist/release/version-bump.js +0 -255
  488. package/dist/release/version-bump.js.map +0 -1
  489. package/dist/remote/index.js +0 -257
  490. package/dist/remote/index.js.map +0 -1
  491. package/dist/repair.js +0 -130
  492. package/dist/repair.js.map +0 -1
  493. package/dist/research/index.js +0 -2
  494. package/dist/research/index.js.map +0 -1
  495. package/dist/roadmap/index.js +0 -59
  496. package/dist/roadmap/index.js.map +0 -1
  497. package/dist/routing/capability-matrix.js +0 -1556
  498. package/dist/routing/capability-matrix.js.map +0 -1
  499. package/dist/routing/index.js +0 -9
  500. package/dist/routing/index.js.map +0 -1
  501. package/dist/scaffold.js +0 -1759
  502. package/dist/scaffold.js.map +0 -1
  503. package/dist/schema-management.js +0 -295
  504. package/dist/schema-management.js.map +0 -1
  505. package/dist/security/index.js +0 -9
  506. package/dist/security/index.js.map +0 -1
  507. package/dist/security/input-sanitization.js +0 -321
  508. package/dist/security/input-sanitization.js.map +0 -1
  509. package/dist/sequence/index.js +0 -295
  510. package/dist/sequence/index.js.map +0 -1
  511. package/dist/sessions/assumptions.js +0 -54
  512. package/dist/sessions/assumptions.js.map +0 -1
  513. package/dist/sessions/briefing.js +0 -377
  514. package/dist/sessions/briefing.js.map +0 -1
  515. package/dist/sessions/context-alert.js +0 -222
  516. package/dist/sessions/context-alert.js.map +0 -1
  517. package/dist/sessions/context-inject.js +0 -61
  518. package/dist/sessions/context-inject.js.map +0 -1
  519. package/dist/sessions/context-monitor.js +0 -98
  520. package/dist/sessions/context-monitor.js.map +0 -1
  521. package/dist/sessions/decisions.js +0 -65
  522. package/dist/sessions/decisions.js.map +0 -1
  523. package/dist/sessions/find.js +0 -65
  524. package/dist/sessions/find.js.map +0 -1
  525. package/dist/sessions/handoff.js +0 -328
  526. package/dist/sessions/handoff.js.map +0 -1
  527. package/dist/sessions/hitl-warnings.js +0 -254
  528. package/dist/sessions/hitl-warnings.js.map +0 -1
  529. package/dist/sessions/index.js +0 -327
  530. package/dist/sessions/index.js.map +0 -1
  531. package/dist/sessions/session-archive.js +0 -40
  532. package/dist/sessions/session-archive.js.map +0 -1
  533. package/dist/sessions/session-cleanup.js +0 -59
  534. package/dist/sessions/session-cleanup.js.map +0 -1
  535. package/dist/sessions/session-drift.js +0 -134
  536. package/dist/sessions/session-drift.js.map +0 -1
  537. package/dist/sessions/session-enforcement.js +0 -144
  538. package/dist/sessions/session-enforcement.js.map +0 -1
  539. package/dist/sessions/session-grade.js +0 -253
  540. package/dist/sessions/session-grade.js.map +0 -1
  541. package/dist/sessions/session-history.js +0 -42
  542. package/dist/sessions/session-history.js.map +0 -1
  543. package/dist/sessions/session-id.js +0 -81
  544. package/dist/sessions/session-id.js.map +0 -1
  545. package/dist/sessions/session-memory-bridge.js +0 -52
  546. package/dist/sessions/session-memory-bridge.js.map +0 -1
  547. package/dist/sessions/session-show.js +0 -24
  548. package/dist/sessions/session-show.js.map +0 -1
  549. package/dist/sessions/session-stats.js +0 -69
  550. package/dist/sessions/session-stats.js.map +0 -1
  551. package/dist/sessions/session-suspend.js +0 -39
  552. package/dist/sessions/session-suspend.js.map +0 -1
  553. package/dist/sessions/session-switch.js +0 -51
  554. package/dist/sessions/session-switch.js.map +0 -1
  555. package/dist/sessions/session-view.js +0 -76
  556. package/dist/sessions/session-view.js.map +0 -1
  557. package/dist/sessions/snapshot.js +0 -213
  558. package/dist/sessions/snapshot.js.map +0 -1
  559. package/dist/sessions/statusline-setup.js +0 -85
  560. package/dist/sessions/statusline-setup.js.map +0 -1
  561. package/dist/sessions/types.js +0 -8
  562. package/dist/sessions/types.js.map +0 -1
  563. package/dist/skills/agents/config.js +0 -94
  564. package/dist/skills/agents/config.js.map +0 -1
  565. package/dist/skills/agents/install.js +0 -116
  566. package/dist/skills/agents/install.js.map +0 -1
  567. package/dist/skills/agents/registry.js +0 -161
  568. package/dist/skills/agents/registry.js.map +0 -1
  569. package/dist/skills/discovery.js +0 -333
  570. package/dist/skills/discovery.js.map +0 -1
  571. package/dist/skills/dispatch.js +0 -347
  572. package/dist/skills/dispatch.js.map +0 -1
  573. package/dist/skills/dynamic-skill-generator.js +0 -87
  574. package/dist/skills/dynamic-skill-generator.js.map +0 -1
  575. package/dist/skills/index.js +0 -44
  576. package/dist/skills/index.js.map +0 -1
  577. package/dist/skills/injection/subagent.js +0 -195
  578. package/dist/skills/injection/subagent.js.map +0 -1
  579. package/dist/skills/injection/token.js +0 -260
  580. package/dist/skills/injection/token.js.map +0 -1
  581. package/dist/skills/install.js +0 -40
  582. package/dist/skills/install.js.map +0 -1
  583. package/dist/skills/manifests/contribution.js +0 -175
  584. package/dist/skills/manifests/contribution.js.map +0 -1
  585. package/dist/skills/manifests/research.js +0 -281
  586. package/dist/skills/manifests/research.js.map +0 -1
  587. package/dist/skills/manifests/resolver.js +0 -146
  588. package/dist/skills/manifests/resolver.js.map +0 -1
  589. package/dist/skills/marketplace.js +0 -90
  590. package/dist/skills/marketplace.js.map +0 -1
  591. package/dist/skills/orchestrator/spawn.js +0 -178
  592. package/dist/skills/orchestrator/spawn.js.map +0 -1
  593. package/dist/skills/orchestrator/startup.js +0 -451
  594. package/dist/skills/orchestrator/startup.js.map +0 -1
  595. package/dist/skills/orchestrator/validator.js +0 -301
  596. package/dist/skills/orchestrator/validator.js.map +0 -1
  597. package/dist/skills/precedence-integration.js +0 -73
  598. package/dist/skills/precedence-integration.js.map +0 -1
  599. package/dist/skills/precedence-types.js +0 -16
  600. package/dist/skills/precedence-types.js.map +0 -1
  601. package/dist/skills/routing-table.js +0 -63
  602. package/dist/skills/routing-table.js.map +0 -1
  603. package/dist/skills/skill-paths.js +0 -217
  604. package/dist/skills/skill-paths.js.map +0 -1
  605. package/dist/skills/test-utility.js +0 -55
  606. package/dist/skills/test-utility.js.map +0 -1
  607. package/dist/skills/types.js +0 -118
  608. package/dist/skills/types.js.map +0 -1
  609. package/dist/skills/validation.js +0 -183
  610. package/dist/skills/validation.js.map +0 -1
  611. package/dist/skills/version.js +0 -57
  612. package/dist/skills/version.js.map +0 -1
  613. package/dist/snapshot/index.js +0 -188
  614. package/dist/snapshot/index.js.map +0 -1
  615. package/dist/spawn/adapter-registry.js +0 -246
  616. package/dist/spawn/adapter-registry.js.map +0 -1
  617. package/dist/spawn/index.js +0 -10
  618. package/dist/spawn/index.js.map +0 -1
  619. package/dist/stats/index.js +0 -343
  620. package/dist/stats/index.js.map +0 -1
  621. package/dist/stats/workflow-telemetry.js +0 -400
  622. package/dist/stats/workflow-telemetry.js.map +0 -1
  623. package/dist/sticky/archive.js +0 -47
  624. package/dist/sticky/archive.js.map +0 -1
  625. package/dist/sticky/convert.js +0 -235
  626. package/dist/sticky/convert.js.map +0 -1
  627. package/dist/sticky/create.js +0 -48
  628. package/dist/sticky/create.js.map +0 -1
  629. package/dist/sticky/id.js +0 -35
  630. package/dist/sticky/id.js.map +0 -1
  631. package/dist/sticky/index.js +0 -16
  632. package/dist/sticky/index.js.map +0 -1
  633. package/dist/sticky/list.js +0 -44
  634. package/dist/sticky/list.js.map +0 -1
  635. package/dist/sticky/purge.js +0 -45
  636. package/dist/sticky/purge.js.map +0 -1
  637. package/dist/sticky/show.js +0 -42
  638. package/dist/sticky/show.js.map +0 -1
  639. package/dist/sticky/types.js +0 -10
  640. package/dist/sticky/types.js.map +0 -1
  641. package/dist/store/agent-registry-accessor.js +0 -783
  642. package/dist/store/agent-registry-accessor.js.map +0 -1
  643. package/dist/store/api-key-kdf.js +0 -84
  644. package/dist/store/api-key-kdf.js.map +0 -1
  645. package/dist/store/atomic.js +0 -167
  646. package/dist/store/atomic.js.map +0 -1
  647. package/dist/store/backup.js +0 -94
  648. package/dist/store/backup.js.map +0 -1
  649. package/dist/store/brain-accessor.js +0 -397
  650. package/dist/store/brain-accessor.js.map +0 -1
  651. package/dist/store/brain-schema.js +0 -215
  652. package/dist/store/brain-schema.js.map +0 -1
  653. package/dist/store/brain-sqlite.js +0 -222
  654. package/dist/store/brain-sqlite.js.map +0 -1
  655. package/dist/store/cache.js +0 -168
  656. package/dist/store/cache.js.map +0 -1
  657. package/dist/store/chain-schema.js +0 -51
  658. package/dist/store/chain-schema.js.map +0 -1
  659. package/dist/store/cleanup-legacy.js +0 -171
  660. package/dist/store/cleanup-legacy.js.map +0 -1
  661. package/dist/store/conduit-sqlite.js +0 -570
  662. package/dist/store/conduit-sqlite.js.map +0 -1
  663. package/dist/store/converters.js +0 -124
  664. package/dist/store/converters.js.map +0 -1
  665. package/dist/store/cross-db-cleanup.js +0 -319
  666. package/dist/store/cross-db-cleanup.js.map +0 -1
  667. package/dist/store/data-accessor.js +0 -26
  668. package/dist/store/data-accessor.js.map +0 -1
  669. package/dist/store/data-safety-central.js +0 -269
  670. package/dist/store/data-safety-central.js.map +0 -1
  671. package/dist/store/data-safety.js +0 -274
  672. package/dist/store/data-safety.js.map +0 -1
  673. package/dist/store/db-helpers.js +0 -224
  674. package/dist/store/db-helpers.js.map +0 -1
  675. package/dist/store/export.js +0 -155
  676. package/dist/store/export.js.map +0 -1
  677. package/dist/store/file-utils.js +0 -270
  678. package/dist/store/file-utils.js.map +0 -1
  679. package/dist/store/git-checkpoint.js +0 -365
  680. package/dist/store/git-checkpoint.js.map +0 -1
  681. package/dist/store/global-salt.js +0 -147
  682. package/dist/store/global-salt.js.map +0 -1
  683. package/dist/store/import-logging.js +0 -139
  684. package/dist/store/import-logging.js.map +0 -1
  685. package/dist/store/import-remap.js +0 -145
  686. package/dist/store/import-remap.js.map +0 -1
  687. package/dist/store/import-sort.js +0 -121
  688. package/dist/store/import-sort.js.map +0 -1
  689. package/dist/store/index.js +0 -29
  690. package/dist/store/index.js.map +0 -1
  691. package/dist/store/json.js +0 -208
  692. package/dist/store/json.js.map +0 -1
  693. package/dist/store/lifecycle-store.js +0 -249
  694. package/dist/store/lifecycle-store.js.map +0 -1
  695. package/dist/store/lock.js +0 -70
  696. package/dist/store/lock.js.map +0 -1
  697. package/dist/store/migrate-signaldock-to-conduit.js +0 -555
  698. package/dist/store/migrate-signaldock-to-conduit.js.map +0 -1
  699. package/dist/store/migration-manager.js +0 -151
  700. package/dist/store/migration-manager.js.map +0 -1
  701. package/dist/store/migration-sqlite.js +0 -676
  702. package/dist/store/migration-sqlite.js.map +0 -1
  703. package/dist/store/nexus-schema.js +0 -62
  704. package/dist/store/nexus-schema.js.map +0 -1
  705. package/dist/store/nexus-sqlite.js +0 -242
  706. package/dist/store/nexus-sqlite.js.map +0 -1
  707. package/dist/store/nexus-validation-schemas.js +0 -40
  708. package/dist/store/nexus-validation-schemas.js.map +0 -1
  709. package/dist/store/parsers.js +0 -37
  710. package/dist/store/parsers.js.map +0 -1
  711. package/dist/store/project-detect.js +0 -457
  712. package/dist/store/project-detect.js.map +0 -1
  713. package/dist/store/provider.js +0 -101
  714. package/dist/store/provider.js.map +0 -1
  715. package/dist/store/safety-data-accessor.js +0 -257
  716. package/dist/store/safety-data-accessor.js.map +0 -1
  717. package/dist/store/schema.js +0 -7
  718. package/dist/store/schema.js.map +0 -1
  719. package/dist/store/session-store.js +0 -219
  720. package/dist/store/session-store.js.map +0 -1
  721. package/dist/store/signaldock-sqlite.js +0 -550
  722. package/dist/store/signaldock-sqlite.js.map +0 -1
  723. package/dist/store/sqlite-backup.js +0 -359
  724. package/dist/store/sqlite-backup.js.map +0 -1
  725. package/dist/store/sqlite-data-accessor.js +0 -787
  726. package/dist/store/sqlite-data-accessor.js.map +0 -1
  727. package/dist/store/sqlite.js +0 -481
  728. package/dist/store/sqlite.js.map +0 -1
  729. package/dist/store/status-registry.js +0 -8
  730. package/dist/store/status-registry.js.map +0 -1
  731. package/dist/store/task-store.js +0 -358
  732. package/dist/store/task-store.js.map +0 -1
  733. package/dist/store/tasks-schema.js +0 -610
  734. package/dist/store/tasks-schema.js.map +0 -1
  735. package/dist/store/typed-query.js +0 -15
  736. package/dist/store/typed-query.js.map +0 -1
  737. package/dist/store/validation-schemas.js +0 -278
  738. package/dist/store/validation-schemas.js.map +0 -1
  739. package/dist/system/archive-analytics.js +0 -277
  740. package/dist/system/archive-analytics.js.map +0 -1
  741. package/dist/system/archive-stats.js +0 -64
  742. package/dist/system/archive-stats.js.map +0 -1
  743. package/dist/system/audit.js +0 -145
  744. package/dist/system/audit.js.map +0 -1
  745. package/dist/system/backup.js +0 -280
  746. package/dist/system/backup.js.map +0 -1
  747. package/dist/system/cleanup.js +0 -134
  748. package/dist/system/cleanup.js.map +0 -1
  749. package/dist/system/health.js +0 -1100
  750. package/dist/system/health.js.map +0 -1
  751. package/dist/system/index.js +0 -18
  752. package/dist/system/index.js.map +0 -1
  753. package/dist/system/inject-generate.js +0 -122
  754. package/dist/system/inject-generate.js.map +0 -1
  755. package/dist/system/labels.js +0 -38
  756. package/dist/system/labels.js.map +0 -1
  757. package/dist/system/metrics.js +0 -61
  758. package/dist/system/metrics.js.map +0 -1
  759. package/dist/system/migrate.js +0 -43
  760. package/dist/system/migrate.js.map +0 -1
  761. package/dist/system/platform-paths.js +0 -80
  762. package/dist/system/platform-paths.js.map +0 -1
  763. package/dist/system/runtime.js +0 -161
  764. package/dist/system/runtime.js.map +0 -1
  765. package/dist/system/safestop.js +0 -99
  766. package/dist/system/safestop.js.map +0 -1
  767. package/dist/system/storage-preflight.js +0 -123
  768. package/dist/system/storage-preflight.js.map +0 -1
  769. package/dist/task-work/index.js +0 -159
  770. package/dist/task-work/index.js.map +0 -1
  771. package/dist/tasks/add.js +0 -736
  772. package/dist/tasks/add.js.map +0 -1
  773. package/dist/tasks/analyze.js +0 -85
  774. package/dist/tasks/analyze.js.map +0 -1
  775. package/dist/tasks/archive.js +0 -90
  776. package/dist/tasks/archive.js.map +0 -1
  777. package/dist/tasks/atomicity.js +0 -83
  778. package/dist/tasks/atomicity.js.map +0 -1
  779. package/dist/tasks/cancel-ops.js +0 -83
  780. package/dist/tasks/cancel-ops.js.map +0 -1
  781. package/dist/tasks/complete.js +0 -214
  782. package/dist/tasks/complete.js.map +0 -1
  783. package/dist/tasks/crossref-extract.js +0 -73
  784. package/dist/tasks/crossref-extract.js.map +0 -1
  785. package/dist/tasks/delete-preview.js +0 -192
  786. package/dist/tasks/delete-preview.js.map +0 -1
  787. package/dist/tasks/delete.js +0 -120
  788. package/dist/tasks/delete.js.map +0 -1
  789. package/dist/tasks/deletion-strategy.js +0 -200
  790. package/dist/tasks/deletion-strategy.js.map +0 -1
  791. package/dist/tasks/dependency-check.js +0 -278
  792. package/dist/tasks/dependency-check.js.map +0 -1
  793. package/dist/tasks/deps-ready.js +0 -32
  794. package/dist/tasks/deps-ready.js.map +0 -1
  795. package/dist/tasks/enforcement.js +0 -86
  796. package/dist/tasks/enforcement.js.map +0 -1
  797. package/dist/tasks/epic-enforcement.js +0 -294
  798. package/dist/tasks/epic-enforcement.js.map +0 -1
  799. package/dist/tasks/find.js +0 -157
  800. package/dist/tasks/find.js.map +0 -1
  801. package/dist/tasks/graph-cache.js +0 -127
  802. package/dist/tasks/graph-cache.js.map +0 -1
  803. package/dist/tasks/graph-ops.js +0 -171
  804. package/dist/tasks/graph-ops.js.map +0 -1
  805. package/dist/tasks/graph-rag.js +0 -328
  806. package/dist/tasks/graph-rag.js.map +0 -1
  807. package/dist/tasks/hierarchy-policy.js +0 -149
  808. package/dist/tasks/hierarchy-policy.js.map +0 -1
  809. package/dist/tasks/hierarchy.js +0 -185
  810. package/dist/tasks/hierarchy.js.map +0 -1
  811. package/dist/tasks/id-generator.js +0 -65
  812. package/dist/tasks/id-generator.js.map +0 -1
  813. package/dist/tasks/index.js +0 -14
  814. package/dist/tasks/index.js.map +0 -1
  815. package/dist/tasks/labels.js +0 -55
  816. package/dist/tasks/labels.js.map +0 -1
  817. package/dist/tasks/list.js +0 -75
  818. package/dist/tasks/list.js.map +0 -1
  819. package/dist/tasks/phase-tracking.js +0 -133
  820. package/dist/tasks/phase-tracking.js.map +0 -1
  821. package/dist/tasks/pipeline-stage.js +0 -248
  822. package/dist/tasks/pipeline-stage.js.map +0 -1
  823. package/dist/tasks/plan.js +0 -268
  824. package/dist/tasks/plan.js.map +0 -1
  825. package/dist/tasks/relates.js +0 -101
  826. package/dist/tasks/relates.js.map +0 -1
  827. package/dist/tasks/show.js +0 -83
  828. package/dist/tasks/show.js.map +0 -1
  829. package/dist/tasks/size-weighting.js +0 -86
  830. package/dist/tasks/size-weighting.js.map +0 -1
  831. package/dist/tasks/staleness.js +0 -86
  832. package/dist/tasks/staleness.js.map +0 -1
  833. package/dist/tasks/task-ops.js +0 -1741
  834. package/dist/tasks/task-ops.js.map +0 -1
  835. package/dist/tasks/update.js +0 -303
  836. package/dist/tasks/update.js.map +0 -1
  837. package/dist/templates/index.js +0 -10
  838. package/dist/templates/index.js.map +0 -1
  839. package/dist/templates/parser.js +0 -254
  840. package/dist/templates/parser.js.map +0 -1
  841. package/dist/ui/aliases.js +0 -153
  842. package/dist/ui/aliases.js.map +0 -1
  843. package/dist/ui/changelog.js +0 -184
  844. package/dist/ui/changelog.js.map +0 -1
  845. package/dist/ui/command-registry.js +0 -168
  846. package/dist/ui/command-registry.js.map +0 -1
  847. package/dist/ui/flags.js +0 -94
  848. package/dist/ui/flags.js.map +0 -1
  849. package/dist/ui/index.js +0 -24
  850. package/dist/ui/index.js.map +0 -1
  851. package/dist/upgrade.js +0 -1148
  852. package/dist/upgrade.js.map +0 -1
  853. package/dist/validation/chain-validation.js +0 -146
  854. package/dist/validation/chain-validation.js.map +0 -1
  855. package/dist/validation/compliance.js +0 -155
  856. package/dist/validation/compliance.js.map +0 -1
  857. package/dist/validation/docs-sync.js +0 -212
  858. package/dist/validation/docs-sync.js.map +0 -1
  859. package/dist/validation/doctor/checks.js +0 -1069
  860. package/dist/validation/doctor/checks.js.map +0 -1
  861. package/dist/validation/doctor/index.js +0 -9
  862. package/dist/validation/doctor/index.js.map +0 -1
  863. package/dist/validation/doctor/project-cache.js +0 -160
  864. package/dist/validation/doctor/project-cache.js.map +0 -1
  865. package/dist/validation/doctor/utils.js +0 -155
  866. package/dist/validation/doctor/utils.js.map +0 -1
  867. package/dist/validation/engine.js +0 -914
  868. package/dist/validation/engine.js.map +0 -1
  869. package/dist/validation/gap-check.js +0 -175
  870. package/dist/validation/gap-check.js.map +0 -1
  871. package/dist/validation/index.js +0 -40
  872. package/dist/validation/index.js.map +0 -1
  873. package/dist/validation/manifest.js +0 -237
  874. package/dist/validation/manifest.js.map +0 -1
  875. package/dist/validation/operation-gate-validators.js +0 -724
  876. package/dist/validation/operation-gate-validators.js.map +0 -1
  877. package/dist/validation/operation-verification-gates.js +0 -532
  878. package/dist/validation/operation-verification-gates.js.map +0 -1
  879. package/dist/validation/param-utils.js +0 -141
  880. package/dist/validation/param-utils.js.map +0 -1
  881. package/dist/validation/protocol-common.js +0 -300
  882. package/dist/validation/protocol-common.js.map +0 -1
  883. package/dist/validation/protocols/_shared.js +0 -82
  884. package/dist/validation/protocols/_shared.js.map +0 -1
  885. package/dist/validation/protocols/architecture-decision.js +0 -31
  886. package/dist/validation/protocols/architecture-decision.js.map +0 -1
  887. package/dist/validation/protocols/artifact-publish.js +0 -28
  888. package/dist/validation/protocols/artifact-publish.js.map +0 -1
  889. package/dist/validation/protocols/consensus.js +0 -41
  890. package/dist/validation/protocols/consensus.js.map +0 -1
  891. package/dist/validation/protocols/contribution.js +0 -27
  892. package/dist/validation/protocols/contribution.js.map +0 -1
  893. package/dist/validation/protocols/decomposition.js +0 -28
  894. package/dist/validation/protocols/decomposition.js.map +0 -1
  895. package/dist/validation/protocols/implementation.js +0 -24
  896. package/dist/validation/protocols/implementation.js.map +0 -1
  897. package/dist/validation/protocols/provenance.js +0 -29
  898. package/dist/validation/protocols/provenance.js.map +0 -1
  899. package/dist/validation/protocols/release.js +0 -29
  900. package/dist/validation/protocols/release.js.map +0 -1
  901. package/dist/validation/protocols/research.js +0 -24
  902. package/dist/validation/protocols/research.js.map +0 -1
  903. package/dist/validation/protocols/specification.js +0 -27
  904. package/dist/validation/protocols/specification.js.map +0 -1
  905. package/dist/validation/protocols/testing.js +0 -30
  906. package/dist/validation/protocols/testing.js.map +0 -1
  907. package/dist/validation/protocols/validation.js +0 -30
  908. package/dist/validation/protocols/validation.js.map +0 -1
  909. package/dist/validation/schema-integrity.js +0 -170
  910. package/dist/validation/schema-integrity.js.map +0 -1
  911. package/dist/validation/schema-validator.js +0 -176
  912. package/dist/validation/schema-validator.js.map +0 -1
  913. package/dist/validation/validate-ops.js +0 -937
  914. package/dist/validation/validate-ops.js.map +0 -1
  915. package/dist/validation/validation-rules.js +0 -226
  916. package/dist/validation/validation-rules.js.map +0 -1
  917. package/dist/validation/verification.js +0 -321
  918. package/dist/validation/verification.js.map +0 -1
@@ -1,1741 +0,0 @@
1
- /**
2
- * Core task non-CRUD operations - business logic extracted from task-engine.ts.
3
- *
4
- * These are pure business logic functions that throw on failure and return
5
- * data directly (no EngineResult wrapper). The engine layer wraps these
6
- * in try/catch to produce EngineResult.
7
- *
8
- * Covers: next, blockers, tree, deps, relates, relatesAdd, analyze, restore,
9
- * unarchive, reorder, reparent, promote, reopen, complexityEstimate, depends,
10
- * stats, export, history, lint, batchValidate, import
11
- *
12
- * @task T4790
13
- * @epic T4654
14
- */
15
- import { TASK_STATUSES } from '@cleocode/contracts';
16
- import { getAccessor } from '../store/data-accessor.js';
17
- import { getDataPath, readJsonFile as storeReadJsonFile } from '../store/file-utils.js';
18
- import { canCancel } from './cancel-ops.js';
19
- import { detectCircularDeps, getBlockedTasks, getLeafBlockers, getReadyTasks, getTransitiveBlockers, validateDependencies, } from './dependency-check.js';
20
- import { depsReady } from './deps-ready.js';
21
- // ============================================================================
22
- // Helpers
23
- // ============================================================================
24
- const PRIORITY_SCORE = {
25
- critical: 100,
26
- high: 75,
27
- medium: 50,
28
- low: 25,
29
- };
30
- async function loadAllTasks(projectRoot) {
31
- const accessor = await getAccessor(projectRoot);
32
- const { tasks } = await accessor.queryTasks({});
33
- return tasks;
34
- }
35
- function buildTreeNode(task, childrenMap) {
36
- const children = (childrenMap.get(task.id) ?? []).map((child) => buildTreeNode(child, childrenMap));
37
- return {
38
- id: task.id,
39
- title: task.title,
40
- status: task.status,
41
- type: task.type,
42
- children,
43
- };
44
- }
45
- function buildUpstreamTree(taskId, taskMap, visited = new Set()) {
46
- const task = taskMap.get(taskId);
47
- if (!task?.depends?.length)
48
- return [];
49
- const nodes = [];
50
- for (const depId of task.depends) {
51
- if (visited.has(depId))
52
- continue;
53
- visited.add(depId);
54
- const dep = taskMap.get(depId);
55
- if (!dep)
56
- continue;
57
- nodes.push({
58
- id: dep.id,
59
- title: dep.title,
60
- status: dep.status,
61
- type: dep.type,
62
- children: buildUpstreamTree(depId, taskMap, visited),
63
- });
64
- }
65
- return nodes;
66
- }
67
- function countNodes(nodes) {
68
- let count = nodes.length;
69
- for (const node of nodes) {
70
- count += countNodes(node.children);
71
- }
72
- return count;
73
- }
74
- function measureDependencyDepth(taskId, taskMap, visited = new Set()) {
75
- if (visited.has(taskId))
76
- return 0;
77
- visited.add(taskId);
78
- const task = taskMap.get(taskId);
79
- if (!task || !task.depends || task.depends.length === 0)
80
- return 0;
81
- let maxDepth = 0;
82
- for (const depId of task.depends) {
83
- const depth = 1 + measureDependencyDepth(depId, taskMap, visited);
84
- if (depth > maxDepth)
85
- maxDepth = depth;
86
- }
87
- return maxDepth;
88
- }
89
- function getHierarchyLimits(projectRoot) {
90
- const configPath = getDataPath(projectRoot, 'config.json');
91
- const config = storeReadJsonFile(configPath);
92
- let maxDepth = 3;
93
- let maxSiblings = 0;
94
- if (config) {
95
- const hierarchy = config.hierarchy;
96
- if (hierarchy) {
97
- if (typeof hierarchy.maxDepth === 'number')
98
- maxDepth = hierarchy.maxDepth;
99
- if (typeof hierarchy.maxSiblings === 'number')
100
- maxSiblings = hierarchy.maxSiblings;
101
- }
102
- }
103
- return { maxDepth, maxSiblings };
104
- }
105
- // ============================================================================
106
- // taskNext
107
- // ============================================================================
108
- /**
109
- * Suggest next task to work on based on priority, phase, age, and deps.
110
- *
111
- * @param projectRoot - Absolute path to the CLEO project root directory
112
- * @param params - Optional scoring configuration
113
- * @param params.count - Number of suggestions to return (default: 1)
114
- * @param params.explain - When true, include scoring reasons in each suggestion
115
- * @returns Ranked suggestions with scores and the total number of eligible candidates
116
- *
117
- * @remarks
118
- * Scoring considers priority weight, current phase alignment, dependency readiness,
119
- * task age, and brain success/failure pattern matches. Results are sorted descending by score.
120
- *
121
- * @example
122
- * ```typescript
123
- * const { suggestions } = await coreTaskNext('/project', { count: 3, explain: true });
124
- * console.log(suggestions[0].id, suggestions[0].score);
125
- * ```
126
- *
127
- * @task T4790
128
- */
129
- export async function coreTaskNext(projectRoot, params) {
130
- const accessor = await getAccessor(projectRoot);
131
- const allTasks = await loadAllTasks(projectRoot);
132
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
133
- const projectMeta = await accessor.getMetaValue('project_meta');
134
- const currentPhase = projectMeta?.currentPhase ?? null;
135
- const candidates = allTasks.filter((t) => t.status === 'pending' && depsReady(t.depends, taskMap));
136
- if (candidates.length === 0) {
137
- return { suggestions: [], totalCandidates: 0 };
138
- }
139
- const scored = candidates
140
- .map((task) => {
141
- const reasons = [];
142
- let score = 0;
143
- score += PRIORITY_SCORE[task.priority] ?? 50;
144
- reasons.push(`priority: ${task.priority} (+${PRIORITY_SCORE[task.priority] ?? 50})`);
145
- if (currentPhase && task.phase === currentPhase) {
146
- score += 20;
147
- reasons.push(`phase alignment: ${currentPhase} (+20)`);
148
- }
149
- if (depsReady(task.depends, taskMap)) {
150
- score += 10;
151
- reasons.push('all dependencies satisfied (+10)');
152
- }
153
- if (task.createdAt) {
154
- const ageMs = Date.now() - new Date(task.createdAt).getTime();
155
- const ageDays = ageMs / (1000 * 60 * 60 * 24);
156
- if (ageDays > 7) {
157
- const ageBonus = Math.min(15, Math.floor(ageDays / 7));
158
- score += ageBonus;
159
- reasons.push(`age: ${Math.floor(ageDays)} days (+${ageBonus})`);
160
- }
161
- }
162
- return { task, score, reasons };
163
- })
164
- .sort((a, b) => b.score - a.score);
165
- // Brain pattern scoring (best-effort)
166
- try {
167
- const { searchPatterns } = await import('../memory/patterns.js');
168
- const [successPatterns, failurePatterns] = await Promise.all([
169
- searchPatterns(projectRoot, { type: 'success', limit: 20 }),
170
- searchPatterns(projectRoot, { type: 'failure', limit: 20 }),
171
- ]);
172
- if (successPatterns.length > 0 || failurePatterns.length > 0) {
173
- for (const item of scored) {
174
- const titleLower = item.task.title.toLowerCase();
175
- const labels = (item.task.labels ?? []).map((l) => l.toLowerCase());
176
- const matchText = [titleLower, ...labels].join(' ');
177
- for (const sp of successPatterns) {
178
- if (matchText.includes(sp.pattern.toLowerCase())) {
179
- item.score += 10;
180
- item.reasons.push(`brain: success pattern match "${sp.pattern}" (+10)`);
181
- break;
182
- }
183
- }
184
- for (const fp of failurePatterns) {
185
- if (matchText.includes(fp.pattern.toLowerCase())) {
186
- item.score -= 5;
187
- item.reasons.push(`brain: failure pattern match "${fp.pattern}" (-5)`);
188
- break;
189
- }
190
- }
191
- }
192
- scored.sort((a, b) => b.score - a.score);
193
- }
194
- }
195
- catch {
196
- // Brain pattern scoring is best-effort
197
- }
198
- const count = Math.min(params?.count || 1, scored.length);
199
- const explain = params?.explain ?? false;
200
- const suggestions = scored.slice(0, count).map(({ task, score, reasons }) => ({
201
- id: task.id,
202
- title: task.title,
203
- priority: task.priority,
204
- phase: task.phase ?? null,
205
- score,
206
- ...(explain && { reasons }),
207
- }));
208
- return { suggestions, totalCandidates: candidates.length };
209
- }
210
- // ============================================================================
211
- // taskBlockers
212
- // ============================================================================
213
- /**
214
- * Show blocked tasks and analyze blocking chains.
215
- *
216
- * @param projectRoot - Absolute path to the CLEO project root directory
217
- * @param params - Optional analysis configuration
218
- * @param params.analyze - When true, compute transitive blocking chains
219
- * @param params.limit - Maximum number of blocked tasks to return (default: 20)
220
- * @returns Blocked tasks with optional blocking chains, critical bottleneck tasks, and a summary
221
- *
222
- * @remarks
223
- * Collects both explicitly blocked tasks and dependency-blocked pending tasks.
224
- * Critical blockers are the top 5 tasks that appear most frequently in blocking chains.
225
- *
226
- * @example
227
- * ```typescript
228
- * const result = await coreTaskBlockers('/project', { analyze: true, limit: 10 });
229
- * console.log(result.summary, result.criticalBlockers);
230
- * ```
231
- *
232
- * @task T4790
233
- */
234
- export async function coreTaskBlockers(projectRoot, params) {
235
- const allTasks = await loadAllTasks(projectRoot);
236
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
237
- const analyze = params?.analyze ?? false;
238
- const effectiveLimit = params?.limit ?? 20;
239
- const blockedTasks = allTasks.filter((t) => t.status === 'blocked');
240
- const depBlockedTasks = allTasks.filter((t) => t.status === 'pending' &&
241
- t.depends &&
242
- t.depends.length > 0 &&
243
- t.depends.some((depId) => {
244
- const dep = taskMap.get(depId);
245
- return dep && dep.status !== 'done' && dep.status !== 'cancelled';
246
- }));
247
- const tasksAsTask = allTasks;
248
- const blockerInfos = [
249
- ...blockedTasks.map((t) => ({
250
- id: t.id,
251
- title: t.title,
252
- status: t.status,
253
- depends: t.depends,
254
- blockingChain: analyze ? getTransitiveBlockers(t.id, tasksAsTask) : [],
255
- })),
256
- ...depBlockedTasks
257
- .filter((t) => !blockedTasks.some((bt) => bt.id === t.id))
258
- .map((t) => ({
259
- id: t.id,
260
- title: t.title,
261
- status: t.status,
262
- depends: t.depends,
263
- blockingChain: analyze ? getTransitiveBlockers(t.id, tasksAsTask) : [],
264
- })),
265
- ];
266
- const total = blockerInfos.length;
267
- const pagedBlockerInfos = blockerInfos.slice(0, effectiveLimit);
268
- const blockerCounts = new Map();
269
- for (const info of pagedBlockerInfos) {
270
- for (const depId of info.blockingChain) {
271
- blockerCounts.set(depId, (blockerCounts.get(depId) ?? 0) + 1);
272
- }
273
- }
274
- const criticalBlockers = [...blockerCounts.entries()]
275
- .sort((a, b) => b[1] - a[1])
276
- .slice(0, 5)
277
- .map(([id, count]) => {
278
- const task = taskMap.get(id);
279
- return { id, title: task?.title ?? 'Unknown', blocksCount: count };
280
- });
281
- return {
282
- blockedTasks: pagedBlockerInfos,
283
- criticalBlockers,
284
- summary: total === 0 ? 'No blocked tasks found' : `${total} blocked task(s)`,
285
- total,
286
- limit: effectiveLimit,
287
- };
288
- }
289
- // ============================================================================
290
- // taskTree
291
- // ============================================================================
292
- /**
293
- * Build hierarchy tree for tasks.
294
- *
295
- * @param projectRoot - Absolute path to the CLEO project root directory
296
- * @param taskId - Optional root task ID; when provided, builds the subtree rooted at this task
297
- * @returns The tree nodes and total node count
298
- *
299
- * @remarks
300
- * When no taskId is given, returns all root-level tasks with their full subtrees.
301
- * When a taskId is given, returns that single task as the root with its descendants.
302
- *
303
- * @example
304
- * ```typescript
305
- * const { tree, totalNodes } = await coreTaskTree('/project', 'T042');
306
- * console.log(`${totalNodes} nodes in subtree`);
307
- * ```
308
- *
309
- * @task T4790
310
- */
311
- export async function coreTaskTree(projectRoot, taskId) {
312
- const allTasks = await loadAllTasks(projectRoot);
313
- if (taskId) {
314
- const task = allTasks.find((t) => t.id === taskId);
315
- if (!task) {
316
- throw new Error(`Task '${taskId}' not found`);
317
- }
318
- }
319
- const childrenMap = new Map();
320
- for (const task of allTasks) {
321
- const parentKey = task.parentId ?? '__root__';
322
- if (!childrenMap.has(parentKey)) {
323
- childrenMap.set(parentKey, []);
324
- }
325
- childrenMap.get(parentKey).push(task);
326
- }
327
- let roots;
328
- if (taskId) {
329
- roots = [allTasks.find((t) => t.id === taskId)];
330
- }
331
- else {
332
- roots = childrenMap.get('__root__') ?? [];
333
- }
334
- const tree = roots.map((root) => buildTreeNode(root, childrenMap));
335
- return { tree, totalNodes: countNodes(tree) };
336
- }
337
- // ============================================================================
338
- // taskDeps
339
- // ============================================================================
340
- /**
341
- * Show dependencies for a task.
342
- *
343
- * @param projectRoot - Absolute path to the CLEO project root directory
344
- * @param taskId - The task ID to inspect dependencies for
345
- * @returns Upstream and downstream dependencies, unresolved deps, and readiness flag
346
- *
347
- * @remarks
348
- * Returns both the tasks this task depends on (upstream) and the tasks that depend
349
- * on it (downstream). Unresolved deps are those not yet done or cancelled.
350
- *
351
- * @example
352
- * ```typescript
353
- * const deps = await coreTaskDeps('/project', 'T100');
354
- * if (!deps.allDepsReady) console.log('Blocked by:', deps.unresolvedDeps);
355
- * ```
356
- *
357
- * @task T4790
358
- */
359
- export async function coreTaskDeps(projectRoot, taskId) {
360
- const allTasks = await loadAllTasks(projectRoot);
361
- const task = allTasks.find((t) => t.id === taskId);
362
- if (!task) {
363
- throw new Error(`Task '${taskId}' not found`);
364
- }
365
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
366
- const completedIds = new Set(allTasks.filter((t) => t.status === 'done' || t.status === 'cancelled').map((t) => t.id));
367
- const dependsOn = (task.depends ?? [])
368
- .map((depId) => {
369
- const dep = taskMap.get(depId);
370
- return dep ? { id: dep.id, title: dep.title, status: dep.status } : null;
371
- })
372
- .filter((d) => d !== null);
373
- const dependedOnBy = allTasks
374
- .filter((t) => t.depends?.includes(taskId))
375
- .map((t) => ({ id: t.id, title: t.title, status: t.status }));
376
- const unresolvedDeps = (task.depends ?? []).filter((depId) => !completedIds.has(depId));
377
- return {
378
- taskId,
379
- dependsOn,
380
- dependedOnBy,
381
- unresolvedDeps,
382
- allDepsReady: unresolvedDeps.length === 0,
383
- };
384
- }
385
- // ============================================================================
386
- // taskRelates
387
- // ============================================================================
388
- /**
389
- * Show task relations.
390
- *
391
- * @param projectRoot - Absolute path to the CLEO project root directory
392
- * @param taskId - The task ID to retrieve relations for
393
- * @returns The task's relations array and count
394
- *
395
- * @remarks
396
- * Relations are non-dependency links between tasks (e.g. "related-to", "duplicates").
397
- * Unlike dependencies, relations do not affect blocking or scheduling.
398
- *
399
- * @example
400
- * ```typescript
401
- * const { relations, count } = await coreTaskRelates('/project', 'T050');
402
- * console.log(`${count} relations found`);
403
- * ```
404
- *
405
- * @task T4790
406
- */
407
- export async function coreTaskRelates(projectRoot, taskId) {
408
- const allTasks = await loadAllTasks(projectRoot);
409
- const task = allTasks.find((t) => t.id === taskId);
410
- if (!task) {
411
- throw new Error(`Task '${taskId}' not found`);
412
- }
413
- const relations = task.relates ?? [];
414
- return { taskId, relations, count: relations.length };
415
- }
416
- // ============================================================================
417
- // taskRelatesAdd
418
- // ============================================================================
419
- /**
420
- * Add a relation between two tasks.
421
- *
422
- * @param projectRoot - Absolute path to the CLEO project root directory
423
- * @param taskId - The source task ID
424
- * @param relatedId - The target task ID to relate to
425
- * @param type - Relation type (e.g. "related-to", "duplicates", "blocks")
426
- * @param reason - Optional human-readable reason for the relation
427
- * @returns Confirmation of the added relation with source, target, and type
428
- *
429
- * @remarks
430
- * Persists the relation both on the task's `relates` array and in the
431
- * `task_relations` table for bidirectional querying.
432
- *
433
- * @example
434
- * ```typescript
435
- * const result = await coreTaskRelatesAdd('/project', 'T010', 'T020', 'related-to', 'Shared scope');
436
- * console.log(result.added); // true
437
- * ```
438
- *
439
- * @task T4790
440
- */
441
- export async function coreTaskRelatesAdd(projectRoot, taskId, relatedId, type, reason) {
442
- const accessor = await getAccessor(projectRoot);
443
- const fromTask = await accessor.loadSingleTask(taskId);
444
- if (!fromTask) {
445
- throw new Error(`Task '${taskId}' not found`);
446
- }
447
- const toExists = await accessor.taskExists(relatedId);
448
- if (!toExists) {
449
- throw new Error(`Task '${relatedId}' not found`);
450
- }
451
- if (!fromTask.relates) {
452
- fromTask.relates = [];
453
- }
454
- fromTask.relates.push({
455
- taskId: relatedId,
456
- type,
457
- reason: reason || undefined,
458
- });
459
- fromTask.updatedAt = new Date().toISOString();
460
- await accessor.upsertSingleTask(fromTask);
461
- // Persist to task_relations table (T5168)
462
- await accessor.addRelation(taskId, relatedId, type, reason);
463
- return { from: taskId, to: relatedId, type, reason, added: true };
464
- }
465
- // ============================================================================
466
- // taskAnalyze
467
- // ============================================================================
468
- /**
469
- * Analyze tasks for priority and leverage.
470
- *
471
- * @param projectRoot - Absolute path to the CLEO project root directory
472
- * @param taskId - Optional task or epic ID to scope the analysis; omit for project-wide
473
- * @param params - Optional analysis configuration
474
- * @param params.tierLimit - Maximum tasks per priority tier in the response (default: 10)
475
- * @returns Analysis with recommended next task, bottlenecks, priority tiers, and aggregate metrics
476
- *
477
- * @remarks
478
- * Computes a leverage score per task (how many other tasks it unblocks) and combines
479
- * it with priority to produce a ranked recommendation. Bottlenecks are the top 5
480
- * incomplete tasks that block the most others.
481
- *
482
- * @example
483
- * ```typescript
484
- * const analysis = await coreTaskAnalyze('/project', undefined, { tierLimit: 5 });
485
- * if (analysis.recommended) console.log('Work on:', analysis.recommended.id);
486
- * ```
487
- *
488
- * @task T4790
489
- */
490
- export async function coreTaskAnalyze(projectRoot, taskId, params) {
491
- const allTasks = await loadAllTasks(projectRoot);
492
- const effectiveTierLimit = params?.tierLimit ?? 10;
493
- const tasks = taskId
494
- ? allTasks.filter((t) => t.id === taskId || t.parentId === taskId)
495
- : allTasks;
496
- const blocksMap = {};
497
- for (const task of tasks) {
498
- if (task.depends) {
499
- for (const dep of task.depends) {
500
- if (!blocksMap[dep])
501
- blocksMap[dep] = [];
502
- blocksMap[dep].push(task.id);
503
- }
504
- }
505
- }
506
- const leverageMap = {};
507
- for (const task of tasks) {
508
- leverageMap[task.id] = (blocksMap[task.id] ?? []).length;
509
- }
510
- const actionable = tasks.filter((t) => t.status === 'pending' || t.status === 'active');
511
- const blocked = tasks.filter((t) => t.status === 'blocked');
512
- const bottlenecks = tasks
513
- .filter((t) => (blocksMap[t.id]?.length ?? 0) > 0 && t.status !== 'done')
514
- .map((t) => ({ id: t.id, title: t.title, blocksCount: blocksMap[t.id].length }))
515
- .sort((a, b) => b.blocksCount - a.blocksCount)
516
- .slice(0, 5);
517
- const scored = actionable.map((t) => ({
518
- id: t.id,
519
- title: t.title,
520
- leverage: leverageMap[t.id] ?? 0,
521
- priority: t.priority,
522
- }));
523
- scored.sort((a, b) => {
524
- const priorityWeight = { critical: 100, high: 50, medium: 20, low: 5 };
525
- const aScore = (priorityWeight[a.priority ?? 'medium'] ?? 20) + a.leverage * 10;
526
- const bScore = (priorityWeight[b.priority ?? 'medium'] ?? 20) + b.leverage * 10;
527
- return bScore - aScore;
528
- });
529
- const critical = scored.filter((t) => t.priority === 'critical');
530
- const high = scored.filter((t) => t.priority === 'high');
531
- const normal = scored.filter((t) => t.priority !== 'critical' && t.priority !== 'high');
532
- const recommended = scored.length > 0
533
- ? {
534
- id: scored[0].id,
535
- title: scored[0].title,
536
- leverage: scored[0].leverage,
537
- reason: 'Highest combined priority and leverage score',
538
- }
539
- : null;
540
- const totalLeverage = Object.values(leverageMap).reduce((s, v) => s + v, 0);
541
- const avgLeverage = tasks.length > 0 ? Math.round((totalLeverage / tasks.length) * 100) / 100 : 0;
542
- return {
543
- recommended,
544
- bottlenecks,
545
- tiers: {
546
- critical: critical
547
- .slice(0, effectiveTierLimit)
548
- .map(({ id, title, leverage }) => ({ id, title, leverage })),
549
- high: high
550
- .slice(0, effectiveTierLimit)
551
- .map(({ id, title, leverage }) => ({ id, title, leverage })),
552
- normal: normal
553
- .slice(0, effectiveTierLimit)
554
- .map(({ id, title, leverage }) => ({ id, title, leverage })),
555
- },
556
- metrics: {
557
- totalTasks: tasks.length,
558
- actionable: actionable.length,
559
- blocked: blocked.length,
560
- avgLeverage,
561
- },
562
- tierLimit: effectiveTierLimit,
563
- };
564
- }
565
- // ============================================================================
566
- // taskRestore
567
- // ============================================================================
568
- /**
569
- * Restore a cancelled task back to pending.
570
- *
571
- * @param projectRoot - Absolute path to the CLEO project root directory
572
- * @param taskId - The cancelled task ID to restore
573
- * @param params - Optional restore options
574
- * @param params.cascade - When true, also restores cancelled child tasks recursively
575
- * @param params.notes - Optional note appended to each restored task's notes array
576
- * @returns The task ID, list of restored task IDs, and total count
577
- *
578
- * @remarks
579
- * Only tasks with status "cancelled" can be restored. Restored tasks are set to
580
- * "pending" with cancellation metadata cleared. A timestamped note is appended.
581
- *
582
- * @example
583
- * ```typescript
584
- * const { restored, count } = await coreTaskRestore('/project', 'T099', { cascade: true });
585
- * console.log(`Restored ${count} tasks:`, restored);
586
- * ```
587
- *
588
- * @task T4790
589
- */
590
- export async function coreTaskRestore(projectRoot, taskId, params) {
591
- const accessor = await getAccessor(projectRoot);
592
- const task = await accessor.loadSingleTask(taskId);
593
- if (!task) {
594
- throw new Error(`Task '${taskId}' not found`);
595
- }
596
- if (task.status !== 'cancelled') {
597
- throw new Error(`Task '${taskId}' is not cancelled (status: ${task.status}). Only cancelled tasks can be restored.`);
598
- }
599
- const tasksToRestore = [task];
600
- if (params?.cascade) {
601
- const findCancelledChildren = async (parentId) => {
602
- const children = await accessor.getChildren(parentId);
603
- const cancelledChildren = children.filter((t) => t.status === 'cancelled');
604
- for (const child of cancelledChildren) {
605
- tasksToRestore.push(child);
606
- await findCancelledChildren(child.id);
607
- }
608
- };
609
- await findCancelledChildren(taskId);
610
- }
611
- const now = new Date().toISOString();
612
- const restored = [];
613
- for (const t of tasksToRestore) {
614
- t.status = 'pending';
615
- t.cancelledAt = undefined;
616
- t.cancellationReason = undefined;
617
- t.updatedAt = now;
618
- if (!t.notes)
619
- t.notes = [];
620
- t.notes.push(`[${now}] Restored from cancelled${params?.notes ? ': ' + params.notes : ''}`);
621
- restored.push(t.id);
622
- }
623
- for (const t of tasksToRestore) {
624
- await accessor.upsertSingleTask(t);
625
- }
626
- return { task: taskId, restored, count: restored.length };
627
- }
628
- // ============================================================================
629
- // taskCancel
630
- // ============================================================================
631
- /**
632
- * Cancel a task (sets status to 'cancelled', a soft terminal state).
633
- * Use restore to reverse. Use delete for permanent removal.
634
- *
635
- * @param projectRoot - Absolute path to the CLEO project root directory
636
- * @param taskId - The task ID to cancel
637
- * @param params - Optional cancel options
638
- * @param params.reason - Human-readable cancellation reason stored on the task
639
- * @returns Confirmation with cancelled flag and timestamp
640
- *
641
- * @remarks
642
- * Cancellation is a soft terminal state -- the task remains in the database and
643
- * can be restored via {@link coreTaskRestore}. Not all statuses are cancellable;
644
- * the `canCancel` guard determines eligibility.
645
- *
646
- * @example
647
- * ```typescript
648
- * const result = await coreTaskCancel('/project', 'T077', { reason: 'Superseded by T080' });
649
- * console.log(result.cancelledAt);
650
- * ```
651
- *
652
- * @task T4529
653
- */
654
- export async function coreTaskCancel(projectRoot, taskId, params) {
655
- const accessor = await getAccessor(projectRoot);
656
- const task = await accessor.loadSingleTask(taskId);
657
- if (!task) {
658
- throw new Error(`Task ${taskId} not found`);
659
- }
660
- const check = canCancel(task);
661
- if (!check.allowed) {
662
- throw new Error(check.reason);
663
- }
664
- const cancelledAt = new Date().toISOString();
665
- task.status = 'cancelled';
666
- task.cancelledAt = cancelledAt;
667
- task.cancellationReason = params?.reason ?? undefined;
668
- task.updatedAt = cancelledAt;
669
- await accessor.upsertSingleTask(task);
670
- return { task: taskId, cancelled: true, reason: params?.reason, cancelledAt };
671
- }
672
- // ============================================================================
673
- // taskUnarchive
674
- // ============================================================================
675
- /**
676
- * Move an archived task back to active tasks.
677
- *
678
- * @param projectRoot - Absolute path to the CLEO project root directory
679
- * @param taskId - The archived task ID to unarchive
680
- * @param params - Optional unarchive options
681
- * @param params.status - Target status for the restored task (default: "pending")
682
- * @param params.preserveStatus - When true, keeps the task's original archived status
683
- * @returns Confirmation with task ID, title, and resulting status
684
- *
685
- * @remarks
686
- * Removes the task from the archive file and upserts it into the active task store.
687
- * Throws if the task already exists in active tasks or is not found in the archive.
688
- *
689
- * @example
690
- * ```typescript
691
- * const result = await coreTaskUnarchive('/project', 'T055', { status: 'active' });
692
- * console.log(`${result.title} is now ${result.status}`);
693
- * ```
694
- *
695
- * @task T4790
696
- */
697
- export async function coreTaskUnarchive(projectRoot, taskId, params) {
698
- const accessor = await getAccessor(projectRoot);
699
- // Check if task already exists in active tasks
700
- const existingTask = await accessor.taskExists(taskId);
701
- if (existingTask) {
702
- throw new Error(`Task '${taskId}' already exists in active tasks`);
703
- }
704
- const archive = await accessor.loadArchive();
705
- if (!archive || !archive.archivedTasks) {
706
- throw new Error('No archive file found');
707
- }
708
- const taskIndex = archive.archivedTasks.findIndex((t) => t.id === taskId);
709
- if (taskIndex === -1) {
710
- throw new Error(`Task '${taskId}' not found in archive`);
711
- }
712
- const task = archive.archivedTasks[taskIndex];
713
- // Remove archive metadata if present on the raw record
714
- if ('_archive' in task) {
715
- Reflect.deleteProperty(task, '_archive');
716
- }
717
- if (!params?.preserveStatus) {
718
- const rawStatus = params?.status || 'pending';
719
- if (!TASK_STATUSES.includes(rawStatus)) {
720
- throw new Error(`Invalid status: ${rawStatus}`);
721
- }
722
- // rawStatus is validated above as a member of TASK_STATUSES
723
- const targetStatus = rawStatus;
724
- if (targetStatus !== 'done') {
725
- task.completedAt = undefined;
726
- }
727
- }
728
- task.updatedAt = new Date().toISOString();
729
- // Fine-grained: upsert the restored task (now active)
730
- await accessor.upsertSingleTask(task);
731
- return { task: taskId, unarchived: true, title: task.title, status: task.status };
732
- }
733
- // ============================================================================
734
- // taskReorder
735
- // ============================================================================
736
- /**
737
- * Change task position within its sibling group.
738
- *
739
- * @param projectRoot - Absolute path to the CLEO project root directory
740
- * @param taskId - The task ID to reorder
741
- * @param position - Target 1-based position within the sibling group
742
- * @returns Confirmation with the new position and total sibling count
743
- *
744
- * @remarks
745
- * Reorders by adjusting `position` and `positionVersion` fields on all siblings.
746
- * Position is clamped to valid bounds. Uses bulk field updates for efficiency.
747
- *
748
- * @example
749
- * ```typescript
750
- * const result = await coreTaskReorder('/project', 'T012', 1);
751
- * console.log(`Moved to position ${result.newPosition} of ${result.totalSiblings}`);
752
- * ```
753
- *
754
- * @task T4790
755
- */
756
- export async function coreTaskReorder(projectRoot, taskId, position) {
757
- const accessor = await getAccessor(projectRoot);
758
- const task = await accessor.loadSingleTask(taskId);
759
- if (!task) {
760
- throw new Error(`Task '${taskId}' not found`);
761
- }
762
- // Get siblings: tasks with same parentId
763
- const parentFilter = task.parentId ? { parentId: task.parentId } : {};
764
- const { tasks: siblingCandidates } = await accessor.queryTasks(parentFilter);
765
- // For root-level tasks (no parentId), filter to only those without a parentId
766
- const allSiblings = task.parentId
767
- ? siblingCandidates.sort((a, b) => (a.position ?? 0) - (b.position ?? 0))
768
- : siblingCandidates
769
- .filter((t) => !t.parentId)
770
- .sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
771
- const currentIndex = allSiblings.findIndex((t) => t.id === taskId);
772
- const newIndex = Math.max(0, Math.min(position - 1, allSiblings.length - 1));
773
- allSiblings.splice(currentIndex, 1);
774
- allSiblings.splice(newIndex, 0, task);
775
- // Use bulk SQL for position updates (T025) — updateTaskFields is lighter than upsertSingleTask
776
- const now = new Date().toISOString();
777
- for (let i = 0; i < allSiblings.length; i++) {
778
- const sibling = allSiblings[i];
779
- const newPos = i + 1;
780
- const newVersion = (sibling.positionVersion ?? 0) + 1;
781
- // Only update if position actually changed
782
- if (sibling.position !== newPos || sibling.id === taskId) {
783
- await accessor.updateTaskFields(sibling.id, {
784
- position: newPos,
785
- positionVersion: newVersion,
786
- updatedAt: now,
787
- });
788
- }
789
- sibling.position = newPos;
790
- sibling.positionVersion = newVersion;
791
- sibling.updatedAt = now;
792
- }
793
- return {
794
- task: taskId,
795
- reordered: true,
796
- newPosition: newIndex + 1,
797
- totalSiblings: allSiblings.length,
798
- };
799
- }
800
- // ============================================================================
801
- // taskReparent
802
- // ============================================================================
803
- /**
804
- * Move task under a different parent.
805
- *
806
- * @param projectRoot - Absolute path to the CLEO project root directory
807
- * @param taskId - The task ID to reparent
808
- * @param newParentId - The new parent task ID, or null to promote to root level
809
- * @returns Confirmation with old and new parent IDs and optional type change
810
- *
811
- * @remarks
812
- * Validates against circular references, depth limits, and sibling limits from
813
- * the project hierarchy config. Automatically adjusts task type based on new depth
814
- * (depth 1 = "task", depth >= 2 = "subtask").
815
- *
816
- * @example
817
- * ```typescript
818
- * const result = await coreTaskReparent('/project', 'T015', 'T010');
819
- * console.log(`Moved from ${result.oldParent} to ${result.newParent}`);
820
- * ```
821
- *
822
- * @task T4790
823
- */
824
- export async function coreTaskReparent(projectRoot, taskId, newParentId) {
825
- const accessor = await getAccessor(projectRoot);
826
- const task = await accessor.loadSingleTask(taskId);
827
- if (!task) {
828
- throw new Error(`Task '${taskId}' not found`);
829
- }
830
- const effectiveParentId = newParentId || null;
831
- if (!effectiveParentId) {
832
- const oldParent = task.parentId ?? null;
833
- task.parentId = null;
834
- if (task.type === 'subtask')
835
- task.type = 'task';
836
- task.updatedAt = new Date().toISOString();
837
- await accessor.upsertSingleTask(task);
838
- return { task: taskId, reparented: true, oldParent, newParent: null, newType: task.type };
839
- }
840
- const newParent = await accessor.loadSingleTask(effectiveParentId);
841
- if (!newParent) {
842
- throw new Error(`Parent task '${effectiveParentId}' not found`);
843
- }
844
- if (newParent.type === 'subtask') {
845
- throw new Error(`Cannot parent under subtask '${effectiveParentId}'`);
846
- }
847
- // Check circular reference using subtree
848
- const subtree = await accessor.getSubtree(taskId);
849
- if (subtree.some((t) => t.id === effectiveParentId)) {
850
- throw new Error(`Moving '${taskId}' under '${effectiveParentId}' would create circular reference`);
851
- }
852
- // Check depth limit using ancestor chain
853
- const ancestors = await accessor.getAncestorChain(effectiveParentId);
854
- const parentDepth = ancestors.length;
855
- const reparentLimits = getHierarchyLimits(projectRoot);
856
- if (parentDepth + 1 >= reparentLimits.maxDepth) {
857
- throw new Error(`Move would exceed max depth of ${reparentLimits.maxDepth}`);
858
- }
859
- // Check sibling limit (0 = unlimited)
860
- const children = await accessor.getChildren(effectiveParentId);
861
- const siblingCount = children.filter((t) => t.id !== taskId).length;
862
- if (reparentLimits.maxSiblings > 0 && siblingCount >= reparentLimits.maxSiblings) {
863
- throw new Error(`Cannot add child to ${effectiveParentId}: max siblings (${reparentLimits.maxSiblings}) exceeded`);
864
- }
865
- const oldParent = task.parentId ?? null;
866
- task.parentId = effectiveParentId;
867
- const newDepth = parentDepth + 1;
868
- if (newDepth === 1)
869
- task.type = 'task';
870
- else if (newDepth >= 2)
871
- task.type = 'subtask';
872
- task.updatedAt = new Date().toISOString();
873
- await accessor.upsertSingleTask(task);
874
- return {
875
- task: taskId,
876
- reparented: true,
877
- oldParent,
878
- newParent: effectiveParentId,
879
- newType: task.type,
880
- };
881
- }
882
- // ============================================================================
883
- // taskPromote
884
- // ============================================================================
885
- /**
886
- * Promote a subtask to task or task to root.
887
- *
888
- * @param projectRoot - Absolute path to the CLEO project root directory
889
- * @param taskId - The task ID to promote
890
- * @returns Confirmation with previous parent and whether the type changed
891
- *
892
- * @remarks
893
- * Removes the task's parentId, making it a root-level task. If the task was
894
- * a "subtask", its type is changed to "task". No-op if the task is already root-level.
895
- *
896
- * @example
897
- * ```typescript
898
- * const result = await coreTaskPromote('/project', 'T025');
899
- * if (result.promoted) console.log('Detached from', result.previousParent);
900
- * ```
901
- *
902
- * @task T4790
903
- */
904
- export async function coreTaskPromote(projectRoot, taskId) {
905
- const accessor = await getAccessor(projectRoot);
906
- const task = await accessor.loadSingleTask(taskId);
907
- if (!task) {
908
- throw new Error(`Task '${taskId}' not found`);
909
- }
910
- if (!task.parentId) {
911
- return { task: taskId, promoted: false, previousParent: null, typeChanged: false };
912
- }
913
- const oldParent = task.parentId;
914
- task.parentId = null;
915
- task.updatedAt = new Date().toISOString();
916
- let typeChanged = false;
917
- if (task.type === 'subtask') {
918
- task.type = 'task';
919
- typeChanged = true;
920
- }
921
- await accessor.upsertSingleTask(task);
922
- return { task: taskId, promoted: true, previousParent: oldParent, typeChanged };
923
- }
924
- // ============================================================================
925
- // taskReopen
926
- // ============================================================================
927
- /**
928
- * Reopen a completed task.
929
- *
930
- * @param projectRoot - Absolute path to the CLEO project root directory
931
- * @param taskId - The completed task ID to reopen
932
- * @param params - Optional reopen options
933
- * @param params.status - Target status after reopening ("pending" or "active", default: "pending")
934
- * @param params.reason - Optional reason appended to the task's notes
935
- * @returns Confirmation with previous and new status
936
- *
937
- * @remarks
938
- * Only tasks with status "done" can be reopened. Clears the `completedAt` timestamp
939
- * and appends a timestamped note recording the reopen event.
940
- *
941
- * @example
942
- * ```typescript
943
- * const result = await coreTaskReopen('/project', 'T033', { status: 'active', reason: 'Tests failed' });
944
- * console.log(`${result.previousStatus} -> ${result.newStatus}`);
945
- * ```
946
- *
947
- * @task T4790
948
- */
949
- export async function coreTaskReopen(projectRoot, taskId, params) {
950
- const accessor = await getAccessor(projectRoot);
951
- const task = await accessor.loadSingleTask(taskId);
952
- if (!task) {
953
- throw new Error(`Task '${taskId}' not found`);
954
- }
955
- if (task.status !== 'done') {
956
- throw new Error(`Task '${taskId}' is not completed (status: ${task.status}). Only done tasks can be reopened.`);
957
- }
958
- const targetStatus = params?.status || 'pending';
959
- if (targetStatus !== 'pending' && targetStatus !== 'active') {
960
- throw new Error(`Invalid target status: ${targetStatus}. Must be 'pending' or 'active'.`);
961
- }
962
- const previousStatus = task.status;
963
- task.status = targetStatus;
964
- task.completedAt = undefined;
965
- task.updatedAt = new Date().toISOString();
966
- if (!task.notes)
967
- task.notes = [];
968
- const reason = params?.reason;
969
- task.notes.push(`[${task.updatedAt}] Reopened from ${previousStatus}${reason ? ': ' + reason : ''}`);
970
- await accessor.upsertSingleTask(task);
971
- return { task: taskId, reopened: true, previousStatus, newStatus: targetStatus };
972
- }
973
- // ============================================================================
974
- // taskComplexityEstimate
975
- // ============================================================================
976
- /**
977
- * Deterministic complexity scoring from task metadata.
978
- *
979
- * @param projectRoot - Absolute path to the CLEO project root directory
980
- * @param params - Parameters containing the task ID to estimate
981
- * @param params.taskId - The task ID to compute complexity for
982
- * @returns Complexity size ("small"/"medium"/"large"), numeric score, contributing factors, and metadata counts
983
- *
984
- * @remarks
985
- * Scores are computed from description length, acceptance criteria count, dependency depth,
986
- * subtask count, and file reference count. Each factor contributes 0-3 points.
987
- * Total score 0-3 = small, 4-7 = medium, 8+ = large.
988
- *
989
- * @example
990
- * ```typescript
991
- * const est = await coreTaskComplexityEstimate('/project', { taskId: 'T042' });
992
- * console.log(`${est.size} (score: ${est.score})`);
993
- * ```
994
- *
995
- * @task T4790
996
- */
997
- export async function coreTaskComplexityEstimate(projectRoot, params) {
998
- const allTasks = await loadAllTasks(projectRoot);
999
- const task = allTasks.find((t) => t.id === params.taskId);
1000
- if (!task) {
1001
- throw new Error(`Task '${params.taskId}' not found`);
1002
- }
1003
- const factors = [];
1004
- let score = 0;
1005
- const descLen = (task.description || '').length;
1006
- let descScore;
1007
- let descLabel;
1008
- if (descLen < 100) {
1009
- descScore = 1;
1010
- descLabel = 'short';
1011
- }
1012
- else if (descLen < 500) {
1013
- descScore = 2;
1014
- descLabel = 'medium';
1015
- }
1016
- else {
1017
- descScore = 3;
1018
- descLabel = 'long';
1019
- }
1020
- score += descScore;
1021
- factors.push({
1022
- name: 'descriptionLength',
1023
- value: descScore,
1024
- detail: `${descLabel} (${descLen} chars)`,
1025
- });
1026
- const acceptanceCount = task.acceptance?.length ?? 0;
1027
- const acceptanceScore = Math.min(acceptanceCount, 3);
1028
- score += acceptanceScore;
1029
- factors.push({
1030
- name: 'acceptanceCriteria',
1031
- value: acceptanceScore,
1032
- detail: `${acceptanceCount} criteria`,
1033
- });
1034
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
1035
- const dependencyDepth = measureDependencyDepth(params.taskId, taskMap);
1036
- const depthScore = Math.min(dependencyDepth, 3);
1037
- score += depthScore;
1038
- factors.push({ name: 'dependencyDepth', value: depthScore, detail: `depth ${dependencyDepth}` });
1039
- const subtaskCount = allTasks.filter((t) => t.parentId === params.taskId).length;
1040
- const subtaskScore = Math.min(subtaskCount, 3);
1041
- score += subtaskScore;
1042
- factors.push({ name: 'subtaskCount', value: subtaskScore, detail: `${subtaskCount} subtasks` });
1043
- const fileCount = task.files?.length ?? 0;
1044
- const fileScore = Math.min(fileCount, 3);
1045
- score += fileScore;
1046
- factors.push({ name: 'fileReferences', value: fileScore, detail: `${fileCount} files` });
1047
- let size;
1048
- if (score <= 3)
1049
- size = 'small';
1050
- else if (score <= 7)
1051
- size = 'medium';
1052
- else
1053
- size = 'large';
1054
- return { size, score, factors, dependencyDepth, subtaskCount, fileCount };
1055
- }
1056
- // ============================================================================
1057
- // taskDepsOverview
1058
- // ============================================================================
1059
- /**
1060
- * Overview of all dependencies across the project.
1061
- *
1062
- * @param projectRoot - Absolute path to the CLEO project root directory
1063
- * @returns Project-wide dependency summary including blocked tasks, ready tasks, and validation results
1064
- *
1065
- * @remarks
1066
- * Aggregates dependency data across all tasks to provide a high-level view of
1067
- * the dependency graph health, including which tasks are blocked and what would unblock them.
1068
- *
1069
- * @example
1070
- * ```typescript
1071
- * const overview = await coreTaskDepsOverview('/project');
1072
- * console.log(`${overview.blockedTasks.length} blocked, ${overview.readyTasks.length} ready`);
1073
- * ```
1074
- *
1075
- * @task T5157
1076
- */
1077
- export async function coreTaskDepsOverview(projectRoot) {
1078
- const allTasks = await loadAllTasks(projectRoot);
1079
- const tasksAsTask = allTasks;
1080
- const tasksWithDeps = allTasks.filter((t) => t.depends && t.depends.length > 0);
1081
- const blocked = getBlockedTasks(tasksAsTask);
1082
- const ready = getReadyTasks(tasksAsTask);
1083
- const validation = validateDependencies(tasksAsTask);
1084
- return {
1085
- totalTasks: allTasks.length,
1086
- tasksWithDeps: tasksWithDeps.length,
1087
- blockedTasks: blocked.map((t) => ({
1088
- id: t.id,
1089
- title: t.title,
1090
- status: t.status,
1091
- unblockedBy: (t.depends ?? []).filter((depId) => {
1092
- const dep = allTasks.find((x) => x.id === depId);
1093
- return dep && dep.status !== 'done' && dep.status !== 'cancelled';
1094
- }),
1095
- })),
1096
- readyTasks: ready
1097
- .filter((t) => t.status !== 'done' && t.status !== 'cancelled')
1098
- .map((t) => ({
1099
- id: t.id,
1100
- title: t.title,
1101
- status: t.status,
1102
- })),
1103
- validation: {
1104
- valid: validation.valid,
1105
- errorCount: validation.errors.length,
1106
- warningCount: validation.warnings.length,
1107
- },
1108
- };
1109
- }
1110
- // ============================================================================
1111
- // taskDepsCycles
1112
- // ============================================================================
1113
- /**
1114
- * Detect circular dependencies across the project.
1115
- *
1116
- * @param projectRoot - Absolute path to the CLEO project root directory
1117
- * @returns Whether cycles exist and the list of detected cycles with their task paths
1118
- *
1119
- * @remarks
1120
- * Iterates through all tasks with dependencies and uses cycle detection to find
1121
- * circular chains. Each cycle includes the full path (e.g. [A, B, C, A]) and
1122
- * the tasks involved with their titles.
1123
- *
1124
- * @example
1125
- * ```typescript
1126
- * const { hasCycles, cycles } = await coreTaskDepsCycles('/project');
1127
- * if (hasCycles) console.log('Circular deps:', cycles.map(c => c.path.join(' -> ')));
1128
- * ```
1129
- *
1130
- * @task T5157
1131
- */
1132
- export async function coreTaskDepsCycles(projectRoot) {
1133
- const allTasks = await loadAllTasks(projectRoot);
1134
- const tasksAsTask = allTasks;
1135
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
1136
- const visited = new Set();
1137
- const cycles = [];
1138
- for (const task of allTasks) {
1139
- if (visited.has(task.id))
1140
- continue;
1141
- if (!task.depends?.length)
1142
- continue;
1143
- const cycle = detectCircularDeps(task.id, tasksAsTask);
1144
- if (cycle.length > 0) {
1145
- cycles.push({
1146
- path: cycle,
1147
- // Deduplicate: detectCircularDeps returns [A,B,C,A] where
1148
- // last element closes the cycle. Use Set for robustness.
1149
- tasks: [...new Set(cycle)].map((id) => {
1150
- const t = taskMap.get(id);
1151
- return { id, title: t?.title ?? 'unknown' };
1152
- }),
1153
- });
1154
- for (const id of cycle) {
1155
- visited.add(id);
1156
- }
1157
- }
1158
- }
1159
- return { hasCycles: cycles.length > 0, cycles };
1160
- }
1161
- // ============================================================================
1162
- // taskDepends
1163
- // ============================================================================
1164
- /**
1165
- * List dependencies for a task in a given direction.
1166
- *
1167
- * @param projectRoot - Absolute path to the CLEO project root directory
1168
- * @param taskId - The task ID to inspect
1169
- * @param direction - Direction to traverse: "upstream" (what this task depends on), "downstream" (what depends on it), or "both"
1170
- * @param options - Optional display configuration
1171
- * @param options.tree - When true, includes a recursive upstream dependency tree
1172
- * @returns Upstream and downstream deps, transitive chain length, leaf blockers, and readiness status
1173
- *
1174
- * @remarks
1175
- * Combines direct dependency lookups with transitive analysis. Leaf blockers are
1176
- * the deepest unresolved tasks in the dependency chain -- resolving them first
1177
- * has the most impact on unblocking.
1178
- *
1179
- * @example
1180
- * ```typescript
1181
- * const deps = await coreTaskDepends('/project', 'T100', 'both', { tree: true });
1182
- * console.log('Leaf blockers:', deps.leafBlockers.map(b => b.id));
1183
- * ```
1184
- *
1185
- * @task T4790
1186
- */
1187
- export async function coreTaskDepends(projectRoot, taskId, direction = 'both', options) {
1188
- const allTasks = await loadAllTasks(projectRoot);
1189
- const task = allTasks.find((t) => t.id === taskId);
1190
- if (!task) {
1191
- throw new Error(`Task '${taskId}' not found`);
1192
- }
1193
- const taskMap = new Map(allTasks.map((t) => [t.id, t]));
1194
- const upstream = [];
1195
- if (direction === 'upstream' || direction === 'both') {
1196
- for (const depId of task.depends ?? []) {
1197
- const dep = taskMap.get(depId);
1198
- if (dep) {
1199
- upstream.push({ id: dep.id, title: dep.title, status: dep.status });
1200
- }
1201
- }
1202
- }
1203
- const downstream = [];
1204
- if (direction === 'downstream' || direction === 'both') {
1205
- for (const t of allTasks) {
1206
- if (t.depends?.includes(taskId)) {
1207
- downstream.push({ id: t.id, title: t.title, status: t.status });
1208
- }
1209
- }
1210
- }
1211
- // Transitive dependency hints
1212
- const tasksAsTask = allTasks;
1213
- const transitiveIds = getTransitiveBlockers(taskId, tasksAsTask);
1214
- const unresolvedChain = transitiveIds.length;
1215
- const leafIds = getLeafBlockers(taskId, tasksAsTask);
1216
- const leafBlockers = leafIds.map((id) => {
1217
- const t = taskMap.get(id);
1218
- return { id: t.id, title: t.title, status: t.status };
1219
- });
1220
- const allDepsReady = unresolvedChain === 0;
1221
- const hint = unresolvedChain > 0
1222
- ? `Run 'ct deps show ${taskId} --tree' for full dependency graph`
1223
- : undefined;
1224
- // Optional upstream tree
1225
- let upstreamTree;
1226
- if (options?.tree) {
1227
- upstreamTree = buildUpstreamTree(taskId, taskMap);
1228
- }
1229
- return {
1230
- taskId,
1231
- direction,
1232
- upstream,
1233
- downstream,
1234
- unresolvedChain,
1235
- leafBlockers,
1236
- allDepsReady,
1237
- ...(hint && { hint }),
1238
- ...(upstreamTree && { upstreamTree }),
1239
- };
1240
- }
1241
- // ============================================================================
1242
- // taskStats
1243
- // ============================================================================
1244
- /**
1245
- * Compute task statistics.
1246
- *
1247
- * @param projectRoot - Absolute path to the CLEO project root directory
1248
- * @param epicId - Optional epic ID to scope stats to that subtree
1249
- * @returns Status counts, priority distribution, and type distribution
1250
- *
1251
- * @remarks
1252
- * When an epicId is provided, statistics are scoped to that epic and all its
1253
- * transitive children. Without an epicId, stats cover the entire project.
1254
- *
1255
- * @example
1256
- * ```typescript
1257
- * const stats = await coreTaskStats('/project', 'T001');
1258
- * console.log(`${stats.done}/${stats.total} complete`);
1259
- * ```
1260
- *
1261
- * @task T4790
1262
- */
1263
- export async function coreTaskStats(projectRoot, epicId) {
1264
- const allTasks = await loadAllTasks(projectRoot);
1265
- let tasks = allTasks;
1266
- if (epicId) {
1267
- const epicIds = new Set();
1268
- epicIds.add(epicId);
1269
- const collectChildren = (parentId) => {
1270
- for (const t of allTasks) {
1271
- if (t.parentId === parentId && !epicIds.has(t.id)) {
1272
- epicIds.add(t.id);
1273
- collectChildren(t.id);
1274
- }
1275
- }
1276
- };
1277
- collectChildren(epicId);
1278
- tasks = allTasks.filter((t) => epicIds.has(t.id));
1279
- }
1280
- const byStatus = {};
1281
- const byPriority = {};
1282
- const byType = {};
1283
- for (const task of tasks) {
1284
- byStatus[task.status] = (byStatus[task.status] ?? 0) + 1;
1285
- byPriority[task.priority] = (byPriority[task.priority] ?? 0) + 1;
1286
- const taskType = task.type ?? 'task';
1287
- byType[taskType] = (byType[taskType] ?? 0) + 1;
1288
- }
1289
- return {
1290
- total: tasks.length,
1291
- pending: byStatus['pending'] ?? 0,
1292
- active: byStatus['active'] ?? 0,
1293
- blocked: byStatus['blocked'] ?? 0,
1294
- done: byStatus['done'] ?? 0,
1295
- cancelled: byStatus['cancelled'] ?? 0,
1296
- byPriority,
1297
- byType,
1298
- };
1299
- }
1300
- // ============================================================================
1301
- // taskExport
1302
- // ============================================================================
1303
- /**
1304
- * Export tasks as JSON or CSV.
1305
- *
1306
- * @param projectRoot - Absolute path to the CLEO project root directory
1307
- * @param params - Optional export configuration
1308
- * @param params.format - Output format: "json" (default) or "csv"
1309
- * @param params.status - Filter to only tasks with this status
1310
- * @param params.parent - Filter to tasks under this parent ID (recursive)
1311
- * @returns Export payload with format, content/tasks, and task count
1312
- *
1313
- * @remarks
1314
- * CSV output includes columns: id, title, status, priority, type, parentId, createdAt.
1315
- * JSON output returns the full task objects. Both formats support status and parent filtering.
1316
- *
1317
- * @example
1318
- * ```typescript
1319
- * const result = await coreTaskExport('/project', { format: 'csv', status: 'done' });
1320
- * console.log(result.content); // CSV string
1321
- * ```
1322
- *
1323
- * @task T4790
1324
- */
1325
- export async function coreTaskExport(projectRoot, params) {
1326
- const allTasks = await loadAllTasks(projectRoot);
1327
- let tasks = allTasks;
1328
- if (params?.status) {
1329
- tasks = tasks.filter((t) => t.status === params.status);
1330
- }
1331
- if (params?.parent) {
1332
- const parentIds = new Set();
1333
- parentIds.add(params.parent);
1334
- const collectChildren = (parentId) => {
1335
- for (const t of allTasks) {
1336
- if (t.parentId === parentId && !parentIds.has(t.id)) {
1337
- parentIds.add(t.id);
1338
- collectChildren(t.id);
1339
- }
1340
- }
1341
- };
1342
- collectChildren(params.parent);
1343
- tasks = tasks.filter((t) => parentIds.has(t.id));
1344
- }
1345
- if (params?.format === 'csv') {
1346
- const headers = ['id', 'title', 'status', 'priority', 'type', 'parentId', 'createdAt'];
1347
- const rows = tasks.map((t) => [
1348
- t.id,
1349
- `"${(t.title || '').replace(/"/g, '""')}"`,
1350
- t.status,
1351
- t.priority,
1352
- t.type ?? 'task',
1353
- t.parentId ?? '',
1354
- t.createdAt,
1355
- ].join(','));
1356
- const csv = [headers.join(','), ...rows].join('\n');
1357
- return { format: 'csv', content: csv, taskCount: tasks.length };
1358
- }
1359
- return { format: 'json', tasks, taskCount: tasks.length };
1360
- }
1361
- // ============================================================================
1362
- // taskHistory
1363
- // ============================================================================
1364
- /**
1365
- * Get task history from the audit log.
1366
- *
1367
- * @param projectRoot - Absolute path to the CLEO project root directory
1368
- * @param taskId - The task ID to retrieve history for
1369
- * @param limit - Maximum number of history entries to return (default: 100)
1370
- * @returns Array of audit log entries ordered by timestamp descending
1371
- *
1372
- * @remarks
1373
- * Queries the SQLite audit_log table for all operations on the given task.
1374
- * Returns an empty array if the database is unavailable or no entries exist.
1375
- *
1376
- * @example
1377
- * ```typescript
1378
- * const history = await coreTaskHistory('/project', 'T042', 10);
1379
- * for (const entry of history) console.log(entry.timestamp, entry.operation);
1380
- * ```
1381
- *
1382
- * @task T4790
1383
- */
1384
- export async function coreTaskHistory(projectRoot, taskId, limit) {
1385
- try {
1386
- const { getDb } = await import('../store/sqlite.js');
1387
- const { auditLog } = await import('../store/tasks-schema.js');
1388
- const { sql } = await import('drizzle-orm');
1389
- const db = await getDb(projectRoot);
1390
- const maxRows = limit && limit > 0 ? limit : 100;
1391
- const rows = await db.all(sql `SELECT * FROM ${auditLog}
1392
- WHERE ${auditLog.taskId} = ${taskId}
1393
- ORDER BY ${auditLog.timestamp} DESC
1394
- LIMIT ${maxRows}`);
1395
- return rows.map((row) => ({
1396
- id: row.id,
1397
- timestamp: row.timestamp,
1398
- operation: row.operation ?? row.action,
1399
- action: row.action,
1400
- taskId: row.task_id,
1401
- actor: row.actor,
1402
- details: row.details_json ? JSON.parse(row.details_json) : {},
1403
- before: row.before_json ? JSON.parse(row.before_json) : undefined,
1404
- after: row.after_json ? JSON.parse(row.after_json) : undefined,
1405
- domain: row.domain,
1406
- sessionId: row.session_id,
1407
- requestId: row.request_id,
1408
- durationMs: row.duration_ms,
1409
- success: row.success === null ? undefined : row.success === 1,
1410
- source: row.source,
1411
- gateway: row.gateway,
1412
- error: row.error_message,
1413
- }));
1414
- }
1415
- catch {
1416
- return [];
1417
- }
1418
- }
1419
- // ============================================================================
1420
- // taskLint
1421
- // ============================================================================
1422
- /**
1423
- * Lint tasks for common issues.
1424
- *
1425
- * @param projectRoot - Absolute path to the CLEO project root directory
1426
- * @param taskId - Optional task ID to lint; omit to lint all tasks
1427
- * @returns Array of lint issues with severity, rule name, and descriptive message
1428
- *
1429
- * @remarks
1430
- * Checks for: duplicate IDs, missing titles, missing descriptions, identical
1431
- * title/description, duplicate descriptions, invalid statuses, future timestamps,
1432
- * invalid parent references, and invalid dependency references.
1433
- *
1434
- * @example
1435
- * ```typescript
1436
- * const issues = await coreTaskLint('/project');
1437
- * const errors = issues.filter(i => i.severity === 'error');
1438
- * console.log(`${errors.length} errors found`);
1439
- * ```
1440
- *
1441
- * @task T4790
1442
- */
1443
- export async function coreTaskLint(projectRoot, taskId) {
1444
- const allTasks = await loadAllTasks(projectRoot);
1445
- const tasks = taskId ? allTasks.filter((t) => t.id === taskId) : allTasks;
1446
- if (taskId && tasks.length === 0) {
1447
- throw new Error(`Task '${taskId}' not found`);
1448
- }
1449
- const issues = [];
1450
- const allDescriptions = new Set();
1451
- const allIds = new Set();
1452
- for (const task of allTasks) {
1453
- if (allIds.has(task.id)) {
1454
- issues.push({
1455
- taskId: task.id,
1456
- severity: 'error',
1457
- rule: 'unique-id',
1458
- message: `Duplicate task ID: ${task.id}`,
1459
- });
1460
- }
1461
- allIds.add(task.id);
1462
- if (taskId && task.id !== taskId) {
1463
- if (task.description)
1464
- allDescriptions.add(task.description.toLowerCase());
1465
- continue;
1466
- }
1467
- if (!task.title || task.title.trim().length === 0) {
1468
- issues.push({
1469
- taskId: task.id,
1470
- severity: 'error',
1471
- rule: 'title-required',
1472
- message: 'Task is missing a title',
1473
- });
1474
- }
1475
- if (!task.description || task.description.trim().length === 0) {
1476
- issues.push({
1477
- taskId: task.id,
1478
- severity: 'warning',
1479
- rule: 'description-required',
1480
- message: 'Task is missing a description',
1481
- });
1482
- }
1483
- if (task.title && task.description && task.title.trim() === task.description.trim()) {
1484
- issues.push({
1485
- taskId: task.id,
1486
- severity: 'warning',
1487
- rule: 'title-description-different',
1488
- message: 'Title and description should not be identical',
1489
- });
1490
- }
1491
- if (task.description) {
1492
- const descLower = task.description.toLowerCase();
1493
- if (allDescriptions.has(descLower)) {
1494
- issues.push({
1495
- taskId: task.id,
1496
- severity: 'warning',
1497
- rule: 'unique-description',
1498
- message: 'Duplicate task description found',
1499
- });
1500
- }
1501
- allDescriptions.add(descLower);
1502
- }
1503
- if (!TASK_STATUSES.includes(task.status)) {
1504
- issues.push({
1505
- taskId: task.id,
1506
- severity: 'error',
1507
- rule: 'valid-status',
1508
- message: `Invalid status: ${task.status}`,
1509
- });
1510
- }
1511
- const now = new Date();
1512
- if (task.createdAt && new Date(task.createdAt) > now) {
1513
- issues.push({
1514
- taskId: task.id,
1515
- severity: 'warning',
1516
- rule: 'no-future-timestamps',
1517
- message: 'createdAt is in the future',
1518
- });
1519
- }
1520
- if (task.parentId && !allTasks.some((t) => t.id === task.parentId)) {
1521
- issues.push({
1522
- taskId: task.id,
1523
- severity: 'error',
1524
- rule: 'valid-parent',
1525
- message: `Parent task '${task.parentId}' does not exist`,
1526
- });
1527
- }
1528
- for (const depId of task.depends ?? []) {
1529
- if (!allTasks.some((t) => t.id === depId)) {
1530
- issues.push({
1531
- taskId: task.id,
1532
- severity: 'warning',
1533
- rule: 'valid-dependency',
1534
- message: `Dependency '${depId}' does not exist`,
1535
- });
1536
- }
1537
- }
1538
- }
1539
- return issues;
1540
- }
1541
- // ============================================================================
1542
- // taskBatchValidate
1543
- // ============================================================================
1544
- /**
1545
- * Validate multiple tasks at once.
1546
- *
1547
- * @param projectRoot - Absolute path to the CLEO project root directory
1548
- * @param taskIds - Array of task IDs to validate
1549
- * @param checkMode - Validation depth: "full" runs all checks, "quick" checks only title/description/status
1550
- * @returns Per-task validation results and an aggregate summary with error/warning counts
1551
- *
1552
- * @remarks
1553
- * In "full" mode, additional checks include title-description equality, parent existence,
1554
- * dependency existence, and future timestamp detection. Tasks that are not found are
1555
- * reported as errors.
1556
- *
1557
- * @example
1558
- * ```typescript
1559
- * const { summary } = await coreTaskBatchValidate('/project', ['T001', 'T002'], 'full');
1560
- * console.log(`${summary.validTasks}/${summary.totalTasks} valid`);
1561
- * ```
1562
- *
1563
- * @task T4790
1564
- */
1565
- export async function coreTaskBatchValidate(projectRoot, taskIds, checkMode = 'full') {
1566
- const allTasks = await loadAllTasks(projectRoot);
1567
- const results = {};
1568
- let totalErrors = 0;
1569
- let totalWarnings = 0;
1570
- for (const id of taskIds) {
1571
- const task = allTasks.find((t) => t.id === id);
1572
- if (!task) {
1573
- results[id] = [{ severity: 'error', rule: 'exists', message: `Task '${id}' not found` }];
1574
- totalErrors++;
1575
- continue;
1576
- }
1577
- const taskIssues = [];
1578
- if (!task.title || task.title.trim().length === 0) {
1579
- taskIssues.push({ severity: 'error', rule: 'title-required', message: 'Missing title' });
1580
- }
1581
- if (!task.description || task.description.trim().length === 0) {
1582
- taskIssues.push({
1583
- severity: 'warning',
1584
- rule: 'description-required',
1585
- message: 'Missing description',
1586
- });
1587
- }
1588
- if (!TASK_STATUSES.includes(task.status)) {
1589
- taskIssues.push({
1590
- severity: 'error',
1591
- rule: 'valid-status',
1592
- message: `Invalid status: ${task.status}`,
1593
- });
1594
- }
1595
- if (checkMode === 'full') {
1596
- if (task.title && task.description && task.title.trim() === task.description.trim()) {
1597
- taskIssues.push({
1598
- severity: 'warning',
1599
- rule: 'title-description-different',
1600
- message: 'Title equals description',
1601
- });
1602
- }
1603
- if (task.parentId && !allTasks.some((t) => t.id === task.parentId)) {
1604
- taskIssues.push({
1605
- severity: 'error',
1606
- rule: 'valid-parent',
1607
- message: `Parent '${task.parentId}' not found`,
1608
- });
1609
- }
1610
- for (const depId of task.depends ?? []) {
1611
- if (!allTasks.some((t) => t.id === depId)) {
1612
- taskIssues.push({
1613
- severity: 'warning',
1614
- rule: 'valid-dependency',
1615
- message: `Dependency '${depId}' not found`,
1616
- });
1617
- }
1618
- }
1619
- const now = new Date();
1620
- if (task.createdAt && new Date(task.createdAt) > now) {
1621
- taskIssues.push({
1622
- severity: 'warning',
1623
- rule: 'no-future-timestamps',
1624
- message: 'createdAt in future',
1625
- });
1626
- }
1627
- }
1628
- results[id] = taskIssues;
1629
- totalErrors += taskIssues.filter((i) => i.severity === 'error').length;
1630
- totalWarnings += taskIssues.filter((i) => i.severity === 'warning').length;
1631
- }
1632
- const invalidTasks = Object.values(results).filter((issues) => issues.some((i) => i.severity === 'error')).length;
1633
- return {
1634
- results,
1635
- summary: {
1636
- totalTasks: taskIds.length,
1637
- validTasks: taskIds.length - invalidTasks,
1638
- invalidTasks,
1639
- totalIssues: totalErrors + totalWarnings,
1640
- errors: totalErrors,
1641
- warnings: totalWarnings,
1642
- },
1643
- };
1644
- }
1645
- // ============================================================================
1646
- // taskImport
1647
- // ============================================================================
1648
- /**
1649
- * Import tasks from a JSON source string.
1650
- *
1651
- * @param projectRoot - Absolute path to the CLEO project root directory
1652
- * @param source - JSON string containing an array of tasks or an object with a `tasks` array
1653
- * @param overwrite - When true, overwrites existing tasks with matching IDs; otherwise skips them
1654
- * @returns Import summary with counts of imported, skipped, errors, and optional ID remap table
1655
- *
1656
- * @remarks
1657
- * When a task ID collides with an existing one and overwrite is false, a new sequential
1658
- * ID is assigned and recorded in the remapTable. Tasks missing required id or title
1659
- * fields are skipped with an error message.
1660
- *
1661
- * @example
1662
- * ```typescript
1663
- * const json = JSON.stringify([{ id: 'T500', title: 'New task', status: 'pending', priority: 'medium' }]);
1664
- * const result = await coreTaskImport('/project', json, false);
1665
- * console.log(`Imported ${result.imported}, skipped ${result.skipped}`);
1666
- * ```
1667
- *
1668
- * @task T4790
1669
- */
1670
- export async function coreTaskImport(projectRoot, source, overwrite) {
1671
- const accessor = await getAccessor(projectRoot);
1672
- // Load all existing task IDs using queryTasks (bulk operation needs full ID set)
1673
- const { tasks: existingTasks } = await accessor.queryTasks({});
1674
- let importData;
1675
- try {
1676
- importData = JSON.parse(source);
1677
- }
1678
- catch {
1679
- throw new Error('Invalid JSON in import source');
1680
- }
1681
- let importTasks = [];
1682
- if (Array.isArray(importData)) {
1683
- importTasks = importData;
1684
- }
1685
- else if (typeof importData === 'object' && importData !== null) {
1686
- const data = importData;
1687
- if (Array.isArray(data.tasks)) {
1688
- importTasks = data.tasks;
1689
- }
1690
- }
1691
- if (importTasks.length === 0) {
1692
- return { imported: 0, skipped: 0, errors: ['No tasks found in import source'] };
1693
- }
1694
- const existingIds = new Set(existingTasks.map((t) => t.id));
1695
- const allIds = new Set(existingTasks.map((t) => t.id));
1696
- const errors = [];
1697
- let imported = 0;
1698
- let skipped = 0;
1699
- const remapTable = {};
1700
- let nextIdNum = 0;
1701
- for (const t of existingTasks) {
1702
- const num = parseInt(t.id.replace('T', ''), 10);
1703
- if (!Number.isNaN(num) && num > nextIdNum)
1704
- nextIdNum = num;
1705
- }
1706
- for (const importTask of importTasks) {
1707
- if (!importTask.id || !importTask.title) {
1708
- errors.push(`Skipped task with missing id or title`);
1709
- skipped++;
1710
- continue;
1711
- }
1712
- if (existingIds.has(importTask.id) && !overwrite) {
1713
- skipped++;
1714
- continue;
1715
- }
1716
- let newId = importTask.id;
1717
- if (allIds.has(importTask.id) && !overwrite) {
1718
- nextIdNum++;
1719
- newId = `T${String(nextIdNum).padStart(3, '0')}`;
1720
- remapTable[importTask.id] = newId;
1721
- }
1722
- const now = new Date().toISOString();
1723
- const newTask = {
1724
- ...importTask,
1725
- id: newId,
1726
- createdAt: importTask.createdAt || now,
1727
- updatedAt: now,
1728
- };
1729
- // Use targeted upsert per task instead of bulk saveTaskFile
1730
- await accessor.upsertSingleTask(newTask);
1731
- allIds.add(newId);
1732
- imported++;
1733
- }
1734
- return {
1735
- imported,
1736
- skipped,
1737
- errors,
1738
- ...(Object.keys(remapTable).length > 0 ? { remapTable } : {}),
1739
- };
1740
- }
1741
- //# sourceMappingURL=task-ops.js.map