@scemoon/cdh 1.0.4 → 1.0.6

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 (269) hide show
  1. package/ai-dlc-skill/SKILL.md +4 -2
  2. package/ai-dlc-skill/agents/master.md +6 -0
  3. package/ai-dlc-skill/agents/plan-agent.md +2 -2
  4. package/ai-dlc-skill/agents/understand-agent.md +4 -4
  5. package/ai-dlc-skill/agents/verify-agent.md +1 -1
  6. package/ai-dlc-skill/architecture/project-structure.md +10 -10
  7. package/ai-dlc-skill/brownfield/README.md +2 -2
  8. package/ai-dlc-skill/brownfield/generate-context.sh +3 -3
  9. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +5 -5
  10. package/ai-dlc-skill/components/backend.md +1 -1
  11. package/ai-dlc-skill/components/web.md +2 -2
  12. package/ai-dlc-skill/contracts/README.md +3 -3
  13. package/ai-dlc-skill/cross-tool/cline/export.sh +1 -1
  14. package/ai-dlc-skill/cross-tool/copilot/export.sh +1 -1
  15. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +7 -3
  16. package/ai-dlc-skill/cross-tool/onecode/export.sh +14 -8
  17. package/ai-dlc-skill/phases/deliver/lifecycle.md +6 -6
  18. package/ai-dlc-skill/phases/deliver/prompt.md +2 -2
  19. package/ai-dlc-skill/phases/deliver/rules.md +1 -1
  20. package/ai-dlc-skill/phases/plan/lifecycle.md +11 -11
  21. package/ai-dlc-skill/phases/plan/prompt.md +6 -6
  22. package/ai-dlc-skill/phases/plan/rules.md +1 -1
  23. package/ai-dlc-skill/phases/understand/entry.md +1 -1
  24. package/ai-dlc-skill/phases/understand/lifecycle.md +7 -7
  25. package/ai-dlc-skill/phases/understand/prompt.md +8 -8
  26. package/ai-dlc-skill/phases/understand/rules.md +5 -5
  27. package/ai-dlc-skill/phases/verify/lifecycle.md +24 -24
  28. package/ai-dlc-skill/phases/verify/prompt.md +8 -8
  29. package/ai-dlc-skill/phases/verify/rules.md +9 -9
  30. package/ai-dlc-skill/providers/README.md +2 -2
  31. package/ai-dlc-skill/providers/aliyun/preview.yaml +2 -2
  32. package/ai-dlc-skill/providers/tcb/preview.yaml +2 -2
  33. package/ai-dlc-skill/requirements.md +7 -7
  34. package/ai-dlc-skill/skill.yaml +4 -4
  35. package/ai-dlc-skill/templates/integration/CHANGELOG.md +2 -2
  36. package/ai-dlc-skill/templates/integration/contract-diff.md +7 -7
  37. package/ai-dlc-skill/templates/integration/contract-spec.md +7 -7
  38. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +1 -1
  39. package/ai-dlc-skill/templates/project/README.md +18 -19
  40. package/ai-dlc-skill/templates/project/template.md +21 -21
  41. package/ai-dlc-skill/walkthrough/collect.sh +1 -1
  42. package/ai-dlc-skill/walkthrough/template.md +2 -2
  43. package/ai-dlc-skill/workflows/ai-dlc.yaml +12 -12
  44. package/ai-dlc-skill/workflows/deployment.yaml +4 -4
  45. package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
  46. package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
  47. package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
  48. package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
  49. package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
  50. package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
  51. package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
  52. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  53. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  54. package/cdh/cdh_mcp_injector.py +115 -0
  55. package/cdh/cdh_mcp_loader.py +67 -0
  56. package/cdh/cdh_mcp_manager.py +73 -0
  57. package/cdh/cdh_session_aggregator.py +258 -0
  58. package/cdh/cdh_skill_manager.py +105 -0
  59. package/cdh/cli.py +64 -4
  60. package/cdh/scaffold.py +192 -41
  61. package/onecode/__init__.py +1 -1
  62. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  63. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  64. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  65. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  66. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  67. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  68. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  69. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  70. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  71. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  72. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  73. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  74. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  75. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  76. package/onecode/agent/agents/types.py +47 -164
  77. package/onecode/agent/attachments.py +0 -1
  78. package/onecode/agent/cdh_loader.py +17 -25
  79. package/onecode/agent/context.py +8 -3
  80. package/onecode/agent/engine.py +835 -220
  81. package/onecode/agent/hooks.py +1 -1
  82. package/onecode/agent/onecode_agent_acp.py +460 -47
  83. package/onecode/agent/onecode_agent_acp.py.bak +2447 -0
  84. package/onecode/agent/permissions.py +0 -1
  85. package/onecode/agent/project_doc.py +19 -0
  86. package/onecode/agent/session.py +17 -3
  87. package/onecode/agent/snapshot.py +3 -4
  88. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  89. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  90. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  91. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  92. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  93. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  94. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  95. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  96. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  97. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  98. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  99. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  100. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  101. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  102. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  103. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  104. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  105. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  106. package/onecode/agent/tools/agent_tools.py +4 -6
  107. package/onecode/agent/tools/apply_patch_tool.py +2 -8
  108. package/onecode/agent/tools/bash_tool.py +32 -12
  109. package/onecode/agent/tools/communication_tools.py +4 -5
  110. package/onecode/agent/tools/config_tool.py +3 -3
  111. package/onecode/agent/tools/cron_tools.py +4 -5
  112. package/onecode/agent/tools/file_ops.py +37 -3
  113. package/onecode/agent/tools/file_tools.py +10 -11
  114. package/onecode/agent/tools/git_tools.py +2 -2
  115. package/onecode/agent/tools/lsp_tools.py +2 -2
  116. package/onecode/agent/tools/mcp_tools.py +3 -5
  117. package/onecode/agent/tools/permission_handler.py +1 -1
  118. package/onecode/agent/tools/protocol.py +1 -1
  119. package/onecode/agent/tools/registry.py +69 -2
  120. package/onecode/agent/tools/sandbox.py +110 -16
  121. package/onecode/agent/tools/skill_tools.py +2 -2
  122. package/onecode/agent/tools/todo_tools.py +38 -19
  123. package/onecode/agent/tools/web_tools.py +6 -7
  124. package/onecode/builtin_skills/agent-browser/SKILL.md +212 -0
  125. package/onecode/builtin_skills/agent-browser/skill.yaml +8 -0
  126. package/onecode/builtin_skills/skill-creator/SKILL.md +106 -0
  127. package/onecode/builtin_skills/skill-creator/skill.yaml +8 -0
  128. package/onecode/cli.py +186 -6
  129. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  130. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  131. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  132. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  133. package/onecode/codebase/chunker.py +0 -5
  134. package/onecode/codebase/indexer.py +14 -1
  135. package/onecode/codebase/retriever.py +13 -2
  136. package/onecode/codebase/storage.py +5 -4
  137. package/onecode/commands.py +81 -6
  138. package/onecode/config.py +41 -12
  139. package/onecode/config_screen.py +7 -3
  140. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  141. package/onecode/mcp/manager.py +2 -3
  142. package/onecode/memory/__init__.py +7 -53
  143. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  144. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  145. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  146. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  147. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  148. package/onecode/memory/backend.py +13 -39
  149. package/onecode/memory/pyramid.py +2 -71
  150. package/onecode/memory/recall.py +38 -3
  151. package/onecode/migrate.py +122 -0
  152. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  153. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  154. package/onecode/models/messages.py +58 -0
  155. package/onecode/models/provider.py +20 -2
  156. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  157. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  158. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  159. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  160. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  161. package/onecode/models/providers/anthropic_provider.py +59 -12
  162. package/onecode/models/providers/glm_provider.py +40 -0
  163. package/onecode/models/providers/minimax_provider.py +3 -0
  164. package/onecode/models/providers/minimaxi_provider.py +3 -0
  165. package/onecode/models/providers/ollama_provider.py +3 -0
  166. package/onecode/server/app.py +1 -1
  167. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  168. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  169. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  170. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  171. package/onecode/skills/argument_substitution.py +0 -1
  172. package/onecode/skills/bootstrap.py +124 -0
  173. package/onecode/skills/loader.py +35 -53
  174. package/onecode/skills/manager.py +2 -2
  175. package/onecode/storage/activity.py +3 -4
  176. package/onecode/storage/session.py +3 -4
  177. package/onecode/tasks/manager.py +23 -10
  178. package/onecode/trace/tracer.py +2 -3
  179. package/package.json +1 -1
  180. package/pyproject.toml +5 -1
  181. package/run.js +68 -14
  182. package/tui/__pycache__/about.cpython-314.pyc +0 -0
  183. package/tui/__pycache__/app.cpython-313.pyc +0 -0
  184. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  185. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  186. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  187. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  188. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  189. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  190. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  191. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  192. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  193. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  194. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  195. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  196. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  197. package/tui/acp/agent.py +125 -58
  198. package/tui/acp/api.py +12 -0
  199. package/tui/acp/messages.py +3 -1
  200. package/tui/acp/prompt.py +0 -57
  201. package/tui/acp/protocol.py +6 -0
  202. package/tui/app.py +11 -33
  203. package/tui/messages.py +2 -0
  204. package/tui/path_complete.py +1 -1
  205. package/tui/paths.py +16 -0
  206. package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
  207. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  208. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  209. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  210. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  211. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  212. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  213. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  214. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  215. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  216. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  217. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  218. package/tui/screens/component_picker.py +35 -15
  219. package/tui/screens/diff_screen.py +84 -0
  220. package/tui/screens/log.py +25 -25
  221. package/tui/screens/main.py +48 -26
  222. package/tui/screens/projects.tcss +5 -1
  223. package/tui/screens/projects_app.py +6 -6
  224. package/tui/screens/projects_screen.py +19 -39
  225. package/tui/screens/sessions.py +3 -5
  226. package/tui/session_tracker.py +3 -0
  227. package/tui/settings_schema.py +1 -1
  228. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  229. package/tui/visuals/columns.py +1 -2
  230. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  231. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  232. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  233. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  234. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  235. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  236. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  237. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  238. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  239. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  240. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  241. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  242. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  243. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  244. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  245. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  246. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  247. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  248. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  249. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  250. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  251. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  252. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  253. package/tui/widgets/agent_response.py +0 -1
  254. package/tui/widgets/agent_thought.py +0 -1
  255. package/tui/widgets/conversation.py +157 -14
  256. package/tui/widgets/diff_view.py +10 -0
  257. package/tui/widgets/load_more.py +24 -0
  258. package/tui/widgets/modified_files.py +86 -12
  259. package/tui/widgets/plan.py +1 -1
  260. package/tui/widgets/project_grid_select.py +9 -2
  261. package/tui/widgets/session_grid_select.py +6 -0
  262. package/tui/widgets/side_bar.py +10 -0
  263. package/tui/widgets/subagent.py +92 -58
  264. package/tui/widgets/subagent_screen.py +638 -115
  265. package/tui/widgets/terminal.py +1 -2
  266. package/tui/widgets/terminal_tool.py +11 -2
  267. package/tui/widgets/tool_call.py +35 -2
  268. package/onecode/memory/offload.py +0 -114
  269. package/onecode/memory/symbolic.py +0 -164
@@ -191,9 +191,8 @@ class GeneralAgent(AgentConfig):
191
191
  permission_bash=AgentPermission.ALLOW,
192
192
  permission_read=AgentPermission.ALLOW,
193
193
  permission_task=AgentPermission.DENY,
194
- permission_question=AgentPermission.DENY,
195
- permission_todowrite=AgentPermission.DENY,
196
- disallowed_tools=["Spawn", "Agent", "AskUser"],
194
+ permission_question=AgentPermission.ALLOW,
195
+ disallowed_tools=["Spawn", "Agent", "AskUser", "TodoCreate", "TodoGet", "TodoList", "TodoUpdate", "TodoOutput", "TodoStop", "TodoClear"],
197
196
  )
198
197
 
199
198
 
@@ -208,8 +207,7 @@ class ExploreAgent(AgentConfig):
208
207
  permission_read=AgentPermission.ALLOW,
209
208
  permission_task=AgentPermission.DENY,
210
209
  permission_question=AgentPermission.DENY,
211
- permission_todowrite=AgentPermission.DENY,
212
- disallowed_tools=["Spawn", "Agent", "AskUser"],
210
+ disallowed_tools=["Spawn", "Agent", "AskUser", "TodoCreate", "TodoGet", "TodoList", "TodoUpdate", "TodoOutput", "TodoStop", "TodoClear"],
213
211
  hidden=True,
214
212
  )
215
213
 
@@ -227,8 +225,7 @@ class ScoutAgent(AgentConfig):
227
225
  permission_websearch=AgentPermission.ALLOW,
228
226
  permission_task=AgentPermission.DENY,
229
227
  permission_question=AgentPermission.DENY,
230
- permission_todowrite=AgentPermission.DENY,
231
- disallowed_tools=["Spawn", "Agent", "AskUser"],
228
+ disallowed_tools=["Spawn", "Agent", "AskUser", "TodoCreate", "TodoGet", "TodoList", "TodoUpdate", "TodoOutput", "TodoStop", "TodoClear"],
232
229
  hidden=True,
233
230
  )
234
231
 
@@ -324,7 +321,7 @@ SUBAGENT_CONSTRAINTS = """
324
321
  You are running as a subagent spawned by a parent agent via the Spawn tool.
325
322
  - You CANNOT spawn subagents (Spawn tool is disabled).
326
323
  - You CANNOT execute batched tool calls (Agent tool is disabled).
327
- - You CANNOT manage task plans (TodoCreate/TodoUpdate/TodoStop are disabled).
324
+ - You CANNOT manage todos (all Todo* tools are disabled). The parent owns the shared plan.
328
325
  - You CANNOT interact with the user (AskUser is disabled).
329
326
  - You are a leaf node in the agent hierarchy. Execute the task in your prompt
330
327
  and return a structured SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS response.
@@ -404,9 +401,10 @@ Rules:
404
401
  - **WebSearch**: websearch(query) - Search the web and return results.
405
402
 
406
403
  ### Agent
407
- - **Task**: task(agent_type, prompt) - Spawn subagent to handle subtask.
404
+ - **Spawn**: spawn(agent_type, prompt) - Delegate execution of a complex todo to a specialized subagent (isolated context). Use for multi-file/multi-step work. Then TodoUpdate(status="completed").
408
405
  - **Agent**: agent(calls, stop_on_error=True) - Execute a batch of tool calls as an atomic step. Each call includes {name, input}. Halts on first error when stop_on_error is true.
409
406
  - **ToolSearch**: tool_search(query) - Search for available tools by keyword.
407
+ - **CodebaseSearch**: codebase_search(query, top_k=5) - Search the indexed codebase for code relevant to a query. Returns code chunks with file paths and line numbers. Use this to find relevant code before making changes.
410
408
  - **Skill**: skill(name) - Load skill by name.
411
409
 
412
410
  ### Communication
@@ -469,14 +467,15 @@ Rules:
469
467
  - **ConfigRead**: config_read(key) - Read configuration values.
470
468
  - **ConfigWrite**: config_write(key, value) - Set allowed configuration values (does NOT expose secrets).
471
469
 
472
- ### Tasks & Planning (CDH)
473
- - **TodoCreate**: todo_create(subject, description, activeForm="", metadata={}) - Create a task. Returns task id.
474
- - **TodoGet**: todo_get(taskId) - Retrieve a task by ID.
475
- - **TodoList**: todo_list() - List all tasks with status, owner, and blockers.
476
- - **TodoUpdate**: todo_update(taskId, subject, description, activeForm, status, owner, addBlocks, addBlockedBy, metadata, output) - Update task fields and dependencies.
477
- - **TodoOutput**: todo_output(task_id) - Get output from a task.
478
- - **TodoStop**: todo_stop(task_id) - Stop a running task.
479
- - **Spawn**: spawn(agent_type, prompt) - Delegate a subtask to a specialized subagent.
470
+ ### Planning (Todo) & Delegation (Spawn)
471
+ - **TodoCreate**: todo_create(subject, description, activeForm="", metadata={}) - Create a todo (plan item). ALL tasks use TodoCreate; persisted to .cdh/todos.json and mirrored to sidebar Plan. Returns todo id.
472
+ - **TodoGet**: todo_get(taskId) - Retrieve a todo by ID.
473
+ - **TodoList**: todo_list() - List all todos with status, owner, and blockers.
474
+ - **TodoUpdate**: todo_update(taskId, subject, description, activeForm, status, owner, addBlocks, addBlockedBy, metadata, output) - Update todo fields, status, and dependencies.
475
+ - **TodoOutput**: todo_output(taskId) - Get output from a todo.
476
+ - **TodoStop**: todo_stop(taskId) - Stop a running todo.
477
+ - **TodoClear**: todo_clear() - Clear ALL todos and start a fresh blank plan.
478
+ - **Spawn**: spawn(agent_type, prompt) - Delegate EXECUTION of a complex todo to a specialized subagent (isolated context). Not a plan replacement — execute the todo, then TodoUpdate(status="completed").
480
479
  """
481
480
 
482
481
  def filter_tool_descriptions(
@@ -518,161 +517,45 @@ def filter_tool_descriptions(
518
517
  return "\n".join(result_lines)
519
518
 
520
519
 
521
- REACT_CYCLE = """
522
- ## ReAct Cycle 思考 → 行动 → 观察
523
-
524
- You operate in a **ReAct loop with Chain of Thought (CoT) reasoning**:
525
-
526
- ```
527
- ┌────────────────────────────────────────────────────┐
528
- │ ╭──────────╮ ╭──────────╮ ╭──────────╮ │
529
- │ │ Thought │ → │ Action │ → │Observa- │ │
530
- │ │ (思考) │ │ (行动) │ │tion(观察)│ ──→ │
531
- │ ╰──────────╯ ╰──────────╯ ╰──────────╯ │
532
- │ ↑ ↓ (cycle continues) │
533
- │ │ │
534
- │ └──────── Feedback Loop ────────────────────┘ │
535
- └────────────────────────────────────────────────────┘
536
- ```
537
-
538
- ### Thought Phase (思考阶段)
539
- Before any action, reason step by step inside `<thinking>`:
540
- 1. **Current state**: What do I know? What has been done? What are the results?
541
- 2. **Goal**: What needs to be accomplished next?
542
- 3. **Plan**: How should I approach it? What's the smallest next step?
543
- 4. **Routing — choose by complexity**:
544
- - **Simple / single-step** → use a direct read/search/exec tool, optionally
545
- track with `TodoCreate` so the sidebar shows progress.
546
- - **Complex / multi-step** → use `Spawn(agent_type, prompt)` to delegate to
547
- a focused subagent.
548
- - **Multi-file refactor / new feature** → ALWAYS use `Spawn`.
549
-
550
- ### Action Phase (行动阶段)
551
- Execute the chosen action. **Action types (in priority order)**:
552
- 1. **Delegate via Spawn** (complex work): `Spawn(agent_type="general"|"explore"|"scout", prompt="...")`.
553
- 2. **Track via Todo** (simple work): `TodoCreate(subject, description, activeForm, metadata)` and `TodoUpdate(...)`. The sidebar shows progress to the user.
554
- 3. **Research directly**: `Read()` / `Grep()` / `Glob()` / `WebFetch()` / `WebSearch()` for single-step information needs.
555
- 4. **Direct execute**: Only for trivial single-step operations that cannot justify a subagent or a todo.
556
-
557
- ### Observation Phase (观察阶段)
558
- The tool result IS your observation. Process it:
559
- - **Success**: Note key outputs, update todo status via `TodoUpdate(status="completed")`, move to next step
560
- - **Error**: Diagnose root cause, decide: retry with fix | modify plan | ask user
561
- - **Partial**: Extract what worked, adjust approach for remaining work
562
-
563
- ### Core Rules
564
- - **ALL reasoning goes in `<thinking>`**: Never narrate "I will now..." in visible text
565
- - **Route by complexity**: Simple → Todo, complex → Spawn. Never blindly use Spawn for trivial work.
566
- - **One responsibility per Spawn / Todo**: Each unit should have a clear, focused goal
567
- - **Pass context**: Include relevant context (file paths, findings) in Spawn prompts and Todo descriptions
568
- - **CoT every cycle**: Every turn starts with `<thinking>` reasoning before any action
569
- """
570
-
571
- PLAN_INSTRUCTIONS = """
572
- ## ReAct Workflow (Thought → Action → Observation)
573
-
574
- The agent is a **ReAct** implementation: each cycle is **Thought → Action → Observation**.
575
- **Human-in-the-loop** means you involve the user at key decision points.
576
-
577
- ```
578
- Loop:
579
- Thought → Reason step by step (CoT) inside <thinking>
580
- Always ask: "Is this simple (Todo) or complex (Spawn)?"
581
- Action → Simple → TodoCreate + direct tool
582
- Complex → Spawn(agent_type, prompt)
583
- Observation → Incorporate results into the next Thought
584
- ```
585
-
586
- Plan/Build/Solo are different configurations of this same ReAct engine:
587
- - **plan** mode: hard gate — execution tools blocked until a todo plan exists.
588
- - **build**/**solo** mode: soft gate — execution allowed but planning encouraged.
589
-
590
- **Routing principle**:
591
- - **Simple todo** = 1 tool call, 1 file, ≤2 lines of code change, single Read/Glob. Use `TodoCreate` + direct tool.
592
- - **Complex work** = >1 tool call, multi-file, research, refactor, new feature. Use `Spawn(agent_type, prompt)`.
593
- - When in doubt, choose `Spawn`. Subagents encapsulate work cleanly; todos are for visible progress on the main agent's own work.
594
-
595
- ---
520
+ REACT_WORKFLOW = """
521
+ ## Workflow: 思考 Todo → 行动 (per-Round)
596
522
 
597
- ### Step 1: Think (CoT) Chain of Thought Reasoning
523
+ Each round: `<thinking>` Todo ops tool execution → TodoUpdate.
524
+ Tool results from the previous round are already in context — review them
525
+ at the start of `<thinking>`. No separate "Observation" step is needed.
598
526
 
599
- Analyze the request with step-by-step reasoning before any action.
527
+ ### Round Structure
600
528
 
601
- - Wrap ALL reasoning in `<thinking>...</thinking>` — visible text is for the user only
602
- - Think step by step: What's the goal? What's the current state? Is this simple or complex?
603
- - **Decide routing**:
604
- - For simple work proceed to `TodoCreate` then act directly.
605
- - For complex work → proceed to spawn subagents.
606
- - Read relevant files, grep for patterns, glob for structure
607
- - Use `webfetch`/`websearch` for external APIs or docs
608
- - Delegate deep research to `explore`/`scout` subagents via `Spawn`
609
- - Ask the user via `AskUser` if requirements are ambiguous
610
- - Do NOT create todos yet — first understand what is needed
529
+ **思考** (inside `<thinking>`):
530
+ 1. Review: what did the last round's tools produce? Any errors to address?
531
+ 2. Progress: which todos are done, which are pending?
532
+ 3. Decide: what is the single next action? Pick: direct tool or `Spawn`?
611
533
 
612
- ---
534
+ **Todo** (before acting):
535
+ - No todo for this work? → `TodoCreate` first.
536
+ - Todo exists? → advance it (`in_progress`).
537
+ - Completed work? → `TodoUpdate(status="completed")` immediately.
538
+ - Do NOT mark a todo as completed unless its work was actually executed.
613
539
 
614
- ### Step 2: Act (Plan) — Create the Todo Plan
540
+ **行动** (execute):
541
+ - Simple (1 tool, 1 file) → call the tool directly.
542
+ - Complex (multi-step/research) → `Spawn(agent_type, prompt)` to delegate.
543
+ - Spawn executes a todo — it does not replace one.
615
544
 
616
- Once you understand the work, create a complete todo plan via `TodoCreate()`.
617
-
618
- **Routing Granularity Rules**
619
- - One todo = one focused unit of work (file, function, or concern).
620
- - Each todo: decide at creation time whether it should be done by the main agent or delegated to a Spawn subagent.
621
- - Mark delegatable todos with `metadata={"delegate_to": "general"}` so the main agent knows to use `Spawn` for that item.
622
- - Simple todos (1 tool call) stay with the main agent.
623
- - If a todo needs >5 tool calls, split it into smaller todos.
624
-
625
- **Creating Todos**
626
- ```
627
- TodoCreate(subject="<verb + noun>", description="<what + acceptance criteria>",
628
- metadata={"priority": "high|medium|low",
629
- "effort": "small|medium|large",
630
- "delegate_to": "general|explore|scout|main"})
631
- ```
632
- - Set `addBlockedBy` on dependent todos so the dependency DAG is clear
633
- - **Create ALL todos upfront** before presenting the plan to the user
634
-
635
- **Present Plan for Review (Human-in-the-loop)**
636
- After creating all todos, use `AskUser` to summarize the plan and get approval
637
- before executing.
638
- Wait for user approval before moving to execution.
639
-
640
- ---
641
-
642
- ### Step 3: Act (Execute) — Route by Complexity
643
-
644
- Execute each todo using the right tool for the work:
645
-
646
- - **Simple todos** (single tool call): execute directly with `Read`/`Edit`/`Bash`, then `TodoUpdate(status="completed")`.
647
- - **Complex todos** (multi-step, multi-file, research):
648
- `Spawn(agent_type="general", prompt="Detailed instructions with context...")`.
649
- Wait for the subagent's SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS output, then
650
- `TodoUpdate(status="completed")`.
651
- - Use `general` subagent for implementation, `explore` for code search, `scout` for research
652
- - Pass enough context in the Spawn prompt: relevant file paths, code snippets, requirements
653
- - After each todo, advance its status: `pending` → `in_progress` → `completed`
654
-
655
- ---
656
-
657
- ### Step 4: Observe — Feed Results Back
658
-
659
- After every Action, the tool result is your **Observation**. Use it to inform the
660
- next Thought:
661
- - Spawn subagent completed → review SUMMARY/CHANGES/EVIDENCE/RISKS/BLOCKERS sections
662
- - TodoCreate succeeded → proceed to present plan or execute the next todo
663
- - Error occurred → diagnose and decide: retry, modify plan, or ask the user
664
- - User denied an action → adapt the todo plan accordingly
665
-
666
- ---
545
+ ### Routing
546
+ - Every task = a `TodoCreate`. No work without a todo.
547
+ - `Spawn` = execution delegation for complex todos only.
548
+ """
667
549
 
668
- ### Rules
550
+ PLAN_GATE_HARD = """
551
+ ### plan mode: hard gate
552
+ Execution tools (Write/Edit/Insert/ApplyPatch/Bash) are BLOCKED until a todo plan exists.
553
+ Create ALL todos upfront with `TodoCreate`, present for user review, then execute.
554
+ """
669
555
 
670
- - **No top-level planning prose**: All planning goes through `TodoCreate`/`TodoUpdate` so the sidebar renders it.
671
- - **CoT in `<thinking>`**: Every turn starts with chain-of-thought reasoning inside `<thinking>`. Never narrate "I will now…" in visible text.
672
- - **Route by complexity**: Simple Todo + direct tool. Complex → Spawn.
673
- - **Todo status discipline**: `pending` → `in_progress` → `completed`. Every todo transitions through all three.
674
- - **No execution without a plan**: Write/Edit/Insert/ApplyPatch/Bash require todos. Create todos first.
675
- - **Human at key decisions**: Present the plan, get approval, then execute. Report progress as you go.
556
+ PLAN_GATE_SOFT = """
557
+ ### build/solo mode: soft gate
558
+ Execution is allowed but planning is encouraged. Create todos first via `TodoCreate`.
676
559
  """
677
560
 
678
561
  COMPACTION_INSTRUCTIONS = """
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import fnmatch
4
3
  import mimetypes
5
4
  from dataclasses import dataclass, field
6
5
  from pathlib import Path
@@ -11,7 +11,7 @@ def _walk_up_parents(workspace_root: Path):
11
11
  """Yield workspace root, then git root.
12
12
 
13
13
  Unlike :class:`~onecode.skills.loader.SkillLoader` we deliberately do
14
- **not** yield ``Path.home()`` — the global ``~/.cdh/`` is the onecode
14
+ **not** yield ``Path.home()`` — the global ``~/.onecode/`` is the onecode
15
15
  user-config directory, not a project-level ``.cdh/``, so including it
16
16
  would cause false-positive matches.
17
17
  """
@@ -61,6 +61,16 @@ class CdhProjectLoader:
61
61
  return candidate
62
62
  return None
63
63
 
64
+ @staticmethod
65
+ def find_cdh_dir_for_todos(workspace_root: Path) -> Optional[Path]:
66
+ """Find ``.cdh/`` strictly at *workspace_root*, without walking up.
67
+
68
+ Used for todo persistence so sub-projects never accidentally load
69
+ or write to a parent project's ``.cdh/todos.json``.
70
+ """
71
+ candidate = workspace_root.resolve() / CdhProjectLoader.CDH_DIRNAME
72
+ return candidate if candidate.is_dir() else None
73
+
64
74
  # ── file readers ───────────────────────────────────────────
65
75
 
66
76
  @staticmethod
@@ -100,17 +110,6 @@ class CdhProjectLoader:
100
110
  encoding="utf-8",
101
111
  )
102
112
 
103
- @staticmethod
104
- def get_skill_content(cdh_dir: Path) -> str:
105
- """Read ``.cdh/SKILL.md`` if it exists."""
106
- skill_path = cdh_dir / "SKILL.md"
107
- if skill_path.exists():
108
- try:
109
- return skill_path.read_text(encoding="utf-8")
110
- except Exception:
111
- pass
112
- return ""
113
-
114
113
  # ── last-session persistence ───────────────────────────────
115
114
 
116
115
  @staticmethod
@@ -191,7 +190,6 @@ class CdhProjectLoader:
191
190
 
192
191
  config = CdhProjectLoader.load_project_config(cdh_dir)
193
192
  state = CdhProjectLoader.load_project_state(cdh_dir)
194
- skill = CdhProjectLoader.get_skill_content(cdh_dir)
195
193
 
196
194
  parts = ["## Project State (.cdh)"]
197
195
  name = config.get("name", cdh_dir.parent.name)
@@ -207,8 +205,6 @@ class CdhProjectLoader:
207
205
  parts.append(f"- Config: {json.dumps(config, ensure_ascii=False)}")
208
206
  if state:
209
207
  parts.append(f"- State: {json.dumps(state, ensure_ascii=False)}")
210
- if skill:
211
- parts.append(f"\n--- .cdh/SKILL.md ---\n{skill}")
212
208
 
213
209
  parts.append(
214
210
  "\n**Important**: Work directly in the project root directory shown above. "
@@ -229,8 +225,12 @@ class CdhProjectLoader:
229
225
  ) -> Path:
230
226
  """Scaffold a ``.cdh/`` directory inside *workspace_root*.
231
227
 
232
- Creates ``.cdh/config.yaml``, ``.cdh/state.json``, and a
233
- stub ``.cdh/SKILL.md``.
228
+ Creates ``.cdh/config.yaml`` and ``.cdh/state.json``.
229
+
230
+ Project-level agent instructions live in the workspace-root
231
+ ``AGENTS.md`` (read by :mod:`onecode.agent.project_doc`); we
232
+ intentionally do **not** create a stub inside ``.cdh/`` — that
233
+ would split a single source of truth across two files.
234
234
 
235
235
  If *workspace_root* is inside a directory that is already a
236
236
  ``.cdh/`` project, a warning is printed and the existing project
@@ -264,12 +264,4 @@ class CdhProjectLoader:
264
264
  state_path = cdh_dir / CdhProjectLoader.STATE_FILENAME
265
265
  state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
266
266
 
267
- skill_path = cdh_dir / "SKILL.md"
268
- if not skill_path.exists():
269
- skill_path.write_text(
270
- f"# {name} — Project Instructions\n\n"
271
- "Add project-specific agent instructions here.\n",
272
- encoding="utf-8",
273
- )
274
-
275
267
  return cdh_dir
@@ -217,15 +217,20 @@ class ContextManager:
217
217
  for b in m.content:
218
218
  if isinstance(b, dict) and b.get("type") == "tool_result":
219
219
  content = b.get("content", "")
220
- if isinstance(content, str) and len(content) > 500:
221
- b["content"] = content[:500] + "\n... [truncated]"
220
+ if isinstance(content, str) and len(content) > 2000:
221
+ # Preserve full output if it contains code blocks
222
+ # or structured JSON results.
223
+ if "```" not in content and not content.lstrip().startswith("{"):
224
+ b["content"] = content[:500] + "\n... [truncated]"
222
225
 
223
226
  def _tier_truncate_old(self, msgs: list[Message], keep_recent: int = 10) -> None:
224
227
  if len(msgs) <= keep_recent:
225
228
  return
226
229
  for m in msgs[:-keep_recent]:
227
230
  if isinstance(m.content, str) and len(m.content) > 200:
228
- m.content = m.content[:200] + "..."
231
+ # Preserve messages containing code blocks or structured data
232
+ if "```" not in m.content:
233
+ m.content = m.content[:200] + "..."
229
234
  elif isinstance(m.content, list):
230
235
  m.content = [b for b in m.content if isinstance(b, dict) and b.get("type") == "tool_use"]
231
236
  if not m.content: