pybao-cli 1.5.19 → 1.5.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/REPL-64WF5V7K.js +50 -0
  2. package/dist/{acp-VADDAIVV.js → acp-VH2FWCMR.js} +31 -31
  3. package/dist/{agentsValidate-VDPY7LYN.js → agentsValidate-4E7AHAMS.js} +7 -7
  4. package/dist/{ask-4ZMUM73X.js → ask-R3YZ5B44.js} +30 -30
  5. package/dist/{autoUpdater-RIDDLHLH.js → autoUpdater-DCNAXD4F.js} +3 -3
  6. package/dist/{chunk-CGFEVSPI.js → chunk-25GZITCX.js} +3 -3
  7. package/dist/{chunk-2FDZ2PEI.js → chunk-2OOER4FR.js} +3 -3
  8. package/dist/{chunk-7SWRPT6M.js → chunk-3UWTN6DM.js} +3 -3
  9. package/dist/{chunk-VB3UZHV6.js → chunk-4ZGZTWMR.js} +4 -4
  10. package/dist/{chunk-YKSGF3T7.js → chunk-56IL2VXC.js} +1 -1
  11. package/dist/{chunk-TNOZ27TG.js → chunk-5VO2CFAL.js} +2 -2
  12. package/dist/{chunk-ZWB3VSTH.js → chunk-6UNYL6XK.js} +245 -50
  13. package/dist/{chunk-ZWB3VSTH.js.map → chunk-6UNYL6XK.js.map} +3 -3
  14. package/dist/{chunk-277JOCVZ.js → chunk-BED7SG2Q.js} +1 -1
  15. package/dist/{chunk-7I4S6UH7.js → chunk-BRSPPFSY.js} +1 -1
  16. package/dist/{chunk-L6J4MPRE.js → chunk-CPYDPN2J.js} +725 -73
  17. package/dist/{chunk-L6J4MPRE.js.map → chunk-CPYDPN2J.js.map} +2 -2
  18. package/dist/{chunk-PHBWXWFD.js → chunk-CSONCQLF.js} +2 -2
  19. package/dist/{chunk-KP7PMNEW.js → chunk-EP62LHB7.js} +1 -1
  20. package/dist/{chunk-M6CFQRHR.js → chunk-GIXE5FJ2.js} +1 -1
  21. package/dist/{chunk-KX7DKI3A.js → chunk-H2ZE5QDY.js} +4 -4
  22. package/dist/{chunk-M3AEV7WD.js → chunk-HA7FKBZI.js} +2 -2
  23. package/dist/{chunk-RUMV5QOU.js → chunk-KMCUZUZG.js} +3 -3
  24. package/dist/{chunk-JKTDFI2S.js → chunk-LRL3MYKR.js} +3 -3
  25. package/dist/{chunk-3JRH6I43.js → chunk-MMMMRMOG.js} +3 -3
  26. package/dist/{chunk-PXAQPDGS.js → chunk-N3T2WAYN.js} +1 -1
  27. package/dist/{chunk-IYGHQUN2.js → chunk-NRQHLVJJ.js} +2 -2
  28. package/dist/{chunk-CZZKRPE2.js → chunk-P5NTGZ5H.js} +1 -1
  29. package/dist/{chunk-CZZKRPE2.js.map → chunk-P5NTGZ5H.js.map} +1 -1
  30. package/dist/{chunk-7AJ4EUUJ.js → chunk-QE7PZPHW.js} +1 -1
  31. package/dist/{chunk-FYOORPZ4.js → chunk-RQ5X6LFM.js} +4 -4
  32. package/dist/{chunk-JR5WF5M6.js → chunk-SE7UGQCE.js} +2 -2
  33. package/dist/{chunk-LXJUYOGP.js → chunk-TBEA6BY3.js} +1 -1
  34. package/dist/{chunk-MRG76U66.js → chunk-TSAURYF2.js} +1 -1
  35. package/dist/{chunk-CEHSLEJ3.js → chunk-TXZ5UTGP.js} +1 -1
  36. package/dist/{chunk-CEHSLEJ3.js.map → chunk-TXZ5UTGP.js.map} +1 -1
  37. package/dist/{chunk-VSKWAGTO.js → chunk-VP5A6FKG.js} +1 -1
  38. package/dist/{chunk-PJ2XKKDM.js → chunk-VY5KEHU5.js} +3 -3
  39. package/dist/{chunk-JTRFDGES.js → chunk-X5LLT4P2.js} +1 -1
  40. package/dist/{chunk-KRBHZ2NW.js → chunk-XRLMQN3Q.js} +4 -4
  41. package/dist/{chunk-BPY6R2EU.js → chunk-YQ2RQUQF.js} +1 -1
  42. package/dist/{chunk-OMCKTGQ5.js → chunk-ZQR3MM2D.js} +17 -2
  43. package/dist/{chunk-OMCKTGQ5.js.map → chunk-ZQR3MM2D.js.map} +2 -2
  44. package/dist/{cli-AK6CYCFX.js → cli-RBMZQ5KF.js} +103 -92
  45. package/dist/cli-RBMZQ5KF.js.map +7 -0
  46. package/dist/commands-WPHK776A.js +54 -0
  47. package/dist/{config-FLSTRDUK.js → config-7TO5SQU5.js} +4 -4
  48. package/dist/{context-JQKLNDEK.js → context-LRA2DKJT.js} +6 -6
  49. package/dist/{conversationPersistence-RVLIJAVU.js → conversationPersistence-Z4QSI5NB.js} +3 -3
  50. package/dist/{conversationTracker-5HLVM6IU.js → conversationTracker-B3DMEHMA.js} +4 -4
  51. package/dist/{customCommands-J2RH24UE.js → customCommands-6JZ2VUO2.js} +4 -4
  52. package/dist/{env-PWLMV4WE.js → env-37ALKFXU.js} +2 -2
  53. package/dist/{file-LY2Z6EYX.js → file-7EOMBX72.js} +4 -4
  54. package/dist/index.js +3 -3
  55. package/dist/{llm-RRAVQWE3.js → llm-3KQG5NEP.js} +31 -31
  56. package/dist/{llmLazy-LRW757BZ.js → llmLazy-ENEH3KAB.js} +1 -1
  57. package/dist/{loader-2LT2GMMI.js → loader-D6V3WFL6.js} +4 -4
  58. package/dist/{lsp-XVTWUOP7.js → lsp-CTPOMI7O.js} +6 -6
  59. package/dist/{lspAnchor-WIAD4UCJ.js → lspAnchor-PPPTHRQH.js} +6 -6
  60. package/dist/{mcp-NNXV4YW5.js → mcp-6M34WBA5.js} +7 -7
  61. package/dist/{mentionProcessor-YXD3BYZG.js → mentionProcessor-TS4SITI3.js} +5 -5
  62. package/dist/{messages-JJ6XSPH4.js → messages-BINU6SYX.js} +1 -1
  63. package/dist/{model-SHEZI5VH.js → model-6IW224UU.js} +5 -5
  64. package/dist/{openai-MAEDGVOM.js → openai-O6CGVMYK.js} +5 -5
  65. package/dist/{outputStyles-Y5T4PH3H.js → outputStyles-7PPMLSV6.js} +4 -4
  66. package/dist/{pluginRuntime-EA5NXHW2.js → pluginRuntime-RU5STQ6F.js} +6 -6
  67. package/dist/{pluginValidation-AA3RZDZQ.js → pluginValidation-JTJTB3TB.js} +6 -6
  68. package/dist/prompts-CAPCICF3.js +56 -0
  69. package/dist/{pybAgentSessionLoad-DKPYB2WI.js → pybAgentSessionLoad-ZXQAHTQS.js} +4 -4
  70. package/dist/{pybAgentSessionResume-QBNQXHZX.js → pybAgentSessionResume-R73KFN3V.js} +4 -4
  71. package/dist/{pybAgentStreamJsonSession-5PBYWXYX.js → pybAgentStreamJsonSession-N4SMTC64.js} +1 -1
  72. package/dist/{pybHooks-66OQ6DF7.js → pybHooks-NGJ5OFAI.js} +4 -4
  73. package/dist/query-CYTIVMQ6.js +54 -0
  74. package/dist/{registry-3YQQGXL6.js → registry-FKY6JQ3L.js} +5 -5
  75. package/dist/{ripgrep-ZHLMP6TJ.js → ripgrep-O7MOW25M.js} +3 -3
  76. package/dist/{skillMarketplace-TXDXKVDH.js → skillMarketplace-VK3AYR6Q.js} +3 -3
  77. package/dist/{state-YDKD6B6T.js → state-T57IG35V.js} +2 -2
  78. package/dist/{theme-WSG2IX32.js → theme-ZEFQIPVH.js} +5 -5
  79. package/dist/{toolPermissionSettings-26CM7QG5.js → toolPermissionSettings-ERNXVP7A.js} +6 -6
  80. package/dist/tools-2XLLIKZM.js +55 -0
  81. package/dist/{userInput-BFWEIUZE.js → userInput-JBAUBHGI.js} +33 -33
  82. package/package.json +1 -1
  83. package/dist/REPL-GNHAV3LL.js +0 -50
  84. package/dist/cli-AK6CYCFX.js.map +0 -7
  85. package/dist/commands-5WWNVLIZ.js +0 -54
  86. package/dist/prompts-PMRRQP3L.js +0 -56
  87. package/dist/query-RHLO6AS2.js +0 -54
  88. package/dist/tools-4HKXD3DV.js +0 -55
  89. /package/dist/{REPL-GNHAV3LL.js.map → REPL-64WF5V7K.js.map} +0 -0
  90. /package/dist/{acp-VADDAIVV.js.map → acp-VH2FWCMR.js.map} +0 -0
  91. /package/dist/{agentsValidate-VDPY7LYN.js.map → agentsValidate-4E7AHAMS.js.map} +0 -0
  92. /package/dist/{ask-4ZMUM73X.js.map → ask-R3YZ5B44.js.map} +0 -0
  93. /package/dist/{autoUpdater-RIDDLHLH.js.map → autoUpdater-DCNAXD4F.js.map} +0 -0
  94. /package/dist/{chunk-CGFEVSPI.js.map → chunk-25GZITCX.js.map} +0 -0
  95. /package/dist/{chunk-2FDZ2PEI.js.map → chunk-2OOER4FR.js.map} +0 -0
  96. /package/dist/{chunk-7SWRPT6M.js.map → chunk-3UWTN6DM.js.map} +0 -0
  97. /package/dist/{chunk-VB3UZHV6.js.map → chunk-4ZGZTWMR.js.map} +0 -0
  98. /package/dist/{chunk-YKSGF3T7.js.map → chunk-56IL2VXC.js.map} +0 -0
  99. /package/dist/{chunk-TNOZ27TG.js.map → chunk-5VO2CFAL.js.map} +0 -0
  100. /package/dist/{chunk-277JOCVZ.js.map → chunk-BED7SG2Q.js.map} +0 -0
  101. /package/dist/{chunk-7I4S6UH7.js.map → chunk-BRSPPFSY.js.map} +0 -0
  102. /package/dist/{chunk-PHBWXWFD.js.map → chunk-CSONCQLF.js.map} +0 -0
  103. /package/dist/{chunk-KP7PMNEW.js.map → chunk-EP62LHB7.js.map} +0 -0
  104. /package/dist/{chunk-M6CFQRHR.js.map → chunk-GIXE5FJ2.js.map} +0 -0
  105. /package/dist/{chunk-KX7DKI3A.js.map → chunk-H2ZE5QDY.js.map} +0 -0
  106. /package/dist/{chunk-M3AEV7WD.js.map → chunk-HA7FKBZI.js.map} +0 -0
  107. /package/dist/{chunk-RUMV5QOU.js.map → chunk-KMCUZUZG.js.map} +0 -0
  108. /package/dist/{chunk-JKTDFI2S.js.map → chunk-LRL3MYKR.js.map} +0 -0
  109. /package/dist/{chunk-3JRH6I43.js.map → chunk-MMMMRMOG.js.map} +0 -0
  110. /package/dist/{chunk-PXAQPDGS.js.map → chunk-N3T2WAYN.js.map} +0 -0
  111. /package/dist/{chunk-IYGHQUN2.js.map → chunk-NRQHLVJJ.js.map} +0 -0
  112. /package/dist/{chunk-7AJ4EUUJ.js.map → chunk-QE7PZPHW.js.map} +0 -0
  113. /package/dist/{chunk-FYOORPZ4.js.map → chunk-RQ5X6LFM.js.map} +0 -0
  114. /package/dist/{chunk-JR5WF5M6.js.map → chunk-SE7UGQCE.js.map} +0 -0
  115. /package/dist/{chunk-LXJUYOGP.js.map → chunk-TBEA6BY3.js.map} +0 -0
  116. /package/dist/{chunk-MRG76U66.js.map → chunk-TSAURYF2.js.map} +0 -0
  117. /package/dist/{chunk-VSKWAGTO.js.map → chunk-VP5A6FKG.js.map} +0 -0
  118. /package/dist/{chunk-PJ2XKKDM.js.map → chunk-VY5KEHU5.js.map} +0 -0
  119. /package/dist/{chunk-JTRFDGES.js.map → chunk-X5LLT4P2.js.map} +0 -0
  120. /package/dist/{chunk-KRBHZ2NW.js.map → chunk-XRLMQN3Q.js.map} +0 -0
  121. /package/dist/{chunk-BPY6R2EU.js.map → chunk-YQ2RQUQF.js.map} +0 -0
  122. /package/dist/{commands-5WWNVLIZ.js.map → commands-WPHK776A.js.map} +0 -0
  123. /package/dist/{config-FLSTRDUK.js.map → config-7TO5SQU5.js.map} +0 -0
  124. /package/dist/{context-JQKLNDEK.js.map → context-LRA2DKJT.js.map} +0 -0
  125. /package/dist/{conversationPersistence-RVLIJAVU.js.map → conversationPersistence-Z4QSI5NB.js.map} +0 -0
  126. /package/dist/{conversationTracker-5HLVM6IU.js.map → conversationTracker-B3DMEHMA.js.map} +0 -0
  127. /package/dist/{customCommands-J2RH24UE.js.map → customCommands-6JZ2VUO2.js.map} +0 -0
  128. /package/dist/{env-PWLMV4WE.js.map → env-37ALKFXU.js.map} +0 -0
  129. /package/dist/{file-LY2Z6EYX.js.map → file-7EOMBX72.js.map} +0 -0
  130. /package/dist/{llm-RRAVQWE3.js.map → llm-3KQG5NEP.js.map} +0 -0
  131. /package/dist/{llmLazy-LRW757BZ.js.map → llmLazy-ENEH3KAB.js.map} +0 -0
  132. /package/dist/{loader-2LT2GMMI.js.map → loader-D6V3WFL6.js.map} +0 -0
  133. /package/dist/{lsp-XVTWUOP7.js.map → lsp-CTPOMI7O.js.map} +0 -0
  134. /package/dist/{lspAnchor-WIAD4UCJ.js.map → lspAnchor-PPPTHRQH.js.map} +0 -0
  135. /package/dist/{mcp-NNXV4YW5.js.map → mcp-6M34WBA5.js.map} +0 -0
  136. /package/dist/{mentionProcessor-YXD3BYZG.js.map → mentionProcessor-TS4SITI3.js.map} +0 -0
  137. /package/dist/{messages-JJ6XSPH4.js.map → messages-BINU6SYX.js.map} +0 -0
  138. /package/dist/{model-SHEZI5VH.js.map → model-6IW224UU.js.map} +0 -0
  139. /package/dist/{openai-MAEDGVOM.js.map → openai-O6CGVMYK.js.map} +0 -0
  140. /package/dist/{outputStyles-Y5T4PH3H.js.map → outputStyles-7PPMLSV6.js.map} +0 -0
  141. /package/dist/{pluginRuntime-EA5NXHW2.js.map → pluginRuntime-RU5STQ6F.js.map} +0 -0
  142. /package/dist/{pluginValidation-AA3RZDZQ.js.map → pluginValidation-JTJTB3TB.js.map} +0 -0
  143. /package/dist/{prompts-PMRRQP3L.js.map → prompts-CAPCICF3.js.map} +0 -0
  144. /package/dist/{pybAgentSessionLoad-DKPYB2WI.js.map → pybAgentSessionLoad-ZXQAHTQS.js.map} +0 -0
  145. /package/dist/{pybAgentSessionResume-QBNQXHZX.js.map → pybAgentSessionResume-R73KFN3V.js.map} +0 -0
  146. /package/dist/{pybAgentStreamJsonSession-5PBYWXYX.js.map → pybAgentStreamJsonSession-N4SMTC64.js.map} +0 -0
  147. /package/dist/{pybHooks-66OQ6DF7.js.map → pybHooks-NGJ5OFAI.js.map} +0 -0
  148. /package/dist/{query-RHLO6AS2.js.map → query-CYTIVMQ6.js.map} +0 -0
  149. /package/dist/{registry-3YQQGXL6.js.map → registry-FKY6JQ3L.js.map} +0 -0
  150. /package/dist/{ripgrep-ZHLMP6TJ.js.map → ripgrep-O7MOW25M.js.map} +0 -0
  151. /package/dist/{skillMarketplace-TXDXKVDH.js.map → skillMarketplace-VK3AYR6Q.js.map} +0 -0
  152. /package/dist/{state-YDKD6B6T.js.map → state-T57IG35V.js.map} +0 -0
  153. /package/dist/{theme-WSG2IX32.js.map → theme-ZEFQIPVH.js.map} +0 -0
  154. /package/dist/{toolPermissionSettings-26CM7QG5.js.map → toolPermissionSettings-ERNXVP7A.js.map} +0 -0
  155. /package/dist/{tools-4HKXD3DV.js.map → tools-2XLLIKZM.js.map} +0 -0
  156. /package/dist/{userInput-BFWEIUZE.js.map → userInput-JBAUBHGI.js.map} +0 -0
@@ -41,57 +41,57 @@ import {
41
41
  runWithTaskListEnv,
42
42
  runWithTaskListId,
43
43
  updateTask
44
- } from "./chunk-ZWB3VSTH.js";
44
+ } from "./chunk-6UNYL6XK.js";
45
45
  import {
46
46
  getCurrentSessionId
47
47
  } from "./chunk-XKYHFZEC.js";
48
48
  import {
49
49
  queryLLM
50
- } from "./chunk-VB3UZHV6.js";
50
+ } from "./chunk-4ZGZTWMR.js";
51
51
  import {
52
52
  FallbackToolUseRejectedMessage,
53
53
  MCPTool,
54
54
  getClients,
55
55
  getMCPTools
56
- } from "./chunk-KX7DKI3A.js";
56
+ } from "./chunk-H2ZE5QDY.js";
57
57
  import {
58
58
  emitReminderEvent
59
- } from "./chunk-OMCKTGQ5.js";
59
+ } from "./chunk-ZQR3MM2D.js";
60
60
  import {
61
61
  getActiveAgents,
62
62
  getAgentByType,
63
63
  getAvailableAgentTypes
64
- } from "./chunk-IYGHQUN2.js";
64
+ } from "./chunk-NRQHLVJJ.js";
65
65
  import {
66
66
  INTERRUPT_MESSAGE,
67
67
  createAssistantMessage,
68
68
  createUserMessageFromBlocks,
69
69
  createUserMessageFromText,
70
70
  getLastAssistantMessageId
71
- } from "./chunk-BPY6R2EU.js";
71
+ } from "./chunk-YQ2RQUQF.js";
72
72
  import {
73
73
  formatDuration,
74
74
  formatNumber
75
75
  } from "./chunk-OUXHGDLH.js";
76
76
  import {
77
77
  getAbsolutePath
78
- } from "./chunk-M3AEV7WD.js";
78
+ } from "./chunk-HA7FKBZI.js";
79
79
  import {
80
80
  LspFacade,
81
81
  formatDiagnosticsPretty
82
- } from "./chunk-KRBHZ2NW.js";
82
+ } from "./chunk-XRLMQN3Q.js";
83
83
  import {
84
84
  getModelManager
85
- } from "./chunk-CGFEVSPI.js";
85
+ } from "./chunk-25GZITCX.js";
86
86
  import {
87
87
  getContext
88
- } from "./chunk-FYOORPZ4.js";
88
+ } from "./chunk-RQ5X6LFM.js";
89
89
  import {
90
90
  getTheme
91
- } from "./chunk-YKSGF3T7.js";
91
+ } from "./chunk-56IL2VXC.js";
92
92
  import {
93
93
  debug
94
- } from "./chunk-LXJUYOGP.js";
94
+ } from "./chunk-TBEA6BY3.js";
95
95
  import {
96
96
  BunShell,
97
97
  MEMORY_DIR,
@@ -103,7 +103,7 @@ import {
103
103
  overwriteLog,
104
104
  readTaskOutput,
105
105
  resolveXdgDataPath
106
- } from "./chunk-VSKWAGTO.js";
106
+ } from "./chunk-VP5A6FKG.js";
107
107
 
108
108
  // src/tools/index.ts
109
109
  import { memoize as memoize2 } from "lodash-es";
@@ -784,7 +784,7 @@ async function analyzeOutputWithLsp(output, exitCode) {
784
784
  if (exitCode !== 0 || errorCount > 0 || warningCount > 0) {
785
785
  try {
786
786
  const { isAbsolute: isAbsolute2, resolve: resolve3 } = await import("path");
787
- const { getSessionRoot: getSessionRoot2 } = await import("./state-YDKD6B6T.js");
787
+ const { getSessionRoot: getSessionRoot2 } = await import("./state-T57IG35V.js");
788
788
  const lines = output.split("\n");
789
789
  const uniqueFiles = /* @__PURE__ */ new Set();
790
790
  const lspSuggestions = [];
@@ -1154,7 +1154,7 @@ var DeleteTool = {
1154
1154
  }
1155
1155
  if (!force) {
1156
1156
  try {
1157
- const { LspFacade: LspFacade2 } = await import("./lsp-XVTWUOP7.js");
1157
+ const { LspFacade: LspFacade2 } = await import("./lsp-CTPOMI7O.js");
1158
1158
  const referenceDetail = await LspFacade2.checkFileReferences(fullPath);
1159
1159
  if (referenceDetail) {
1160
1160
  failedItems.push(
@@ -2688,12 +2688,20 @@ function mapStatusToOutput(status) {
2688
2688
  return status;
2689
2689
  }
2690
2690
  function toTaskListItem(task) {
2691
- return {
2691
+ const projection = getTaskCollaborationProjection(task);
2692
+ const item = {
2692
2693
  id: task.id,
2693
2694
  subject: task.subject,
2694
2695
  status: mapStatusToOutput(task.status),
2695
2696
  blockedBy: task.blockedBy ?? []
2696
2697
  };
2698
+ if (projection.owner) item.owner = projection.owner;
2699
+ if (projection.worktree) item.worktree = projection.worktree;
2700
+ if (projection.lane) item.lane = projection.lane;
2701
+ if (projection.agent) item.agent = projection.agent;
2702
+ if (projection.created_at !== void 0) item.created_at = projection.created_at;
2703
+ if (projection.updated_at !== void 0) item.updated_at = projection.updated_at;
2704
+ return item;
2697
2705
  }
2698
2706
  function toTaskDetail(task) {
2699
2707
  return {
@@ -2708,13 +2716,33 @@ function toTaskDetail(task) {
2708
2716
  };
2709
2717
  }
2710
2718
  function toTaskGetDetail(task) {
2711
- return {
2719
+ const projection = getTaskCollaborationProjection(task);
2720
+ const detail = {
2712
2721
  subject: task.subject,
2713
2722
  description: task.description,
2723
+ activeForm: task.activeForm,
2714
2724
  status: mapStatusToOutput(task.status),
2725
+ metadata: task.metadata,
2715
2726
  blocks: task.blocks ?? [],
2716
2727
  blockedBy: task.blockedBy ?? []
2717
2728
  };
2729
+ if (projection.owner) detail.owner = projection.owner;
2730
+ if (projection.worktree) detail.worktree = projection.worktree;
2731
+ if (projection.lane) detail.lane = projection.lane;
2732
+ if (projection.agent) detail.agent = projection.agent;
2733
+ if (projection.created_at !== void 0) detail.created_at = projection.created_at;
2734
+ if (projection.updated_at !== void 0) detail.updated_at = projection.updated_at;
2735
+ return detail;
2736
+ }
2737
+ function getTaskCollaborationProjection(task) {
2738
+ const metadata = task.metadata ?? {};
2739
+ const owner = typeof metadata.owner === "string" ? metadata.owner : void 0;
2740
+ const worktree = typeof metadata.worktree === "string" ? metadata.worktree : void 0;
2741
+ const lane = typeof metadata.lane === "string" ? metadata.lane : void 0;
2742
+ const agent = typeof metadata.agent === "string" ? metadata.agent : void 0;
2743
+ const created_at = typeof metadata.created_at === "number" || typeof metadata.created_at === "string" ? metadata.created_at : void 0;
2744
+ const updated_at = typeof metadata.updated_at === "number" || typeof metadata.updated_at === "string" ? metadata.updated_at : void 0;
2745
+ return { owner, worktree, lane, agent, created_at, updated_at };
2718
2746
  }
2719
2747
  function createTaskToolError(params) {
2720
2748
  return {
@@ -2756,15 +2784,24 @@ Skip using this tool only when:
2756
2784
  - Use TaskCreate when scope changes during execution.
2757
2785
  - Use TaskCreate when a milestone is completed and the next concrete work unit begins.
2758
2786
 
2787
+ ## Core Workflow
2788
+
2789
+ **The Two-Phase Pattern (IMPORTANT):**
2790
+ - **Phase 1 - Create**: Create all tasks one by one WITHOUT dependencies (blockedBy=[]).
2791
+ - **Phase 2 - Link**: Use TaskUpdate to add blockedBy AFTER all related tasks exist.
2792
+
2793
+ This pattern ensures clean dependency graph construction and prevents reference errors.
2794
+
2759
2795
  ## Input Notes
2760
2796
  - subject is required.
2761
2797
  - listId is optional; omit to use the default list.
2762
2798
  - TaskCreate only supports single-task creation; create multiple tasks one by one.
2763
2799
  - For multi-step plans, create the structured task list without dependencies and add blockedBy later via TaskUpdate.
2764
- - activeForm is required and must not equal subject.
2800
+ - activeForm is required.
2801
+ - metadata is optional and should only include stable coordination fields you want to persist.
2765
2802
  - blockedBy is always stored as an array (empty when not used).
2766
2803
  - description and blockedBy are kept separate in JSON; any joining is only for terminal rendering.
2767
- - Task ordering relies on task id; do not use priority fields.
2804
+ - Task ordering relies on task id;
2768
2805
  - Use metadata.planFinalized="true" in TaskUpdate when dependencies are ready to be validated globally.
2769
2806
  - Do not mention tool names or tool usage in user-facing messages.
2770
2807
  - When uncertain whether to track, prefer tracking.
@@ -2788,50 +2825,296 @@ Preferred single-task template:
2788
2825
  ## Status Notes
2789
2826
  - Use pending when dependencies prevent work and fill blockedBy.
2790
2827
 
2828
+ ## Task Lifecycle Overview
2829
+
2830
+ Tasks flow through these states:
2831
+
2832
+ - pending --(start work)--> in_progress --(complete)--> done
2833
+ - pending --(cancel)--> deleted
2834
+ - in_progress --(cancel)--> deleted
2835
+
2836
+ **State Definitions:**
2837
+ - **pending**: Not started, may be blocked by dependencies
2838
+ - **in_progress**: Currently being worked on (only ONE task at a time)
2839
+ - **done**: Successfully completed (triggers unlock propagation)
2840
+ - **deleted**: Cancelled or no longer needed
2841
+
2842
+ **Ready vs Blocked:**
2843
+ - A task is **ready** when: status=pending AND blockedBy=[] (all dependencies satisfied)
2844
+ - A task is **blocked** when: blockedBy contains task IDs that are not yet done/deleted
2845
+
2846
+ ## Dependency Relationships
2847
+
2848
+ Tasks can have dependencies on other tasks:
2849
+
2850
+ - **blockedBy**: List of task IDs that must complete before this task can start
2851
+ - **blocks**: List of task IDs that are waiting for this task (auto-synced, do not set manually)
2852
+
2853
+ **How it works:**
2854
+
2855
+ Task A (blockedBy: [])
2856
+ Task B (blockedBy: ["A"]) \u2190 B waits for A
2857
+ Task C (blockedBy: ["A"]) \u2190 C waits for A
2858
+
2859
+ When Task A completes:
2860
+ - blockedBy is cleared from B and C
2861
+ - Both B and C become ready (can run in parallel)
2862
+
2863
+ **Important:** When you set blockedBy via TaskUpdate, the reverse blocks relationship is automatically synchronized. Never manually set blocks.
2864
+
2865
+ ## Handling Natural Language Requests
2866
+
2867
+ When users provide vague or high-level requests (e.g., "build a user auth module"), you must:
2868
+ 1. **Decompose** the request into logical subtasks based on software engineering best practices
2869
+ 2. **Identify dependencies** between subtasks (what must complete before what can start)
2870
+ 3. **Create tasks first** with blockedBy=[] for all tasks
2871
+ 4. **Add dependencies second** using TaskUpdate.addBlockedBy
2872
+
2873
+ Common decomposition patterns:
2874
+ - **Database/API pattern**: Schema design \u2192 Table implementation \u2192 API endpoints \u2192 Tests
2875
+ - **Frontend pattern**: Design \u2192 Components \u2192 Integration \u2192 Testing
2876
+ - **Full-stack pattern**: Backend \u2192 API \u2192 Frontend \u2192 Integration tests
2877
+
2791
2878
  ## Examples of When to Use TaskCreate
2792
2879
 
2880
+ ### Category A: No Explicit Dependencies or Order (Most Common)
2881
+
2882
+ User provides a high-level request without specifying how to break it down or what should be done first.
2883
+
2793
2884
  <example>
2794
- User: I need to implement user registration, product catalog, and checkout.
2795
- Assistant: I will create tasks for each feature one by one.
2796
- *Creates tasks:*
2797
- 1. User registration
2798
- 2. Product catalog
2799
- 3. Checkout flow
2885
+ User: Build a user authentication module
2886
+
2887
+ Assistant: This is a complex feature that requires multiple components. Let me plan the implementation steps.
2888
+
2889
+ *Creates tasks (Phase 1):*
2890
+ TaskCreate(subject="Design auth database schema", activeForm="Designing auth database schema")
2891
+ TaskCreate(subject="Implement users table", activeForm="Implementing users table")
2892
+ TaskCreate(subject="Implement sessions table", activeForm="Implementing sessions table")
2893
+ TaskCreate(subject="Build auth API endpoints", activeForm="Building auth API endpoints")
2894
+ TaskCreate(subject="Write unit tests", activeForm="Writing unit tests")
2895
+ TaskCreate(subject="Write integration tests", activeForm="Writing integration tests")
2896
+
2897
+ *Adds dependencies (Phase 2):*
2898
+ TaskUpdate(taskId="2", addBlockedBy=["1"])
2899
+ TaskUpdate(taskId="3", addBlockedBy=["1"])
2900
+ TaskUpdate(taskId="4", addBlockedBy=["2", "3"])
2901
+ TaskUpdate(taskId="5", addBlockedBy=["4"])
2902
+ TaskUpdate(taskId="6", addBlockedBy=["4"])
2903
+
2904
+ Auth module planned: 6 tasks with dependency graph established. Starting with database design.
2905
+
2906
+ <reasoning>
2907
+ The assistant used TaskCreate because:
2908
+ 1. User provided a high-level feature request without task breakdown
2909
+ 2. Authentication module requires multiple components (database, tables, API, tests)
2910
+ 3. The assistant inferred dependencies based on software engineering practices: schema before tables, tables before API, API before tests
2911
+ 4. Two-phase pattern: create all tasks first, then link dependencies
2912
+ </reasoning>
2800
2913
  </example>
2801
2914
 
2802
2915
  <example>
2803
- User: Please add tests and run lint after the refactor.
2804
- Assistant: I'll seed tasks for the refactor and verification steps.
2805
- *Creates tasks:*
2806
- 1. Refactor target module
2807
- 2. Add tests
2808
- 3. Run lint and typecheck
2916
+ User: I want to add a dark mode toggle to the application settings. Make sure you run the tests when you're done!
2917
+
2918
+ Assistant: I'll help add a dark mode toggle. Let me plan the implementation steps.
2919
+
2920
+ *Creates tasks (Phase 1):*
2921
+ TaskCreate(subject="Create dark mode toggle component", activeForm="Creating dark mode toggle component")
2922
+ TaskCreate(subject="Add dark mode state management", activeForm="Adding dark mode state management")
2923
+ TaskCreate(subject="Implement dark theme styles", activeForm="Implementing dark theme styles")
2924
+ TaskCreate(subject="Update components for theme switching", activeForm="Updating components for theme switching")
2925
+ TaskCreate(subject="Run tests and fix failures", activeForm="Running tests and fixing failures")
2926
+
2927
+ *Adds dependencies (Phase 2):*
2928
+ TaskUpdate(taskId="3", addBlockedBy=["2"])
2929
+ TaskUpdate(taskId="4", addBlockedBy=["1", "3"])
2930
+ TaskUpdate(taskId="5", addBlockedBy=["4"])
2931
+
2932
+ Dark mode toggle planned: 5 tasks. Starting with the toggle component.
2933
+
2934
+ <reasoning>
2935
+ The assistant used TaskCreate because:
2936
+ 1. Adding dark mode is a multi-step feature requiring UI, state management, and styling changes
2937
+ 2. User explicitly requested tests be run afterward - this becomes the final task
2938
+ 3. Dependencies inferred: styles depend on state management, components depend on toggle and styles, tests run last
2939
+ </reasoning>
2809
2940
  </example>
2810
2941
 
2811
2942
  <example>
2812
- User: The API task depends on database schema changes.
2813
- Assistant: I'll create the tasks first, then add blockedBy using TaskUpdate.
2814
- *Creates tasks without dependencies, then updates blockedBy*
2943
+ User: Help optimize my React app performance, rendering is slow
2944
+
2945
+ Assistant: Let me first examine the codebase to identify performance bottlenecks.
2946
+
2947
+ *Examines component structure, render patterns, state management*
2948
+
2949
+ After analyzing the codebase, I've identified several performance issues. Let me plan the optimizations.
2950
+
2951
+ *Creates tasks (Phase 1):*
2952
+ TaskCreate(subject="Add memoization to ProductList calculations", activeForm="Adding memoization to ProductList")
2953
+ TaskCreate(subject="Implement virtualization for Dashboard lists", activeForm="Implementing list virtualization")
2954
+ TaskCreate(subject="Optimize image loading in Gallery", activeForm="Optimizing image loading")
2955
+ TaskCreate(subject="Fix state update loops in ShoppingCart", activeForm="Fixing state update loops")
2956
+
2957
+ *Dependencies: These can be done at the same time, no specific order needed*
2958
+
2959
+ React performance optimization planned: 4 tasks. Starting with ProductList memoization.
2960
+
2961
+ <reasoning>
2962
+ The assistant used TaskCreate because:
2963
+ 1. First examined the codebase to identify specific performance issues
2964
+ 2. Multiple independent optimizations were identified - each becomes a task
2965
+ 3. These tasks have NO dependencies - they can run in parallel
2966
+ 4. Todo list helps track which optimizations have been addressed
2967
+ </reasoning>
2968
+ </example>
2969
+
2970
+ ### Category B: Explicit Order Specified by User
2971
+
2972
+ User clearly indicates what should be done first, second, etc. using words like "first... then... finally..." or numbered lists.
2973
+
2974
+ <example>
2975
+ User: First design the database, then create the users table and sessions table, then write the API, and finally test
2976
+
2977
+ Assistant: User has explicitly specified the order. Let me plan tasks according to this sequence.
2978
+
2979
+ *Creates tasks (Phase 1):*
2980
+ TaskCreate(subject="Design database schema", activeForm="Designing database schema")
2981
+ TaskCreate(subject="Implement users table", activeForm="Implementing users table")
2982
+ TaskCreate(subject="Implement sessions table", activeForm="Implementing sessions table")
2983
+ TaskCreate(subject="Build API endpoints", activeForm="Building API endpoints")
2984
+ TaskCreate(subject="Write tests", activeForm="Writing tests")
2985
+
2986
+ *Adds dependencies based on user's explicit order (Phase 2):*
2987
+ TaskUpdate(taskId="2", addBlockedBy=["1"]) // users table waits for database
2988
+ TaskUpdate(taskId="3", addBlockedBy=["1"]) // sessions table waits for database
2989
+ TaskUpdate(taskId="4", addBlockedBy=["2", "3"]) // API waits for both tables
2990
+ TaskUpdate(taskId="5", addBlockedBy=["4"]) // tests wait for API
2991
+
2992
+ Tasks planned in your specified order: database \u2192 users/sessions tables \u2192 API \u2192 tests
2993
+
2994
+ <reasoning>
2995
+ The assistant used TaskCreate because:
2996
+ 1. User explicitly specified the order: database first, then tables, then API, finally tests
2997
+ 2. This order translates directly into dependency relationships
2998
+ 3. Users table and sessions table can run in parallel after database (both depend only on task 1)
2999
+ 4. Two-phase pattern: create all tasks, then add dependencies matching user's specified order
3000
+ </reasoning>
2815
3001
  </example>
2816
3002
 
2817
3003
  <example>
2818
- User: Let's sketch the task list first and add dependencies later.
2819
- Assistant: I'll create the tasks now and we can add blockedBy with TaskUpdate afterward.
2820
- *Creates tasks without blockedBy*
3004
+ User: I need to add a character limit to the bio field. First, add the validation logic to the backend, then update the frontend form.
3005
+
3006
+ Assistant: I'll plan this with the order you specified.
3007
+
3008
+ *Creates tasks (Phase 1):*
3009
+ TaskCreate(subject="Add backend validation for bio character limit", activeForm="Adding backend validation")
3010
+ TaskCreate(subject="Update frontend form to enforce character limit", activeForm="Updating frontend form")
3011
+
3012
+ *Adds dependencies (Phase 2):*
3013
+ TaskUpdate(taskId="2", addBlockedBy=["1"]) // frontend waits for backend
3014
+
3015
+ Bio character limit planned: backend validation first, then frontend update.
3016
+
3017
+ <reasoning>
3018
+ The assistant used TaskCreate because:
3019
+ 1. User used "First... then..." which explicitly defines the order
3020
+ 2. Backend must be done before frontend - this is a dependency relationship
3021
+ 3. Two tasks with one dependency
3022
+ </reasoning>
2821
3023
  </example>
2822
3024
 
2823
3025
  <example>
2824
- User: Create just one task.
2825
- Assistant: I'll create a single task.
2826
- *Creates one task without auto dependency chaining*
3026
+ User: I need to implement user registration, product catalog, shopping cart, and checkout flow
3027
+
3028
+ Assistant: These are core e-commerce features. Let me plan tasks for each module.
3029
+
3030
+ *Creates tasks for each feature (Phase 1):*
3031
+ TaskCreate(subject="Implement user registration", activeForm="Implementing user registration")
3032
+ TaskCreate(subject="Implement product catalog", activeForm="Implementing product catalog")
3033
+ TaskCreate(subject="Implement shopping cart", activeForm="Implementing shopping cart")
3034
+ TaskCreate(subject="Implement checkout flow", activeForm="Implementing checkout flow")
3035
+
3036
+ *Adds dependencies (Phase 2):*
3037
+ TaskUpdate(taskId="3", addBlockedBy=["2"]) // cart depends on product catalog
3038
+ TaskUpdate(taskId="4", addBlockedBy=["1", "3"]) // checkout depends on registration and cart
3039
+
3040
+ E-commerce features planned: user registration and product catalog can start together, cart waits for catalog, checkout waits for registration and cart.
3041
+
3042
+ <reasoning>
3043
+ The assistant used TaskCreate because:
3044
+ 1. User provided multiple complex features in a comma-separated list
3045
+ 2. These features have natural dependencies: cart needs products, checkout needs user and cart
3046
+ 3. Registration and catalog can run in parallel (no dependency between them)
3047
+ 4. Todo list helps organize these large features into manageable tasks
3048
+ </reasoning>
3049
+ </example>
3050
+
3051
+ ### Category C: Simple or Single Task
3052
+
3053
+ User's request is straightforward and doesn't require complex planning.
3054
+
3055
+ <example>
3056
+ User: Just fix the typo in the documentation
3057
+
3058
+ Assistant: This is a straightforward fix. I'll create a single task to track it.
3059
+
3060
+ *Creates one task:*
3061
+ TaskCreate(subject="Fix typo in documentation", activeForm="Fixing documentation typo")
3062
+
3063
+ <reasoning>
3064
+ The assistant used TaskCreate because:
3065
+ 1. This is a single task that can be tracked
3066
+ 2. No complex breakdown needed
3067
+ 3. Still useful to track for completeness and progress visibility
3068
+ </reasoning>
3069
+ </example>
3070
+
3071
+ <example>
3072
+ User: Add a comment to the calculateTotal function explaining what it does
3073
+
3074
+ Assistant: This is a simple single-step task.
3075
+
3076
+ *Creates one task:*
3077
+ TaskCreate(subject="Add comment to calculateTotal function", activeForm="Adding function comment")
3078
+
3079
+ <reasoning>
3080
+ The assistant used TaskCreate because:
3081
+ 1. Single straightforward task in one location
3082
+ 2. Creating a task helps track completion
3083
+ </reasoning>
3084
+ </example>
3085
+
3086
+ ### Category D: Adding Forgotten Tasks
3087
+
3088
+ User realizes something was missed after the initial plan.
3089
+
3090
+ <example>
3091
+ User: I forgot, we also need logging for the auth module
3092
+
3093
+ Assistant: Let me add the logging task and link it appropriately.
3094
+
3095
+ TaskCreate(subject="Add auth logging", activeForm="Adding auth logging")
3096
+
3097
+ *The logging task depends on API endpoints being ready:*
3098
+ TaskUpdate(taskId="7", addBlockedBy=["4"]) // logging depends on API
3099
+
3100
+ Auth logging added. It will be done after the API endpoints are complete.
3101
+
3102
+ <reasoning>
3103
+ The assistant used TaskCreate because:
3104
+ 1. User added a new requirement after initial planning
3105
+ 2. New task was created first with TaskCreate
3106
+ 3. Then linked to existing tasks via TaskUpdate.addBlockedBy
3107
+ 4. Logging logically depends on API endpoints existence
3108
+ </reasoning>
2827
3109
  </example>
2828
3110
  `.trim();
2829
3111
 
2830
3112
  // src/tools/interaction/TaskCreateTool/TaskCreateTool.tsx
2831
3113
  var inputSchema8 = z9.strictObject({
3114
+ listId: z9.string().min(1).optional(),
2832
3115
  subject: z9.string().min(1),
2833
3116
  description: z9.string().min(1),
2834
- activeForm: z9.string().min(1).optional(),
3117
+ activeForm: z9.string().min(1),
2835
3118
  metadata: metadataSchema.optional()
2836
3119
  });
2837
3120
  var TaskCreateTool = {
@@ -2876,14 +3159,17 @@ var TaskCreateTool = {
2876
3159
  description: input.description,
2877
3160
  activeForm: input.activeForm,
2878
3161
  metadata: input.metadata
2879
- });
2880
- const { listId } = getTaskListPaths();
2881
- emitReminderEvent("task.created", {
3162
+ }, { listId: input.listId });
3163
+ const { listId } = getTaskListPaths(input.listId);
3164
+ const timestamp = Date.now();
3165
+ const payload = {
2882
3166
  listId,
2883
3167
  taskId: task.id,
2884
3168
  task,
2885
- timestamp: Date.now()
2886
- });
3169
+ timestamp
3170
+ };
3171
+ emitReminderEvent("task.created", payload);
3172
+ emitReminderEvent("task.created.v1", payload);
2887
3173
  yield {
2888
3174
  type: "result",
2889
3175
  data: {
@@ -2941,6 +3227,7 @@ Assistant: I'll fetch the task details first.
2941
3227
 
2942
3228
  // src/tools/interaction/TaskGetTool/TaskGetTool.tsx
2943
3229
  var inputSchema9 = z10.strictObject({
3230
+ listId: z10.string().min(1).optional(),
2944
3231
  taskId: z10.string().min(1)
2945
3232
  });
2946
3233
  var TaskGetTool = {
@@ -2978,8 +3265,8 @@ var TaskGetTool = {
2978
3265
  return null;
2979
3266
  },
2980
3267
  async *call(input) {
2981
- const { listId } = getTaskListPaths();
2982
- const task = getTask(input.taskId);
3268
+ const { listId } = getTaskListPaths(input.listId);
3269
+ const task = getTask(input.taskId, { listId: input.listId });
2983
3270
  if (!task) {
2984
3271
  yield {
2985
3272
  type: "result",
@@ -3026,6 +3313,7 @@ Skip using this tool when:
3026
3313
  NOTE that TaskList is for summaries and readiness; use TaskGet for details.
3027
3314
 
3028
3315
  ## Input Notes
3316
+ - listId is optional; omit to use the default list.
3029
3317
  - status filters the returned items; omit to exclude deleted tasks by default.
3030
3318
  - blockedBy may be empty early in planning and will appear as dependencies are added.
3031
3319
  - Do not mention tool names or tool usage in user-facing messages.
@@ -3053,6 +3341,7 @@ Assistant: I'll list tasks to show the updated ready/blocked breakdown.
3053
3341
 
3054
3342
  // src/tools/interaction/TaskListTool/TaskListTool.tsx
3055
3343
  var inputSchema10 = z11.strictObject({
3344
+ listId: z11.string().min(1).optional(),
3056
3345
  status: z11.enum(["pending", "in_progress", "completed", "deleted"]).optional()
3057
3346
  });
3058
3347
  var filterByStatus = (tasks, statuses) => {
@@ -3069,6 +3358,21 @@ var mapStatusFilterInput = (input) => {
3069
3358
  if (input === "pending") return ["pending"];
3070
3359
  return ["in_progress"];
3071
3360
  };
3361
+ var getActiveBlockers = (task, tasksById) => {
3362
+ const blockers = task.blockedBy ?? [];
3363
+ const active = [];
3364
+ for (const blockerId of blockers) {
3365
+ const blocker = tasksById.get(blockerId);
3366
+ if (!blocker) {
3367
+ active.push(blockerId);
3368
+ continue;
3369
+ }
3370
+ if (blocker.status !== "done" && blocker.status !== "deleted") {
3371
+ active.push(blockerId);
3372
+ }
3373
+ }
3374
+ return active;
3375
+ };
3072
3376
  var TaskListTool = {
3073
3377
  name: "TaskList",
3074
3378
  cachedDescription: DESCRIPTION7,
@@ -3105,10 +3409,19 @@ var TaskListTool = {
3105
3409
  },
3106
3410
  async *call(input) {
3107
3411
  try {
3108
- const { listId } = getTaskListPaths();
3109
- const tasks = listTasks();
3412
+ const { listId } = getTaskListPaths(input.listId);
3413
+ const tasks = listTasks({ listId: input.listId });
3110
3414
  const filtered = filterByStatus(tasks, mapStatusFilterInput(input.status));
3111
- const items = filtered.map(toTaskListItem);
3415
+ const tasksById = new Map(tasks.map((task) => [task.id, task]));
3416
+ const items = filtered.map((task) => {
3417
+ const base = toTaskListItem(task);
3418
+ const activeBlockers = getActiveBlockers(task, tasksById);
3419
+ return {
3420
+ ...base,
3421
+ ready: task.status === "pending" && activeBlockers.length === 0,
3422
+ activeBlockers
3423
+ };
3424
+ });
3112
3425
  yield {
3113
3426
  type: "result",
3114
3427
  data: {
@@ -3157,40 +3470,350 @@ NOTE that TaskUpdate should be used when you need to persist task changes.
3157
3470
  - listId is optional; omit to use the default list.
3158
3471
  - Dependencies are validated for cycles; invalid cycles will be rejected.
3159
3472
  - Use TaskUpdate to add blockedBy after tasks are created.
3473
+ - Use addBlocks when the current task should block other tasks; the reverse blockedBy relation is synchronized.
3160
3474
  - You can set metadata.planFinalized="true" to trigger a full dependency validation pass.
3161
- - activeForm must be provided; it is not generated from subject.
3475
+ - activeForm is optional in updates; when omitted, existing value is preserved.
3162
3476
  - blockedBy is always stored as an array (empty when not used).
3163
3477
  - description and blockedBy are kept separate in JSON; any joining is only for terminal rendering.
3164
3478
  - Task ordering relies on task id; do not use priority fields.
3165
3479
  - Do not mention tool names or tool usage in user-facing messages.
3166
3480
 
3481
+ ## The Two Usage Patterns
3482
+
3483
+ ### Pattern 1: Dependency Linking (After TaskCreate)
3484
+ Use TaskUpdate to establish dependencies AFTER all tasks are created:
3485
+ - Create tasks with TaskCreate (blockedBy=[])
3486
+ - Link dependencies with TaskUpdate.addBlockedBy or TaskUpdate.addBlocks
3487
+ - This ensures reference validity and clean graph construction
3488
+
3489
+ ### Pattern 2: Status Progression
3490
+ Use TaskUpdate to move tasks through the execution lifecycle:
3491
+ - pending \u2192 in_progress: When starting work on a task
3492
+ - in_progress \u2192 completed: When task is done (triggers unlock propagation)
3493
+ - Any \u2192 deleted: When task is obsolete or cancelled
3494
+
3495
+ ## Update Patterns
3496
+ - Simple status-only update: update one task status directly (pending \u2192 in_progress \u2192 completed) when no dependency change is needed.
3497
+ - Complex dependency and unlock update: update blockedBy/addBlocks and status together, then consume unlockResult.readyNow immediately.
3498
+ - Cancel or retire path: use deleted when a task is intentionally retired and should no longer appear in default lists.
3499
+
3167
3500
  ## Field Guidance
3168
3501
  - activeForm: short verb phrase describing the in-progress action.
3169
3502
  - description: prefer a one-line overview plus bullet points for multi-step tasks; for very simple tasks a short sentence is fine.
3503
+ - collaboration metadata keys:
3504
+ - metadata.owner for task owner identity
3505
+ - metadata.worktree for bound worktree name
3506
+ - metadata.lane for collaboration lane
3507
+ - metadata.agent for agent role or identifier
3508
+ - metadata.created_at for creation timestamp
3509
+ - metadata.updated_at for update timestamp
3170
3510
 
3171
3511
  ## Status Notes
3172
3512
  - Use in_progress for the task you are actively working on.
3173
3513
  - Use pending when dependencies prevent progress and set blockedBy.
3174
3514
  - Use completed only when all dependencies are satisfied.
3515
+ - When status becomes completed, consume unlockResult.readyNow immediately.
3516
+ - If readyNow is returned, continue with those tasks without calling TaskList.
3517
+
3518
+ ## Task Lifecycle Overview
3519
+
3520
+ Tasks flow through these states:
3521
+
3522
+ - pending --(start work)--> in_progress --(complete)--> done
3523
+ - pending --(cancel)--> deleted
3524
+ - in_progress --(cancel)--> deleted
3525
+
3526
+ **State Definitions:**
3527
+ - **pending**: Not started, may be blocked by dependencies
3528
+ - **in_progress**: Currently being worked on (only ONE task at a time)
3529
+ - **done**: Successfully completed (triggers unlock propagation)
3530
+ - **deleted**: Cancelled or no longer needed
3531
+
3532
+ **Ready vs Blocked:**
3533
+ - A task is **ready** when: status=pending AND blockedBy=[] (all dependencies satisfied)
3534
+ - A task is **blocked** when: blockedBy contains task IDs that are not yet done/deleted
3535
+
3536
+ ## Dependency Relationships
3537
+
3538
+ Tasks can have dependencies on other tasks:
3539
+
3540
+ - **blockedBy**: List of task IDs that must complete before this task can start
3541
+ - **blocks**: List of task IDs that are waiting for this task (auto-synced, do not set manually)
3542
+
3543
+ **How it works:**
3544
+
3545
+ Task A (blockedBy: [])
3546
+ Task B (blockedBy: ["A"]) \u2190 B waits for A
3547
+ Task C (blockedBy: ["A"]) \u2190 C waits for A
3548
+
3549
+ When Task A completes:
3550
+ - blockedBy is cleared from B and C
3551
+ - Both B and C become ready (can run in parallel)
3552
+
3553
+ **Important:** When you set blockedBy via TaskUpdate, the reverse blocks relationship is automatically synchronized. Never manually set blocks.
3554
+
3555
+ ## Understanding Unlock Propagation
3556
+
3557
+ When a task is marked as completed:
3558
+ 1. It is removed from the blockedBy list of all tasks it was blocking
3559
+ 2. Any tasks that become unblocked (blockedBy becomes empty) appear in unlockResult.readyNow
3560
+ 3. You should immediately continue with those readyNow tasks without calling TaskList
3561
+
3562
+ This enables efficient "chain execution" without redundant status checks.
3175
3563
 
3176
3564
  ## Examples of When to Use TaskUpdate
3177
3565
 
3566
+ ### Category A: Status Progression (Moving Tasks Forward)
3567
+
3178
3568
  <example>
3179
- User: Mark the API task as in progress.
3180
- Assistant: I'll update the task status.
3181
- *Updates task status to in_progress*
3569
+ User: The database design is done, let's start on the users table
3570
+
3571
+ Assistant: Database design is complete. Let me update the task status and continue to the next step.
3572
+
3573
+ TaskUpdate(taskId="1", status="completed")
3574
+ *Result shows readyNow: ["2", "3"]*
3575
+
3576
+ Both the users table and sessions table are now ready. I'll start with the users table.
3577
+
3578
+ TaskUpdate(taskId="2", status="in_progress")
3579
+
3580
+ <reasoning>
3581
+ The assistant used TaskUpdate because:
3582
+ 1. User indicated the database design is done
3583
+ 2. Completing task 1 triggers unlock - tasks 2 and 3 become ready
3584
+ 3. User said to start the users table
3585
+ 4. The unlockResult.readyNow tells us what tasks are now unblocked
3586
+ </reasoning>
3587
+ </example>
3588
+
3589
+ <example>
3590
+ User: I've finished the API endpoints. What should I work on next?
3591
+
3592
+ Assistant: Let me mark the API task complete and see what's unblocked.
3593
+
3594
+ TaskUpdate(taskId="4", status="completed")
3595
+ *Result shows readyNow: ["5", "6"]*
3596
+
3597
+ The unit tests and integration tests are now ready. Would you like to start with unit tests?
3598
+
3599
+ <reasoning>
3600
+ The assistant used TaskUpdate because:
3601
+ 1. User said they finished the API endpoints
3602
+ 2. Completing this task triggers unlock propagation
3603
+ 3. The readyNow field shows which tasks can now start
3604
+ 4. This enables efficient "chain execution" without calling TaskList
3605
+ </reasoning>
3606
+ </example>
3607
+
3608
+ <example>
3609
+ User: Start writing the tests
3610
+
3611
+ Assistant: I'll mark the test task as in progress.
3612
+
3613
+ TaskUpdate(taskId="5", status="in_progress")
3614
+
3615
+ <reasoning>
3616
+ The assistant used TaskUpdate because:
3617
+ 1. User wants to start working on tests
3618
+ 2. Simple status progression: pending \u2192 in_progress
3619
+ </reasoning>
3620
+ </example>
3621
+
3622
+ ### Category B: Task Completion and Chain Execution
3623
+
3624
+ <example>
3625
+ User: The database design is complete
3626
+
3627
+ Assistant: Database design task is complete. Let me check what tasks are now ready.
3628
+
3629
+ TaskUpdate(taskId="1", status="completed")
3630
+ *Result shows unlockResult.readyNow: ["2", "3"]*
3631
+
3632
+ The users table and sessions table can now be done together. I'll continue with the users table.
3633
+
3634
+ TaskUpdate(taskId="2", status="in_progress")
3635
+ *Continuing with unblocked task without calling TaskList*
3636
+
3637
+ <reasoning>
3638
+ The assistant used TaskUpdate because:
3639
+ 1. User reported completion of database design
3640
+ 2. unlockResult.readyNow shows tasks 2 and 3 are now unblocked and can run in parallel
3641
+ 3. Assistant immediately continues with task 2 - efficient chain execution
3642
+ 4. No need to call TaskList to check status
3643
+ </reasoning>
3644
+ </example>
3645
+
3646
+ ### Category C: Task Obsolescence or Cancellation
3647
+
3648
+ <example>
3649
+ User: This feature is no longer needed, let's skip it for now
3650
+
3651
+ Assistant: I'll mark this task as deleted.
3652
+
3653
+ TaskUpdate(taskId="3", status="deleted")
3654
+
3655
+ <reasoning>
3656
+ The assistant used TaskUpdate because:
3657
+ 1. User said the feature is no longer needed
3658
+ 2. "deleted" status removes it from active task flow
3659
+ 3. This may unblock other tasks that were waiting on this one
3660
+ </reasoning>
3661
+ </example>
3662
+
3663
+ <example>
3664
+ User: Actually, we don't need the session table anymore. We're using JWT instead.
3665
+
3666
+ Assistant: I'll mark the session table task as deleted since we're switching to JWT.
3667
+
3668
+ TaskUpdate(taskId="3", status="deleted")
3669
+
3670
+ *If task 3 was blocking other tasks, they may now be unblocked*
3671
+
3672
+ <reasoning>
3673
+ The assistant used TaskUpdate because:
3674
+ 1. User indicated a change in approach (JWT instead of sessions)
3675
+ 2. The session table task is now obsolete
3676
+ 3. Marking as deleted removes it from active work
3677
+ </reasoning>
3678
+ </example>
3679
+
3680
+ ### Category D: Adding New Requirements During Execution
3681
+
3682
+ <example>
3683
+ User: The auth module also needs a password reset feature
3684
+
3685
+ Assistant: Adding password reset functionality. Let me create a new task and add it to the existing plan.
3686
+
3687
+ TaskCreate(subject="Implement password reset", activeForm="Implementing password reset")
3688
+
3689
+ *This new task may need to be linked to existing tasks:*
3690
+ TaskUpdate(taskId="7", addBlockedBy=["4"]) // password reset depends on API endpoints
3691
+
3692
+ Password reset feature added to task list, depends on API endpoints completion.
3693
+
3694
+ <reasoning>
3695
+ The assistant used TaskUpdate because:
3696
+ 1. User added a new requirement during execution
3697
+ 2. New task was created first
3698
+ 3. Then dependency was added using TaskUpdate
3699
+ 4. Password reset logically depends on the API endpoints being ready
3700
+ </reasoning>
3701
+ </example>
3702
+
3703
+ <example>
3704
+ User: We need to add rate limiting to the auth endpoints too
3705
+
3706
+ Assistant: I'll add a rate limiting task and link it appropriately.
3707
+
3708
+ TaskCreate(subject="Add rate limiting to auth endpoints", activeForm="Adding rate limiting")
3709
+ TaskUpdate(taskId="8", addBlockedBy=["4"]) // rate limiting depends on API
3710
+
3711
+ Rate limiting task added. It will start after the API endpoints are complete.
3712
+
3713
+ <reasoning>
3714
+ The assistant used TaskUpdate because:
3715
+ 1. User added a new requirement
3716
+ 2. Create task first, then add dependency
3717
+ 3. Rate limiting applies to API endpoints, so it depends on task 4
3718
+ </reasoning>
3719
+ </example>
3720
+
3721
+ ### Category E: Dependency Adjustment
3722
+
3723
+ <example>
3724
+ User: The users table doesn't need to wait for database design, we can do it at the same time
3725
+
3726
+ Assistant: I'll remove this dependency.
3727
+
3728
+ TaskUpdate(taskId="2", blockedBy=[])
3729
+
3730
+ The users table can now start immediately, no need to wait for database design.
3731
+
3732
+ <reasoning>
3733
+ The assistant used TaskUpdate because:
3734
+ 1. User said the users table no longer needs to wait for database design
3735
+ 2. Setting blockedBy=[] removes all blockers
3736
+ 3. Task 2 is now ready to start immediately
3737
+ </reasoning>
3182
3738
  </example>
3183
3739
 
3184
3740
  <example>
3185
- User: The UI task depends on the API task now.
3186
- Assistant: I'll update dependencies.
3187
- *Updates blockedBy to include the API task*
3741
+ User: Tests should wait until all development tasks are complete
3742
+
3743
+ Assistant: I'll set the test task to wait for all development tasks.
3744
+
3745
+ TaskUpdate(taskId="5", addBlockedBy=["1", "2", "3", "4"])
3746
+
3747
+ The test task will now wait for tasks 1-4 to all complete before starting.
3748
+
3749
+ <reasoning>
3750
+ The assistant used TaskUpdate because:
3751
+ 1. User specified that tests should wait for all development tasks
3752
+ 2. addBlockedBy adds new dependencies without removing existing ones
3753
+ 3. Task 5 will only be ready after all four development tasks complete
3754
+ </reasoning>
3188
3755
  </example>
3189
3756
 
3190
3757
  <example>
3191
- User: We've finished adding dependencies and want to finalize the plan.
3192
- Assistant: I'll set metadata.planFinalized to trigger the global validation.
3193
- *Updates metadata.planFinalized to "true"*
3758
+ User: The API doesn't need to wait for the sessions table anymore, just the users table
3759
+
3760
+ Assistant: I'll adjust the API's dependencies.
3761
+
3762
+ TaskUpdate(taskId="4", blockedBy=["2"]) // only keep users table dependency
3763
+
3764
+ The API now only needs to wait for the users table to complete.
3765
+
3766
+ <reasoning>
3767
+ The assistant used TaskUpdate because:
3768
+ 1. User specified a change in dependencies
3769
+ 2. Sessions table is no longer a blocker for API
3770
+ 3. Setting the full blockedBy list replaces the previous one
3771
+ </reasoning>
3772
+ </example>
3773
+
3774
+ ### Category F: Changing Execution Order
3775
+
3776
+ User wants to change the planned execution order.
3777
+
3778
+ <example>
3779
+ User: Wait, let's do the users table first, then the database
3780
+
3781
+ Assistant: I understand you want to change the execution order. Let me adjust the dependencies.
3782
+
3783
+ *Current state: users table (task 2) depends on database (task 1)*
3784
+
3785
+ TaskUpdate(taskId="2", blockedBy=[]) // users table no longer waits for database
3786
+ TaskUpdate(taskId="1", addBlockedBy=["2"]) // database now waits for users table
3787
+
3788
+ Order adjusted: users table first, then database. The users table can start immediately.
3789
+
3790
+ <reasoning>
3791
+ The assistant used TaskUpdate because:
3792
+ 1. User requested a reversal of execution order
3793
+ 2. First, remove the existing dependency from task 2
3794
+ 3. Then, create a reverse dependency where database waits for users table
3795
+ 4. Task 2 is now unblocked and ready to start immediately
3796
+ </reasoning>
3797
+ </example>
3798
+
3799
+ <example>
3800
+ User: Actually, let's do the users table and sessions table first, before the database design
3801
+
3802
+ Assistant: I'll reverse the dependency chain so both tables come before database design.
3803
+
3804
+ TaskUpdate(taskId="2", blockedBy=[]) // users table no longer blocked
3805
+ TaskUpdate(taskId="3", blockedBy=[]) // sessions table no longer blocked
3806
+ TaskUpdate(taskId="1", addBlockedBy=["2", "3"]) // database waits for both tables
3807
+
3808
+ Both tables can now start immediately. Database design will wait for both to complete.
3809
+
3810
+ <reasoning>
3811
+ The assistant used TaskUpdate because:
3812
+ 1. User wanted to completely reverse the execution order
3813
+ 2. Multiple dependencies needed to be cleared first
3814
+ 3. Then reverse dependencies were added via addBlockedBy
3815
+ 4. Tasks 2 and 3 are now unblocked and can run in parallel
3816
+ </reasoning>
3194
3817
  </example>
3195
3818
  `.trim();
3196
3819
 
@@ -3264,6 +3887,7 @@ var compareTaskId = (left, right) => {
3264
3887
  return left.id.localeCompare(right.id);
3265
3888
  };
3266
3889
  var inputSchema11 = z12.strictObject({
3890
+ listId: z12.string().min(1).optional(),
3267
3891
  taskId: z12.string().min(1),
3268
3892
  subject: z12.string().optional(),
3269
3893
  description: z12.string().optional(),
@@ -3308,8 +3932,8 @@ var TaskUpdateTool = {
3308
3932
  return null;
3309
3933
  },
3310
3934
  async *call(input) {
3311
- const { listId } = getTaskListPaths();
3312
- const existing = getTask(input.taskId);
3935
+ const { listId } = getTaskListPaths(input.listId);
3936
+ const existing = getTask(input.taskId, { listId: input.listId });
3313
3937
  if (!existing) {
3314
3938
  yield {
3315
3939
  type: "result",
@@ -3322,7 +3946,7 @@ var TaskUpdateTool = {
3322
3946
  };
3323
3947
  return;
3324
3948
  }
3325
- const tasks = listTasks();
3949
+ const tasks = listTasks({ listId: input.listId });
3326
3950
  const subject = input.subject ?? existing.subject;
3327
3951
  const mergedBlockedBy = mergeDeps(existing.blockedBy, input.addBlockedBy);
3328
3952
  const mappedStatus = mapStatusInput(input.status);
@@ -3454,7 +4078,7 @@ var TaskUpdateTool = {
3454
4078
  }
3455
4079
  }
3456
4080
  if (same) continue;
3457
- updateTask(task.id, { blockedBy: merged });
4081
+ updateTask(task.id, { blockedBy: merged }, { listId: input.listId });
3458
4082
  }
3459
4083
  const result = updateTask(
3460
4084
  input.taskId,
@@ -3465,23 +4089,30 @@ var TaskUpdateTool = {
3465
4089
  status: mappedStatus,
3466
4090
  metadata: metadataUpdate,
3467
4091
  blockedBy: mergedBlockedBy
3468
- }
4092
+ },
4093
+ { listId: input.listId }
3469
4094
  );
3470
4095
  const didDepsChange = depsChanged(existing, result.task);
3471
- emitReminderEvent("task.updated", {
4096
+ const updatedTimestamp = Date.now();
4097
+ const updatedPayload = {
3472
4098
  listId,
3473
4099
  taskId: result.task.id,
3474
4100
  task: result.task,
3475
- timestamp: Date.now()
3476
- });
4101
+ timestamp: updatedTimestamp
4102
+ };
4103
+ emitReminderEvent("task.updated", updatedPayload);
4104
+ emitReminderEvent("task.updated.v1", updatedPayload);
3477
4105
  if (existing.status !== result.task.status) {
3478
- emitReminderEvent("task.status_changed", {
4106
+ const statusTimestamp = Date.now();
4107
+ const statusPayload = {
3479
4108
  listId,
3480
4109
  taskId: result.task.id,
3481
4110
  previousStatus: existing.status,
3482
4111
  status: result.task.status,
3483
- timestamp: Date.now()
3484
- });
4112
+ timestamp: statusTimestamp
4113
+ };
4114
+ emitReminderEvent("task.status_changed", statusPayload);
4115
+ emitReminderEvent("task.status_changed.v1", statusPayload);
3485
4116
  }
3486
4117
  if (didDepsChange) {
3487
4118
  emitReminderEvent("task.deps_changed", {
@@ -3492,12 +4123,33 @@ var TaskUpdateTool = {
3492
4123
  timestamp: Date.now()
3493
4124
  });
3494
4125
  }
4126
+ if (result.unlockResult) {
4127
+ emitReminderEvent("task.unblocked.v1", {
4128
+ listId,
4129
+ taskId: result.task.id,
4130
+ unblocked: result.unlockResult.unblocked.map((task) => task.id),
4131
+ readyNow: result.unlockResult.readyNow.map((task) => task.id),
4132
+ touchedTaskIds: result.unlockResult.unlockSummary.touchedTaskIds,
4133
+ timestamp: Date.now()
4134
+ });
4135
+ }
3495
4136
  yield {
3496
4137
  type: "result",
3497
4138
  data: {
3498
4139
  listId,
3499
4140
  item: toTaskDetail(result.task),
3500
- depsChanged: didDepsChange
4141
+ depsChanged: didDepsChange,
4142
+ unlockResult: result.unlockResult ? {
4143
+ unblocked: result.unlockResult.unblocked.map(toTaskDetail),
4144
+ partiallyUnblocked: result.unlockResult.partiallyUnblocked.map(
4145
+ (item) => ({
4146
+ task: toTaskDetail(item.task),
4147
+ remainingBlockers: item.remainingBlockers
4148
+ })
4149
+ ),
4150
+ readyNow: result.unlockResult.readyNow.map(toTaskDetail),
4151
+ unlockSummary: result.unlockResult.unlockSummary
4152
+ } : void 0
3501
4153
  }
3502
4154
  };
3503
4155
  } catch (error) {