agent-toolkit-cli 1.11.0__py3-none-win_amd64.whl

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 (438) hide show
  1. agent_toolkit/__init__.py +4 -0
  2. agent_toolkit/__main__.py +5 -0
  3. agent_toolkit/_paths.py +145 -0
  4. agent_toolkit/bin/.gitkeep +0 -0
  5. agent_toolkit/bin/agent-toolkit.exe +0 -0
  6. agent_toolkit/cli/__init__.py +0 -0
  7. agent_toolkit/cli/__main__.py +5 -0
  8. agent_toolkit/cli/build.py +278 -0
  9. agent_toolkit/cli/completion.py +297 -0
  10. agent_toolkit/cli/context_budget.py +455 -0
  11. agent_toolkit/cli/devcompanion.py +923 -0
  12. agent_toolkit/cli/devcompanion_queue.py +235 -0
  13. agent_toolkit/cli/diff.py +176 -0
  14. agent_toolkit/cli/doctor.py +1052 -0
  15. agent_toolkit/cli/insights.py +771 -0
  16. agent_toolkit/cli/install.py +706 -0
  17. agent_toolkit/cli/main.py +171 -0
  18. agent_toolkit/cli/mcp.py +537 -0
  19. agent_toolkit/cli/memory.py +739 -0
  20. agent_toolkit/cli/plugin.py +224 -0
  21. agent_toolkit/cli/project.py +459 -0
  22. agent_toolkit/cli/release.py +178 -0
  23. agent_toolkit/cli/skills.py +461 -0
  24. agent_toolkit/cli/uninstall.py +166 -0
  25. agent_toolkit/cli/update.py +298 -0
  26. agent_toolkit/cli/workspace.py +1713 -0
  27. agent_toolkit/compiler/hook_registry.py +110 -0
  28. agent_toolkit/compiler/loader.py +338 -0
  29. agent_toolkit/compiler/mcp_registry.py +87 -0
  30. agent_toolkit/compiler/model.py +182 -0
  31. agent_toolkit/compiler/provenance.py +140 -0
  32. agent_toolkit/compiler/registry_emit.py +263 -0
  33. agent_toolkit/compiler/target_registry.py +122 -0
  34. agent_toolkit/compiler/targets/__init__.py +1 -0
  35. agent_toolkit/compiler/targets/agent_plugins.py +160 -0
  36. agent_toolkit/compiler/targets/base.py +229 -0
  37. agent_toolkit/compiler/targets/claude_code.py +241 -0
  38. agent_toolkit/compiler/targets/codex.py +261 -0
  39. agent_toolkit/compiler/targets/copilot.py +275 -0
  40. agent_toolkit/compiler/targets/cursor.py +207 -0
  41. agent_toolkit/compiler/targets/gemini_cli.py +213 -0
  42. agent_toolkit/compiler/targets/muse_code.py +113 -0
  43. agent_toolkit/compiler/targets/opencode.py +204 -0
  44. agent_toolkit/compiler/targets/pi.py +263 -0
  45. agent_toolkit/compiler/targets/windsurf.py +267 -0
  46. agent_toolkit/compiler/tool_mapping.py +83 -0
  47. agent_toolkit/data/.gitignore +4 -0
  48. agent_toolkit/data/__init__.py +1 -0
  49. agent_toolkit/data/agents/agentic-security-reviewer/AGENT.md +60 -0
  50. agent_toolkit/data/agents/architect/AGENT.md +30 -0
  51. agent_toolkit/data/agents/assistant/AGENT.md +59 -0
  52. agent_toolkit/data/agents/build-error-resolver/AGENT.md +30 -0
  53. agent_toolkit/data/agents/client-workflow-bootstrap/AGENT.md +60 -0
  54. agent_toolkit/data/agents/code-reviewer/AGENT.md +49 -0
  55. agent_toolkit/data/agents/database-reviewer/AGENT.md +44 -0
  56. agent_toolkit/data/agents/docs-lookup/AGENT.md +28 -0
  57. agent_toolkit/data/agents/e2e-runner/AGENT.md +38 -0
  58. agent_toolkit/data/agents/performance-optimizer/AGENT.md +52 -0
  59. agent_toolkit/data/agents/planner/AGENT.md +41 -0
  60. agent_toolkit/data/agents/refactor-cleaner/AGENT.md +43 -0
  61. agent_toolkit/data/agents/reference-lookup/AGENT.md +33 -0
  62. agent_toolkit/data/agents/security-reviewer/AGENT.md +47 -0
  63. agent_toolkit/data/agents/tdd-guide/AGENT.md +58 -0
  64. agent_toolkit/data/agents/tech-assistant/AGENT.md +11 -0
  65. agent_toolkit/data/agents/typescript-reviewer/AGENT.md +61 -0
  66. agent_toolkit/data/capabilities/hooks/README.md +6 -0
  67. agent_toolkit/data/capabilities/hooks/pre-commit-validate.yaml +26 -0
  68. agent_toolkit/data/capabilities/hooks/scripts/pre-commit-validate.sh +41 -0
  69. agent_toolkit/data/capabilities/hooks/scripts/session-start-context.sh +11 -0
  70. agent_toolkit/data/capabilities/hooks/session-start-context.yaml +23 -0
  71. agent_toolkit/data/capabilities/targets/registry.yaml +90 -0
  72. agent_toolkit/data/capabilities/upstream.lock +118 -0
  73. agent_toolkit/data/catalogs/agent-catalog.yaml +81 -0
  74. agent_toolkit/data/catalogs/loop-catalog.yaml +55 -0
  75. agent_toolkit/data/catalogs/skill-catalog.yaml +520 -0
  76. agent_toolkit/data/catalogs/skills-layout.json +391 -0
  77. agent_toolkit/data/distributions/products.yaml +190 -0
  78. agent_toolkit/data/distributions/targets/claude-code.yaml +47 -0
  79. agent_toolkit/data/distributions/targets/cursor.yaml +42 -0
  80. agent_toolkit/data/distributions/targets/opencode.yaml +55 -0
  81. agent_toolkit/data/loops/changelog-drafter/loop.yaml +40 -0
  82. agent_toolkit/data/loops/ci-sweeper/loop.yaml +53 -0
  83. agent_toolkit/data/loops/daily-triage/loop.yaml +47 -0
  84. agent_toolkit/data/loops/dep-sweeper/loop.yaml +46 -0
  85. agent_toolkit/data/loops/issue-triage/loop.yaml +40 -0
  86. agent_toolkit/data/loops/oss-daily-briefing/loop.yaml +65 -0
  87. agent_toolkit/data/loops/oss-pr-monitor/loop.yaml +86 -0
  88. agent_toolkit/data/loops/oss-triage/loop.yaml +67 -0
  89. agent_toolkit/data/loops/post-merge-cleanup/loop.yaml +44 -0
  90. agent_toolkit/data/loops/pr-babysitter/loop.yaml +46 -0
  91. agent_toolkit/data/mcp/registry/chrome-devtools.yaml +61 -0
  92. agent_toolkit/data/mcp/registry/clickup.yaml +48 -0
  93. agent_toolkit/data/mcp/registry/figma.yaml +44 -0
  94. agent_toolkit/data/mcp/registry/github.yaml +52 -0
  95. agent_toolkit/data/mcp/registry/linear.yaml +47 -0
  96. agent_toolkit/data/mcp/registry/notion.yaml +48 -0
  97. agent_toolkit/data/mcp/registry/slack.yaml +46 -0
  98. agent_toolkit/data/mcp/templates/chrome-devtools/README.md +57 -0
  99. agent_toolkit/data/mcp/templates/chrome-devtools/config.template.json +6 -0
  100. agent_toolkit/data/mcp/templates/clickup/README.md +45 -0
  101. agent_toolkit/data/mcp/templates/clickup/config.template.json +8 -0
  102. agent_toolkit/data/mcp/templates/clickup/wrapper.sh +23 -0
  103. agent_toolkit/data/mcp/templates/figma/README.md +54 -0
  104. agent_toolkit/data/mcp/templates/figma/config.template.json +9 -0
  105. agent_toolkit/data/mcp/templates/github/README.md +16 -0
  106. agent_toolkit/data/mcp/templates/github/config.template.json +15 -0
  107. agent_toolkit/data/mcp/templates/github/wrapper.sh +6 -0
  108. agent_toolkit/data/mcp/templates/linear/README.md +49 -0
  109. agent_toolkit/data/mcp/templates/linear/config.template.json +10 -0
  110. agent_toolkit/data/mcp/templates/notion/README.md +7 -0
  111. agent_toolkit/data/mcp/templates/notion/config.template.json +8 -0
  112. agent_toolkit/data/mcp/templates/notion/wrapper.sh +23 -0
  113. agent_toolkit/data/mcp/templates/slack/README.md +8 -0
  114. agent_toolkit/data/mcp/templates/slack/config.template.json +9 -0
  115. agent_toolkit/data/mcp/templates/slack/wrapper.sh +23 -0
  116. agent_toolkit/data/packs/README.md +66 -0
  117. agent_toolkit/data/packs/agentic-security/README.md +19 -0
  118. agent_toolkit/data/packs/agentic-security/config.yaml +25 -0
  119. agent_toolkit/data/packs/architecture/README.md +22 -0
  120. agent_toolkit/data/packs/architecture/config.yaml +27 -0
  121. agent_toolkit/data/packs/code-quality/README.md +19 -0
  122. agent_toolkit/data/packs/code-quality/config.yaml +21 -0
  123. agent_toolkit/data/packs/delivery-discipline/README.md +19 -0
  124. agent_toolkit/data/packs/delivery-discipline/config.yaml +42 -0
  125. agent_toolkit/data/packs/design-engineering/README.md +19 -0
  126. agent_toolkit/data/packs/design-engineering/config.yaml +41 -0
  127. agent_toolkit/data/packs/engineering-workflow/README.md +21 -0
  128. agent_toolkit/data/packs/engineering-workflow/config.yaml +57 -0
  129. agent_toolkit/data/packs/oss-maintenance/README.md +245 -0
  130. agent_toolkit/data/packs/oss-maintenance/config.yaml +75 -0
  131. agent_toolkit/data/profiles/claude-code/CLAUDE.md +110 -0
  132. agent_toolkit/data/profiles/claude-code/agents/assistant.md +59 -0
  133. agent_toolkit/data/profiles/claude-code/agents/build-error-resolver.md +30 -0
  134. agent_toolkit/data/profiles/claude-code/agents/client-workflow-bootstrap.md +60 -0
  135. agent_toolkit/data/profiles/claude-code/agents/contribution-planner.md +39 -0
  136. agent_toolkit/data/profiles/claude-code/agents/database-reviewer.md +44 -0
  137. agent_toolkit/data/profiles/claude-code/agents/docs-lookup.md +28 -0
  138. agent_toolkit/data/profiles/claude-code/agents/e2e-runner.md +38 -0
  139. agent_toolkit/data/profiles/claude-code/agents/performance-optimizer.md +52 -0
  140. agent_toolkit/data/profiles/claude-code/agents/planner.md +41 -0
  141. agent_toolkit/data/profiles/claude-code/agents/refactor-cleaner.md +43 -0
  142. agent_toolkit/data/profiles/claude-code/agents/reference-lookup.md +33 -0
  143. agent_toolkit/data/profiles/claude-code/agents/security-reviewer.md +47 -0
  144. agent_toolkit/data/profiles/claude-code/agents/tdd-guide.md +58 -0
  145. agent_toolkit/data/profiles/claude-code/agents/typescript-reviewer.md +61 -0
  146. agent_toolkit/data/profiles/claude-code/settings.json +86 -0
  147. agent_toolkit/data/profiles/copilot/copilot-instructions.md +15 -0
  148. agent_toolkit/data/profiles/cursor/README.md +33 -0
  149. agent_toolkit/data/profiles/cursor/rules/architect.mdc +23 -0
  150. agent_toolkit/data/profiles/cursor/rules/assistant.mdc +61 -0
  151. agent_toolkit/data/profiles/cursor/rules/build-error-resolver.mdc +20 -0
  152. agent_toolkit/data/profiles/cursor/rules/code-reviewer.mdc +21 -0
  153. agent_toolkit/data/profiles/cursor/rules/database-reviewer.mdc +29 -0
  154. agent_toolkit/data/profiles/cursor/rules/docs-lookup.mdc +15 -0
  155. agent_toolkit/data/profiles/cursor/rules/e2e-runner.mdc +30 -0
  156. agent_toolkit/data/profiles/cursor/rules/performance-optimizer.mdc +27 -0
  157. agent_toolkit/data/profiles/cursor/rules/planner.mdc +28 -0
  158. agent_toolkit/data/profiles/cursor/rules/refactor-cleaner.mdc +26 -0
  159. agent_toolkit/data/profiles/cursor/rules/reference-lookup.mdc +20 -0
  160. agent_toolkit/data/profiles/cursor/rules/security-reviewer.mdc +20 -0
  161. agent_toolkit/data/profiles/cursor/rules/tdd-guide.mdc +26 -0
  162. agent_toolkit/data/profiles/cursor/rules/typescript-reviewer.mdc +28 -0
  163. agent_toolkit/data/profiles/muse-code/README.md +35 -0
  164. agent_toolkit/data/profiles/opencode/README.md +44 -0
  165. agent_toolkit/data/profiles/opencode/agents/architect.md +30 -0
  166. agent_toolkit/data/profiles/opencode/agents/assistant.md +96 -0
  167. agent_toolkit/data/profiles/opencode/agents/build-error-resolver.md +31 -0
  168. agent_toolkit/data/profiles/opencode/agents/client-workflow-bootstrap.md +66 -0
  169. agent_toolkit/data/profiles/opencode/agents/code-reviewer.md +47 -0
  170. agent_toolkit/data/profiles/opencode/agents/contribution-planner.md +44 -0
  171. agent_toolkit/data/profiles/opencode/agents/database-reviewer.md +43 -0
  172. agent_toolkit/data/profiles/opencode/agents/docs-lookup.md +28 -0
  173. agent_toolkit/data/profiles/opencode/agents/e2e-runner.md +33 -0
  174. agent_toolkit/data/profiles/opencode/agents/performance-optimizer.md +34 -0
  175. agent_toolkit/data/profiles/opencode/agents/planner.md +27 -0
  176. agent_toolkit/data/profiles/opencode/agents/refactor-cleaner.md +27 -0
  177. agent_toolkit/data/profiles/opencode/agents/reference-lookup.md +27 -0
  178. agent_toolkit/data/profiles/opencode/agents/security-reviewer.md +27 -0
  179. agent_toolkit/data/profiles/opencode/agents/tdd-guide.md +27 -0
  180. agent_toolkit/data/profiles/opencode/agents/typescript-reviewer.md +30 -0
  181. agent_toolkit/data/profiles/opencode/opencode.json +3 -0
  182. agent_toolkit/data/profiles/pi/skills/architect/skill.md +5 -0
  183. agent_toolkit/data/profiles/pi/skills/assistant/skill.md +3 -0
  184. agent_toolkit/data/profiles/pi/skills/code-reviewer/skill.md +5 -0
  185. agent_toolkit/data/profiles/pi/skills/planner/skill.md +3 -0
  186. agent_toolkit/data/profiles/pi/skills/security-reviewer/skill.md +3 -0
  187. agent_toolkit/data/profiles/windsurf/memories/global_rules.md +114 -0
  188. agent_toolkit/data/profiles/windsurf/rules/architect.mdc +23 -0
  189. agent_toolkit/data/profiles/windsurf/rules/assistant.mdc +61 -0
  190. agent_toolkit/data/profiles/windsurf/rules/build-error-resolver.mdc +20 -0
  191. agent_toolkit/data/profiles/windsurf/rules/code-reviewer.mdc +21 -0
  192. agent_toolkit/data/profiles/windsurf/rules/database-reviewer.mdc +29 -0
  193. agent_toolkit/data/profiles/windsurf/rules/docs-lookup.mdc +15 -0
  194. agent_toolkit/data/profiles/windsurf/rules/e2e-runner.mdc +30 -0
  195. agent_toolkit/data/profiles/windsurf/rules/performance-optimizer.mdc +27 -0
  196. agent_toolkit/data/profiles/windsurf/rules/planner.mdc +28 -0
  197. agent_toolkit/data/profiles/windsurf/rules/refactor-cleaner.mdc +26 -0
  198. agent_toolkit/data/profiles/windsurf/rules/reference-lookup.mdc +20 -0
  199. agent_toolkit/data/profiles/windsurf/rules/security-reviewer.mdc +20 -0
  200. agent_toolkit/data/profiles/windsurf/rules/tdd-guide.mdc +26 -0
  201. agent_toolkit/data/profiles/windsurf/rules/typescript-reviewer.mdc +28 -0
  202. agent_toolkit/data/skills/accessibility/review/SKILL.md +116 -0
  203. agent_toolkit/data/skills/accessibility/review/references/a11y-checklist.md +25 -0
  204. agent_toolkit/data/skills/accessibility/review/references/a11y-findings-template.md +56 -0
  205. agent_toolkit/data/skills/accessibility/review/references/research.md +47 -0
  206. agent_toolkit/data/skills/agentic-security/mcp-audit/SKILL.md +116 -0
  207. agent_toolkit/data/skills/agentic-security/mcp-audit/references/mcp-audit-template.md +51 -0
  208. agent_toolkit/data/skills/agentic-security/owasp-agentic-review/SKILL.md +73 -0
  209. agent_toolkit/data/skills/agentic-security/owasp-agentic-review/references/owasp-agentic-template.md +32 -0
  210. agent_toolkit/data/skills/agentic-security/supply-chain-audit/SKILL.md +142 -0
  211. agent_toolkit/data/skills/agentic-security/threat-modeling/SKILL.md +100 -0
  212. agent_toolkit/data/skills/agentic-security/threat-modeling/references/threat-model-template.md +55 -0
  213. agent_toolkit/data/skills/architecture/c4-model/SKILL.md +49 -0
  214. agent_toolkit/data/skills/cloud/aws-well-architected-review/SKILL.md +37 -0
  215. agent_toolkit/data/skills/cloud/cloud-design-patterns/SKILL.md +38 -0
  216. agent_toolkit/data/skills/core/assistant/SKILL.md +216 -0
  217. agent_toolkit/data/skills/core/assistant/references/AGENTS_TEMPLATE.md +0 -0
  218. agent_toolkit/data/skills/core/assistant/references/ORCHESTRATION.md +0 -0
  219. agent_toolkit/data/skills/core/assistant/references/REPO_INSPECTION.md +0 -0
  220. agent_toolkit/data/skills/core/dev-companion/SKILL.md +65 -0
  221. agent_toolkit/data/skills/core/dev-companion/references/LOOP_GUARDRAILS.md +0 -0
  222. agent_toolkit/data/skills/core/onboarding/SKILL.md +122 -0
  223. agent_toolkit/data/skills/core/output-handshake/SKILL.md +26 -0
  224. agent_toolkit/data/skills/core/pr-fallback/SKILL.md +35 -0
  225. agent_toolkit/data/skills/core/pr-fallback/references/pr-body-default.md +0 -0
  226. agent_toolkit/data/skills/core/project/SKILL.md +89 -0
  227. agent_toolkit/data/skills/core/workspace/SKILL.md +103 -0
  228. agent_toolkit/data/skills/core/workspace-knowledge-sync/SKILL.md +140 -0
  229. agent_toolkit/data/skills/data/dbt-validation/SKILL.md +41 -0
  230. agent_toolkit/data/skills/data/snowflake-validation/SKILL.md +38 -0
  231. agent_toolkit/data/skills/delivery/adr/SKILL.md +56 -0
  232. agent_toolkit/data/skills/delivery/adr/references/default-template.md +35 -0
  233. agent_toolkit/data/skills/delivery/adr/references/example-001-graphql-adoption.md +66 -0
  234. agent_toolkit/data/skills/delivery/agreement/SKILL.md +24 -0
  235. agent_toolkit/data/skills/delivery/agreement/references/default-template.md +17 -0
  236. agent_toolkit/data/skills/delivery/agreement/references/example-api-versioning.md +29 -0
  237. agent_toolkit/data/skills/delivery/bug/SKILL.md +26 -0
  238. agent_toolkit/data/skills/delivery/bug/references/default-template.md +26 -0
  239. agent_toolkit/data/skills/delivery/bug/references/example-search-filter-bug.md +58 -0
  240. agent_toolkit/data/skills/delivery/decision-log/SKILL.md +28 -0
  241. agent_toolkit/data/skills/delivery/decision-log/references/default-template.md +17 -0
  242. agent_toolkit/data/skills/delivery/decision-log/references/example-repository-pattern.md +27 -0
  243. agent_toolkit/data/skills/delivery/development-workflow/SKILL.md +34 -0
  244. agent_toolkit/data/skills/delivery/development-workflow/references/default-workflow-checklist.md +44 -0
  245. agent_toolkit/data/skills/delivery/epic/SKILL.md +22 -0
  246. agent_toolkit/data/skills/delivery/epic/references/default-template.md +26 -0
  247. agent_toolkit/data/skills/delivery/epic/references/example-unified-dashboard.md +40 -0
  248. agent_toolkit/data/skills/delivery/incident/SKILL.md +24 -0
  249. agent_toolkit/data/skills/delivery/incident/references/default-template.md +29 -0
  250. agent_toolkit/data/skills/delivery/incident/references/example-payment-outage.md +62 -0
  251. agent_toolkit/data/skills/delivery/management-unit-assessment/SKILL.md +104 -0
  252. agent_toolkit/data/skills/delivery/management-unit-assessment/references/default-template.md +24 -0
  253. agent_toolkit/data/skills/delivery/management-unit-assessment/references/example-team-assessment.md +126 -0
  254. agent_toolkit/data/skills/delivery/meeting-minutes/SKILL.md +25 -0
  255. agent_toolkit/data/skills/delivery/meeting-minutes/references/default-template.md +22 -0
  256. agent_toolkit/data/skills/delivery/meeting-minutes/references/example-weekly-sync.md +72 -0
  257. agent_toolkit/data/skills/delivery/planning/SKILL.md +31 -0
  258. agent_toolkit/data/skills/delivery/planning/references/default-template.md +25 -0
  259. agent_toolkit/data/skills/delivery/planning/references/example-sprint-planning.md +62 -0
  260. agent_toolkit/data/skills/delivery/prd/SKILL.md +46 -0
  261. agent_toolkit/data/skills/delivery/prd/references/default-template.md +31 -0
  262. agent_toolkit/data/skills/delivery/prd/references/example-unified-api.md +71 -0
  263. agent_toolkit/data/skills/delivery/project-assessment/SKILL.md +90 -0
  264. agent_toolkit/data/skills/delivery/project-assessment/references/default-template.md +26 -0
  265. agent_toolkit/data/skills/delivery/project-assessment/references/example-platform-assessment.md +122 -0
  266. agent_toolkit/data/skills/delivery/project-assessment-evidence/SKILL.md +88 -0
  267. agent_toolkit/data/skills/delivery/project-assessment-evidence/references/default-template.md +24 -0
  268. agent_toolkit/data/skills/delivery/project-assessment-evidence/references/example-evidence-map.md +46 -0
  269. agent_toolkit/data/skills/delivery/spike/SKILL.md +24 -0
  270. agent_toolkit/data/skills/delivery/spike/references/default-template.md +29 -0
  271. agent_toolkit/data/skills/delivery/spike/references/example-graphql-federation.md +79 -0
  272. agent_toolkit/data/skills/delivery/task/SKILL.md +21 -0
  273. agent_toolkit/data/skills/delivery/task/references/default-template.md +21 -0
  274. agent_toolkit/data/skills/delivery/task/references/example-nav-system.md +33 -0
  275. agent_toolkit/data/skills/delivery/technical-unit-assessment/SKILL.md +58 -0
  276. agent_toolkit/data/skills/delivery/technical-unit-assessment/references/default-template.md +26 -0
  277. agent_toolkit/data/skills/delivery/technical-unit-assessment/references/example-frontend-assessment.md +112 -0
  278. agent_toolkit/data/skills/delivery/technical-unit-assessment/references/indicator-groups.md +65 -0
  279. agent_toolkit/data/skills/delivery/trd/SKILL.md +49 -0
  280. agent_toolkit/data/skills/delivery/trd/references/default-template.md +31 -0
  281. agent_toolkit/data/skills/delivery/trd/references/example-api-migration.md +122 -0
  282. agent_toolkit/data/skills/delivery/user-story/SKILL.md +21 -0
  283. agent_toolkit/data/skills/delivery/user-story/references/default-template.md +21 -0
  284. agent_toolkit/data/skills/delivery/user-story/references/example-advanced-filtering.md +37 -0
  285. agent_toolkit/data/skills/delivery/work-item/SKILL.md +31 -0
  286. agent_toolkit/data/skills/delivery/work-item/references/default-template.md +21 -0
  287. agent_toolkit/data/skills/delivery/work-item/references/example-routing-dashboard.md +23 -0
  288. agent_toolkit/data/skills/delivery/workflow-client-bootstrap/SKILL.md +148 -0
  289. agent_toolkit/data/skills/delivery/workflow-client-bootstrap/questions.yaml +165 -0
  290. agent_toolkit/data/skills/delivery/workflow-generic-project/SKILL.md +79 -0
  291. agent_toolkit/data/skills/design/design-assessment/SKILL.md +150 -0
  292. agent_toolkit/data/skills/design/design-assessment/references/design-scorecard-template.md +78 -0
  293. agent_toolkit/data/skills/design/design-improvement/SKILL.md +167 -0
  294. agent_toolkit/data/skills/design/design-improvement/references/improvement-plan-template.md +113 -0
  295. agent_toolkit/data/skills/design/figma/LICENSE.txt +2 -0
  296. agent_toolkit/data/skills/design/figma/NOTICE.txt +25 -0
  297. agent_toolkit/data/skills/design/figma/SKILL.md +98 -0
  298. agent_toolkit/data/skills/design/figma/references/figma-mcp-config.md +82 -0
  299. agent_toolkit/data/skills/design/figma/references/figma-tools-and-prompts.md +34 -0
  300. agent_toolkit/data/skills/design/figma-code-connect-components/LICENSE.txt +2 -0
  301. agent_toolkit/data/skills/design/figma-code-connect-components/NOTICE.txt +18 -0
  302. agent_toolkit/data/skills/design/figma-code-connect-components/SKILL.md +354 -0
  303. agent_toolkit/data/skills/design/figma-code-connect-components/references/mapping-checklist.md +7 -0
  304. agent_toolkit/data/skills/design/figma-code-connect-components/scripts/normalize_node_id.py +25 -0
  305. agent_toolkit/data/skills/design/figma-create-design-system-rules/LICENSE.txt +2 -0
  306. agent_toolkit/data/skills/design/figma-create-design-system-rules/NOTICE.txt +19 -0
  307. agent_toolkit/data/skills/design/figma-create-design-system-rules/SKILL.md +554 -0
  308. agent_toolkit/data/skills/design/figma-create-design-system-rules/references/rule-template.md +15 -0
  309. agent_toolkit/data/skills/design/figma-create-design-system-rules/scripts/check_agents_md.sh +9 -0
  310. agent_toolkit/data/skills/design/figma-create-new-file/LICENSE.txt +2 -0
  311. agent_toolkit/data/skills/design/figma-create-new-file/NOTICE.txt +17 -0
  312. agent_toolkit/data/skills/design/figma-create-new-file/SKILL.md +72 -0
  313. agent_toolkit/data/skills/design/figma-implement-design/LICENSE.txt +2 -0
  314. agent_toolkit/data/skills/design/figma-implement-design/NOTICE.txt +19 -0
  315. agent_toolkit/data/skills/design/figma-implement-design/SKILL.md +268 -0
  316. agent_toolkit/data/skills/design/frontend-design/LICENSE.txt +177 -0
  317. agent_toolkit/data/skills/design/frontend-design/SKILL.md +82 -0
  318. agent_toolkit/data/skills/design/frontend-design/UPSTREAM.md +14 -0
  319. agent_toolkit/data/skills/design/frontend-design-review/LICENSE +21 -0
  320. agent_toolkit/data/skills/design/frontend-design-review/SKILL.md +194 -0
  321. agent_toolkit/data/skills/design/frontend-design-review/references/pattern-examples.md +21 -0
  322. agent_toolkit/data/skills/design/frontend-design-review/references/quick-checklist.md +38 -0
  323. agent_toolkit/data/skills/design/frontend-design-review/references/review-output-format.md +68 -0
  324. agent_toolkit/data/skills/design/frontend-design-review/references/review-type-modifiers.md +31 -0
  325. agent_toolkit/data/skills/design/web-design-guidelines/SKILL.md +78 -0
  326. agent_toolkit/data/skills/design/web-design-guidelines/references/LICENSE +21 -0
  327. agent_toolkit/data/skills/design/web-design-guidelines/references/web-interface-guidelines.md +180 -0
  328. agent_toolkit/data/skills/forge/gh-address-comments/LICENSE.txt +202 -0
  329. agent_toolkit/data/skills/forge/gh-address-comments/NOTICE.txt +20 -0
  330. agent_toolkit/data/skills/forge/gh-address-comments/SKILL.md +72 -0
  331. agent_toolkit/data/skills/forge/gh-address-comments/scripts/fetch_comments.py +239 -0
  332. agent_toolkit/data/skills/forge/gh-contribution-planner/SKILL.md +160 -0
  333. agent_toolkit/data/skills/forge/gh-contribution-planner/scripts/inspect_contributions.py +818 -0
  334. agent_toolkit/data/skills/forge/gh-fix-ci/LICENSE.txt +201 -0
  335. agent_toolkit/data/skills/forge/gh-fix-ci/NOTICE.txt +20 -0
  336. agent_toolkit/data/skills/forge/gh-fix-ci/SKILL.md +74 -0
  337. agent_toolkit/data/skills/forge/gh-fix-ci/scripts/inspect_pr_checks.py +509 -0
  338. agent_toolkit/data/skills/forge/github-cli-workflow/SKILL.md +49 -0
  339. agent_toolkit/data/skills/forge/gitlab-cli-workflow/SKILL.md +44 -0
  340. agent_toolkit/data/skills/forge/workflow-client-bootstrap/SKILL.md +14 -0
  341. agent_toolkit/data/skills/forge/workflow-generic-project/SKILL.md +14 -0
  342. agent_toolkit/data/skills/forge/worktree/SKILL.md +113 -0
  343. agent_toolkit/data/skills/integrations/clickup-cli/SKILL.md +78 -0
  344. agent_toolkit/data/skills/integrations/clickup-cli/references/docs-management.md +57 -0
  345. agent_toolkit/data/skills/integrations/clickup-cli/references/task-management.md +131 -0
  346. agent_toolkit/data/skills/integrations/clickup-cli/references/time-tracking.md +38 -0
  347. agent_toolkit/data/skills/integrations/linear/LICENSE.txt +202 -0
  348. agent_toolkit/data/skills/integrations/linear/NOTICE.txt +23 -0
  349. agent_toolkit/data/skills/integrations/linear/SKILL.md +134 -0
  350. agent_toolkit/data/skills/integrations/mcp/SKILL.md +88 -0
  351. agent_toolkit/data/skills/integrations/slack-assistant/SKILL.md +138 -0
  352. agent_toolkit/data/skills/integrations/slack-cli/SKILL.md +109 -0
  353. agent_toolkit/data/skills/integrations/slack-cli/references/INSTALLATION.md +42 -0
  354. agent_toolkit/data/skills/loops/loop-runner/SKILL.md +92 -0
  355. agent_toolkit/data/skills/ops/docs-generator/SKILL.md +120 -0
  356. agent_toolkit/data/skills/ops/llm-cost-advisor/SKILL.md +87 -0
  357. agent_toolkit/data/skills/ops/swarm/SKILL.md +108 -0
  358. agent_toolkit/data/skills/ops/swarm-handoff/SKILL.md +112 -0
  359. agent_toolkit/data/skills/ops/swarm-observer/SKILL.md +102 -0
  360. agent_toolkit/data/skills/ops/triage/SKILL.md +119 -0
  361. agent_toolkit/data/skills/quality/codeql/SKILL.md +106 -0
  362. agent_toolkit/data/skills/quality/codeql/references/codeql-queries.md +43 -0
  363. agent_toolkit/data/skills/quality/megalinter/SKILL.md +162 -0
  364. agent_toolkit/data/skills/quality/megalinter/references/megalinter-images.md +36 -0
  365. agent_toolkit/data/skills/quality/megalinter/references/megalinter-license.md +41 -0
  366. agent_toolkit/data/skills/quality/megalinter/references/megalinter-targets.md +66 -0
  367. agent_toolkit/data/skills/tooling/chrome-devtools/SKILL.md +146 -0
  368. agent_toolkit/data/skills/tooling/herdr/SKILL.md +109 -0
  369. agent_toolkit/data/skills/tooling/inventory/SKILL.md +81 -0
  370. agent_toolkit/data/skills/tooling/jupyter-notebook/LICENSE.txt +201 -0
  371. agent_toolkit/data/skills/tooling/jupyter-notebook/NOTICE.txt +27 -0
  372. agent_toolkit/data/skills/tooling/jupyter-notebook/SKILL.md +145 -0
  373. agent_toolkit/data/skills/tooling/jupyter-notebook/assets/experiment-template.ipynb +117 -0
  374. agent_toolkit/data/skills/tooling/jupyter-notebook/assets/tutorial-template.ipynb +115 -0
  375. agent_toolkit/data/skills/tooling/jupyter-notebook/references/experiment-patterns.md +10 -0
  376. agent_toolkit/data/skills/tooling/jupyter-notebook/references/notebook-structure.md +17 -0
  377. agent_toolkit/data/skills/tooling/jupyter-notebook/references/quality-checklist.md +11 -0
  378. agent_toolkit/data/skills/tooling/jupyter-notebook/references/tutorial-patterns.md +9 -0
  379. agent_toolkit/data/skills/tooling/jupyter-notebook/scripts/new_notebook.py +132 -0
  380. agent_toolkit/data/skills/tooling/mermaid/SKILL.md +36 -0
  381. agent_toolkit/data/skills/tooling/playwright-cli/LICENSE.txt +201 -0
  382. agent_toolkit/data/skills/tooling/playwright-cli/NOTICE.txt +29 -0
  383. agent_toolkit/data/skills/tooling/playwright-cli/SKILL.md +154 -0
  384. agent_toolkit/data/skills/tooling/playwright-cli/references/cli.md +116 -0
  385. agent_toolkit/data/skills/tooling/playwright-cli/references/workflows.md +98 -0
  386. agent_toolkit/data/skills/tooling/playwright-cli/scripts/executable_playwright_cli.sh +25 -0
  387. agent_toolkit/data_cache.py +79 -0
  388. agent_toolkit/data_sync.py +144 -0
  389. agent_toolkit/installer/__init__.py +0 -0
  390. agent_toolkit/installer/merge.py +59 -0
  391. agent_toolkit/installer/receipt.py +89 -0
  392. agent_toolkit/installer/sources.py +92 -0
  393. agent_toolkit/installer/tracking.py +63 -0
  394. agent_toolkit/launcher.py +69 -0
  395. agent_toolkit/loop/__init__.py +0 -0
  396. agent_toolkit/loop/budget.py +107 -0
  397. agent_toolkit/loop/gh_gate.py +923 -0
  398. agent_toolkit/loop/loop-gh-gate +923 -0
  399. agent_toolkit/loop/pack.py +65 -0
  400. agent_toolkit/loop/runner.py +2722 -0
  401. agent_toolkit/runner/__init__.py +0 -0
  402. agent_toolkit/runner/dispatcher.py +163 -0
  403. agent_toolkit/runner/policy.py +356 -0
  404. agent_toolkit/runner/providers/__init__.py +21 -0
  405. agent_toolkit/runner/providers/anthropic_provider.py +109 -0
  406. agent_toolkit/runner/providers/base.py +53 -0
  407. agent_toolkit/runner/providers/ollama_provider.py +108 -0
  408. agent_toolkit/runner/providers/openai_provider.py +103 -0
  409. agent_toolkit/runner/providers/opencode_provider.py +127 -0
  410. agent_toolkit/swarm/__init__.py +5 -0
  411. agent_toolkit/swarm/approvals.py +121 -0
  412. agent_toolkit/swarm/backends/__init__.py +596 -0
  413. agent_toolkit/swarm/budget.py +83 -0
  414. agent_toolkit/swarm/cli.py +2448 -0
  415. agent_toolkit/swarm/config.py +351 -0
  416. agent_toolkit/swarm/handoff.py +174 -0
  417. agent_toolkit/swarm/models.py +230 -0
  418. agent_toolkit/swarm/prompts.py +177 -0
  419. agent_toolkit/swarm/recipes.py +304 -0
  420. agent_toolkit/swarm/runner.py +267 -0
  421. agent_toolkit/swarm/state.py +93 -0
  422. agent_toolkit/swarm/store.py +148 -0
  423. agent_toolkit/swarm/worktree.py +105 -0
  424. agent_toolkit/templates/workspace/.gitignore +19 -0
  425. agent_toolkit/templates/workspace/AGENTS.md +82 -0
  426. agent_toolkit/templates/workspace/knowledge/README.md +22 -0
  427. agent_toolkit/templates/workspace/knowledge/learnings/general.md +3 -0
  428. agent_toolkit/templates/workspace/knowledge/todos/pending.md +7 -0
  429. agent_toolkit/templates/workspace/packs/README.md +24 -0
  430. agent_toolkit/templates/workspace/personas/architect.md +12 -0
  431. agent_toolkit/templates/workspace/personas/implementer.md +12 -0
  432. agent_toolkit/templates/workspace/personas/researcher.md +12 -0
  433. agent_toolkit/templates/workspace/personas/reviewer.md +12 -0
  434. agent_toolkit_cli-1.11.0.dist-info/METADATA +363 -0
  435. agent_toolkit_cli-1.11.0.dist-info/RECORD +438 -0
  436. agent_toolkit_cli-1.11.0.dist-info/WHEEL +4 -0
  437. agent_toolkit_cli-1.11.0.dist-info/entry_points.txt +4 -0
  438. agent_toolkit_cli-1.11.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,923 @@
1
+ """
2
+ devcompanion — background job queue for agent-toolkit workspaces.
3
+
4
+ Usage:
5
+ agent-toolkit devcompanion queue <project> [--template NAME] [--request "..."] [--id ID]
6
+ agent-toolkit devcompanion run-once [--no-llm]
7
+ agent-toolkit devcompanion status
8
+ agent-toolkit devcompanion done <job-id>
9
+ agent-toolkit devcompanion sync-todos
10
+
11
+ Aliases: dc
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import re
18
+ import shutil
19
+ import subprocess
20
+ import sys
21
+ import sys as _sys
22
+ from datetime import datetime, timezone
23
+ from pathlib import Path
24
+
25
+ if _sys.platform == "win32":
26
+ try:
27
+ _sys.stdout.reconfigure(encoding="utf-8", errors="replace")
28
+ _sys.stderr.reconfigure(encoding="utf-8", errors="replace")
29
+ except Exception:
30
+ pass
31
+
32
+ from agent_toolkit.cli.devcompanion_queue import (
33
+ DCConfig,
34
+ find_job_path,
35
+ get_dc_config,
36
+ iter_jobs,
37
+ job_project_name,
38
+ job_project_path,
39
+ mark_job_done,
40
+ pending_jobs,
41
+ queue_job_path,
42
+ read_job,
43
+ write_job,
44
+ )
45
+
46
+ # ── workspace detection ───────────────────────────────────────────────────────
47
+
48
+
49
+ def _find_workspace() -> Path:
50
+ """Return workspace root: AGENT_TOOLKIT_WORKSPACE / HARNESS_DIR / walk-up / cwd."""
51
+ from agent_toolkit._paths import find_workspace_root
52
+
53
+ ws = find_workspace_root()
54
+ if ws is not None:
55
+ return ws
56
+ # Devcompanion also accepts .devcompanion as a marker
57
+ cwd = Path.cwd().resolve()
58
+ for parent in [cwd, *cwd.parents]:
59
+ if (parent / ".devcompanion").is_dir():
60
+ return parent
61
+ return cwd
62
+
63
+
64
+ WORKSPACE_ROOT: Path = _find_workspace()
65
+
66
+
67
+ def _workspace() -> Path:
68
+ """Fresh workspace root (respects env changes in tests)."""
69
+ return _find_workspace()
70
+
71
+
72
+ def _projects_dir() -> Path:
73
+ return _workspace() / "projects"
74
+
75
+
76
+ def _templates_dir() -> Path:
77
+ return _workspace() / "templates" / "jobs"
78
+
79
+
80
+ def _knowledge_todos() -> Path:
81
+ return _workspace() / "knowledge" / "todos" / "pending.md"
82
+
83
+
84
+ def _cfg() -> DCConfig:
85
+ return get_dc_config(_workspace())
86
+
87
+
88
+ # ── colors ────────────────────────────────────────────────────────────────────
89
+
90
+ _USE_COLOR = sys.stdout.isatty() and not os.environ.get("NO_COLOR")
91
+
92
+
93
+ def _c(code: str, text: str) -> str:
94
+ return f"\033[{code}m{text}\033[0m" if _USE_COLOR else text
95
+
96
+
97
+ def _blue(t: str) -> str:
98
+ return _c("1;34", t)
99
+
100
+
101
+ def _green(t: str) -> str:
102
+ return _c("1;32", t)
103
+
104
+
105
+ def _yellow(t: str) -> str:
106
+ return _c("1;33", t)
107
+
108
+
109
+ def _red(t: str) -> str:
110
+ return _c("1;31", t)
111
+
112
+
113
+ def _cyan(t: str) -> str:
114
+ return _c("0;36", t)
115
+
116
+
117
+ def _log(msg: str) -> None:
118
+ print(f"{_blue('[devcompanion]')} {msg}")
119
+
120
+
121
+ def _ok(msg: str) -> None:
122
+ print(f"{_green('[devcompanion]')} {msg}")
123
+
124
+
125
+ def _warn(msg: str) -> None:
126
+ print(f"{_yellow('[devcompanion]')} {msg}")
127
+
128
+
129
+ def _err(msg: str) -> None:
130
+ print(f"{_red('[devcompanion]')} {msg}", file=sys.stderr)
131
+
132
+
133
+ # ── time helpers ──────────────────────────────────────────────────────────────
134
+
135
+
136
+ def _utc_now() -> str:
137
+ return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
138
+
139
+
140
+ # ── project resolution ────────────────────────────────────────────────────────
141
+
142
+
143
+ def _resolve_project(name: str) -> Path | None:
144
+ """Resolve project name → real repo path via projects/ symlinks."""
145
+ projects_dir = _projects_dir()
146
+ if not projects_dir.is_dir():
147
+ return None
148
+ link = projects_dir / name
149
+ if link.is_symlink():
150
+ return link.resolve()
151
+ for entry in projects_dir.iterdir():
152
+ if entry.is_symlink() and name in entry.name:
153
+ return entry.resolve()
154
+ return None
155
+
156
+
157
+ def _list_projects() -> list[tuple[str, Path | None]]:
158
+ projects_dir = _projects_dir()
159
+ if not projects_dir.is_dir():
160
+ return []
161
+ result = []
162
+ for entry in sorted(projects_dir.iterdir()):
163
+ if entry.is_symlink():
164
+ target = entry.resolve() if entry.resolve().is_dir() else None
165
+ result.append((entry.name, target))
166
+ return result
167
+
168
+
169
+ # ── gh gate (reuse loop runner shim) ─────────────────────────────────────────
170
+
171
+ _MUTATING_DC_TEMPLATES = frozenset(
172
+ {
173
+ "create-pr",
174
+ "fix-ci",
175
+ "refactor",
176
+ "implement",
177
+ "investigate",
178
+ }
179
+ )
180
+
181
+
182
+ def _gate_script_path() -> Path:
183
+ return Path(__file__).resolve().parent.parent / "loop" / "loop-gh-gate"
184
+
185
+
186
+ def _job_is_mutating(job: dict) -> bool:
187
+ template = str(job.get("template") or "")
188
+ if template in _MUTATING_DC_TEMPLATES:
189
+ return True
190
+ actions = job.get("actions_allowed") or []
191
+ return bool(actions) and actions != ["plan_only"]
192
+
193
+
194
+ def _install_dc_gate(job: dict, out_dir: Path) -> dict[str, str]:
195
+ """Install loop-gh-gate PATH shim for devcompanion LLM runners."""
196
+ from agent_toolkit.loop.gh_gate import install_gh_shim
197
+
198
+ gate_script = _gate_script_path()
199
+ if not gate_script.is_file():
200
+ raise RuntimeError(f"loop-gh-gate missing at {gate_script} — refusing ungated run")
201
+
202
+ gate = job.get("loop_gate") or {}
203
+ tier = str(gate.get("tier", "L1"))
204
+ allow = list(gate.get("allowlist") or [])
205
+ deny = list(gate.get("deny") or [])
206
+ verifier = str(gate.get("verifier") or "")
207
+ run_dir = gate.get("run_dir")
208
+ gate_run_dir = Path(run_dir) if run_dir else out_dir
209
+
210
+ env = install_gh_shim(
211
+ gate_run_dir,
212
+ tier=tier,
213
+ allowlist=allow,
214
+ deny=deny,
215
+ verifier=verifier,
216
+ gate_script=gate_script,
217
+ )
218
+ _log(f"Hard gate active: gh shim → tier={tier} allow=[{', '.join(allow) or '∅'}]")
219
+ return env
220
+
221
+
222
+ def _runner_env_for_job(job: dict, out_dir: Path) -> dict[str, str]:
223
+ """Return subprocess env with gh gate installed; fail closed for mutating jobs."""
224
+ base = os.environ.copy()
225
+ try:
226
+ gate_env = _install_dc_gate(job, out_dir)
227
+ except RuntimeError as exc:
228
+ if _job_is_mutating(job):
229
+ raise RuntimeError(f"mutating devcompanion job requires gh gate: {exc}") from exc
230
+ _warn(f"gh gate not installed ({exc}); proceeding without gate")
231
+ return base
232
+ merged = base.copy()
233
+ for key, value in gate_env.items():
234
+ if key.startswith("LOOP_GATE_") or key == "PATH":
235
+ merged[key] = value
236
+ return merged
237
+
238
+
239
+ # ── template loading ──────────────────────────────────────────────────────────
240
+
241
+
242
+ class TemplateNotFoundError(FileNotFoundError):
243
+ """Raised when a job template YAML is missing (#48 / CLI-011)."""
244
+
245
+
246
+ def _load_template(name: str) -> dict:
247
+ templates_dir = _templates_dir()
248
+ tpl_file = templates_dir / f"{name}.yaml"
249
+ if not tpl_file.exists():
250
+ raise TemplateNotFoundError(f"Template not found: {name} (looked in {templates_dir}/)")
251
+
252
+ text = tpl_file.read_text(encoding="utf-8")
253
+ lines = text.splitlines()
254
+
255
+ def _extract(field: str) -> str:
256
+ for i, line in enumerate(lines):
257
+ if line.lstrip().startswith("#"):
258
+ continue
259
+ if re.match(rf"^{field}:\s*\|\s*$", line):
260
+ block_lines = []
261
+ for j in range(i + 1, len(lines)):
262
+ bl = lines[j]
263
+ if bl and not bl.startswith((" ", "\t", "#")):
264
+ break
265
+ if bl.lstrip().startswith("#"):
266
+ continue
267
+ block_lines.append(re.sub(r"^ ", "", bl))
268
+ return "\n".join(block_lines).rstrip()
269
+ m = re.match(rf"^{field}:\s+(.+)$", line)
270
+ if m:
271
+ return m.group(1).strip().strip('"').strip("'")
272
+ return ""
273
+
274
+ return {
275
+ "name": _extract("name") or name,
276
+ "description": _extract("description"),
277
+ "request": _extract("request"),
278
+ }
279
+
280
+
281
+ # ── todos sync ────────────────────────────────────────────────────────────────
282
+
283
+
284
+ def _sync_todos() -> None:
285
+ """Scan done job plans for checklist items and sync to knowledge/todos/pending.md."""
286
+ todos: list[str] = []
287
+ cfg = _cfg()
288
+ runs_dir = cfg.runs_dir
289
+
290
+ if runs_dir.is_dir():
291
+ for plan_md in sorted(runs_dir.rglob("plan.md")):
292
+ try:
293
+ for line in plan_md.read_text(encoding="utf-8").splitlines():
294
+ if line.strip().startswith("- [ ]"):
295
+ todos.append(line.strip())
296
+ except Exception:
297
+ pass
298
+
299
+ knowledge_todos = _knowledge_todos()
300
+ knowledge_todos.parent.mkdir(parents=True, exist_ok=True)
301
+ existing = ""
302
+ if knowledge_todos.exists():
303
+ existing = knowledge_todos.read_text(encoding="utf-8")
304
+
305
+ if todos:
306
+ block = "\n## Synced from devcompanion runs\n\n" + "\n".join(todos) + "\n"
307
+ marker = "\n## Synced from devcompanion runs\n"
308
+ if marker in existing:
309
+ pre = existing[: existing.index(marker)]
310
+ knowledge_todos.write_text(pre + block, encoding="utf-8")
311
+ else:
312
+ knowledge_todos.write_text(
313
+ (existing.rstrip() + "\n" + block) if existing else block, encoding="utf-8"
314
+ )
315
+ _ok(f"Synced {len(todos)} todo(s) → {knowledge_todos}")
316
+ else:
317
+ _ok("No '- [ ]' items found in run plans.")
318
+
319
+
320
+ # ── runners ───────────────────────────────────────────────────────────────────
321
+
322
+
323
+ def _import_harness_runner():
324
+ """Try to import the harness workstation runner."""
325
+ runner_root = os.environ.get("HARNESS_RUNNER_DIR", "").strip()
326
+ if not runner_root:
327
+ runner_root = str(Path.home() / ".local" / "share" / "agentic-harness" / "runner")
328
+ runner_dir = Path(runner_root) / "runner"
329
+ if not runner_dir.is_dir():
330
+ return None, f"runner dir not found: {runner_dir}"
331
+ if str(runner_dir) not in sys.path:
332
+ sys.path.insert(0, str(runner_dir))
333
+ try:
334
+ import dots_ai_devcompanion_runner as runner_mod
335
+
336
+ return runner_mod, None
337
+ except ImportError as exc:
338
+ return None, str(exc)
339
+
340
+
341
+ def _has_loops(repo_path: str) -> bool:
342
+ if not repo_path:
343
+ return False
344
+ loops_dir = Path(repo_path) / "loops"
345
+ return loops_dir.is_dir() and any(loops_dir.iterdir())
346
+
347
+
348
+ def _try_harness_runner(job_file: Path, out_dir: Path) -> bool:
349
+ runner, _reason = _import_harness_runner()
350
+ if runner is None:
351
+ return False
352
+
353
+ argv = ["--job", str(job_file), "--out", str(out_dir)]
354
+ try:
355
+ rc = runner.main(argv)
356
+ except Exception as exc:
357
+ _warn(f"Harness runner failed: {exc}")
358
+ return False
359
+
360
+ if rc is None:
361
+ rc = 0
362
+ if rc == 0:
363
+ _ok("Harness runner completed")
364
+ return True
365
+
366
+ _warn(f"Harness runner exited {rc}")
367
+ return False
368
+
369
+
370
+ def _try_loop_runner(job: dict, out_dir: Path) -> bool:
371
+ repo_path = job_project_path(job)
372
+ if not _has_loops(repo_path):
373
+ return False
374
+
375
+ toolkit_bin = shutil.which("agent-toolkit")
376
+ if not toolkit_bin:
377
+ return False
378
+
379
+ request = job.get("request", "")
380
+ try:
381
+ result = subprocess.run(
382
+ [toolkit_bin, "loop", "run", "--request", request],
383
+ capture_output=True,
384
+ text=True,
385
+ cwd=repo_path,
386
+ timeout=1800,
387
+ )
388
+ except subprocess.TimeoutExpired:
389
+ _warn("agent-toolkit loop run timed out (1800s)")
390
+ return False
391
+
392
+ out_dir.mkdir(parents=True, exist_ok=True)
393
+ if result.returncode == 0:
394
+ plan_md = out_dir / "plan.md"
395
+ if not plan_md.exists() and result.stdout.strip():
396
+ plan_md.write_text(result.stdout, encoding="utf-8")
397
+ _ok("agent-toolkit loop run completed")
398
+ return True
399
+
400
+ _warn(f"agent-toolkit loop run exited {result.returncode}: {result.stderr[:200]}")
401
+ return False
402
+
403
+
404
+ def _try_claude_runner(job: dict, out_dir: Path) -> bool:
405
+ claude_bin = shutil.which("claude")
406
+ if not claude_bin:
407
+ return False
408
+
409
+ repo_path = job_project_path(job)
410
+ request = job.get("request", "")
411
+ context = f"Repository: {repo_path}\n" if repo_path else ""
412
+
413
+ prompt = (
414
+ f"You are an AI assistant executing a background job.\n"
415
+ f"Workspace root: {_workspace()}\n"
416
+ f"{context}"
417
+ f"Output directory: {out_dir}\n\n"
418
+ f"{request}\n\n"
419
+ f"Write your plan to {out_dir}/plan.md. "
420
+ f"Work from the workspace root shown above."
421
+ )
422
+
423
+ try:
424
+ env = _runner_env_for_job(job, out_dir)
425
+ except RuntimeError as exc:
426
+ _err(str(exc))
427
+ return False
428
+
429
+ limits = job.get("limits") or {}
430
+ timeout = int(limits.get("timeout_sec", 1800))
431
+
432
+ try:
433
+ result = subprocess.run(
434
+ [claude_bin, "--print", "--allowedTools", "Bash,Read,Write,Edit,Glob,Grep"],
435
+ input=prompt,
436
+ capture_output=True,
437
+ text=True,
438
+ cwd=str(_workspace()),
439
+ timeout=timeout,
440
+ env=env,
441
+ )
442
+ except subprocess.TimeoutExpired:
443
+ _warn(f"claude runner timed out ({timeout}s)")
444
+ return False
445
+
446
+ out_dir.mkdir(parents=True, exist_ok=True)
447
+ if result.returncode == 0:
448
+ plan_md = out_dir / "plan.md"
449
+ if not plan_md.exists() and result.stdout.strip():
450
+ plan_md.write_text(result.stdout, encoding="utf-8")
451
+ _ok("claude runner completed")
452
+ return True
453
+
454
+ _warn(f"claude runner exited {result.returncode}: {result.stderr[:200]}")
455
+ return False
456
+
457
+
458
+ def _try_opencode_runner(job: dict, out_dir: Path) -> bool:
459
+ opencode_bin = shutil.which("opencode")
460
+ if not opencode_bin:
461
+ return False
462
+
463
+ request = job.get("request", "")
464
+ prompt = (
465
+ f"You are executing an autonomous loop run in an agentic-harness workspace.\n"
466
+ f"Workspace root: {_workspace()}\n"
467
+ f"Output directory: {out_dir}\n\n"
468
+ f"{request}\n\n"
469
+ f"Write your final report to {out_dir}/report.md and your plan to "
470
+ f"{out_dir}/plan.md. Work from the workspace root shown above."
471
+ )
472
+
473
+ try:
474
+ env = _runner_env_for_job(job, out_dir)
475
+ except RuntimeError as exc:
476
+ _err(str(exc))
477
+ return False
478
+
479
+ limits = job.get("limits") or {}
480
+ timeout = int(limits.get("timeout_sec", 900))
481
+
482
+ try:
483
+ result = subprocess.run(
484
+ [opencode_bin, "run", "--print-logs"],
485
+ input=prompt,
486
+ capture_output=True,
487
+ text=True,
488
+ cwd=str(_workspace()),
489
+ timeout=timeout,
490
+ env=env,
491
+ )
492
+ except subprocess.TimeoutExpired:
493
+ _warn(f"opencode runner timed out ({timeout}s)")
494
+ return False
495
+
496
+ if result.returncode == 0:
497
+ out_dir.mkdir(parents=True, exist_ok=True)
498
+ report_md = out_dir / "report.md"
499
+ if not report_md.exists() and result.stdout.strip():
500
+ report_md.write_text(result.stdout, encoding="utf-8")
501
+ _ok("opencode runner completed")
502
+ return True
503
+
504
+ _warn(f"opencode runner exited {result.returncode}: {result.stderr[:200]}")
505
+ return False
506
+
507
+
508
+ def _skeleton_run(job: dict, out_dir: Path) -> int:
509
+ out_dir.mkdir(parents=True, exist_ok=True)
510
+ try:
511
+ job_id = job.get("id", "unknown")
512
+ project = job_project_name(job)
513
+ request = job.get("request", "(no request)")
514
+
515
+ plan = f"""# Plan — {job_id}
516
+
517
+ **Generated**: {_utc_now()}
518
+ **Mode**: skeleton (no LLM)
519
+ **Project**: {project}
520
+
521
+ ## Request
522
+
523
+ {request}
524
+
525
+ ## Steps
526
+
527
+ > This is a skeleton plan. Run without --no-llm for AI-generated steps.
528
+
529
+ - [ ] Read project README and AGENTS.md
530
+ - [ ] Understand existing conventions and patterns
531
+ - [ ] Analyse the request in context
532
+ - [ ] Implement changes following project conventions
533
+ - [ ] Run tests and verify
534
+ - [ ] Create PR
535
+
536
+ ## Notes
537
+
538
+ - Job ID: {job_id}
539
+ - Project path: {job_project_path(job) or "not set"}
540
+ """
541
+ (out_dir / "plan.md").write_text(plan, encoding="utf-8")
542
+ _ok(f"Skeleton plan written → {out_dir / 'plan.md'}")
543
+ return 0
544
+ except Exception as exc:
545
+ _err(f"Skeleton runner failed: {exc}")
546
+ return 1
547
+
548
+
549
+ def _dispatch_run(cfg: DCConfig, job_file: Path, job: dict, out_dir: Path, no_llm: bool) -> int:
550
+ if no_llm:
551
+ _log("--no-llm flag set, using skeleton runner.")
552
+ return _skeleton_run(job, out_dir)
553
+
554
+ if _job_is_mutating(job) and not shutil.which("gh"):
555
+ _err(
556
+ "Mutating devcompanion job requires `gh` on PATH for loop-gh-gate "
557
+ f"(template={job.get('template') or 'custom'})"
558
+ )
559
+ return 2
560
+
561
+ if cfg.harness_mode:
562
+ runner, reason = _import_harness_runner()
563
+ if runner is not None:
564
+ if _try_harness_runner(job_file, out_dir):
565
+ return 0
566
+ elif reason:
567
+ _warn(f"Harness runner not available ({reason}). Trying fallbacks.")
568
+
569
+ if _try_claude_runner(job, out_dir):
570
+ return 0
571
+ if _try_opencode_runner(job, out_dir):
572
+ return 0
573
+ _warn("No LLM runner found, falling back to skeleton plan.")
574
+ return _skeleton_run(job, out_dir)
575
+
576
+ if _try_loop_runner(job, out_dir):
577
+ return 0
578
+ if _try_claude_runner(job, out_dir):
579
+ return 0
580
+ _warn("No LLM runner found, falling back to skeleton plan.")
581
+ return _skeleton_run(job, out_dir)
582
+
583
+
584
+ # ── subcommands ───────────────────────────────────────────────────────────────
585
+
586
+
587
+ def _safe_parse(parser, argv: list[str]) -> tuple[object | None, int | None]:
588
+ """Parse argv without letting argparse SystemExit bypass cmd return codes (#48)."""
589
+ try:
590
+ return parser.parse_args(argv), None
591
+ except SystemExit as exc:
592
+ if exc.code in (0, None):
593
+ return None, 0
594
+ return None, int(exc.code) if isinstance(exc.code, int) else 2
595
+
596
+
597
+ def _cmd_queue(argv: list[str]) -> int:
598
+ import argparse
599
+
600
+ p = argparse.ArgumentParser(prog="agent-toolkit devcompanion queue", add_help=True)
601
+ p.add_argument("project", nargs="?", help="Project name (maps to projects/<project>)")
602
+ p.add_argument("--template", "-t", help="Job template name from templates/jobs/")
603
+ p.add_argument("--request", "-r", help="Custom request string")
604
+ p.add_argument("--id", help="Custom job ID (default: <project>-<timestamp>)")
605
+ args, parse_err = _safe_parse(p, argv)
606
+ if parse_err is not None:
607
+ return parse_err
608
+
609
+ if not args.project:
610
+ _err(
611
+ 'Usage: agent-toolkit devcompanion queue <project> [--template NAME] [--request "..."]'
612
+ )
613
+ return 1
614
+
615
+ project_path = _resolve_project(args.project)
616
+ if project_path is None:
617
+ _err(f"Project not found: '{args.project}'")
618
+ projects = _list_projects()
619
+ if projects:
620
+ print("\nKnown projects:")
621
+ for name, target in projects:
622
+ s = str(target) if target else _red("(broken)")
623
+ print(f" {_cyan(f'{name:<30}')} → {s}")
624
+ else:
625
+ print(" (no projects indexed)")
626
+ return 1
627
+
628
+ request = ""
629
+ if args.template:
630
+ try:
631
+ tpl = _load_template(args.template)
632
+ except TemplateNotFoundError as exc:
633
+ _err(str(exc))
634
+ return 1
635
+ request = tpl["request"]
636
+ if args.request:
637
+ request = f"{request}\n\n---\n\n{args.request}"
638
+ elif args.request:
639
+ request = args.request
640
+ else:
641
+ _err("Provide --request or --template")
642
+ return 1
643
+
644
+ cfg = _cfg()
645
+ job_id = args.id or f"{args.project}-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
646
+
647
+ if cfg.harness_mode:
648
+ job: dict = {
649
+ "id": job_id,
650
+ "created_at": _utc_now(),
651
+ "request": request,
652
+ "repo_path": str(project_path),
653
+ "llm": True,
654
+ "limits": {"timeout_sec": 1800, "max_steps": 25},
655
+ "actions_allowed": ["plan_only"],
656
+ }
657
+ else:
658
+ job = {
659
+ "id": job_id,
660
+ "created_at": _utc_now(),
661
+ "project": args.project,
662
+ "project_path": str(project_path),
663
+ "request": request,
664
+ "template": args.template or "",
665
+ "status": "pending",
666
+ }
667
+
668
+ job_file = queue_job_path(cfg, job_id)
669
+ write_job(job_file, job)
670
+
671
+ _log(f"Project : {args.project}")
672
+ _log(f"Path : {project_path}")
673
+ _log(f"Job ID : {job_id}")
674
+ _ok(f"Job written → {job_file}")
675
+ print()
676
+ print(_cyan("Plan stub:"))
677
+ print(" Run 'agent-toolkit devcompanion run-once' to execute")
678
+ print(" Run 'agent-toolkit devcompanion status' to check progress")
679
+ return 0
680
+
681
+
682
+ def _cmd_run_once(argv: list[str]) -> int:
683
+ import argparse
684
+
685
+ p = argparse.ArgumentParser(prog="agent-toolkit devcompanion run-once", add_help=True)
686
+ p.add_argument("--no-llm", action="store_true", help="Always use skeleton plan, skip LLM")
687
+ args, parse_err = _safe_parse(p, argv)
688
+ if parse_err is not None:
689
+ return parse_err
690
+
691
+ cfg = _cfg()
692
+ pending = pending_jobs(cfg)
693
+
694
+ if not pending:
695
+ _ok("No pending jobs.")
696
+ return 0
697
+
698
+ job_file, job = pending[0]
699
+ job_id = job["id"]
700
+ out_dir = cfg.runs_dir / job_id
701
+
702
+ _log(f"Running job: {job_id}")
703
+ _log(f"Project : {job_project_name(job)}")
704
+ _log(f"Artifacts → {out_dir}")
705
+
706
+ if cfg.harness_mode:
707
+ cfg.queue_processing.mkdir(parents=True, exist_ok=True)
708
+ processing_file = cfg.queue_processing / job_file.name
709
+ job_file.rename(processing_file)
710
+ job_file = processing_file
711
+ else:
712
+ job["status"] = "running"
713
+ write_job(job_file, job)
714
+
715
+ rc = _dispatch_run(cfg, job_file, job, out_dir, args.no_llm)
716
+
717
+ if cfg.harness_mode:
718
+ dest_dir = cfg.queue_done if rc == 0 else cfg.queue_failed
719
+ dest_dir.mkdir(parents=True, exist_ok=True)
720
+ if job_file.exists():
721
+ job_file.rename(dest_dir / job_file.name)
722
+ else:
723
+ job["status"] = "done" if rc == 0 else "failed"
724
+ job["completed_at"] = _utc_now()
725
+ write_job(job_file, job)
726
+
727
+ if rc == 0:
728
+ _ok(f"Job done: {job_id}")
729
+ plan_path = out_dir / "plan.md"
730
+ if plan_path.exists():
731
+ print()
732
+ print(_cyan(f"── plan.md {'─' * 50}"))
733
+ print(plan_path.read_text(encoding="utf-8")[:2000])
734
+ else:
735
+ _err(f"Job failed: {job_id}")
736
+
737
+ return rc
738
+
739
+
740
+ def _cmd_status(_argv: list[str]) -> int:
741
+ cfg = _cfg()
742
+ print()
743
+ print(_blue("=== devcompanion queue status ==="))
744
+ print()
745
+
746
+ jobs = iter_jobs(cfg)
747
+ if not jobs:
748
+ print(" (queue is empty)")
749
+ print()
750
+ return 0
751
+
752
+ if cfg.harness_mode:
753
+ for state, directory, color in (
754
+ ("pending", cfg.queue_pending, _yellow),
755
+ ("processing", cfg.queue_processing, _cyan),
756
+ ("done", cfg.queue_done, _green),
757
+ ("failed", cfg.queue_failed, _red),
758
+ ):
759
+ if not directory.is_dir():
760
+ continue
761
+ state_jobs = [item for item in jobs if item[0] == state]
762
+ print(f"{color(f'{state:<12}')} {len(state_jobs)} job(s)")
763
+ for _, jf, job in state_jobs[:5]:
764
+ jid = job.get("id", jf.stem)
765
+ project = job_project_name(job)
766
+ request = job.get("request", "").split("\n")[0][:60]
767
+ print(f" {_cyan(f'{jid:<45}')} [{project}] {request}")
768
+ if len(state_jobs) > 5:
769
+ print(f" … and {len(state_jobs) - 5} more")
770
+ print()
771
+ return 0
772
+
773
+ col_id = 42
774
+ col_project = 20
775
+ col_status = 12
776
+ col_created = 20
777
+
778
+ header = (
779
+ f"{'JOB ID':<{col_id}} "
780
+ f"{'PROJECT':<{col_project}} "
781
+ f"{'STATUS':<{col_status}} "
782
+ f"{'CREATED AT':<{col_created}}"
783
+ )
784
+ print(_cyan(header))
785
+ print("─" * (col_id + col_project + col_status + col_created + 6))
786
+
787
+ status_color = {
788
+ "pending": _yellow,
789
+ "running": _cyan,
790
+ "done": _green,
791
+ "failed": _red,
792
+ }
793
+
794
+ for status, jf, job in jobs:
795
+ try:
796
+ jid = job.get("id", jf.stem)[:col_id]
797
+ project = job_project_name(job)[:col_project]
798
+ created = job.get("created_at", "")[:19]
799
+ color = status_color.get(status, lambda x: x)
800
+ print(
801
+ f"{jid:<{col_id}} "
802
+ f"{project:<{col_project}} "
803
+ f"{color(f'{status:<{col_status}}')} "
804
+ f"{created:<{col_created}}"
805
+ )
806
+ except Exception:
807
+ print(f" {jf.name} (unreadable)")
808
+
809
+ print()
810
+ return 0
811
+
812
+
813
+ def _cmd_done(argv: list[str]) -> int:
814
+ import argparse
815
+
816
+ p = argparse.ArgumentParser(prog="agent-toolkit devcompanion done", add_help=True)
817
+ p.add_argument("job_id", nargs="?", help="Job ID to mark as done")
818
+ args, parse_err = _safe_parse(p, argv)
819
+ if parse_err is not None:
820
+ return parse_err
821
+
822
+ if not args.job_id:
823
+ _err("Usage: agent-toolkit devcompanion done <job-id>")
824
+ return 1
825
+
826
+ cfg = _cfg()
827
+ job_id = args.job_id
828
+
829
+ if cfg.harness_mode:
830
+ if mark_job_done(cfg, job_id, _utc_now()):
831
+ _ok(f"Marked as done: {job_id}")
832
+ return 0
833
+ _warn(f"Job file not found: {job_id}.job")
834
+ return 1
835
+
836
+ job_file = find_job_path(cfg, job_id)
837
+ if job_file is None:
838
+ _warn(f"Job file not found: {job_id}.json")
839
+ return 1
840
+
841
+ job = read_job(job_file)
842
+ job["status"] = "done"
843
+ job["completed_at"] = _utc_now()
844
+ write_job(job_file, job)
845
+ _ok(f"Marked as done: {job_id}")
846
+ return 0
847
+
848
+
849
+ def _cmd_sync_todos(_argv: list[str]) -> int:
850
+ _sync_todos()
851
+ return 0
852
+
853
+
854
+ def _cmd_help(_argv: list[str]) -> int:
855
+ cfg = _cfg()
856
+ queue_loc = str(cfg.dc_home / "queue") if cfg.harness_mode else str(cfg.queue_dir)
857
+ mode = "harness (.job files)" if cfg.harness_mode else "workspace (.json files)"
858
+ print(f"""
859
+ {_blue("agent-toolkit devcompanion")} — background job queue for AI Workspace
860
+
861
+ {_cyan("Usage:")}
862
+ agent-toolkit devcompanion queue <project> [options] Queue a job
863
+ agent-toolkit devcompanion run-once [--no-llm] Run oldest pending job
864
+ agent-toolkit devcompanion status Show all jobs
865
+ agent-toolkit devcompanion done <job-id> Mark a job as done
866
+ agent-toolkit devcompanion sync-todos Sync todos from plan.md files
867
+
868
+ {_cyan("Queue options:")}
869
+ --template NAME Job template from templates/jobs/ directory
870
+ --request "..." Custom request string (required if no --template)
871
+ --id ID Custom job ID (default: <project>-<timestamp>)
872
+
873
+ {_cyan("Workspace detection:")}
874
+ AGENT_TOOLKIT_WORKSPACE env var, or walk up from CWD looking for .devcompanion/
875
+
876
+ {_cyan("Queue mode:")}
877
+ {mode}
878
+ HARNESS_DC_HOME or HARNESS_DIR → harness queue under ~/.local/share/agentic-harness/dev-companion
879
+
880
+ {_cyan("Queue location:")}
881
+ {queue_loc}
882
+
883
+ {_cyan("Runs location:")}
884
+ {cfg.runs_dir}
885
+
886
+ {_cyan("Examples:")}
887
+ agent-toolkit devcompanion queue my-api --template code-review
888
+ agent-toolkit devcompanion queue my-api --request "add pagination to GET /users"
889
+ agent-toolkit devcompanion run-once
890
+ agent-toolkit devcompanion run-once --no-llm
891
+ agent-toolkit devcompanion status
892
+ agent-toolkit devcompanion done my-api-20260804-120000
893
+ agent-toolkit devcompanion sync-todos
894
+
895
+ {_cyan("Alias:")}
896
+ agent-toolkit dc <subcommand>
897
+ """)
898
+ return 0
899
+
900
+
901
+ def cmd_devcompanion(argv: list[str]) -> int:
902
+ if not argv or argv[0] in ("-h", "--help", "help"):
903
+ return _cmd_help([])
904
+
905
+ subcommand = argv[0]
906
+ rest = argv[1:]
907
+
908
+ dispatch = {
909
+ "queue": _cmd_queue,
910
+ "run-once": _cmd_run_once,
911
+ "status": _cmd_status,
912
+ "done": _cmd_done,
913
+ "sync-todos": _cmd_sync_todos,
914
+ "help": _cmd_help,
915
+ }
916
+
917
+ fn = dispatch.get(subcommand)
918
+ if fn is None:
919
+ _err(f"Unknown subcommand: {subcommand}")
920
+ print("Run 'agent-toolkit devcompanion help' for usage.", file=sys.stderr)
921
+ return 1
922
+
923
+ return fn(rest)