gsd-pi 2.28.0-dev.e19bf89 → 2.29.0-dev.23d50d0

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 (285) hide show
  1. package/README.md +24 -17
  2. package/dist/cli.js +15 -9
  3. package/dist/headless.js +4 -0
  4. package/dist/resource-loader.js +80 -8
  5. package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
  6. package/dist/resources/extensions/gsd/auto-dashboard.ts +217 -65
  7. package/dist/resources/extensions/gsd/auto-dispatch.ts +2 -2
  8. package/dist/resources/extensions/gsd/auto-post-unit.ts +53 -6
  9. package/dist/resources/extensions/gsd/auto-prompts.ts +27 -14
  10. package/dist/resources/extensions/gsd/auto-recovery.ts +33 -23
  11. package/dist/resources/extensions/gsd/auto-start.ts +25 -10
  12. package/dist/resources/extensions/gsd/auto-verification.ts +41 -7
  13. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  14. package/dist/resources/extensions/gsd/auto-worktree.ts +9 -0
  15. package/dist/resources/extensions/gsd/auto.ts +67 -22
  16. package/dist/resources/extensions/gsd/commands-handlers.ts +3 -11
  17. package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
  18. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  19. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  20. package/dist/resources/extensions/gsd/commands.ts +75 -29
  21. package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  22. package/dist/resources/extensions/gsd/doctor-types.ts +13 -0
  23. package/dist/resources/extensions/gsd/doctor.ts +2 -6
  24. package/dist/resources/extensions/gsd/export.ts +28 -2
  25. package/dist/resources/extensions/gsd/gsd-db.ts +19 -0
  26. package/dist/resources/extensions/gsd/index.ts +2 -1
  27. package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
  28. package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
  29. package/dist/resources/extensions/gsd/metrics.ts +17 -31
  30. package/dist/resources/extensions/gsd/paths.ts +17 -8
  31. package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
  32. package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
  33. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
  34. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  35. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
  36. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
  37. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  38. package/dist/resources/extensions/gsd/queue-order.ts +10 -11
  39. package/dist/resources/extensions/gsd/routing-history.ts +13 -17
  40. package/dist/resources/extensions/gsd/session-lock.ts +284 -0
  41. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  42. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  43. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  44. package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  45. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  46. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  47. package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  48. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  49. package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
  50. package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  51. package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
  52. package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  53. package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  54. package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  55. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  56. package/dist/resources/extensions/gsd/types.ts +3 -0
  57. package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
  58. package/dist/resources/extensions/gsd/verification-evidence.ts +2 -0
  59. package/dist/resources/extensions/gsd/verification-gate.ts +13 -2
  60. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  61. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  62. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  63. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  64. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  65. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  66. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  67. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  68. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  69. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  70. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  71. package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  72. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  73. package/dist/resources/extensions/remote-questions/notify.ts +1 -2
  74. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  75. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  76. package/dist/resources/extensions/remote-questions/types.ts +3 -0
  77. package/dist/resources/extensions/shared/mod.ts +3 -0
  78. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  79. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  80. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  81. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  82. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  83. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  84. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  85. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  86. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  87. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  88. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  89. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  90. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  91. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  92. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  93. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  94. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  95. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  96. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  97. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  98. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  99. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  100. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  101. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  102. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  103. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  104. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  105. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  106. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  107. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  108. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  109. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  110. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  111. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  112. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  113. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  114. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  115. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  116. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  117. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  118. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  119. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  120. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  121. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  122. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  123. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  124. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  125. package/package.json +6 -3
  126. package/packages/native/dist/native.d.ts +2 -0
  127. package/packages/native/dist/native.js +19 -5
  128. package/packages/native/src/native.ts +23 -9
  129. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
  131. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
  134. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  136. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  138. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
  141. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  143. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -1
  144. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  145. package/packages/pi-coding-agent/package.json +1 -1
  146. package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
  147. package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
  148. package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
  149. package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
  150. package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
  151. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -1
  152. package/packages/pi-tui/dist/autocomplete.d.ts +3 -0
  153. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  154. package/packages/pi-tui/dist/autocomplete.js +14 -0
  155. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  156. package/packages/pi-tui/src/autocomplete.ts +19 -1
  157. package/pkg/package.json +1 -1
  158. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  159. package/src/resources/extensions/gsd/auto-dashboard.ts +217 -65
  160. package/src/resources/extensions/gsd/auto-dispatch.ts +2 -2
  161. package/src/resources/extensions/gsd/auto-post-unit.ts +53 -6
  162. package/src/resources/extensions/gsd/auto-prompts.ts +27 -14
  163. package/src/resources/extensions/gsd/auto-recovery.ts +33 -23
  164. package/src/resources/extensions/gsd/auto-start.ts +25 -10
  165. package/src/resources/extensions/gsd/auto-verification.ts +41 -7
  166. package/src/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  167. package/src/resources/extensions/gsd/auto-worktree.ts +9 -0
  168. package/src/resources/extensions/gsd/auto.ts +67 -22
  169. package/src/resources/extensions/gsd/commands-handlers.ts +3 -11
  170. package/src/resources/extensions/gsd/commands-logs.ts +536 -0
  171. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  172. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  173. package/src/resources/extensions/gsd/commands.ts +75 -29
  174. package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  175. package/src/resources/extensions/gsd/doctor-types.ts +13 -0
  176. package/src/resources/extensions/gsd/doctor.ts +2 -6
  177. package/src/resources/extensions/gsd/export.ts +28 -2
  178. package/src/resources/extensions/gsd/gsd-db.ts +19 -0
  179. package/src/resources/extensions/gsd/index.ts +2 -1
  180. package/src/resources/extensions/gsd/json-persistence.ts +67 -0
  181. package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
  182. package/src/resources/extensions/gsd/metrics.ts +17 -31
  183. package/src/resources/extensions/gsd/paths.ts +17 -8
  184. package/src/resources/extensions/gsd/preferences-models.ts +7 -1
  185. package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
  186. package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
  187. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  188. package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
  189. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
  190. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  191. package/src/resources/extensions/gsd/queue-order.ts +10 -11
  192. package/src/resources/extensions/gsd/routing-history.ts +13 -17
  193. package/src/resources/extensions/gsd/session-lock.ts +284 -0
  194. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  195. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  196. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  197. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  198. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  199. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  200. package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
  201. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  202. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
  203. package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  204. package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
  205. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  206. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  207. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  208. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  209. package/src/resources/extensions/gsd/types.ts +3 -0
  210. package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
  211. package/src/resources/extensions/gsd/verification-evidence.ts +2 -0
  212. package/src/resources/extensions/gsd/verification-gate.ts +13 -2
  213. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  214. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  215. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  216. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  217. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  218. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  219. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  220. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  221. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  222. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  223. package/src/resources/extensions/mcp-client/index.ts +459 -0
  224. package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  225. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  226. package/src/resources/extensions/remote-questions/notify.ts +1 -2
  227. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  228. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  229. package/src/resources/extensions/remote-questions/types.ts +3 -0
  230. package/src/resources/extensions/shared/mod.ts +3 -0
  231. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  232. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  233. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  234. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  235. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  236. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  237. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  238. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  239. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  240. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  241. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  242. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  243. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  244. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  245. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  246. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  247. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  248. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  249. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  250. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  251. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  252. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  253. package/src/resources/skills/create-skill/SKILL.md +184 -0
  254. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  255. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  256. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  257. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  258. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  259. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  260. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  261. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  262. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  263. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  264. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  265. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  266. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  267. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  268. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  269. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  270. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  271. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  272. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  273. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  274. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  275. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  276. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  277. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  278. package/dist/resources/extensions/gsd/preferences-hooks.ts +0 -10
  279. package/dist/resources/extensions/mcporter/index.ts +0 -525
  280. package/dist/resources/extensions/shared/progress-widget.ts +0 -282
  281. package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
  282. package/src/resources/extensions/gsd/preferences-hooks.ts +0 -10
  283. package/src/resources/extensions/mcporter/index.ts +0 -525
  284. package/src/resources/extensions/shared/progress-widget.ts +0 -282
  285. package/src/resources/extensions/shared/thinking-widget.ts +0 -107
@@ -0,0 +1,536 @@
1
+ /**
2
+ * /gsd logs — Browse activity logs, debug logs, and metrics.
3
+ *
4
+ * Subcommands:
5
+ * /gsd logs — List recent activity + debug logs
6
+ * /gsd logs <N> — Show summary of activity log #N
7
+ * /gsd logs debug — List debug log files
8
+ * /gsd logs debug <N> — Show debug log summary #N
9
+ * /gsd logs tail [N] — Show last N activity log entries (default 5)
10
+ * /gsd logs clear — Remove old activity and debug logs
11
+ */
12
+
13
+ import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
14
+ import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { gsdRoot } from "./paths.js";
17
+ import { loadJsonFileOrNull } from "./json-persistence.js";
18
+
19
+ // ─── Types ──────────────────────────────────────────────────────────────────
20
+
21
+ interface LogEntry {
22
+ seq: number;
23
+ filename: string;
24
+ unitType: string;
25
+ unitId: string;
26
+ size: number;
27
+ mtime: Date;
28
+ }
29
+
30
+ interface DebugLogEntry {
31
+ filename: string;
32
+ size: number;
33
+ mtime: Date;
34
+ }
35
+
36
+ // ─── Helpers ────────────────────────────────────────────────────────────────
37
+
38
+ function activityDir(basePath: string): string {
39
+ return join(gsdRoot(basePath), "activity");
40
+ }
41
+
42
+ function debugDir(basePath: string): string {
43
+ return join(gsdRoot(basePath), "debug");
44
+ }
45
+
46
+ function listActivityLogs(basePath: string): LogEntry[] {
47
+ const dir = activityDir(basePath);
48
+ if (!existsSync(dir)) return [];
49
+
50
+ const entries: LogEntry[] = [];
51
+ try {
52
+ for (const f of readdirSync(dir)) {
53
+ if (!f.endsWith(".jsonl")) continue;
54
+ // Filename format: {seq}-{unitType}-{unitId}.jsonl
55
+ // unitType is lowercase-with-hyphens (e.g., "execute-task", "complete-slice")
56
+ // unitId starts with M followed by digits (e.g., "M001-S01-T01")
57
+ const match = f.match(/^(\d+)-([\w-]+?)-(M\d[\w-]*)\.jsonl$/);
58
+ if (!match) continue;
59
+
60
+ const filePath = join(dir, f);
61
+ let stat;
62
+ try { stat = statSync(filePath); } catch { continue; }
63
+
64
+ entries.push({
65
+ seq: parseInt(match[1], 10),
66
+ filename: f,
67
+ unitType: match[2],
68
+ unitId: match[3].replace(/-/g, "/"),
69
+ size: stat.size,
70
+ mtime: stat.mtime,
71
+ });
72
+ }
73
+ } catch { /* dir not readable */ }
74
+
75
+ return entries.sort((a, b) => a.seq - b.seq);
76
+ }
77
+
78
+ function listDebugLogs(basePath: string): DebugLogEntry[] {
79
+ const dir = debugDir(basePath);
80
+ if (!existsSync(dir)) return [];
81
+
82
+ const entries: DebugLogEntry[] = [];
83
+ try {
84
+ for (const f of readdirSync(dir)) {
85
+ if (!f.endsWith(".log")) continue;
86
+ const filePath = join(dir, f);
87
+ let stat;
88
+ try { stat = statSync(filePath); } catch { continue; }
89
+ entries.push({ filename: f, size: stat.size, mtime: stat.mtime });
90
+ }
91
+ } catch { /* dir not readable */ }
92
+
93
+ return entries.sort((a, b) => a.mtime.getTime() - b.mtime.getTime());
94
+ }
95
+
96
+ function formatSize(bytes: number): string {
97
+ if (bytes < 1024) return `${bytes}B`;
98
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
99
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
100
+ }
101
+
102
+ function formatAge(date: Date): string {
103
+ const ms = Date.now() - date.getTime();
104
+ const mins = Math.floor(ms / 60_000);
105
+ if (mins < 1) return "just now";
106
+ if (mins < 60) return `${mins}m ago`;
107
+ const hrs = Math.floor(mins / 60);
108
+ if (hrs < 24) return `${hrs}h ago`;
109
+ const days = Math.floor(hrs / 24);
110
+ return `${days}d ago`;
111
+ }
112
+
113
+ /**
114
+ * Extract a summary from an activity log JSONL file.
115
+ * Parses the entries to count tool calls, errors, and extract key events.
116
+ */
117
+ function summarizeActivityLog(filePath: string): {
118
+ toolCalls: number;
119
+ errors: number;
120
+ filesWritten: string[];
121
+ commandsRun: Array<{ command: string; failed: boolean }>;
122
+ lastReasoning: string;
123
+ entryCount: number;
124
+ } {
125
+ const result = {
126
+ toolCalls: 0,
127
+ errors: 0,
128
+ filesWritten: new Set<string>(),
129
+ commandsRun: [] as Array<{ command: string; failed: boolean }>,
130
+ lastReasoning: "",
131
+ entryCount: 0,
132
+ };
133
+
134
+ let raw: string;
135
+ try { raw = readFileSync(filePath, "utf-8"); } catch { return { ...result, filesWritten: [] }; }
136
+
137
+ const lines = raw.split("\n").filter(l => l.trim());
138
+ result.entryCount = lines.length;
139
+
140
+ for (const line of lines) {
141
+ let entry: Record<string, unknown>;
142
+ try { entry = JSON.parse(line); } catch { continue; }
143
+
144
+ // Count tool calls
145
+ if (entry.type === "toolCall" || (entry.role === "assistant" && entry.content && Array.isArray(entry.content))) {
146
+ if (entry.type === "toolCall") {
147
+ result.toolCalls++;
148
+ const name = entry.name as string | undefined;
149
+ const args = entry.arguments as Record<string, unknown> | undefined;
150
+
151
+ if (name === "write" || name === "edit") {
152
+ const path = args?.file_path as string | undefined;
153
+ if (path) result.filesWritten.add(path);
154
+ }
155
+ if (name === "bash") {
156
+ const cmd = args?.command as string | undefined;
157
+ if (cmd) result.commandsRun.push({ command: cmd.slice(0, 80), failed: false });
158
+ }
159
+ }
160
+ }
161
+
162
+ // Count errors
163
+ if (entry.role === "toolResult" && entry.isError) {
164
+ result.errors++;
165
+ // Mark last command as failed
166
+ if (result.commandsRun.length > 0) {
167
+ result.commandsRun[result.commandsRun.length - 1].failed = true;
168
+ }
169
+ }
170
+
171
+ // Track assistant reasoning
172
+ if (entry.role === "assistant" && typeof entry.content === "string") {
173
+ result.lastReasoning = entry.content.slice(0, 200);
174
+ }
175
+ }
176
+
177
+ return {
178
+ ...result,
179
+ filesWritten: [...result.filesWritten],
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Extract summary events from a debug log file.
185
+ */
186
+ function summarizeDebugLog(filePath: string): {
187
+ events: number;
188
+ duration: string;
189
+ dispatches: number;
190
+ errors: Array<{ event: string; message: string }>;
191
+ } {
192
+ const result = {
193
+ events: 0,
194
+ duration: "unknown",
195
+ dispatches: 0,
196
+ errors: [] as Array<{ event: string; message: string }>,
197
+ };
198
+
199
+ let raw: string;
200
+ try { raw = readFileSync(filePath, "utf-8"); } catch { return result; }
201
+
202
+ const lines = raw.split("\n").filter(l => l.trim());
203
+ result.events = lines.length;
204
+
205
+ let firstTs = 0;
206
+ let lastTs = 0;
207
+
208
+ for (const line of lines) {
209
+ let entry: Record<string, unknown>;
210
+ try { entry = JSON.parse(line); } catch { continue; }
211
+
212
+ const ts = entry.ts as string | undefined;
213
+ if (ts) {
214
+ const t = new Date(ts).getTime();
215
+ if (!firstTs) firstTs = t;
216
+ lastTs = t;
217
+ }
218
+
219
+ const event = entry.event as string | undefined;
220
+ if (!event) continue;
221
+
222
+ if (event === "debug-summary") {
223
+ result.dispatches = (entry.dispatches as number) ?? 0;
224
+ }
225
+
226
+ if (event.includes("error") || event.includes("failed")) {
227
+ const msg = (entry.error as string) ?? (entry.message as string) ?? JSON.stringify(entry).slice(0, 100);
228
+ result.errors.push({ event, message: msg });
229
+ }
230
+ }
231
+
232
+ if (firstTs && lastTs) {
233
+ const elapsed = lastTs - firstTs;
234
+ const mins = Math.floor(elapsed / 60_000);
235
+ if (mins < 1) result.duration = `${Math.floor(elapsed / 1000)}s`;
236
+ else if (mins < 60) result.duration = `${mins}m`;
237
+ else result.duration = `${Math.floor(mins / 60)}h ${mins % 60}m`;
238
+ }
239
+
240
+ return result;
241
+ }
242
+
243
+ // ─── Main Handler ───────────────────────────────────────────────────────────
244
+
245
+ export async function handleLogs(args: string, ctx: ExtensionCommandContext): Promise<void> {
246
+ const basePath = process.cwd();
247
+ const parts = args.trim().split(/\s+/).filter(Boolean);
248
+ const subCmd = parts[0] ?? "";
249
+
250
+ // /gsd logs clear
251
+ if (subCmd === "clear") {
252
+ await handleLogsClear(basePath, ctx);
253
+ return;
254
+ }
255
+
256
+ // /gsd logs debug [N]
257
+ if (subCmd === "debug") {
258
+ const idx = parts[1] ? parseInt(parts[1], 10) : undefined;
259
+ await handleLogsDebug(basePath, ctx, idx);
260
+ return;
261
+ }
262
+
263
+ // /gsd logs tail [N]
264
+ if (subCmd === "tail") {
265
+ const count = parts[1] ? parseInt(parts[1], 10) : 5;
266
+ await handleLogsTail(basePath, ctx, count);
267
+ return;
268
+ }
269
+
270
+ // /gsd logs <N> — show specific activity log
271
+ if (subCmd && /^\d+$/.test(subCmd)) {
272
+ const seq = parseInt(subCmd, 10);
273
+ await handleLogsShow(basePath, ctx, seq);
274
+ return;
275
+ }
276
+
277
+ // /gsd logs — list overview
278
+ await handleLogsList(basePath, ctx);
279
+ }
280
+
281
+ // ─── Subcommand Handlers ────────────────────────────────────────────────────
282
+
283
+ async function handleLogsList(basePath: string, ctx: ExtensionCommandContext): Promise<void> {
284
+ const activities = listActivityLogs(basePath);
285
+ const debugLogs = listDebugLogs(basePath);
286
+
287
+ if (activities.length === 0 && debugLogs.length === 0) {
288
+ ctx.ui.notify(
289
+ "No logs found.\n\nActivity logs are created during auto-mode.\nDebug logs require GSD_DEBUG=1.",
290
+ "info",
291
+ );
292
+ return;
293
+ }
294
+
295
+ const lines: string[] = [];
296
+
297
+ if (activities.length > 0) {
298
+ lines.push("Activity Logs (.gsd/activity/):");
299
+ lines.push(" # Unit Type Unit ID Size Age");
300
+ lines.push(" " + "─".repeat(70));
301
+
302
+ // Show last 15 entries
303
+ const recent = activities.slice(-15);
304
+ for (const e of recent) {
305
+ const seq = String(e.seq).padStart(3, " ");
306
+ const type = e.unitType.padEnd(18, " ");
307
+ const id = e.unitId.padEnd(20, " ");
308
+ const size = formatSize(e.size).padStart(7, " ");
309
+ const age = formatAge(e.mtime);
310
+ lines.push(` ${seq} ${type} ${id} ${size} ${age}`);
311
+ }
312
+
313
+ if (activities.length > 15) {
314
+ lines.push(` ... and ${activities.length - 15} older entries`);
315
+ }
316
+ lines.push("");
317
+ lines.push(" View details: /gsd logs <#>");
318
+ }
319
+
320
+ if (debugLogs.length > 0) {
321
+ lines.push("");
322
+ lines.push("Debug Logs (.gsd/debug/):");
323
+ for (let i = 0; i < debugLogs.length; i++) {
324
+ const d = debugLogs[i];
325
+ const size = formatSize(d.size).padStart(7, " ");
326
+ const age = formatAge(d.mtime);
327
+ lines.push(` ${i + 1}. ${d.filename} ${size} ${age}`);
328
+ }
329
+ lines.push("");
330
+ lines.push(" View details: /gsd logs debug <#>");
331
+ }
332
+
333
+ // Metrics summary
334
+ const metricsPath = join(gsdRoot(basePath), "metrics.json");
335
+ const isMetrics = (d: unknown): d is { units: Array<Record<string, unknown>> } =>
336
+ d !== null && typeof d === "object" && "units" in d! && Array.isArray((d as Record<string, unknown>).units);
337
+ const metrics = loadJsonFileOrNull(metricsPath, isMetrics);
338
+ if (metrics && metrics.units.length > 0) {
339
+ const units = metrics.units;
340
+ const totalCost = units.reduce((sum: number, u) => sum + ((u.cost as number) ?? 0), 0);
341
+ const totalTokens = units.reduce((sum: number, u) => {
342
+ const t = u.tokens as Record<string, number> | undefined;
343
+ return sum + (t?.total ?? 0);
344
+ }, 0);
345
+ lines.push("");
346
+ lines.push(`Metrics: ${units.length} units tracked · $${totalCost.toFixed(2)} · ${(totalTokens / 1000).toFixed(0)}K tokens`);
347
+ }
348
+
349
+ lines.push("");
350
+ lines.push("Tip: Enable debug logging with GSD_DEBUG=1 before /gsd auto");
351
+
352
+ ctx.ui.notify(lines.join("\n"), "info");
353
+ }
354
+
355
+ async function handleLogsShow(basePath: string, ctx: ExtensionCommandContext, seq: number): Promise<void> {
356
+ const activities = listActivityLogs(basePath);
357
+ const entry = activities.find(e => e.seq === seq);
358
+
359
+ if (!entry) {
360
+ ctx.ui.notify(`Activity log #${seq} not found. Run /gsd logs to see available logs.`, "warning");
361
+ return;
362
+ }
363
+
364
+ const filePath = join(activityDir(basePath), entry.filename);
365
+ const summary = summarizeActivityLog(filePath);
366
+
367
+ const lines: string[] = [];
368
+ lines.push(`Activity Log #${entry.seq}: ${entry.unitType} — ${entry.unitId}`);
369
+ lines.push("─".repeat(60));
370
+ lines.push(`File: ${entry.filename}`);
371
+ lines.push(`Size: ${formatSize(entry.size)} | Age: ${formatAge(entry.mtime)}`);
372
+ lines.push(`Entries: ${summary.entryCount} | Tool calls: ${summary.toolCalls} | Errors: ${summary.errors}`);
373
+
374
+ if (summary.filesWritten.length > 0) {
375
+ lines.push("");
376
+ lines.push("Files written/edited:");
377
+ for (const f of summary.filesWritten.slice(0, 10)) {
378
+ lines.push(` ${f}`);
379
+ }
380
+ if (summary.filesWritten.length > 10) {
381
+ lines.push(` ... and ${summary.filesWritten.length - 10} more`);
382
+ }
383
+ }
384
+
385
+ if (summary.commandsRun.length > 0) {
386
+ lines.push("");
387
+ lines.push("Commands run:");
388
+ for (const c of summary.commandsRun.slice(0, 10)) {
389
+ const status = c.failed ? " FAILED" : "";
390
+ lines.push(` ${c.command}${status}`);
391
+ }
392
+ if (summary.commandsRun.length > 10) {
393
+ lines.push(` ... and ${summary.commandsRun.length - 10} more`);
394
+ }
395
+ }
396
+
397
+ if (summary.errors > 0) {
398
+ lines.push("");
399
+ lines.push(`${summary.errors} error(s) encountered during this unit.`);
400
+ }
401
+
402
+ if (summary.lastReasoning) {
403
+ lines.push("");
404
+ lines.push("Last reasoning:");
405
+ lines.push(` "${summary.lastReasoning}${summary.lastReasoning.length >= 200 ? "..." : ""}"`);
406
+ }
407
+
408
+ lines.push("");
409
+ lines.push(`Full log: ${filePath}`);
410
+
411
+ ctx.ui.notify(lines.join("\n"), "info");
412
+ }
413
+
414
+ async function handleLogsDebug(basePath: string, ctx: ExtensionCommandContext, idx?: number): Promise<void> {
415
+ const debugLogs = listDebugLogs(basePath);
416
+
417
+ if (debugLogs.length === 0) {
418
+ ctx.ui.notify(
419
+ "No debug logs found.\n\nEnable debug logging: GSD_DEBUG=1 gsd auto",
420
+ "info",
421
+ );
422
+ return;
423
+ }
424
+
425
+ if (idx === undefined) {
426
+ // List debug logs
427
+ const lines: string[] = ["Debug Logs (.gsd/debug/):", ""];
428
+ for (let i = 0; i < debugLogs.length; i++) {
429
+ const d = debugLogs[i];
430
+ lines.push(` ${i + 1}. ${d.filename} ${formatSize(d.size)} ${formatAge(d.mtime)}`);
431
+ }
432
+ lines.push("");
433
+ lines.push("View details: /gsd logs debug <#>");
434
+ ctx.ui.notify(lines.join("\n"), "info");
435
+ return;
436
+ }
437
+
438
+ // Show specific debug log
439
+ if (idx < 1 || idx > debugLogs.length) {
440
+ ctx.ui.notify(`Debug log #${idx} not found. Available: 1-${debugLogs.length}`, "warning");
441
+ return;
442
+ }
443
+
444
+ const entry = debugLogs[idx - 1];
445
+ const filePath = join(debugDir(basePath), entry.filename);
446
+ const summary = summarizeDebugLog(filePath);
447
+
448
+ const lines: string[] = [];
449
+ lines.push(`Debug Log: ${entry.filename}`);
450
+ lines.push("─".repeat(60));
451
+ lines.push(`Size: ${formatSize(entry.size)} | Age: ${formatAge(entry.mtime)}`);
452
+ lines.push(`Events: ${summary.events} | Duration: ${summary.duration} | Dispatches: ${summary.dispatches}`);
453
+
454
+ if (summary.errors.length > 0) {
455
+ lines.push("");
456
+ lines.push("Errors/failures:");
457
+ for (const e of summary.errors.slice(0, 10)) {
458
+ lines.push(` [${e.event}] ${e.message}`);
459
+ }
460
+ if (summary.errors.length > 10) {
461
+ lines.push(` ... and ${summary.errors.length - 10} more`);
462
+ }
463
+ }
464
+
465
+ lines.push("");
466
+ lines.push(`Full log: ${filePath}`);
467
+
468
+ ctx.ui.notify(lines.join("\n"), "info");
469
+ }
470
+
471
+ async function handleLogsTail(basePath: string, ctx: ExtensionCommandContext, count: number): Promise<void> {
472
+ const activities = listActivityLogs(basePath);
473
+
474
+ if (activities.length === 0) {
475
+ ctx.ui.notify("No activity logs found. Logs are created during auto-mode.", "info");
476
+ return;
477
+ }
478
+
479
+ const recent = activities.slice(-Math.max(1, Math.min(count, 20)));
480
+ const lines: string[] = [`Last ${recent.length} activity log(s):`, ""];
481
+
482
+ for (const e of recent) {
483
+ const filePath = join(activityDir(basePath), e.filename);
484
+ const summary = summarizeActivityLog(filePath);
485
+ const status = summary.errors > 0 ? `${summary.errors} err` : "ok";
486
+ lines.push(` #${e.seq} ${e.unitType} ${e.unitId} — ${summary.toolCalls} tools, ${status}, ${formatAge(e.mtime)}`);
487
+ }
488
+
489
+ ctx.ui.notify(lines.join("\n"), "info");
490
+ }
491
+
492
+ async function handleLogsClear(basePath: string, ctx: ExtensionCommandContext): Promise<void> {
493
+ let removedActivity = 0;
494
+ let removedDebug = 0;
495
+
496
+ // Clear activity logs older than 7 days, keep the 5 most recent
497
+ const activities = listActivityLogs(basePath);
498
+ const keepRecent = activities.slice(-5);
499
+ const keepSeqs = new Set(keepRecent.map(e => e.seq));
500
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
501
+
502
+ for (const e of activities) {
503
+ if (keepSeqs.has(e.seq)) continue;
504
+ if (e.mtime.getTime() < cutoff) {
505
+ try {
506
+ unlinkSync(join(activityDir(basePath), e.filename));
507
+ removedActivity++;
508
+ } catch { /* ignore */ }
509
+ }
510
+ }
511
+
512
+ // Clear debug logs older than 3 days, keep latest 2
513
+ const debugLogs = listDebugLogs(basePath);
514
+ const keepDebug = debugLogs.slice(-2);
515
+ const keepDebugNames = new Set(keepDebug.map(d => d.filename));
516
+ const debugCutoff = Date.now() - 3 * 24 * 60 * 60 * 1000;
517
+
518
+ for (const d of debugLogs) {
519
+ if (keepDebugNames.has(d.filename)) continue;
520
+ if (d.mtime.getTime() < debugCutoff) {
521
+ try {
522
+ unlinkSync(join(debugDir(basePath), d.filename));
523
+ removedDebug++;
524
+ } catch { /* ignore */ }
525
+ }
526
+ }
527
+
528
+ if (removedActivity === 0 && removedDebug === 0) {
529
+ ctx.ui.notify("No old logs to clear.", "info");
530
+ } else {
531
+ ctx.ui.notify(
532
+ `Cleared ${removedActivity} activity log(s) and ${removedDebug} debug log(s).`,
533
+ "info",
534
+ );
535
+ }
536
+ }