@cleocode/core 2026.4.12 → 2026.4.14

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 (924) hide show
  1. package/dist/index.js +69233 -175
  2. package/dist/index.js.map +7 -1
  3. package/dist/init.d.ts.map +1 -1
  4. package/dist/internal.d.ts +16 -5
  5. package/dist/internal.d.ts.map +1 -1
  6. package/dist/memory/brain-embedding.d.ts +1 -1
  7. package/dist/memory/embedding-local.d.ts +8 -3
  8. package/dist/memory/embedding-local.d.ts.map +1 -1
  9. package/dist/memory/embedding-worker.d.ts +1 -1
  10. package/dist/memory/learnings.d.ts +2 -2
  11. package/dist/memory/patterns.d.ts +6 -6
  12. package/dist/store/agent-registry-accessor.d.ts +54 -1
  13. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  14. package/dist/store/backup-crypto.d.ts +89 -0
  15. package/dist/store/backup-crypto.d.ts.map +1 -0
  16. package/dist/store/backup-pack.d.ts +91 -0
  17. package/dist/store/backup-pack.d.ts.map +1 -0
  18. package/dist/store/backup-unpack.d.ts +140 -0
  19. package/dist/store/backup-unpack.d.ts.map +1 -0
  20. package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -1
  21. package/dist/store/regenerators.d.ts +126 -0
  22. package/dist/store/regenerators.d.ts.map +1 -0
  23. package/dist/store/restore-conflict-report.d.ts +118 -0
  24. package/dist/store/restore-conflict-report.d.ts.map +1 -0
  25. package/dist/store/restore-json-merge.d.ts +187 -0
  26. package/dist/store/restore-json-merge.d.ts.map +1 -0
  27. package/dist/store/sqlite-backup.d.ts +60 -5
  28. package/dist/store/sqlite-backup.d.ts.map +1 -1
  29. package/dist/store/t310-readiness.d.ts +83 -0
  30. package/dist/store/t310-readiness.d.ts.map +1 -0
  31. package/package.json +11 -9
  32. package/src/__tests__/cli-parity.test.ts +19 -14
  33. package/src/__tests__/human-output.test.ts +13 -11
  34. package/src/init.ts +18 -8
  35. package/src/internal.ts +52 -2
  36. package/src/memory/__tests__/brain-automation.test.ts +2 -2
  37. package/src/memory/brain-embedding.ts +1 -1
  38. package/src/memory/embedding-local.ts +10 -5
  39. package/src/memory/embedding-worker.ts +1 -1
  40. package/src/skills/__tests__/discovery.test.ts +22 -7
  41. package/src/store/__tests__/backup-crypto.test.ts +101 -0
  42. package/src/store/__tests__/backup-pack.test.ts +491 -0
  43. package/src/store/__tests__/backup-unpack.test.ts +298 -0
  44. package/src/store/__tests__/performance-safety.test.ts +11 -5
  45. package/src/store/__tests__/regenerators.test.ts +234 -0
  46. package/src/store/__tests__/restore-conflict-report.test.ts +274 -0
  47. package/src/store/__tests__/restore-json-merge.test.ts +521 -0
  48. package/src/store/__tests__/t310-readiness.test.ts +111 -0
  49. package/src/store/__tests__/t311-integration.test.ts +661 -0
  50. package/src/store/backup-crypto.ts +209 -0
  51. package/src/store/backup-pack.ts +739 -0
  52. package/src/store/backup-unpack.ts +583 -0
  53. package/src/store/migrate-signaldock-to-conduit.ts +14 -7
  54. package/src/store/regenerators.ts +243 -0
  55. package/src/store/restore-conflict-report.ts +317 -0
  56. package/src/store/restore-json-merge.ts +653 -0
  57. package/src/store/t310-readiness.ts +119 -0
  58. package/src/validation/protocols/_shared.ts +1 -1
  59. package/dist/adapters/adapter-registry.js +0 -64
  60. package/dist/adapters/adapter-registry.js.map +0 -1
  61. package/dist/adapters/discovery.js +0 -83
  62. package/dist/adapters/discovery.js.map +0 -1
  63. package/dist/adapters/index.js +0 -9
  64. package/dist/adapters/index.js.map +0 -1
  65. package/dist/adapters/manager.js +0 -260
  66. package/dist/adapters/manager.js.map +0 -1
  67. package/dist/admin/export-tasks.js +0 -171
  68. package/dist/admin/export-tasks.js.map +0 -1
  69. package/dist/admin/export.js +0 -103
  70. package/dist/admin/export.js.map +0 -1
  71. package/dist/admin/help.js +0 -106
  72. package/dist/admin/help.js.map +0 -1
  73. package/dist/admin/import-tasks.js +0 -182
  74. package/dist/admin/import-tasks.js.map +0 -1
  75. package/dist/admin/import.js +0 -129
  76. package/dist/admin/import.js.map +0 -1
  77. package/dist/admin/index.js +0 -13
  78. package/dist/admin/index.js.map +0 -1
  79. package/dist/adrs/find.js +0 -134
  80. package/dist/adrs/find.js.map +0 -1
  81. package/dist/adrs/index.js +0 -15
  82. package/dist/adrs/index.js.map +0 -1
  83. package/dist/adrs/link-pipeline.js +0 -160
  84. package/dist/adrs/link-pipeline.js.map +0 -1
  85. package/dist/adrs/list.js +0 -43
  86. package/dist/adrs/list.js.map +0 -1
  87. package/dist/adrs/parse.js +0 -51
  88. package/dist/adrs/parse.js.map +0 -1
  89. package/dist/adrs/show.js +0 -22
  90. package/dist/adrs/show.js.map +0 -1
  91. package/dist/adrs/sync.js +0 -188
  92. package/dist/adrs/sync.js.map +0 -1
  93. package/dist/adrs/types.js +0 -9
  94. package/dist/adrs/types.js.map +0 -1
  95. package/dist/adrs/validate.js +0 -57
  96. package/dist/adrs/validate.js.map +0 -1
  97. package/dist/agents/agent-registry.js +0 -288
  98. package/dist/agents/agent-registry.js.map +0 -1
  99. package/dist/agents/agent-schema.js +0 -82
  100. package/dist/agents/agent-schema.js.map +0 -1
  101. package/dist/agents/capacity.js +0 -116
  102. package/dist/agents/capacity.js.map +0 -1
  103. package/dist/agents/execution-learning.js +0 -474
  104. package/dist/agents/execution-learning.js.map +0 -1
  105. package/dist/agents/health-monitor.js +0 -217
  106. package/dist/agents/health-monitor.js.map +0 -1
  107. package/dist/agents/index.js +0 -29
  108. package/dist/agents/index.js.map +0 -1
  109. package/dist/agents/registry.js +0 -314
  110. package/dist/agents/registry.js.map +0 -1
  111. package/dist/agents/retry.js +0 -215
  112. package/dist/agents/retry.js.map +0 -1
  113. package/dist/audit-prune.js +0 -94
  114. package/dist/audit-prune.js.map +0 -1
  115. package/dist/audit.js +0 -68
  116. package/dist/audit.js.map +0 -1
  117. package/dist/backfill/index.js +0 -229
  118. package/dist/backfill/index.js.map +0 -1
  119. package/dist/bootstrap.js +0 -344
  120. package/dist/bootstrap.js.map +0 -1
  121. package/dist/caamp/adapter.js +0 -259
  122. package/dist/caamp/adapter.js.map +0 -1
  123. package/dist/caamp/capability-check.js +0 -38
  124. package/dist/caamp/capability-check.js.map +0 -1
  125. package/dist/caamp/index.js +0 -21
  126. package/dist/caamp/index.js.map +0 -1
  127. package/dist/caamp-init.js +0 -16
  128. package/dist/caamp-init.js.map +0 -1
  129. package/dist/cleo.js +0 -322
  130. package/dist/cleo.js.map +0 -1
  131. package/dist/code/index.js +0 -10
  132. package/dist/code/index.js.map +0 -1
  133. package/dist/code/outline.js +0 -165
  134. package/dist/code/outline.js.map +0 -1
  135. package/dist/code/parser.js +0 -295
  136. package/dist/code/parser.js.map +0 -1
  137. package/dist/code/search.js +0 -135
  138. package/dist/code/search.js.map +0 -1
  139. package/dist/code/unfold.js +0 -155
  140. package/dist/code/unfold.js.map +0 -1
  141. package/dist/codebase-map/analyzers/architecture.js +0 -129
  142. package/dist/codebase-map/analyzers/architecture.js.map +0 -1
  143. package/dist/codebase-map/analyzers/concerns.js +0 -122
  144. package/dist/codebase-map/analyzers/concerns.js.map +0 -1
  145. package/dist/codebase-map/analyzers/conventions.js +0 -149
  146. package/dist/codebase-map/analyzers/conventions.js.map +0 -1
  147. package/dist/codebase-map/analyzers/integrations.js +0 -108
  148. package/dist/codebase-map/analyzers/integrations.js.map +0 -1
  149. package/dist/codebase-map/analyzers/stack.js +0 -117
  150. package/dist/codebase-map/analyzers/stack.js.map +0 -1
  151. package/dist/codebase-map/analyzers/structure.js +0 -137
  152. package/dist/codebase-map/analyzers/structure.js.map +0 -1
  153. package/dist/codebase-map/analyzers/testing.js +0 -118
  154. package/dist/codebase-map/analyzers/testing.js.map +0 -1
  155. package/dist/codebase-map/index.js +0 -57
  156. package/dist/codebase-map/index.js.map +0 -1
  157. package/dist/codebase-map/store.js +0 -122
  158. package/dist/codebase-map/store.js.map +0 -1
  159. package/dist/codebase-map/summary.js +0 -152
  160. package/dist/codebase-map/summary.js.map +0 -1
  161. package/dist/compliance/index.js +0 -288
  162. package/dist/compliance/index.js.map +0 -1
  163. package/dist/compliance/protocol-enforcement.js +0 -332
  164. package/dist/compliance/protocol-enforcement.js.map +0 -1
  165. package/dist/compliance/protocol-rules.js +0 -786
  166. package/dist/compliance/protocol-rules.js.map +0 -1
  167. package/dist/compliance/protocol-types.js +0 -79
  168. package/dist/compliance/protocol-types.js.map +0 -1
  169. package/dist/compliance/store.js +0 -53
  170. package/dist/compliance/store.js.map +0 -1
  171. package/dist/conduit/conduit-client.js +0 -107
  172. package/dist/conduit/conduit-client.js.map +0 -1
  173. package/dist/conduit/factory.js +0 -52
  174. package/dist/conduit/factory.js.map +0 -1
  175. package/dist/conduit/http-transport.js +0 -155
  176. package/dist/conduit/http-transport.js.map +0 -1
  177. package/dist/conduit/index.js +0 -15
  178. package/dist/conduit/index.js.map +0 -1
  179. package/dist/conduit/local-transport.js +0 -255
  180. package/dist/conduit/local-transport.js.map +0 -1
  181. package/dist/conduit/sse-transport.js +0 -299
  182. package/dist/conduit/sse-transport.js.map +0 -1
  183. package/dist/config/build-config.js +0 -29
  184. package/dist/config/build-config.js.map +0 -1
  185. package/dist/config.js +0 -400
  186. package/dist/config.js.map +0 -1
  187. package/dist/constants.js +0 -18
  188. package/dist/constants.js.map +0 -1
  189. package/dist/context/index.js +0 -137
  190. package/dist/context/index.js.map +0 -1
  191. package/dist/crypto/credentials.js +0 -191
  192. package/dist/crypto/credentials.js.map +0 -1
  193. package/dist/discovery.js +0 -182
  194. package/dist/discovery.js.map +0 -1
  195. package/dist/engine-result.js +0 -12
  196. package/dist/engine-result.js.map +0 -1
  197. package/dist/error-catalog.js +0 -404
  198. package/dist/error-catalog.js.map +0 -1
  199. package/dist/error-registry.js +0 -393
  200. package/dist/error-registry.js.map +0 -1
  201. package/dist/errors.js +0 -173
  202. package/dist/errors.js.map +0 -1
  203. package/dist/hooks/handlers/agent-hooks.js +0 -106
  204. package/dist/hooks/handlers/agent-hooks.js.map +0 -1
  205. package/dist/hooks/handlers/context-hooks.js +0 -111
  206. package/dist/hooks/handlers/context-hooks.js.map +0 -1
  207. package/dist/hooks/handlers/error-hooks.js +0 -52
  208. package/dist/hooks/handlers/error-hooks.js.map +0 -1
  209. package/dist/hooks/handlers/file-hooks.js +0 -104
  210. package/dist/hooks/handlers/file-hooks.js.map +0 -1
  211. package/dist/hooks/handlers/handler-helpers.js +0 -61
  212. package/dist/hooks/handlers/handler-helpers.js.map +0 -1
  213. package/dist/hooks/handlers/index.js +0 -28
  214. package/dist/hooks/handlers/index.js.map +0 -1
  215. package/dist/hooks/handlers/memory-bridge-refresh.js +0 -42
  216. package/dist/hooks/handlers/memory-bridge-refresh.js.map +0 -1
  217. package/dist/hooks/handlers/notification-hooks.js +0 -62
  218. package/dist/hooks/handlers/notification-hooks.js.map +0 -1
  219. package/dist/hooks/handlers/session-hooks.js +0 -142
  220. package/dist/hooks/handlers/session-hooks.js.map +0 -1
  221. package/dist/hooks/handlers/task-hooks.js +0 -65
  222. package/dist/hooks/handlers/task-hooks.js.map +0 -1
  223. package/dist/hooks/handlers/work-capture-hooks.js +0 -165
  224. package/dist/hooks/handlers/work-capture-hooks.js.map +0 -1
  225. package/dist/hooks/index.js +0 -13
  226. package/dist/hooks/index.js.map +0 -1
  227. package/dist/hooks/payload-schemas.js +0 -220
  228. package/dist/hooks/payload-schemas.js.map +0 -1
  229. package/dist/hooks/provider-hooks.js +0 -66
  230. package/dist/hooks/provider-hooks.js.map +0 -1
  231. package/dist/hooks/registry.js +0 -229
  232. package/dist/hooks/registry.js.map +0 -1
  233. package/dist/hooks/types.js +0 -66
  234. package/dist/hooks/types.js.map +0 -1
  235. package/dist/hooks.js +0 -136
  236. package/dist/hooks.js.map +0 -1
  237. package/dist/init.js +0 -851
  238. package/dist/init.js.map +0 -1
  239. package/dist/inject/index.js +0 -82
  240. package/dist/inject/index.js.map +0 -1
  241. package/dist/injection.js +0 -343
  242. package/dist/injection.js.map +0 -1
  243. package/dist/intelligence/adaptive-validation.js +0 -497
  244. package/dist/intelligence/adaptive-validation.js.map +0 -1
  245. package/dist/intelligence/impact.js +0 -675
  246. package/dist/intelligence/impact.js.map +0 -1
  247. package/dist/intelligence/index.js +0 -22
  248. package/dist/intelligence/index.js.map +0 -1
  249. package/dist/intelligence/patterns.js +0 -492
  250. package/dist/intelligence/patterns.js.map +0 -1
  251. package/dist/intelligence/prediction.js +0 -499
  252. package/dist/intelligence/prediction.js.map +0 -1
  253. package/dist/intelligence/types.js +0 -13
  254. package/dist/intelligence/types.js.map +0 -1
  255. package/dist/internal.js +0 -306
  256. package/dist/internal.js.map +0 -1
  257. package/dist/issue/create.js +0 -121
  258. package/dist/issue/create.js.map +0 -1
  259. package/dist/issue/diagnostics.js +0 -59
  260. package/dist/issue/diagnostics.js.map +0 -1
  261. package/dist/issue/index.js +0 -10
  262. package/dist/issue/index.js.map +0 -1
  263. package/dist/issue/template-parser.js +0 -267
  264. package/dist/issue/template-parser.js.map +0 -1
  265. package/dist/json-schema-validator.js +0 -76
  266. package/dist/json-schema-validator.js.map +0 -1
  267. package/dist/lib/index.js +0 -11
  268. package/dist/lib/index.js.map +0 -1
  269. package/dist/lib/retry.js +0 -152
  270. package/dist/lib/retry.js.map +0 -1
  271. package/dist/lib/tree-sitter-languages.js +0 -71
  272. package/dist/lib/tree-sitter-languages.js.map +0 -1
  273. package/dist/lifecycle/chain-composition.js +0 -152
  274. package/dist/lifecycle/chain-composition.js.map +0 -1
  275. package/dist/lifecycle/chain-store.js +0 -246
  276. package/dist/lifecycle/chain-store.js.map +0 -1
  277. package/dist/lifecycle/consolidate-rcasd.js +0 -352
  278. package/dist/lifecycle/consolidate-rcasd.js.map +0 -1
  279. package/dist/lifecycle/default-chain.js +0 -176
  280. package/dist/lifecycle/default-chain.js.map +0 -1
  281. package/dist/lifecycle/evidence.js +0 -180
  282. package/dist/lifecycle/evidence.js.map +0 -1
  283. package/dist/lifecycle/frontmatter.js +0 -363
  284. package/dist/lifecycle/frontmatter.js.map +0 -1
  285. package/dist/lifecycle/index.js +0 -756
  286. package/dist/lifecycle/index.js.map +0 -1
  287. package/dist/lifecycle/pipeline.js +0 -656
  288. package/dist/lifecycle/pipeline.js.map +0 -1
  289. package/dist/lifecycle/rcasd-index.js +0 -326
  290. package/dist/lifecycle/rcasd-index.js.map +0 -1
  291. package/dist/lifecycle/rcasd-paths.js +0 -220
  292. package/dist/lifecycle/rcasd-paths.js.map +0 -1
  293. package/dist/lifecycle/resume.js +0 -864
  294. package/dist/lifecycle/resume.js.map +0 -1
  295. package/dist/lifecycle/stage-artifacts.js +0 -94
  296. package/dist/lifecycle/stage-artifacts.js.map +0 -1
  297. package/dist/lifecycle/stage-guidance.js +0 -234
  298. package/dist/lifecycle/stage-guidance.js.map +0 -1
  299. package/dist/lifecycle/stages.js +0 -534
  300. package/dist/lifecycle/stages.js.map +0 -1
  301. package/dist/lifecycle/state-machine.js +0 -516
  302. package/dist/lifecycle/state-machine.js.map +0 -1
  303. package/dist/lifecycle/tessera-engine.js +0 -249
  304. package/dist/lifecycle/tessera-engine.js.map +0 -1
  305. package/dist/logger.js +0 -140
  306. package/dist/logger.js.map +0 -1
  307. package/dist/memory/auto-extract.js +0 -177
  308. package/dist/memory/auto-extract.js.map +0 -1
  309. package/dist/memory/brain-embedding.js +0 -66
  310. package/dist/memory/brain-embedding.js.map +0 -1
  311. package/dist/memory/brain-lifecycle.js +0 -298
  312. package/dist/memory/brain-lifecycle.js.map +0 -1
  313. package/dist/memory/brain-links.js +0 -161
  314. package/dist/memory/brain-links.js.map +0 -1
  315. package/dist/memory/brain-maintenance.js +0 -114
  316. package/dist/memory/brain-maintenance.js.map +0 -1
  317. package/dist/memory/brain-migration.js +0 -149
  318. package/dist/memory/brain-migration.js.map +0 -1
  319. package/dist/memory/brain-reasoning.js +0 -215
  320. package/dist/memory/brain-reasoning.js.map +0 -1
  321. package/dist/memory/brain-retrieval.js +0 -542
  322. package/dist/memory/brain-retrieval.js.map +0 -1
  323. package/dist/memory/brain-row-types.js +0 -10
  324. package/dist/memory/brain-row-types.js.map +0 -1
  325. package/dist/memory/brain-search.js +0 -519
  326. package/dist/memory/brain-search.js.map +0 -1
  327. package/dist/memory/brain-similarity.js +0 -145
  328. package/dist/memory/brain-similarity.js.map +0 -1
  329. package/dist/memory/claude-mem-migration.js +0 -277
  330. package/dist/memory/claude-mem-migration.js.map +0 -1
  331. package/dist/memory/decisions.js +0 -162
  332. package/dist/memory/decisions.js.map +0 -1
  333. package/dist/memory/embedding-local.js +0 -97
  334. package/dist/memory/embedding-local.js.map +0 -1
  335. package/dist/memory/embedding-queue.js +0 -271
  336. package/dist/memory/embedding-queue.js.map +0 -1
  337. package/dist/memory/embedding-worker.js +0 -58
  338. package/dist/memory/embedding-worker.js.map +0 -1
  339. package/dist/memory/engine-compat.js +0 -1397
  340. package/dist/memory/engine-compat.js.map +0 -1
  341. package/dist/memory/index.js +0 -1140
  342. package/dist/memory/index.js.map +0 -1
  343. package/dist/memory/learnings.js +0 -121
  344. package/dist/memory/learnings.js.map +0 -1
  345. package/dist/memory/memory-bridge.js +0 -370
  346. package/dist/memory/memory-bridge.js.map +0 -1
  347. package/dist/memory/patterns.js +0 -122
  348. package/dist/memory/patterns.js.map +0 -1
  349. package/dist/memory/pipeline-manifest-sqlite.js +0 -975
  350. package/dist/memory/pipeline-manifest-sqlite.js.map +0 -1
  351. package/dist/memory/session-memory.js +0 -331
  352. package/dist/memory/session-memory.js.map +0 -1
  353. package/dist/metrics/ab-test.js +0 -260
  354. package/dist/metrics/ab-test.js.map +0 -1
  355. package/dist/metrics/aggregation.js +0 -363
  356. package/dist/metrics/aggregation.js.map +0 -1
  357. package/dist/metrics/common.js +0 -64
  358. package/dist/metrics/common.js.map +0 -1
  359. package/dist/metrics/enums.js +0 -78
  360. package/dist/metrics/enums.js.map +0 -1
  361. package/dist/metrics/index.js +0 -19
  362. package/dist/metrics/index.js.map +0 -1
  363. package/dist/metrics/model-provider-registry.js +0 -88
  364. package/dist/metrics/model-provider-registry.js.map +0 -1
  365. package/dist/metrics/otel-integration.js +0 -263
  366. package/dist/metrics/otel-integration.js.map +0 -1
  367. package/dist/metrics/provider-detection.js +0 -103
  368. package/dist/metrics/provider-detection.js.map +0 -1
  369. package/dist/metrics/token-estimation.js +0 -253
  370. package/dist/metrics/token-estimation.js.map +0 -1
  371. package/dist/metrics/token-service.js +0 -450
  372. package/dist/metrics/token-service.js.map +0 -1
  373. package/dist/migration/agent-outputs.js +0 -316
  374. package/dist/migration/agent-outputs.js.map +0 -1
  375. package/dist/migration/checksum.js +0 -92
  376. package/dist/migration/checksum.js.map +0 -1
  377. package/dist/migration/index.js +0 -282
  378. package/dist/migration/index.js.map +0 -1
  379. package/dist/migration/logger.js +0 -360
  380. package/dist/migration/logger.js.map +0 -1
  381. package/dist/migration/preflight.js +0 -9
  382. package/dist/migration/preflight.js.map +0 -1
  383. package/dist/migration/state.js +0 -421
  384. package/dist/migration/state.js.map +0 -1
  385. package/dist/migration/validate.js +0 -241
  386. package/dist/migration/validate.js.map +0 -1
  387. package/dist/mvi-helpers.js +0 -74
  388. package/dist/mvi-helpers.js.map +0 -1
  389. package/dist/nexus/deps.js +0 -375
  390. package/dist/nexus/deps.js.map +0 -1
  391. package/dist/nexus/discover.js +0 -288
  392. package/dist/nexus/discover.js.map +0 -1
  393. package/dist/nexus/hash.js +0 -10
  394. package/dist/nexus/hash.js.map +0 -1
  395. package/dist/nexus/index.js +0 -40
  396. package/dist/nexus/index.js.map +0 -1
  397. package/dist/nexus/migrate-json-to-sqlite.js +0 -115
  398. package/dist/nexus/migrate-json-to-sqlite.js.map +0 -1
  399. package/dist/nexus/permissions.js +0 -105
  400. package/dist/nexus/permissions.js.map +0 -1
  401. package/dist/nexus/query.js +0 -175
  402. package/dist/nexus/query.js.map +0 -1
  403. package/dist/nexus/registry.js +0 -584
  404. package/dist/nexus/registry.js.map +0 -1
  405. package/dist/nexus/sharing/index.js +0 -288
  406. package/dist/nexus/sharing/index.js.map +0 -1
  407. package/dist/nexus/transfer-types.js +0 -8
  408. package/dist/nexus/transfer-types.js.map +0 -1
  409. package/dist/nexus/transfer.js +0 -263
  410. package/dist/nexus/transfer.js.map +0 -1
  411. package/dist/nexus/workspace.js +0 -355
  412. package/dist/nexus/workspace.js.map +0 -1
  413. package/dist/observability/index.js +0 -103
  414. package/dist/observability/index.js.map +0 -1
  415. package/dist/observability/log-filter.js +0 -63
  416. package/dist/observability/log-filter.js.map +0 -1
  417. package/dist/observability/log-parser.js +0 -99
  418. package/dist/observability/log-parser.js.map +0 -1
  419. package/dist/observability/log-reader.js +0 -139
  420. package/dist/observability/log-reader.js.map +0 -1
  421. package/dist/observability/types.js +0 -19
  422. package/dist/observability/types.js.map +0 -1
  423. package/dist/orchestration/analyze.js +0 -107
  424. package/dist/orchestration/analyze.js.map +0 -1
  425. package/dist/orchestration/bootstrap.js +0 -132
  426. package/dist/orchestration/bootstrap.js.map +0 -1
  427. package/dist/orchestration/context.js +0 -56
  428. package/dist/orchestration/context.js.map +0 -1
  429. package/dist/orchestration/critical-path.js +0 -100
  430. package/dist/orchestration/critical-path.js.map +0 -1
  431. package/dist/orchestration/hierarchy.js +0 -183
  432. package/dist/orchestration/hierarchy.js.map +0 -1
  433. package/dist/orchestration/index.js +0 -287
  434. package/dist/orchestration/index.js.map +0 -1
  435. package/dist/orchestration/parallel.js +0 -89
  436. package/dist/orchestration/parallel.js.map +0 -1
  437. package/dist/orchestration/protocol-validators.js +0 -815
  438. package/dist/orchestration/protocol-validators.js.map +0 -1
  439. package/dist/orchestration/skill-ops.js +0 -98
  440. package/dist/orchestration/skill-ops.js.map +0 -1
  441. package/dist/orchestration/status.js +0 -107
  442. package/dist/orchestration/status.js.map +0 -1
  443. package/dist/orchestration/unblock.js +0 -103
  444. package/dist/orchestration/unblock.js.map +0 -1
  445. package/dist/orchestration/validate-spawn.js +0 -67
  446. package/dist/orchestration/validate-spawn.js.map +0 -1
  447. package/dist/orchestration/waves.js +0 -86
  448. package/dist/orchestration/waves.js.map +0 -1
  449. package/dist/otel/index.js +0 -163
  450. package/dist/otel/index.js.map +0 -1
  451. package/dist/output.js +0 -164
  452. package/dist/output.js.map +0 -1
  453. package/dist/pagination.js +0 -64
  454. package/dist/pagination.js.map +0 -1
  455. package/dist/paths.js +0 -842
  456. package/dist/paths.js.map +0 -1
  457. package/dist/phases/deps.js +0 -372
  458. package/dist/phases/deps.js.map +0 -1
  459. package/dist/phases/index.js +0 -349
  460. package/dist/phases/index.js.map +0 -1
  461. package/dist/pipeline/index.js +0 -10
  462. package/dist/pipeline/index.js.map +0 -1
  463. package/dist/pipeline/phase.js +0 -45
  464. package/dist/pipeline/phase.js.map +0 -1
  465. package/dist/platform.js +0 -211
  466. package/dist/platform.js.map +0 -1
  467. package/dist/project-info.js +0 -84
  468. package/dist/project-info.js.map +0 -1
  469. package/dist/reconciliation/index.js +0 -10
  470. package/dist/reconciliation/index.js.map +0 -1
  471. package/dist/reconciliation/link-store.js +0 -129
  472. package/dist/reconciliation/link-store.js.map +0 -1
  473. package/dist/reconciliation/reconciliation-engine.js +0 -298
  474. package/dist/reconciliation/reconciliation-engine.js.map +0 -1
  475. package/dist/release/artifacts.js +0 -427
  476. package/dist/release/artifacts.js.map +0 -1
  477. package/dist/release/changelog-writer.js +0 -151
  478. package/dist/release/changelog-writer.js.map +0 -1
  479. package/dist/release/channel.js +0 -144
  480. package/dist/release/channel.js.map +0 -1
  481. package/dist/release/ci.js +0 -166
  482. package/dist/release/ci.js.map +0 -1
  483. package/dist/release/github-pr.js +0 -225
  484. package/dist/release/github-pr.js.map +0 -1
  485. package/dist/release/guards.js +0 -116
  486. package/dist/release/guards.js.map +0 -1
  487. package/dist/release/index.js +0 -22
  488. package/dist/release/index.js.map +0 -1
  489. package/dist/release/release-config.js +0 -158
  490. package/dist/release/release-config.js.map +0 -1
  491. package/dist/release/release-manifest.js +0 -1019
  492. package/dist/release/release-manifest.js.map +0 -1
  493. package/dist/release/version-bump.js +0 -255
  494. package/dist/release/version-bump.js.map +0 -1
  495. package/dist/remote/index.js +0 -257
  496. package/dist/remote/index.js.map +0 -1
  497. package/dist/repair.js +0 -130
  498. package/dist/repair.js.map +0 -1
  499. package/dist/research/index.js +0 -2
  500. package/dist/research/index.js.map +0 -1
  501. package/dist/roadmap/index.js +0 -59
  502. package/dist/roadmap/index.js.map +0 -1
  503. package/dist/routing/capability-matrix.js +0 -1556
  504. package/dist/routing/capability-matrix.js.map +0 -1
  505. package/dist/routing/index.js +0 -9
  506. package/dist/routing/index.js.map +0 -1
  507. package/dist/scaffold.js +0 -1759
  508. package/dist/scaffold.js.map +0 -1
  509. package/dist/schema-management.js +0 -295
  510. package/dist/schema-management.js.map +0 -1
  511. package/dist/security/index.js +0 -9
  512. package/dist/security/index.js.map +0 -1
  513. package/dist/security/input-sanitization.js +0 -321
  514. package/dist/security/input-sanitization.js.map +0 -1
  515. package/dist/sequence/index.js +0 -295
  516. package/dist/sequence/index.js.map +0 -1
  517. package/dist/sessions/assumptions.js +0 -54
  518. package/dist/sessions/assumptions.js.map +0 -1
  519. package/dist/sessions/briefing.js +0 -377
  520. package/dist/sessions/briefing.js.map +0 -1
  521. package/dist/sessions/context-alert.js +0 -222
  522. package/dist/sessions/context-alert.js.map +0 -1
  523. package/dist/sessions/context-inject.js +0 -61
  524. package/dist/sessions/context-inject.js.map +0 -1
  525. package/dist/sessions/context-monitor.js +0 -98
  526. package/dist/sessions/context-monitor.js.map +0 -1
  527. package/dist/sessions/decisions.js +0 -65
  528. package/dist/sessions/decisions.js.map +0 -1
  529. package/dist/sessions/find.js +0 -65
  530. package/dist/sessions/find.js.map +0 -1
  531. package/dist/sessions/handoff.js +0 -328
  532. package/dist/sessions/handoff.js.map +0 -1
  533. package/dist/sessions/hitl-warnings.js +0 -254
  534. package/dist/sessions/hitl-warnings.js.map +0 -1
  535. package/dist/sessions/index.js +0 -327
  536. package/dist/sessions/index.js.map +0 -1
  537. package/dist/sessions/session-archive.js +0 -40
  538. package/dist/sessions/session-archive.js.map +0 -1
  539. package/dist/sessions/session-cleanup.js +0 -59
  540. package/dist/sessions/session-cleanup.js.map +0 -1
  541. package/dist/sessions/session-drift.js +0 -134
  542. package/dist/sessions/session-drift.js.map +0 -1
  543. package/dist/sessions/session-enforcement.js +0 -144
  544. package/dist/sessions/session-enforcement.js.map +0 -1
  545. package/dist/sessions/session-grade.js +0 -253
  546. package/dist/sessions/session-grade.js.map +0 -1
  547. package/dist/sessions/session-history.js +0 -42
  548. package/dist/sessions/session-history.js.map +0 -1
  549. package/dist/sessions/session-id.js +0 -81
  550. package/dist/sessions/session-id.js.map +0 -1
  551. package/dist/sessions/session-memory-bridge.js +0 -52
  552. package/dist/sessions/session-memory-bridge.js.map +0 -1
  553. package/dist/sessions/session-show.js +0 -24
  554. package/dist/sessions/session-show.js.map +0 -1
  555. package/dist/sessions/session-stats.js +0 -69
  556. package/dist/sessions/session-stats.js.map +0 -1
  557. package/dist/sessions/session-suspend.js +0 -39
  558. package/dist/sessions/session-suspend.js.map +0 -1
  559. package/dist/sessions/session-switch.js +0 -51
  560. package/dist/sessions/session-switch.js.map +0 -1
  561. package/dist/sessions/session-view.js +0 -76
  562. package/dist/sessions/session-view.js.map +0 -1
  563. package/dist/sessions/snapshot.js +0 -213
  564. package/dist/sessions/snapshot.js.map +0 -1
  565. package/dist/sessions/statusline-setup.js +0 -85
  566. package/dist/sessions/statusline-setup.js.map +0 -1
  567. package/dist/sessions/types.js +0 -8
  568. package/dist/sessions/types.js.map +0 -1
  569. package/dist/skills/agents/config.js +0 -94
  570. package/dist/skills/agents/config.js.map +0 -1
  571. package/dist/skills/agents/install.js +0 -116
  572. package/dist/skills/agents/install.js.map +0 -1
  573. package/dist/skills/agents/registry.js +0 -161
  574. package/dist/skills/agents/registry.js.map +0 -1
  575. package/dist/skills/discovery.js +0 -333
  576. package/dist/skills/discovery.js.map +0 -1
  577. package/dist/skills/dispatch.js +0 -347
  578. package/dist/skills/dispatch.js.map +0 -1
  579. package/dist/skills/dynamic-skill-generator.js +0 -87
  580. package/dist/skills/dynamic-skill-generator.js.map +0 -1
  581. package/dist/skills/index.js +0 -44
  582. package/dist/skills/index.js.map +0 -1
  583. package/dist/skills/injection/subagent.js +0 -195
  584. package/dist/skills/injection/subagent.js.map +0 -1
  585. package/dist/skills/injection/token.js +0 -260
  586. package/dist/skills/injection/token.js.map +0 -1
  587. package/dist/skills/install.js +0 -40
  588. package/dist/skills/install.js.map +0 -1
  589. package/dist/skills/manifests/contribution.js +0 -175
  590. package/dist/skills/manifests/contribution.js.map +0 -1
  591. package/dist/skills/manifests/research.js +0 -281
  592. package/dist/skills/manifests/research.js.map +0 -1
  593. package/dist/skills/manifests/resolver.js +0 -146
  594. package/dist/skills/manifests/resolver.js.map +0 -1
  595. package/dist/skills/marketplace.js +0 -90
  596. package/dist/skills/marketplace.js.map +0 -1
  597. package/dist/skills/orchestrator/spawn.js +0 -178
  598. package/dist/skills/orchestrator/spawn.js.map +0 -1
  599. package/dist/skills/orchestrator/startup.js +0 -451
  600. package/dist/skills/orchestrator/startup.js.map +0 -1
  601. package/dist/skills/orchestrator/validator.js +0 -301
  602. package/dist/skills/orchestrator/validator.js.map +0 -1
  603. package/dist/skills/precedence-integration.js +0 -73
  604. package/dist/skills/precedence-integration.js.map +0 -1
  605. package/dist/skills/precedence-types.js +0 -16
  606. package/dist/skills/precedence-types.js.map +0 -1
  607. package/dist/skills/routing-table.js +0 -63
  608. package/dist/skills/routing-table.js.map +0 -1
  609. package/dist/skills/skill-paths.js +0 -217
  610. package/dist/skills/skill-paths.js.map +0 -1
  611. package/dist/skills/test-utility.js +0 -55
  612. package/dist/skills/test-utility.js.map +0 -1
  613. package/dist/skills/types.js +0 -118
  614. package/dist/skills/types.js.map +0 -1
  615. package/dist/skills/validation.js +0 -183
  616. package/dist/skills/validation.js.map +0 -1
  617. package/dist/skills/version.js +0 -57
  618. package/dist/skills/version.js.map +0 -1
  619. package/dist/snapshot/index.js +0 -188
  620. package/dist/snapshot/index.js.map +0 -1
  621. package/dist/spawn/adapter-registry.js +0 -246
  622. package/dist/spawn/adapter-registry.js.map +0 -1
  623. package/dist/spawn/index.js +0 -10
  624. package/dist/spawn/index.js.map +0 -1
  625. package/dist/stats/index.js +0 -343
  626. package/dist/stats/index.js.map +0 -1
  627. package/dist/stats/workflow-telemetry.js +0 -400
  628. package/dist/stats/workflow-telemetry.js.map +0 -1
  629. package/dist/sticky/archive.js +0 -47
  630. package/dist/sticky/archive.js.map +0 -1
  631. package/dist/sticky/convert.js +0 -235
  632. package/dist/sticky/convert.js.map +0 -1
  633. package/dist/sticky/create.js +0 -48
  634. package/dist/sticky/create.js.map +0 -1
  635. package/dist/sticky/id.js +0 -35
  636. package/dist/sticky/id.js.map +0 -1
  637. package/dist/sticky/index.js +0 -16
  638. package/dist/sticky/index.js.map +0 -1
  639. package/dist/sticky/list.js +0 -44
  640. package/dist/sticky/list.js.map +0 -1
  641. package/dist/sticky/purge.js +0 -45
  642. package/dist/sticky/purge.js.map +0 -1
  643. package/dist/sticky/show.js +0 -42
  644. package/dist/sticky/show.js.map +0 -1
  645. package/dist/sticky/types.js +0 -10
  646. package/dist/sticky/types.js.map +0 -1
  647. package/dist/store/agent-registry-accessor.js +0 -783
  648. package/dist/store/agent-registry-accessor.js.map +0 -1
  649. package/dist/store/api-key-kdf.js +0 -84
  650. package/dist/store/api-key-kdf.js.map +0 -1
  651. package/dist/store/atomic.js +0 -167
  652. package/dist/store/atomic.js.map +0 -1
  653. package/dist/store/backup.js +0 -94
  654. package/dist/store/backup.js.map +0 -1
  655. package/dist/store/brain-accessor.js +0 -397
  656. package/dist/store/brain-accessor.js.map +0 -1
  657. package/dist/store/brain-schema.js +0 -215
  658. package/dist/store/brain-schema.js.map +0 -1
  659. package/dist/store/brain-sqlite.js +0 -222
  660. package/dist/store/brain-sqlite.js.map +0 -1
  661. package/dist/store/cache.js +0 -168
  662. package/dist/store/cache.js.map +0 -1
  663. package/dist/store/chain-schema.js +0 -51
  664. package/dist/store/chain-schema.js.map +0 -1
  665. package/dist/store/cleanup-legacy.js +0 -171
  666. package/dist/store/cleanup-legacy.js.map +0 -1
  667. package/dist/store/conduit-sqlite.js +0 -570
  668. package/dist/store/conduit-sqlite.js.map +0 -1
  669. package/dist/store/converters.js +0 -124
  670. package/dist/store/converters.js.map +0 -1
  671. package/dist/store/cross-db-cleanup.js +0 -319
  672. package/dist/store/cross-db-cleanup.js.map +0 -1
  673. package/dist/store/data-accessor.js +0 -26
  674. package/dist/store/data-accessor.js.map +0 -1
  675. package/dist/store/data-safety-central.js +0 -269
  676. package/dist/store/data-safety-central.js.map +0 -1
  677. package/dist/store/data-safety.js +0 -274
  678. package/dist/store/data-safety.js.map +0 -1
  679. package/dist/store/db-helpers.js +0 -224
  680. package/dist/store/db-helpers.js.map +0 -1
  681. package/dist/store/export.js +0 -155
  682. package/dist/store/export.js.map +0 -1
  683. package/dist/store/file-utils.js +0 -270
  684. package/dist/store/file-utils.js.map +0 -1
  685. package/dist/store/git-checkpoint.js +0 -365
  686. package/dist/store/git-checkpoint.js.map +0 -1
  687. package/dist/store/global-salt.js +0 -147
  688. package/dist/store/global-salt.js.map +0 -1
  689. package/dist/store/import-logging.js +0 -139
  690. package/dist/store/import-logging.js.map +0 -1
  691. package/dist/store/import-remap.js +0 -145
  692. package/dist/store/import-remap.js.map +0 -1
  693. package/dist/store/import-sort.js +0 -121
  694. package/dist/store/import-sort.js.map +0 -1
  695. package/dist/store/index.js +0 -29
  696. package/dist/store/index.js.map +0 -1
  697. package/dist/store/json.js +0 -208
  698. package/dist/store/json.js.map +0 -1
  699. package/dist/store/lifecycle-store.js +0 -249
  700. package/dist/store/lifecycle-store.js.map +0 -1
  701. package/dist/store/lock.js +0 -70
  702. package/dist/store/lock.js.map +0 -1
  703. package/dist/store/migrate-signaldock-to-conduit.js +0 -555
  704. package/dist/store/migrate-signaldock-to-conduit.js.map +0 -1
  705. package/dist/store/migration-manager.js +0 -151
  706. package/dist/store/migration-manager.js.map +0 -1
  707. package/dist/store/migration-sqlite.js +0 -676
  708. package/dist/store/migration-sqlite.js.map +0 -1
  709. package/dist/store/nexus-schema.js +0 -62
  710. package/dist/store/nexus-schema.js.map +0 -1
  711. package/dist/store/nexus-sqlite.js +0 -242
  712. package/dist/store/nexus-sqlite.js.map +0 -1
  713. package/dist/store/nexus-validation-schemas.js +0 -40
  714. package/dist/store/nexus-validation-schemas.js.map +0 -1
  715. package/dist/store/parsers.js +0 -37
  716. package/dist/store/parsers.js.map +0 -1
  717. package/dist/store/project-detect.js +0 -457
  718. package/dist/store/project-detect.js.map +0 -1
  719. package/dist/store/provider.js +0 -101
  720. package/dist/store/provider.js.map +0 -1
  721. package/dist/store/safety-data-accessor.js +0 -257
  722. package/dist/store/safety-data-accessor.js.map +0 -1
  723. package/dist/store/schema.js +0 -7
  724. package/dist/store/schema.js.map +0 -1
  725. package/dist/store/session-store.js +0 -219
  726. package/dist/store/session-store.js.map +0 -1
  727. package/dist/store/signaldock-sqlite.js +0 -550
  728. package/dist/store/signaldock-sqlite.js.map +0 -1
  729. package/dist/store/sqlite-backup.js +0 -359
  730. package/dist/store/sqlite-backup.js.map +0 -1
  731. package/dist/store/sqlite-data-accessor.js +0 -787
  732. package/dist/store/sqlite-data-accessor.js.map +0 -1
  733. package/dist/store/sqlite.js +0 -481
  734. package/dist/store/sqlite.js.map +0 -1
  735. package/dist/store/status-registry.js +0 -8
  736. package/dist/store/status-registry.js.map +0 -1
  737. package/dist/store/task-store.js +0 -358
  738. package/dist/store/task-store.js.map +0 -1
  739. package/dist/store/tasks-schema.js +0 -610
  740. package/dist/store/tasks-schema.js.map +0 -1
  741. package/dist/store/typed-query.js +0 -15
  742. package/dist/store/typed-query.js.map +0 -1
  743. package/dist/store/validation-schemas.js +0 -278
  744. package/dist/store/validation-schemas.js.map +0 -1
  745. package/dist/system/archive-analytics.js +0 -277
  746. package/dist/system/archive-analytics.js.map +0 -1
  747. package/dist/system/archive-stats.js +0 -64
  748. package/dist/system/archive-stats.js.map +0 -1
  749. package/dist/system/audit.js +0 -145
  750. package/dist/system/audit.js.map +0 -1
  751. package/dist/system/backup.js +0 -280
  752. package/dist/system/backup.js.map +0 -1
  753. package/dist/system/cleanup.js +0 -134
  754. package/dist/system/cleanup.js.map +0 -1
  755. package/dist/system/health.js +0 -1100
  756. package/dist/system/health.js.map +0 -1
  757. package/dist/system/index.js +0 -18
  758. package/dist/system/index.js.map +0 -1
  759. package/dist/system/inject-generate.js +0 -122
  760. package/dist/system/inject-generate.js.map +0 -1
  761. package/dist/system/labels.js +0 -38
  762. package/dist/system/labels.js.map +0 -1
  763. package/dist/system/metrics.js +0 -61
  764. package/dist/system/metrics.js.map +0 -1
  765. package/dist/system/migrate.js +0 -43
  766. package/dist/system/migrate.js.map +0 -1
  767. package/dist/system/platform-paths.js +0 -80
  768. package/dist/system/platform-paths.js.map +0 -1
  769. package/dist/system/runtime.js +0 -161
  770. package/dist/system/runtime.js.map +0 -1
  771. package/dist/system/safestop.js +0 -99
  772. package/dist/system/safestop.js.map +0 -1
  773. package/dist/system/storage-preflight.js +0 -123
  774. package/dist/system/storage-preflight.js.map +0 -1
  775. package/dist/task-work/index.js +0 -159
  776. package/dist/task-work/index.js.map +0 -1
  777. package/dist/tasks/add.js +0 -736
  778. package/dist/tasks/add.js.map +0 -1
  779. package/dist/tasks/analyze.js +0 -85
  780. package/dist/tasks/analyze.js.map +0 -1
  781. package/dist/tasks/archive.js +0 -90
  782. package/dist/tasks/archive.js.map +0 -1
  783. package/dist/tasks/atomicity.js +0 -83
  784. package/dist/tasks/atomicity.js.map +0 -1
  785. package/dist/tasks/cancel-ops.js +0 -83
  786. package/dist/tasks/cancel-ops.js.map +0 -1
  787. package/dist/tasks/complete.js +0 -214
  788. package/dist/tasks/complete.js.map +0 -1
  789. package/dist/tasks/crossref-extract.js +0 -73
  790. package/dist/tasks/crossref-extract.js.map +0 -1
  791. package/dist/tasks/delete-preview.js +0 -192
  792. package/dist/tasks/delete-preview.js.map +0 -1
  793. package/dist/tasks/delete.js +0 -120
  794. package/dist/tasks/delete.js.map +0 -1
  795. package/dist/tasks/deletion-strategy.js +0 -200
  796. package/dist/tasks/deletion-strategy.js.map +0 -1
  797. package/dist/tasks/dependency-check.js +0 -278
  798. package/dist/tasks/dependency-check.js.map +0 -1
  799. package/dist/tasks/deps-ready.js +0 -32
  800. package/dist/tasks/deps-ready.js.map +0 -1
  801. package/dist/tasks/enforcement.js +0 -86
  802. package/dist/tasks/enforcement.js.map +0 -1
  803. package/dist/tasks/epic-enforcement.js +0 -294
  804. package/dist/tasks/epic-enforcement.js.map +0 -1
  805. package/dist/tasks/find.js +0 -157
  806. package/dist/tasks/find.js.map +0 -1
  807. package/dist/tasks/graph-cache.js +0 -127
  808. package/dist/tasks/graph-cache.js.map +0 -1
  809. package/dist/tasks/graph-ops.js +0 -171
  810. package/dist/tasks/graph-ops.js.map +0 -1
  811. package/dist/tasks/graph-rag.js +0 -328
  812. package/dist/tasks/graph-rag.js.map +0 -1
  813. package/dist/tasks/hierarchy-policy.js +0 -149
  814. package/dist/tasks/hierarchy-policy.js.map +0 -1
  815. package/dist/tasks/hierarchy.js +0 -185
  816. package/dist/tasks/hierarchy.js.map +0 -1
  817. package/dist/tasks/id-generator.js +0 -65
  818. package/dist/tasks/id-generator.js.map +0 -1
  819. package/dist/tasks/index.js +0 -14
  820. package/dist/tasks/index.js.map +0 -1
  821. package/dist/tasks/labels.js +0 -55
  822. package/dist/tasks/labels.js.map +0 -1
  823. package/dist/tasks/list.js +0 -75
  824. package/dist/tasks/list.js.map +0 -1
  825. package/dist/tasks/phase-tracking.js +0 -133
  826. package/dist/tasks/phase-tracking.js.map +0 -1
  827. package/dist/tasks/pipeline-stage.js +0 -248
  828. package/dist/tasks/pipeline-stage.js.map +0 -1
  829. package/dist/tasks/plan.js +0 -268
  830. package/dist/tasks/plan.js.map +0 -1
  831. package/dist/tasks/relates.js +0 -101
  832. package/dist/tasks/relates.js.map +0 -1
  833. package/dist/tasks/show.js +0 -83
  834. package/dist/tasks/show.js.map +0 -1
  835. package/dist/tasks/size-weighting.js +0 -86
  836. package/dist/tasks/size-weighting.js.map +0 -1
  837. package/dist/tasks/staleness.js +0 -86
  838. package/dist/tasks/staleness.js.map +0 -1
  839. package/dist/tasks/task-ops.js +0 -1741
  840. package/dist/tasks/task-ops.js.map +0 -1
  841. package/dist/tasks/update.js +0 -303
  842. package/dist/tasks/update.js.map +0 -1
  843. package/dist/templates/index.js +0 -10
  844. package/dist/templates/index.js.map +0 -1
  845. package/dist/templates/parser.js +0 -254
  846. package/dist/templates/parser.js.map +0 -1
  847. package/dist/ui/aliases.js +0 -153
  848. package/dist/ui/aliases.js.map +0 -1
  849. package/dist/ui/changelog.js +0 -184
  850. package/dist/ui/changelog.js.map +0 -1
  851. package/dist/ui/command-registry.js +0 -168
  852. package/dist/ui/command-registry.js.map +0 -1
  853. package/dist/ui/flags.js +0 -94
  854. package/dist/ui/flags.js.map +0 -1
  855. package/dist/ui/index.js +0 -24
  856. package/dist/ui/index.js.map +0 -1
  857. package/dist/upgrade.js +0 -1148
  858. package/dist/upgrade.js.map +0 -1
  859. package/dist/validation/chain-validation.js +0 -146
  860. package/dist/validation/chain-validation.js.map +0 -1
  861. package/dist/validation/compliance.js +0 -155
  862. package/dist/validation/compliance.js.map +0 -1
  863. package/dist/validation/docs-sync.js +0 -212
  864. package/dist/validation/docs-sync.js.map +0 -1
  865. package/dist/validation/doctor/checks.js +0 -1069
  866. package/dist/validation/doctor/checks.js.map +0 -1
  867. package/dist/validation/doctor/index.js +0 -9
  868. package/dist/validation/doctor/index.js.map +0 -1
  869. package/dist/validation/doctor/project-cache.js +0 -160
  870. package/dist/validation/doctor/project-cache.js.map +0 -1
  871. package/dist/validation/doctor/utils.js +0 -155
  872. package/dist/validation/doctor/utils.js.map +0 -1
  873. package/dist/validation/engine.js +0 -914
  874. package/dist/validation/engine.js.map +0 -1
  875. package/dist/validation/gap-check.js +0 -175
  876. package/dist/validation/gap-check.js.map +0 -1
  877. package/dist/validation/index.js +0 -40
  878. package/dist/validation/index.js.map +0 -1
  879. package/dist/validation/manifest.js +0 -237
  880. package/dist/validation/manifest.js.map +0 -1
  881. package/dist/validation/operation-gate-validators.js +0 -724
  882. package/dist/validation/operation-gate-validators.js.map +0 -1
  883. package/dist/validation/operation-verification-gates.js +0 -532
  884. package/dist/validation/operation-verification-gates.js.map +0 -1
  885. package/dist/validation/param-utils.js +0 -141
  886. package/dist/validation/param-utils.js.map +0 -1
  887. package/dist/validation/protocol-common.js +0 -300
  888. package/dist/validation/protocol-common.js.map +0 -1
  889. package/dist/validation/protocols/_shared.js +0 -82
  890. package/dist/validation/protocols/_shared.js.map +0 -1
  891. package/dist/validation/protocols/architecture-decision.js +0 -31
  892. package/dist/validation/protocols/architecture-decision.js.map +0 -1
  893. package/dist/validation/protocols/artifact-publish.js +0 -28
  894. package/dist/validation/protocols/artifact-publish.js.map +0 -1
  895. package/dist/validation/protocols/consensus.js +0 -41
  896. package/dist/validation/protocols/consensus.js.map +0 -1
  897. package/dist/validation/protocols/contribution.js +0 -27
  898. package/dist/validation/protocols/contribution.js.map +0 -1
  899. package/dist/validation/protocols/decomposition.js +0 -28
  900. package/dist/validation/protocols/decomposition.js.map +0 -1
  901. package/dist/validation/protocols/implementation.js +0 -24
  902. package/dist/validation/protocols/implementation.js.map +0 -1
  903. package/dist/validation/protocols/provenance.js +0 -29
  904. package/dist/validation/protocols/provenance.js.map +0 -1
  905. package/dist/validation/protocols/release.js +0 -29
  906. package/dist/validation/protocols/release.js.map +0 -1
  907. package/dist/validation/protocols/research.js +0 -24
  908. package/dist/validation/protocols/research.js.map +0 -1
  909. package/dist/validation/protocols/specification.js +0 -27
  910. package/dist/validation/protocols/specification.js.map +0 -1
  911. package/dist/validation/protocols/testing.js +0 -30
  912. package/dist/validation/protocols/testing.js.map +0 -1
  913. package/dist/validation/protocols/validation.js +0 -30
  914. package/dist/validation/protocols/validation.js.map +0 -1
  915. package/dist/validation/schema-integrity.js +0 -170
  916. package/dist/validation/schema-integrity.js.map +0 -1
  917. package/dist/validation/schema-validator.js +0 -176
  918. package/dist/validation/schema-validator.js.map +0 -1
  919. package/dist/validation/validate-ops.js +0 -937
  920. package/dist/validation/validate-ops.js.map +0 -1
  921. package/dist/validation/validation-rules.js +0 -226
  922. package/dist/validation/validation-rules.js.map +0 -1
  923. package/dist/validation/verification.js +0 -321
  924. 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