@chankov/agent-skills 0.1.0 → 0.3.0

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 (328) hide show
  1. package/.claude/commands/{doctor.md → doctor-agent-skills.md} +1 -1
  2. package/.pi/extensions/agent-skills-update-check/README.md +58 -0
  3. package/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  4. package/.pi/extensions/agent-skills-update-check/package.json +6 -0
  5. package/.pi/prompts/{doctor.md → doctor-agent-skills.md} +1 -1
  6. package/.versions/0.2.0/.claude/commands/build.md +18 -0
  7. package/.versions/0.2.0/.claude/commands/code-simplify.md +22 -0
  8. package/.versions/0.2.0/.claude/commands/design-agent.md +14 -0
  9. package/.versions/0.2.0/.claude/commands/doctor-agent-skills.md +13 -0
  10. package/.versions/0.2.0/.claude/commands/plan.md +16 -0
  11. package/.versions/0.2.0/.claude/commands/prime.md +22 -0
  12. package/.versions/0.2.0/.claude/commands/review.md +16 -0
  13. package/.versions/0.2.0/.claude/commands/setup-agent-skills.md +19 -0
  14. package/.versions/0.2.0/.claude/commands/ship.md +17 -0
  15. package/.versions/0.2.0/.claude/commands/spec.md +15 -0
  16. package/.versions/0.2.0/.claude/commands/test.md +19 -0
  17. package/.versions/0.2.0/.opencode/commands/as-build.md +17 -0
  18. package/.versions/0.2.0/.opencode/commands/as-code-simplify.md +16 -0
  19. package/.versions/0.2.0/.opencode/commands/as-design-agent.md +15 -0
  20. package/.versions/0.2.0/.opencode/commands/as-doctor-agent-skills.md +11 -0
  21. package/.versions/0.2.0/.opencode/commands/as-plan.md +16 -0
  22. package/.versions/0.2.0/.opencode/commands/as-prime.md +22 -0
  23. package/.versions/0.2.0/.opencode/commands/as-review.md +15 -0
  24. package/.versions/0.2.0/.opencode/commands/as-setup-agent-skills.md +11 -0
  25. package/.versions/0.2.0/.opencode/commands/as-ship.md +16 -0
  26. package/.versions/0.2.0/.opencode/commands/as-spec.md +16 -0
  27. package/.versions/0.2.0/.opencode/commands/as-test.md +21 -0
  28. package/.versions/0.2.0/.pi/agents/agent-chain.yaml +49 -0
  29. package/.versions/0.2.0/.pi/agents/bowser.md +19 -0
  30. package/.versions/0.2.0/.pi/agents/pi-pi/agent-expert.md +98 -0
  31. package/.versions/0.2.0/.pi/agents/pi-pi/cli-expert.md +41 -0
  32. package/.versions/0.2.0/.pi/agents/pi-pi/config-expert.md +63 -0
  33. package/.versions/0.2.0/.pi/agents/pi-pi/ext-expert.md +43 -0
  34. package/.versions/0.2.0/.pi/agents/pi-pi/keybinding-expert.md +134 -0
  35. package/.versions/0.2.0/.pi/agents/pi-pi/pi-orchestrator.md +57 -0
  36. package/.versions/0.2.0/.pi/agents/pi-pi/prompt-expert.md +70 -0
  37. package/.versions/0.2.0/.pi/agents/pi-pi/skill-expert.md +42 -0
  38. package/.versions/0.2.0/.pi/agents/pi-pi/theme-expert.md +40 -0
  39. package/.versions/0.2.0/.pi/agents/pi-pi/tui-expert.md +85 -0
  40. package/.versions/0.2.0/.pi/agents/teams.yaml +31 -0
  41. package/.versions/0.2.0/.pi/damage-control-rules.yaml +278 -0
  42. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/README.md +58 -0
  43. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  44. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/package.json +6 -0
  45. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/README.md +39 -0
  46. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/index.ts +61 -0
  47. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/package.json +6 -0
  48. package/.versions/0.2.0/.pi/extensions/compact-and-continue/README.md +42 -0
  49. package/.versions/0.2.0/.pi/extensions/compact-and-continue/index.ts +120 -0
  50. package/.versions/0.2.0/.pi/extensions/compact-and-continue/package.json +6 -0
  51. package/.versions/0.2.0/.pi/extensions/mcp-bridge/README.md +46 -0
  52. package/.versions/0.2.0/.pi/extensions/mcp-bridge/index.ts +206 -0
  53. package/.versions/0.2.0/.pi/extensions/mcp-bridge/package.json +6 -0
  54. package/.versions/0.2.0/.pi/extensions/package-lock.json +1143 -0
  55. package/.versions/0.2.0/.pi/extensions/package.json +9 -0
  56. package/.versions/0.2.0/.pi/harnesses/agent-chain/README.md +37 -0
  57. package/.versions/0.2.0/.pi/harnesses/agent-chain/index.ts +795 -0
  58. package/.versions/0.2.0/.pi/harnesses/agent-chain/package.json +6 -0
  59. package/.versions/0.2.0/.pi/harnesses/agent-team/README.md +38 -0
  60. package/.versions/0.2.0/.pi/harnesses/agent-team/index.ts +732 -0
  61. package/.versions/0.2.0/.pi/harnesses/agent-team/package.json +6 -0
  62. package/.versions/0.2.0/.pi/harnesses/coms/README.md +36 -0
  63. package/.versions/0.2.0/.pi/harnesses/coms/index.ts +1595 -0
  64. package/.versions/0.2.0/.pi/harnesses/coms/package.json +6 -0
  65. package/.versions/0.2.0/.pi/harnesses/coms-net/README.md +46 -0
  66. package/.versions/0.2.0/.pi/harnesses/coms-net/index.ts +1637 -0
  67. package/.versions/0.2.0/.pi/harnesses/coms-net/package.json +6 -0
  68. package/.versions/0.2.0/.pi/harnesses/damage-control/README.md +38 -0
  69. package/.versions/0.2.0/.pi/harnesses/damage-control/index.ts +207 -0
  70. package/.versions/0.2.0/.pi/harnesses/damage-control/package.json +6 -0
  71. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/README.md +37 -0
  72. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/index.ts +234 -0
  73. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/package.json +6 -0
  74. package/.versions/0.2.0/.pi/harnesses/minimal/README.md +27 -0
  75. package/.versions/0.2.0/.pi/harnesses/minimal/index.ts +32 -0
  76. package/.versions/0.2.0/.pi/harnesses/minimal/package.json +6 -0
  77. package/.versions/0.2.0/.pi/harnesses/package-lock.json +35 -0
  78. package/.versions/0.2.0/.pi/harnesses/package.json +9 -0
  79. package/.versions/0.2.0/.pi/harnesses/pi-pi/README.md +39 -0
  80. package/.versions/0.2.0/.pi/harnesses/pi-pi/index.ts +631 -0
  81. package/.versions/0.2.0/.pi/harnesses/pi-pi/package.json +6 -0
  82. package/.versions/0.2.0/.pi/harnesses/purpose-gate/README.md +27 -0
  83. package/.versions/0.2.0/.pi/harnesses/purpose-gate/index.ts +82 -0
  84. package/.versions/0.2.0/.pi/harnesses/purpose-gate/package.json +6 -0
  85. package/.versions/0.2.0/.pi/harnesses/session-replay/README.md +28 -0
  86. package/.versions/0.2.0/.pi/harnesses/session-replay/index.ts +214 -0
  87. package/.versions/0.2.0/.pi/harnesses/session-replay/package.json +6 -0
  88. package/.versions/0.2.0/.pi/harnesses/subagent-widget/README.md +36 -0
  89. package/.versions/0.2.0/.pi/harnesses/subagent-widget/index.ts +479 -0
  90. package/.versions/0.2.0/.pi/harnesses/subagent-widget/package.json +6 -0
  91. package/.versions/0.2.0/.pi/harnesses/system-select/README.md +39 -0
  92. package/.versions/0.2.0/.pi/harnesses/system-select/index.ts +165 -0
  93. package/.versions/0.2.0/.pi/harnesses/system-select/package.json +6 -0
  94. package/.versions/0.2.0/.pi/harnesses/tilldone/README.md +35 -0
  95. package/.versions/0.2.0/.pi/harnesses/tilldone/index.ts +724 -0
  96. package/.versions/0.2.0/.pi/harnesses/tilldone/package.json +6 -0
  97. package/.versions/0.2.0/.pi/harnesses/tool-counter/README.md +31 -0
  98. package/.versions/0.2.0/.pi/harnesses/tool-counter/index.ts +100 -0
  99. package/.versions/0.2.0/.pi/harnesses/tool-counter/package.json +6 -0
  100. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/README.md +27 -0
  101. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/index.ts +66 -0
  102. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/package.json +6 -0
  103. package/.versions/0.2.0/.pi/prompts/build.md +24 -0
  104. package/.versions/0.2.0/.pi/prompts/code-simplify.md +22 -0
  105. package/.versions/0.2.0/.pi/prompts/doctor-agent-skills.md +13 -0
  106. package/.versions/0.2.0/.pi/prompts/plan.md +16 -0
  107. package/.versions/0.2.0/.pi/prompts/review.md +16 -0
  108. package/.versions/0.2.0/.pi/prompts/setup-agent-skills.md +19 -0
  109. package/.versions/0.2.0/.pi/prompts/ship.md +17 -0
  110. package/.versions/0.2.0/.pi/prompts/spec.md +15 -0
  111. package/.versions/0.2.0/.pi/prompts/test.md +19 -0
  112. package/.versions/0.2.0/.pi/skills/bowser/SKILL.md +114 -0
  113. package/.versions/0.2.0/.version +1 -0
  114. package/.versions/0.2.0/agents/builder.md +6 -0
  115. package/.versions/0.2.0/agents/code-reviewer.md +93 -0
  116. package/.versions/0.2.0/agents/documenter.md +6 -0
  117. package/.versions/0.2.0/agents/plan-reviewer.md +22 -0
  118. package/.versions/0.2.0/agents/planner.md +6 -0
  119. package/.versions/0.2.0/agents/scout.md +6 -0
  120. package/.versions/0.2.0/agents/security-auditor.md +97 -0
  121. package/.versions/0.2.0/agents/test-engineer.md +89 -0
  122. package/.versions/0.2.0/hooks/SIMPLIFY-IGNORE.md +90 -0
  123. package/.versions/0.2.0/hooks/hooks.json +14 -0
  124. package/.versions/0.2.0/hooks/session-start.sh +74 -0
  125. package/.versions/0.2.0/hooks/simplify-ignore-test.sh +247 -0
  126. package/.versions/0.2.0/hooks/simplify-ignore.sh +302 -0
  127. package/.versions/0.2.0/references/accessibility-checklist.md +159 -0
  128. package/.versions/0.2.0/references/performance-checklist.md +121 -0
  129. package/.versions/0.2.0/references/prompting-patterns.md +380 -0
  130. package/.versions/0.2.0/references/security-checklist.md +134 -0
  131. package/.versions/0.2.0/references/testing-patterns.md +236 -0
  132. package/.versions/0.2.0/skills/api-and-interface-design/SKILL.md +294 -0
  133. package/.versions/0.2.0/skills/browser-testing-with-devtools/SKILL.md +335 -0
  134. package/.versions/0.2.0/skills/ci-cd-and-automation/SKILL.md +390 -0
  135. package/.versions/0.2.0/skills/code-review-and-quality/SKILL.md +347 -0
  136. package/.versions/0.2.0/skills/code-simplification/SKILL.md +331 -0
  137. package/.versions/0.2.0/skills/context-engineering/SKILL.md +291 -0
  138. package/.versions/0.2.0/skills/debugging-and-error-recovery/SKILL.md +300 -0
  139. package/.versions/0.2.0/skills/deprecation-and-migration/SKILL.md +206 -0
  140. package/.versions/0.2.0/skills/designing-agents/SKILL.md +394 -0
  141. package/.versions/0.2.0/skills/designing-agents/pi-harness-authoring.md +213 -0
  142. package/.versions/0.2.0/skills/documentation-and-adrs/SKILL.md +278 -0
  143. package/.versions/0.2.0/skills/frontend-ui-engineering/SKILL.md +322 -0
  144. package/.versions/0.2.0/skills/git-workflow-and-versioning/SKILL.md +316 -0
  145. package/.versions/0.2.0/skills/guided-workspace-setup/SKILL.md +331 -0
  146. package/.versions/0.2.0/skills/idea-refine/SKILL.md +178 -0
  147. package/.versions/0.2.0/skills/idea-refine/examples.md +238 -0
  148. package/.versions/0.2.0/skills/idea-refine/frameworks.md +99 -0
  149. package/.versions/0.2.0/skills/idea-refine/refinement-criteria.md +113 -0
  150. package/.versions/0.2.0/skills/idea-refine/scripts/idea-refine.sh +15 -0
  151. package/.versions/0.2.0/skills/incremental-implementation/SKILL.md +279 -0
  152. package/.versions/0.2.0/skills/performance-optimization/SKILL.md +350 -0
  153. package/.versions/0.2.0/skills/planning-and-task-breakdown/SKILL.md +237 -0
  154. package/.versions/0.2.0/skills/security-and-hardening/SKILL.md +349 -0
  155. package/.versions/0.2.0/skills/shipping-and-launch/SKILL.md +309 -0
  156. package/.versions/0.2.0/skills/source-driven-development/SKILL.md +194 -0
  157. package/.versions/0.2.0/skills/spec-driven-development/SKILL.md +237 -0
  158. package/.versions/0.2.0/skills/test-driven-development/SKILL.md +379 -0
  159. package/.versions/0.2.0/skills/using-agent-skills/SKILL.md +176 -0
  160. package/.versions/0.3.0/.claude/commands/build.md +18 -0
  161. package/.versions/0.3.0/.claude/commands/code-simplify.md +22 -0
  162. package/.versions/0.3.0/.claude/commands/design-agent.md +14 -0
  163. package/.versions/0.3.0/.claude/commands/doctor-agent-skills.md +13 -0
  164. package/.versions/0.3.0/.claude/commands/plan.md +16 -0
  165. package/.versions/0.3.0/.claude/commands/prime.md +22 -0
  166. package/.versions/0.3.0/.claude/commands/review.md +16 -0
  167. package/.versions/0.3.0/.claude/commands/setup-agent-skills.md +19 -0
  168. package/.versions/0.3.0/.claude/commands/ship.md +17 -0
  169. package/.versions/0.3.0/.claude/commands/spec.md +15 -0
  170. package/.versions/0.3.0/.claude/commands/test.md +19 -0
  171. package/.versions/0.3.0/.opencode/commands/as-build.md +17 -0
  172. package/.versions/0.3.0/.opencode/commands/as-code-simplify.md +16 -0
  173. package/.versions/0.3.0/.opencode/commands/as-design-agent.md +15 -0
  174. package/.versions/0.3.0/.opencode/commands/as-doctor-agent-skills.md +11 -0
  175. package/.versions/0.3.0/.opencode/commands/as-plan.md +16 -0
  176. package/.versions/0.3.0/.opencode/commands/as-prime.md +22 -0
  177. package/.versions/0.3.0/.opencode/commands/as-review.md +15 -0
  178. package/.versions/0.3.0/.opencode/commands/as-setup-agent-skills.md +11 -0
  179. package/.versions/0.3.0/.opencode/commands/as-ship.md +16 -0
  180. package/.versions/0.3.0/.opencode/commands/as-spec.md +16 -0
  181. package/.versions/0.3.0/.opencode/commands/as-test.md +21 -0
  182. package/.versions/0.3.0/.pi/agents/agent-chain.yaml +49 -0
  183. package/.versions/0.3.0/.pi/agents/bowser.md +19 -0
  184. package/.versions/0.3.0/.pi/agents/pi-pi/agent-expert.md +98 -0
  185. package/.versions/0.3.0/.pi/agents/pi-pi/cli-expert.md +41 -0
  186. package/.versions/0.3.0/.pi/agents/pi-pi/config-expert.md +63 -0
  187. package/.versions/0.3.0/.pi/agents/pi-pi/ext-expert.md +43 -0
  188. package/.versions/0.3.0/.pi/agents/pi-pi/keybinding-expert.md +134 -0
  189. package/.versions/0.3.0/.pi/agents/pi-pi/pi-orchestrator.md +57 -0
  190. package/.versions/0.3.0/.pi/agents/pi-pi/prompt-expert.md +70 -0
  191. package/.versions/0.3.0/.pi/agents/pi-pi/skill-expert.md +42 -0
  192. package/.versions/0.3.0/.pi/agents/pi-pi/theme-expert.md +40 -0
  193. package/.versions/0.3.0/.pi/agents/pi-pi/tui-expert.md +85 -0
  194. package/.versions/0.3.0/.pi/agents/teams.yaml +31 -0
  195. package/.versions/0.3.0/.pi/damage-control-rules.yaml +278 -0
  196. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/README.md +58 -0
  197. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  198. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/package.json +6 -0
  199. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/README.md +39 -0
  200. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/index.ts +61 -0
  201. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/package.json +6 -0
  202. package/.versions/0.3.0/.pi/extensions/compact-and-continue/README.md +42 -0
  203. package/.versions/0.3.0/.pi/extensions/compact-and-continue/index.ts +120 -0
  204. package/.versions/0.3.0/.pi/extensions/compact-and-continue/package.json +6 -0
  205. package/.versions/0.3.0/.pi/extensions/mcp-bridge/README.md +46 -0
  206. package/.versions/0.3.0/.pi/extensions/mcp-bridge/index.ts +206 -0
  207. package/.versions/0.3.0/.pi/extensions/mcp-bridge/package.json +6 -0
  208. package/.versions/0.3.0/.pi/extensions/package-lock.json +1143 -0
  209. package/.versions/0.3.0/.pi/extensions/package.json +9 -0
  210. package/.versions/0.3.0/.pi/harnesses/agent-chain/README.md +37 -0
  211. package/.versions/0.3.0/.pi/harnesses/agent-chain/index.ts +795 -0
  212. package/.versions/0.3.0/.pi/harnesses/agent-chain/package.json +6 -0
  213. package/.versions/0.3.0/.pi/harnesses/agent-team/README.md +38 -0
  214. package/.versions/0.3.0/.pi/harnesses/agent-team/index.ts +732 -0
  215. package/.versions/0.3.0/.pi/harnesses/agent-team/package.json +6 -0
  216. package/.versions/0.3.0/.pi/harnesses/coms/README.md +36 -0
  217. package/.versions/0.3.0/.pi/harnesses/coms/index.ts +1595 -0
  218. package/.versions/0.3.0/.pi/harnesses/coms/package.json +6 -0
  219. package/.versions/0.3.0/.pi/harnesses/coms-net/README.md +46 -0
  220. package/.versions/0.3.0/.pi/harnesses/coms-net/index.ts +1637 -0
  221. package/.versions/0.3.0/.pi/harnesses/coms-net/package.json +6 -0
  222. package/.versions/0.3.0/.pi/harnesses/damage-control/README.md +38 -0
  223. package/.versions/0.3.0/.pi/harnesses/damage-control/index.ts +207 -0
  224. package/.versions/0.3.0/.pi/harnesses/damage-control/package.json +6 -0
  225. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/README.md +37 -0
  226. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/index.ts +234 -0
  227. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/package.json +6 -0
  228. package/.versions/0.3.0/.pi/harnesses/minimal/README.md +27 -0
  229. package/.versions/0.3.0/.pi/harnesses/minimal/index.ts +32 -0
  230. package/.versions/0.3.0/.pi/harnesses/minimal/package.json +6 -0
  231. package/.versions/0.3.0/.pi/harnesses/package-lock.json +35 -0
  232. package/.versions/0.3.0/.pi/harnesses/package.json +9 -0
  233. package/.versions/0.3.0/.pi/harnesses/pi-pi/README.md +39 -0
  234. package/.versions/0.3.0/.pi/harnesses/pi-pi/index.ts +631 -0
  235. package/.versions/0.3.0/.pi/harnesses/pi-pi/package.json +6 -0
  236. package/.versions/0.3.0/.pi/harnesses/purpose-gate/README.md +27 -0
  237. package/.versions/0.3.0/.pi/harnesses/purpose-gate/index.ts +82 -0
  238. package/.versions/0.3.0/.pi/harnesses/purpose-gate/package.json +6 -0
  239. package/.versions/0.3.0/.pi/harnesses/session-replay/README.md +28 -0
  240. package/.versions/0.3.0/.pi/harnesses/session-replay/index.ts +214 -0
  241. package/.versions/0.3.0/.pi/harnesses/session-replay/package.json +6 -0
  242. package/.versions/0.3.0/.pi/harnesses/subagent-widget/README.md +36 -0
  243. package/.versions/0.3.0/.pi/harnesses/subagent-widget/index.ts +479 -0
  244. package/.versions/0.3.0/.pi/harnesses/subagent-widget/package.json +6 -0
  245. package/.versions/0.3.0/.pi/harnesses/system-select/README.md +39 -0
  246. package/.versions/0.3.0/.pi/harnesses/system-select/index.ts +165 -0
  247. package/.versions/0.3.0/.pi/harnesses/system-select/package.json +6 -0
  248. package/.versions/0.3.0/.pi/harnesses/tilldone/README.md +35 -0
  249. package/.versions/0.3.0/.pi/harnesses/tilldone/index.ts +724 -0
  250. package/.versions/0.3.0/.pi/harnesses/tilldone/package.json +6 -0
  251. package/.versions/0.3.0/.pi/harnesses/tool-counter/README.md +31 -0
  252. package/.versions/0.3.0/.pi/harnesses/tool-counter/index.ts +100 -0
  253. package/.versions/0.3.0/.pi/harnesses/tool-counter/package.json +6 -0
  254. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/README.md +27 -0
  255. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/index.ts +66 -0
  256. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/package.json +6 -0
  257. package/.versions/0.3.0/.pi/prompts/build.md +24 -0
  258. package/.versions/0.3.0/.pi/prompts/code-simplify.md +22 -0
  259. package/.versions/0.3.0/.pi/prompts/doctor-agent-skills.md +13 -0
  260. package/.versions/0.3.0/.pi/prompts/plan.md +16 -0
  261. package/.versions/0.3.0/.pi/prompts/review.md +16 -0
  262. package/.versions/0.3.0/.pi/prompts/setup-agent-skills.md +19 -0
  263. package/.versions/0.3.0/.pi/prompts/ship.md +17 -0
  264. package/.versions/0.3.0/.pi/prompts/spec.md +15 -0
  265. package/.versions/0.3.0/.pi/prompts/test.md +19 -0
  266. package/.versions/0.3.0/.pi/skills/bowser/SKILL.md +114 -0
  267. package/.versions/0.3.0/.version +1 -0
  268. package/.versions/0.3.0/agents/builder.md +6 -0
  269. package/.versions/0.3.0/agents/code-reviewer.md +93 -0
  270. package/.versions/0.3.0/agents/documenter.md +6 -0
  271. package/.versions/0.3.0/agents/plan-reviewer.md +22 -0
  272. package/.versions/0.3.0/agents/planner.md +6 -0
  273. package/.versions/0.3.0/agents/scout.md +6 -0
  274. package/.versions/0.3.0/agents/security-auditor.md +97 -0
  275. package/.versions/0.3.0/agents/test-engineer.md +89 -0
  276. package/.versions/0.3.0/hooks/SIMPLIFY-IGNORE.md +90 -0
  277. package/.versions/0.3.0/hooks/hooks.json +14 -0
  278. package/.versions/0.3.0/hooks/session-start.sh +74 -0
  279. package/.versions/0.3.0/hooks/simplify-ignore-test.sh +247 -0
  280. package/.versions/0.3.0/hooks/simplify-ignore.sh +302 -0
  281. package/.versions/0.3.0/references/accessibility-checklist.md +159 -0
  282. package/.versions/0.3.0/references/performance-checklist.md +121 -0
  283. package/.versions/0.3.0/references/prompting-patterns.md +380 -0
  284. package/.versions/0.3.0/references/security-checklist.md +134 -0
  285. package/.versions/0.3.0/references/testing-patterns.md +236 -0
  286. package/.versions/0.3.0/skills/api-and-interface-design/SKILL.md +294 -0
  287. package/.versions/0.3.0/skills/browser-testing-with-devtools/SKILL.md +335 -0
  288. package/.versions/0.3.0/skills/ci-cd-and-automation/SKILL.md +390 -0
  289. package/.versions/0.3.0/skills/code-review-and-quality/SKILL.md +347 -0
  290. package/.versions/0.3.0/skills/code-simplification/SKILL.md +331 -0
  291. package/.versions/0.3.0/skills/context-engineering/SKILL.md +291 -0
  292. package/.versions/0.3.0/skills/debugging-and-error-recovery/SKILL.md +300 -0
  293. package/.versions/0.3.0/skills/deprecation-and-migration/SKILL.md +206 -0
  294. package/.versions/0.3.0/skills/designing-agents/SKILL.md +394 -0
  295. package/.versions/0.3.0/skills/designing-agents/pi-harness-authoring.md +213 -0
  296. package/.versions/0.3.0/skills/documentation-and-adrs/SKILL.md +278 -0
  297. package/.versions/0.3.0/skills/frontend-ui-engineering/SKILL.md +322 -0
  298. package/.versions/0.3.0/skills/git-workflow-and-versioning/SKILL.md +316 -0
  299. package/.versions/0.3.0/skills/guided-workspace-setup/SKILL.md +331 -0
  300. package/.versions/0.3.0/skills/idea-refine/SKILL.md +178 -0
  301. package/.versions/0.3.0/skills/idea-refine/examples.md +238 -0
  302. package/.versions/0.3.0/skills/idea-refine/frameworks.md +99 -0
  303. package/.versions/0.3.0/skills/idea-refine/refinement-criteria.md +113 -0
  304. package/.versions/0.3.0/skills/idea-refine/scripts/idea-refine.sh +15 -0
  305. package/.versions/0.3.0/skills/incremental-implementation/SKILL.md +279 -0
  306. package/.versions/0.3.0/skills/performance-optimization/SKILL.md +350 -0
  307. package/.versions/0.3.0/skills/planning-and-task-breakdown/SKILL.md +237 -0
  308. package/.versions/0.3.0/skills/security-and-hardening/SKILL.md +349 -0
  309. package/.versions/0.3.0/skills/shipping-and-launch/SKILL.md +309 -0
  310. package/.versions/0.3.0/skills/source-driven-development/SKILL.md +194 -0
  311. package/.versions/0.3.0/skills/spec-driven-development/SKILL.md +237 -0
  312. package/.versions/0.3.0/skills/test-driven-development/SKILL.md +379 -0
  313. package/.versions/0.3.0/skills/using-agent-skills/SKILL.md +176 -0
  314. package/CHANGELOG.md +108 -0
  315. package/README.md +5 -5
  316. package/bin/cli.js +133 -22
  317. package/bin/lib/bootstrap.js +254 -0
  318. package/bin/lib/doctor.js +1 -1
  319. package/bin/lib/update-notifier.js +195 -0
  320. package/docs/getting-started.md +2 -2
  321. package/docs/npm-install.md +91 -8
  322. package/hooks/session-start.sh +66 -12
  323. package/package.json +1 -1
  324. package/skills/guided-workspace-setup/SKILL.md +41 -3
  325. /package/.claude/commands/{setup.md → setup-agent-skills.md} +0 -0
  326. /package/.opencode/commands/{as-doctor.md → as-doctor-agent-skills.md} +0 -0
  327. /package/.opencode/commands/{as-setup.md → as-setup-agent-skills.md} +0 -0
  328. /package/.pi/prompts/{setup.md → setup-agent-skills.md} +0 -0
@@ -0,0 +1,795 @@
1
+ /**
2
+ * Agent Chain — Sequential pipeline orchestrator
3
+ *
4
+ * Runs opinionated, repeatable agent workflows. Chains are defined in
5
+ * .pi/agents/agent-chain.yaml — each chain is a sequence of agent steps
6
+ * with prompt templates. The user's original prompt flows into step 1,
7
+ * the output becomes $INPUT for step 2's prompt template, and so on.
8
+ * $ORIGINAL is always the user's original prompt.
9
+ *
10
+ * The primary Pi agent has NO codebase tools — it can ONLY kick off the
11
+ * pipeline via the `run_chain` tool. On boot you select a chain; the
12
+ * agent decides when to run it based on the user's prompt.
13
+ *
14
+ * Agents maintain session context within a Pi session — re-running the
15
+ * chain lets each agent resume where it left off.
16
+ *
17
+ * Commands:
18
+ * /chain — switch active chain
19
+ * /chain-list — list all available chains
20
+ *
21
+ * Usage: pi -e extensions/agent-chain.ts
22
+ */
23
+
24
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
25
+ import { Type } from "@sinclair/typebox";
26
+ import { Text, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
27
+ import { spawn } from "child_process";
28
+ import { readFileSync, existsSync, readdirSync, mkdirSync, unlinkSync } from "fs";
29
+ import { join, resolve } from "path";
30
+
31
+ // ── Types ────────────────────────────────────────
32
+
33
+ interface ChainStep {
34
+ agent: string;
35
+ prompt: string;
36
+ }
37
+
38
+ interface ChainDef {
39
+ name: string;
40
+ description: string;
41
+ steps: ChainStep[];
42
+ }
43
+
44
+ interface AgentDef {
45
+ name: string;
46
+ description: string;
47
+ tools: string;
48
+ systemPrompt: string;
49
+ }
50
+
51
+ interface StepState {
52
+ agent: string;
53
+ status: "pending" | "running" | "done" | "error";
54
+ elapsed: number;
55
+ lastWork: string;
56
+ }
57
+
58
+ // ── Display Name Helper ──────────────────────────
59
+
60
+ function displayName(name: string): string {
61
+ return name.split("-").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
62
+ }
63
+
64
+ // ── Chain YAML Parser ────────────────────────────
65
+
66
+ function parseChainYaml(raw: string): ChainDef[] {
67
+ const chains: ChainDef[] = [];
68
+ let current: ChainDef | null = null;
69
+ let currentStep: ChainStep | null = null;
70
+
71
+ for (const line of raw.split("\n")) {
72
+ // Chain name: top-level key
73
+ const chainMatch = line.match(/^(\S[^:]*):$/);
74
+ if (chainMatch) {
75
+ if (current && currentStep) {
76
+ current.steps.push(currentStep);
77
+ currentStep = null;
78
+ }
79
+ current = { name: chainMatch[1].trim(), description: "", steps: [] };
80
+ chains.push(current);
81
+ continue;
82
+ }
83
+
84
+ // Chain description
85
+ const descMatch = line.match(/^\s+description:\s+(.+)$/);
86
+ if (descMatch && current && !currentStep) {
87
+ let desc = descMatch[1].trim();
88
+ if ((desc.startsWith('"') && desc.endsWith('"')) ||
89
+ (desc.startsWith("'") && desc.endsWith("'"))) {
90
+ desc = desc.slice(1, -1);
91
+ }
92
+ current.description = desc;
93
+ continue;
94
+ }
95
+
96
+ // "steps:" label — skip
97
+ if (line.match(/^\s+steps:\s*$/) && current) {
98
+ continue;
99
+ }
100
+
101
+ // Step agent line
102
+ const agentMatch = line.match(/^\s+-\s+agent:\s+(.+)$/);
103
+ if (agentMatch && current) {
104
+ if (currentStep) {
105
+ current.steps.push(currentStep);
106
+ }
107
+ currentStep = { agent: agentMatch[1].trim(), prompt: "" };
108
+ continue;
109
+ }
110
+
111
+ // Step prompt line
112
+ const promptMatch = line.match(/^\s+prompt:\s+(.+)$/);
113
+ if (promptMatch && currentStep) {
114
+ let prompt = promptMatch[1].trim();
115
+ if ((prompt.startsWith('"') && prompt.endsWith('"')) ||
116
+ (prompt.startsWith("'") && prompt.endsWith("'"))) {
117
+ prompt = prompt.slice(1, -1);
118
+ }
119
+ prompt = prompt.replace(/\\n/g, "\n");
120
+ currentStep.prompt = prompt;
121
+ continue;
122
+ }
123
+ }
124
+
125
+ if (current && currentStep) {
126
+ current.steps.push(currentStep);
127
+ }
128
+
129
+ return chains;
130
+ }
131
+
132
+ // ── Frontmatter Parser ───────────────────────────
133
+
134
+ function parseAgentFile(filePath: string): AgentDef | null {
135
+ try {
136
+ const raw = readFileSync(filePath, "utf-8");
137
+ const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
138
+ if (!match) return null;
139
+
140
+ const frontmatter: Record<string, string> = {};
141
+ for (const line of match[1].split("\n")) {
142
+ const idx = line.indexOf(":");
143
+ if (idx > 0) {
144
+ frontmatter[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
145
+ }
146
+ }
147
+
148
+ if (!frontmatter.name) return null;
149
+
150
+ return {
151
+ name: frontmatter.name,
152
+ description: frontmatter.description || "",
153
+ tools: frontmatter.tools || "read,grep,find,ls",
154
+ systemPrompt: match[2].trim(),
155
+ };
156
+ } catch {
157
+ return null;
158
+ }
159
+ }
160
+
161
+ function scanAgentDirs(cwd: string): Map<string, AgentDef> {
162
+ const dirs = [
163
+ join(cwd, "agents"),
164
+ join(cwd, ".claude", "agents"),
165
+ join(cwd, ".pi", "agents"),
166
+ ];
167
+
168
+ const agents = new Map<string, AgentDef>();
169
+
170
+ for (const dir of dirs) {
171
+ if (!existsSync(dir)) continue;
172
+ try {
173
+ for (const file of readdirSync(dir)) {
174
+ if (!file.endsWith(".md")) continue;
175
+ const fullPath = resolve(dir, file);
176
+ const def = parseAgentFile(fullPath);
177
+ if (def && !agents.has(def.name.toLowerCase())) {
178
+ agents.set(def.name.toLowerCase(), def);
179
+ }
180
+ }
181
+ } catch {}
182
+ }
183
+
184
+ return agents;
185
+ }
186
+
187
+ // ── Extension ────────────────────────────────────
188
+
189
+ export default function (pi: ExtensionAPI) {
190
+ let allAgents: Map<string, AgentDef> = new Map();
191
+ let chains: ChainDef[] = [];
192
+ let activeChain: ChainDef | null = null;
193
+ let widgetCtx: any;
194
+ let sessionDir = "";
195
+ const agentSessions: Map<string, string | null> = new Map();
196
+
197
+ // Per-step state for the active chain
198
+ let stepStates: StepState[] = [];
199
+ let pendingReset = false;
200
+
201
+ function loadChains(cwd: string) {
202
+ sessionDir = join(cwd, ".pi", "agent-sessions");
203
+ if (!existsSync(sessionDir)) {
204
+ mkdirSync(sessionDir, { recursive: true });
205
+ }
206
+
207
+ allAgents = scanAgentDirs(cwd);
208
+
209
+ agentSessions.clear();
210
+ for (const [key] of allAgents) {
211
+ const sessionFile = join(sessionDir, `chain-${key}.json`);
212
+ agentSessions.set(key, existsSync(sessionFile) ? sessionFile : null);
213
+ }
214
+
215
+ const chainPath = join(cwd, ".pi", "agents", "agent-chain.yaml");
216
+ if (existsSync(chainPath)) {
217
+ try {
218
+ chains = parseChainYaml(readFileSync(chainPath, "utf-8"));
219
+ } catch {
220
+ chains = [];
221
+ }
222
+ } else {
223
+ chains = [];
224
+ }
225
+ }
226
+
227
+ function activateChain(chain: ChainDef) {
228
+ activeChain = chain;
229
+ stepStates = chain.steps.map(s => ({
230
+ agent: s.agent,
231
+ status: "pending" as const,
232
+ elapsed: 0,
233
+ lastWork: "",
234
+ }));
235
+ // Skip widget re-registration if reset is pending — let before_agent_start handle it
236
+ if (!pendingReset) {
237
+ updateWidget();
238
+ }
239
+ }
240
+
241
+ // ── Card Rendering ──────────────────────────
242
+
243
+ function renderCard(state: StepState, colWidth: number, theme: any): string[] {
244
+ const w = colWidth - 2;
245
+ const truncate = (s: string, max: number) => s.length > max ? s.slice(0, max - 3) + "..." : s;
246
+
247
+ const statusColor = state.status === "pending" ? "dim"
248
+ : state.status === "running" ? "accent"
249
+ : state.status === "done" ? "success" : "error";
250
+ const statusIcon = state.status === "pending" ? "○"
251
+ : state.status === "running" ? "●"
252
+ : state.status === "done" ? "✓" : "✗";
253
+
254
+ const name = displayName(state.agent);
255
+ const nameStr = theme.fg("accent", theme.bold(truncate(name, w)));
256
+ const nameVisible = Math.min(name.length, w);
257
+
258
+ const statusStr = `${statusIcon} ${state.status}`;
259
+ const timeStr = state.status !== "pending" ? ` ${Math.round(state.elapsed / 1000)}s` : "";
260
+ const statusLine = theme.fg(statusColor, statusStr + timeStr);
261
+ const statusVisible = statusStr.length + timeStr.length;
262
+
263
+ const workRaw = state.lastWork || "";
264
+ const workText = workRaw ? truncate(workRaw, Math.min(50, w - 1)) : "";
265
+ const workLine = workText ? theme.fg("muted", workText) : theme.fg("dim", "—");
266
+ const workVisible = workText ? workText.length : 1;
267
+
268
+ const top = "┌" + "─".repeat(w) + "┐";
269
+ const bot = "└" + "─".repeat(w) + "┘";
270
+ const border = (content: string, visLen: number) =>
271
+ theme.fg("dim", "│") + content + " ".repeat(Math.max(0, w - visLen)) + theme.fg("dim", "│");
272
+
273
+ return [
274
+ theme.fg("dim", top),
275
+ border(" " + nameStr, 1 + nameVisible),
276
+ border(" " + statusLine, 1 + statusVisible),
277
+ border(" " + workLine, 1 + workVisible),
278
+ theme.fg("dim", bot),
279
+ ];
280
+ }
281
+
282
+ function updateWidget() {
283
+ if (!widgetCtx) return;
284
+
285
+ widgetCtx.ui.setWidget("agent-chain", (_tui: any, theme: any) => {
286
+ const text = new Text("", 0, 1);
287
+
288
+ return {
289
+ render(width: number): string[] {
290
+ if (!activeChain || stepStates.length === 0) {
291
+ text.setText(theme.fg("dim", "No chain active. Use /chain to select one."));
292
+ return text.render(width);
293
+ }
294
+
295
+ const arrowWidth = 5; // " ──▶ "
296
+ const cols = stepStates.length;
297
+ const totalArrowWidth = arrowWidth * (cols - 1);
298
+ const colWidth = Math.max(12, Math.floor((width - totalArrowWidth) / cols));
299
+ const arrowRow = 2; // middle of 5-line card (0-indexed)
300
+
301
+ const cards = stepStates.map(s => renderCard(s, colWidth, theme));
302
+ const cardHeight = cards[0].length;
303
+ const outputLines: string[] = [];
304
+
305
+ for (let line = 0; line < cardHeight; line++) {
306
+ let row = cards[0][line];
307
+ for (let c = 1; c < cols; c++) {
308
+ if (line === arrowRow) {
309
+ row += theme.fg("dim", " ──▶ ");
310
+ } else {
311
+ row += " ".repeat(arrowWidth);
312
+ }
313
+ row += cards[c][line];
314
+ }
315
+ outputLines.push(row);
316
+ }
317
+
318
+ text.setText(outputLines.join("\n"));
319
+ return text.render(width);
320
+ },
321
+ invalidate() {
322
+ text.invalidate();
323
+ },
324
+ };
325
+ });
326
+ }
327
+
328
+ // ── Run Agent (subprocess) ──────────────────
329
+
330
+ function runAgent(
331
+ agentDef: AgentDef,
332
+ task: string,
333
+ stepIndex: number,
334
+ ctx: any,
335
+ ): Promise<{ output: string; exitCode: number; elapsed: number }> {
336
+ const model = ctx.model
337
+ ? `${ctx.model.provider}/${ctx.model.id}`
338
+ : "openrouter/google/gemini-3-flash-preview";
339
+
340
+ const agentKey = agentDef.name.toLowerCase().replace(/\s+/g, "-");
341
+ const agentSessionFile = join(sessionDir, `chain-${agentKey}.json`);
342
+ const hasSession = agentSessions.get(agentKey);
343
+
344
+ const args = [
345
+ "--mode", "json",
346
+ "-p",
347
+ "--no-extensions",
348
+ "--model", model,
349
+ "--tools", agentDef.tools,
350
+ "--thinking", "off",
351
+ "--append-system-prompt", agentDef.systemPrompt,
352
+ "--session", agentSessionFile,
353
+ ];
354
+
355
+ if (hasSession) {
356
+ args.push("-c");
357
+ }
358
+
359
+ args.push(task);
360
+
361
+ const textChunks: string[] = [];
362
+ const startTime = Date.now();
363
+ const state = stepStates[stepIndex];
364
+
365
+ return new Promise((resolve) => {
366
+ const proc = spawn("pi", args, {
367
+ stdio: ["ignore", "pipe", "pipe"],
368
+ env: { ...process.env },
369
+ });
370
+
371
+ const timer = setInterval(() => {
372
+ state.elapsed = Date.now() - startTime;
373
+ updateWidget();
374
+ }, 1000);
375
+
376
+ let buffer = "";
377
+
378
+ proc.stdout!.setEncoding("utf-8");
379
+ proc.stdout!.on("data", (chunk: string) => {
380
+ buffer += chunk;
381
+ const lines = buffer.split("\n");
382
+ buffer = lines.pop() || "";
383
+ for (const line of lines) {
384
+ if (!line.trim()) continue;
385
+ try {
386
+ const event = JSON.parse(line);
387
+ if (event.type === "message_update") {
388
+ const delta = event.assistantMessageEvent;
389
+ if (delta?.type === "text_delta") {
390
+ textChunks.push(delta.delta || "");
391
+ const full = textChunks.join("");
392
+ const last = full.split("\n").filter((l: string) => l.trim()).pop() || "";
393
+ state.lastWork = last;
394
+ updateWidget();
395
+ }
396
+ }
397
+ } catch {}
398
+ }
399
+ });
400
+
401
+ proc.stderr!.setEncoding("utf-8");
402
+ proc.stderr!.on("data", () => {});
403
+
404
+ proc.on("close", (code) => {
405
+ if (buffer.trim()) {
406
+ try {
407
+ const event = JSON.parse(buffer);
408
+ if (event.type === "message_update") {
409
+ const delta = event.assistantMessageEvent;
410
+ if (delta?.type === "text_delta") textChunks.push(delta.delta || "");
411
+ }
412
+ } catch {}
413
+ }
414
+
415
+ clearInterval(timer);
416
+ const elapsed = Date.now() - startTime;
417
+ state.elapsed = elapsed;
418
+ const output = textChunks.join("");
419
+ state.lastWork = output.split("\n").filter((l: string) => l.trim()).pop() || "";
420
+
421
+ if (code === 0) {
422
+ agentSessions.set(agentKey, agentSessionFile);
423
+ }
424
+
425
+ resolve({ output, exitCode: code ?? 1, elapsed });
426
+ });
427
+
428
+ proc.on("error", (err) => {
429
+ clearInterval(timer);
430
+ resolve({
431
+ output: `Error spawning agent: ${err.message}`,
432
+ exitCode: 1,
433
+ elapsed: Date.now() - startTime,
434
+ });
435
+ });
436
+ });
437
+ }
438
+
439
+ // ── Run Chain (sequential pipeline) ─────────
440
+
441
+ async function runChain(
442
+ task: string,
443
+ ctx: any,
444
+ ): Promise<{ output: string; success: boolean; elapsed: number }> {
445
+ if (!activeChain) {
446
+ return { output: "No chain active", success: false, elapsed: 0 };
447
+ }
448
+
449
+ const chainStart = Date.now();
450
+
451
+ // Reset all steps to pending
452
+ stepStates = activeChain.steps.map(s => ({
453
+ agent: s.agent,
454
+ status: "pending" as const,
455
+ elapsed: 0,
456
+ lastWork: "",
457
+ }));
458
+ updateWidget();
459
+
460
+ let input = task;
461
+ const originalPrompt = task;
462
+
463
+ for (let i = 0; i < activeChain.steps.length; i++) {
464
+ const step = activeChain.steps[i];
465
+ stepStates[i].status = "running";
466
+ updateWidget();
467
+
468
+ const resolvedPrompt = step.prompt
469
+ .replace(/\$INPUT/g, input)
470
+ .replace(/\$ORIGINAL/g, originalPrompt);
471
+
472
+ const agentDef = allAgents.get(step.agent.toLowerCase());
473
+ if (!agentDef) {
474
+ stepStates[i].status = "error";
475
+ stepStates[i].lastWork = `Agent "${step.agent}" not found`;
476
+ updateWidget();
477
+ return {
478
+ output: `Error at step ${i + 1}: Agent "${step.agent}" not found. Available: ${Array.from(allAgents.keys()).join(", ")}`,
479
+ success: false,
480
+ elapsed: Date.now() - chainStart,
481
+ };
482
+ }
483
+
484
+ const result = await runAgent(agentDef, resolvedPrompt, i, ctx);
485
+
486
+ if (result.exitCode !== 0) {
487
+ stepStates[i].status = "error";
488
+ updateWidget();
489
+ return {
490
+ output: `Error at step ${i + 1} (${step.agent}): ${result.output}`,
491
+ success: false,
492
+ elapsed: Date.now() - chainStart,
493
+ };
494
+ }
495
+
496
+ stepStates[i].status = "done";
497
+ updateWidget();
498
+
499
+ input = result.output;
500
+ }
501
+
502
+ return { output: input, success: true, elapsed: Date.now() - chainStart };
503
+ }
504
+
505
+ // ── run_chain Tool ──────────────────────────
506
+
507
+ pi.registerTool({
508
+ name: "run_chain",
509
+ label: "Run Chain",
510
+ description: "Execute the active agent chain pipeline. Each step runs sequentially — output from one step feeds into the next. Agents maintain session context across runs.",
511
+ parameters: Type.Object({
512
+ task: Type.String({ description: "The task/prompt for the chain to process" }),
513
+ }),
514
+
515
+ async execute(_toolCallId, params, _signal, onUpdate, ctx) {
516
+ const { task } = params as { task: string };
517
+
518
+ if (onUpdate) {
519
+ onUpdate({
520
+ content: [{ type: "text", text: `Starting chain: ${activeChain?.name}...` }],
521
+ details: { chain: activeChain?.name, task, status: "running" },
522
+ });
523
+ }
524
+
525
+ const result = await runChain(task, ctx);
526
+
527
+ const truncated = result.output.length > 8000
528
+ ? result.output.slice(0, 8000) + "\n\n... [truncated]"
529
+ : result.output;
530
+
531
+ const status = result.success ? "done" : "error";
532
+ const summary = `[chain:${activeChain?.name}] ${status} in ${Math.round(result.elapsed / 1000)}s`;
533
+
534
+ return {
535
+ content: [{ type: "text", text: `${summary}\n\n${truncated}` }],
536
+ details: {
537
+ chain: activeChain?.name,
538
+ task,
539
+ status,
540
+ elapsed: result.elapsed,
541
+ fullOutput: result.output,
542
+ },
543
+ };
544
+ },
545
+
546
+ renderCall(args, theme) {
547
+ const task = (args as any).task || "";
548
+ const preview = task.length > 60 ? task.slice(0, 57) + "..." : task;
549
+ return new Text(
550
+ theme.fg("toolTitle", theme.bold("run_chain ")) +
551
+ theme.fg("accent", activeChain?.name || "?") +
552
+ theme.fg("dim", " — ") +
553
+ theme.fg("muted", preview),
554
+ 0, 0,
555
+ );
556
+ },
557
+
558
+ renderResult(result, options, theme) {
559
+ const details = result.details as any;
560
+ if (!details) {
561
+ const text = result.content[0];
562
+ return new Text(text?.type === "text" ? text.text : "", 0, 0);
563
+ }
564
+
565
+ if (options.isPartial || details.status === "running") {
566
+ return new Text(
567
+ theme.fg("accent", `● ${details.chain || "chain"}`) +
568
+ theme.fg("dim", " running..."),
569
+ 0, 0,
570
+ );
571
+ }
572
+
573
+ const icon = details.status === "done" ? "✓" : "✗";
574
+ const color = details.status === "done" ? "success" : "error";
575
+ const elapsed = typeof details.elapsed === "number" ? Math.round(details.elapsed / 1000) : 0;
576
+ const header = theme.fg(color, `${icon} ${details.chain}`) +
577
+ theme.fg("dim", ` ${elapsed}s`);
578
+
579
+ if (options.expanded && details.fullOutput) {
580
+ const output = details.fullOutput.length > 4000
581
+ ? details.fullOutput.slice(0, 4000) + "\n... [truncated]"
582
+ : details.fullOutput;
583
+ return new Text(header + "\n" + theme.fg("muted", output), 0, 0);
584
+ }
585
+
586
+ return new Text(header, 0, 0);
587
+ },
588
+ });
589
+
590
+ // ── Commands ─────────────────────────────────
591
+
592
+ pi.registerCommand("chain", {
593
+ description: "Switch active chain",
594
+ handler: async (_args, ctx) => {
595
+ widgetCtx = ctx;
596
+ if (chains.length === 0) {
597
+ ctx.ui.notify("No chains defined in .pi/agents/agent-chain.yaml", "warning");
598
+ return;
599
+ }
600
+
601
+ const options = chains.map(c => {
602
+ const steps = c.steps.map(s => displayName(s.agent)).join(" → ");
603
+ const desc = c.description ? ` — ${c.description}` : "";
604
+ return `${c.name}${desc} (${steps})`;
605
+ });
606
+
607
+ const choice = await ctx.ui.select("Select Chain", options);
608
+ if (choice === undefined) return;
609
+
610
+ const idx = options.indexOf(choice);
611
+ activateChain(chains[idx]);
612
+ const flow = chains[idx].steps.map(s => displayName(s.agent)).join(" → ");
613
+ ctx.ui.setStatus("agent-chain", `Chain: ${chains[idx].name} (${chains[idx].steps.length} steps)`);
614
+ ctx.ui.notify(
615
+ `Chain: ${chains[idx].name}\n${chains[idx].description}\n${flow}`,
616
+ "info",
617
+ );
618
+ },
619
+ });
620
+
621
+ pi.registerCommand("chain-list", {
622
+ description: "List all available chains",
623
+ handler: async (_args, ctx) => {
624
+ widgetCtx = ctx;
625
+ if (chains.length === 0) {
626
+ ctx.ui.notify("No chains defined in .pi/agents/agent-chain.yaml", "warning");
627
+ return;
628
+ }
629
+
630
+ const list = chains.map(c => {
631
+ const desc = c.description ? ` ${c.description}` : "";
632
+ const steps = c.steps.map((s, i) =>
633
+ ` ${i + 1}. ${displayName(s.agent)}`
634
+ ).join("\n");
635
+ return `${c.name}:${desc ? "\n" + desc : ""}\n${steps}`;
636
+ }).join("\n\n");
637
+
638
+ ctx.ui.notify(list, "info");
639
+ },
640
+ });
641
+
642
+ // ── System Prompt Override ───────────────────
643
+
644
+ pi.on("before_agent_start", async (_event, _ctx) => {
645
+ // Force widget reset on first turn after /new
646
+ if (pendingReset && activeChain) {
647
+ pendingReset = false;
648
+ widgetCtx = _ctx;
649
+ stepStates = activeChain.steps.map(s => ({
650
+ agent: s.agent,
651
+ status: "pending" as const,
652
+ elapsed: 0,
653
+ lastWork: "",
654
+ }));
655
+ updateWidget();
656
+ }
657
+
658
+ if (!activeChain) return {};
659
+
660
+ const flow = activeChain.steps.map(s => displayName(s.agent)).join(" → ");
661
+ const desc = activeChain.description ? `\n${activeChain.description}` : "";
662
+
663
+ // Build pipeline steps summary
664
+ const steps = activeChain.steps.map((s, i) => {
665
+ const agentDef = allAgents.get(s.agent.toLowerCase());
666
+ const agentDesc = agentDef?.description || "";
667
+ return `${i + 1}. **${displayName(s.agent)}** — ${agentDesc}`;
668
+ }).join("\n");
669
+
670
+ // Build full agent catalog (like agent-team.ts)
671
+ const seen = new Set<string>();
672
+ const agentCatalog = activeChain.steps
673
+ .filter(s => {
674
+ const key = s.agent.toLowerCase();
675
+ if (seen.has(key)) return false;
676
+ seen.add(key);
677
+ return true;
678
+ })
679
+ .map(s => {
680
+ const agentDef = allAgents.get(s.agent.toLowerCase());
681
+ if (!agentDef) return `### ${displayName(s.agent)}\nAgent not found.`;
682
+ return `### ${displayName(agentDef.name)}\n${agentDef.description}\n**Tools:** ${agentDef.tools}\n**Role:** ${agentDef.systemPrompt}`;
683
+ })
684
+ .join("\n\n");
685
+
686
+ return {
687
+ systemPrompt: `You are an agent with a sequential pipeline called "${activeChain.name}" at your disposal.${desc}
688
+ You have full access to your own tools AND the run_chain tool to delegate to your team.
689
+
690
+ ## Active Chain: ${activeChain.name}
691
+ Flow: ${flow}
692
+
693
+ ${steps}
694
+
695
+ ## Agent Details
696
+
697
+ ${agentCatalog}
698
+
699
+ ## When to Use run_chain
700
+ - Significant work: new features, refactors, multi-file changes, anything non-trivial
701
+ - Tasks that benefit from the full pipeline: planning, building, reviewing
702
+ - When you want structured, multi-agent collaboration on a problem
703
+
704
+ ## When to Work Directly
705
+ - Simple one-off commands: reading a file, checking status, listing contents
706
+ - Quick lookups, small edits, answering questions about the codebase
707
+ - Anything you can handle in a single step without needing the pipeline
708
+
709
+ ## How run_chain Works
710
+ - Pass a clear task description to run_chain
711
+ - Each step's output feeds into the next step as $INPUT
712
+ - Agents maintain session context — they remember previous work within this session
713
+ - You can run the chain multiple times with different tasks if needed
714
+ - After the chain completes, review the result and summarize for the user
715
+
716
+ ## Guidelines
717
+ - Use your judgment — if it's quick, just do it; if it's real work, run the chain
718
+ - Keep chain tasks focused and clearly described
719
+ - You can mix direct work and chain runs in the same conversation`,
720
+ };
721
+ });
722
+
723
+ // ── Session Start ───────────────────────────
724
+
725
+ pi.on("session_start", async (_event, _ctx) => {
726
+ // Clear widget with both old and new ctx — one of them will be valid
727
+ if (widgetCtx) {
728
+ widgetCtx.ui.setWidget("agent-chain", undefined);
729
+ }
730
+ _ctx.ui.setWidget("agent-chain", undefined);
731
+ widgetCtx = _ctx;
732
+
733
+ // Reset execution state — widget re-registration deferred to before_agent_start
734
+ stepStates = [];
735
+ activeChain = null;
736
+ pendingReset = true;
737
+
738
+ // Wipe chain session files — reset agent context on /new and launch
739
+ const sessDir = join(_ctx.cwd, ".pi", "agent-sessions");
740
+ if (existsSync(sessDir)) {
741
+ for (const f of readdirSync(sessDir)) {
742
+ if (f.startsWith("chain-") && f.endsWith(".json")) {
743
+ try { unlinkSync(join(sessDir, f)); } catch {}
744
+ }
745
+ }
746
+ }
747
+
748
+ // Reload chains + clear agentSessions map (all agents start fresh)
749
+ loadChains(_ctx.cwd);
750
+
751
+ if (chains.length === 0) {
752
+ _ctx.ui.notify("No chains found in .pi/agents/agent-chain.yaml", "warning");
753
+ return;
754
+ }
755
+
756
+ // Default to first chain — use /chain to switch
757
+ activateChain(chains[0]);
758
+
759
+ // run_chain is registered as a tool — available alongside all default tools
760
+
761
+ const flow = activeChain!.steps.map(s => displayName(s.agent)).join(" → ");
762
+ _ctx.ui.setStatus("agent-chain", `Chain: ${activeChain!.name} (${activeChain!.steps.length} steps)`);
763
+ _ctx.ui.notify(
764
+ `Chain: ${activeChain!.name}\n${activeChain!.description}\n${flow}\n\n` +
765
+ `/chain Switch chain\n` +
766
+ `/chain-list List all chains`,
767
+ "info",
768
+ );
769
+
770
+ // Footer: model | chain name | context bar
771
+ _ctx.ui.setFooter((_tui, theme, _footerData) => ({
772
+ dispose: () => {},
773
+ invalidate() {},
774
+ render(width: number): string[] {
775
+ const model = _ctx.model?.id || "no-model";
776
+ const usage = _ctx.getContextUsage();
777
+ const pct = usage ? usage.percent : 0;
778
+ const filled = Math.round(pct / 10);
779
+ const bar = "#".repeat(filled) + "-".repeat(10 - filled);
780
+
781
+ const chainLabel = activeChain
782
+ ? theme.fg("accent", activeChain.name)
783
+ : theme.fg("dim", "no chain");
784
+
785
+ const left = theme.fg("dim", ` ${model}`) +
786
+ theme.fg("muted", " · ") +
787
+ chainLabel;
788
+ const right = theme.fg("dim", `[${bar}] ${Math.round(pct)}% `);
789
+ const pad = " ".repeat(Math.max(1, width - visibleWidth(left) - visibleWidth(right)));
790
+
791
+ return [truncateToWidth(left + pad + right, width)];
792
+ },
793
+ }));
794
+ });
795
+ }