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,241 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdirSync, mkdtempSync, writeFileSync, rmSync, existsSync, utimesSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+
7
+ import { handleLogs } from "../commands-logs.ts";
8
+
9
+ // ─── Test helpers ───────────────────────────────────────────────────────────
10
+
11
+ function createTestDir(): string {
12
+ const dir = mkdtempSync(join(tmpdir(), "gsd-logs-test-"));
13
+ mkdirSync(join(dir, ".gsd", "activity"), { recursive: true });
14
+ mkdirSync(join(dir, ".gsd", "debug"), { recursive: true });
15
+ return dir;
16
+ }
17
+
18
+ function createMockCtx(): { notifications: Array<{ msg: string; level: string }>; ui: any } {
19
+ const notifications: Array<{ msg: string; level: string }> = [];
20
+ return {
21
+ notifications,
22
+ ui: {
23
+ notify(msg: string, level: string) { notifications.push({ msg, level }); },
24
+ setStatus() {},
25
+ setWidget() {},
26
+ setFooter() {},
27
+ },
28
+ };
29
+ }
30
+
31
+ function writeActivityLog(dir: string, seq: number, unitType: string, unitId: string, entries: Record<string, unknown>[]): void {
32
+ const safeId = unitId.replace(/\//g, "-");
33
+ const filename = `${String(seq).padStart(3, "0")}-${unitType}-${safeId}.jsonl`;
34
+ const content = entries.map(e => JSON.stringify(e)).join("\n") + "\n";
35
+ writeFileSync(join(dir, ".gsd", "activity", filename), content);
36
+ }
37
+
38
+ function writeDebugLog(dir: string, name: string, entries: Record<string, unknown>[]): void {
39
+ const content = entries.map(e => JSON.stringify(e)).join("\n") + "\n";
40
+ writeFileSync(join(dir, ".gsd", "debug", name), content);
41
+ }
42
+
43
+ // ─── Tests ──────────────────────────────────────────────────────────────────
44
+
45
+ test("logs shows empty state message when no logs exist", async () => {
46
+ const dir = createTestDir();
47
+ const ctx = createMockCtx();
48
+ const origCwd = process.cwd();
49
+ process.chdir(dir);
50
+ try {
51
+ await handleLogs("", ctx as any);
52
+ assert.equal(ctx.notifications.length, 1);
53
+ assert.ok(ctx.notifications[0].msg.includes("No logs found"));
54
+ } finally {
55
+ process.chdir(origCwd);
56
+ rmSync(dir, { recursive: true, force: true });
57
+ }
58
+ });
59
+
60
+ test("logs lists activity logs", async () => {
61
+ const dir = createTestDir();
62
+ const ctx = createMockCtx();
63
+ const origCwd = process.cwd();
64
+ process.chdir(dir);
65
+
66
+ writeActivityLog(dir, 1, "execute-task", "M001/S01/T01", [
67
+ { type: "toolCall", name: "bash", arguments: { command: "npm test" } },
68
+ { role: "toolResult", toolCallId: "1", toolName: "bash", isError: false },
69
+ ]);
70
+ writeActivityLog(dir, 2, "complete-slice", "M001/S01", [
71
+ { role: "assistant", content: "Completing slice S01" },
72
+ ]);
73
+
74
+ try {
75
+ await handleLogs("", ctx as any);
76
+ assert.equal(ctx.notifications.length, 1);
77
+ const msg = ctx.notifications[0].msg;
78
+ assert.ok(msg.includes("Activity Logs"), "should show activity logs header");
79
+ assert.ok(msg.includes("execute-task"), "should show unit type");
80
+ assert.ok(msg.includes("complete-slice"), "should show second log");
81
+ assert.ok(msg.includes("/gsd logs <#>"), "should show usage hint");
82
+ } finally {
83
+ process.chdir(origCwd);
84
+ rmSync(dir, { recursive: true, force: true });
85
+ }
86
+ });
87
+
88
+ test("logs <N> shows activity log details", async () => {
89
+ const dir = createTestDir();
90
+ const ctx = createMockCtx();
91
+ const origCwd = process.cwd();
92
+ process.chdir(dir);
93
+
94
+ writeActivityLog(dir, 1, "execute-task", "M001/S01/T01", [
95
+ { type: "toolCall", name: "bash", arguments: { command: "npm test" } },
96
+ { type: "toolCall", name: "write", arguments: { file_path: "/tmp/test.ts" } },
97
+ { role: "toolResult", toolCallId: "1", toolName: "bash", isError: false },
98
+ { role: "toolResult", toolCallId: "2", toolName: "write", isError: true },
99
+ { role: "assistant", content: "I ran the tests and wrote a file" },
100
+ ]);
101
+
102
+ try {
103
+ await handleLogs("1", ctx as any);
104
+ assert.equal(ctx.notifications.length, 1);
105
+ const msg = ctx.notifications[0].msg;
106
+ assert.ok(msg.includes("Activity Log #1"), "should show log number");
107
+ assert.ok(msg.includes("execute-task"), "should show unit type");
108
+ assert.ok(msg.includes("Tool calls: 2"), "should count tool calls");
109
+ assert.ok(msg.includes("Errors: 1"), "should count errors");
110
+ assert.ok(msg.includes("/tmp/test.ts"), "should show files written");
111
+ assert.ok(msg.includes("npm test"), "should show commands run");
112
+ } finally {
113
+ process.chdir(origCwd);
114
+ rmSync(dir, { recursive: true, force: true });
115
+ }
116
+ });
117
+
118
+ test("logs <N> shows not found for invalid seq", async () => {
119
+ const dir = createTestDir();
120
+ const ctx = createMockCtx();
121
+ const origCwd = process.cwd();
122
+ process.chdir(dir);
123
+
124
+ try {
125
+ await handleLogs("999", ctx as any);
126
+ assert.equal(ctx.notifications.length, 1);
127
+ assert.ok(ctx.notifications[0].msg.includes("not found"));
128
+ assert.equal(ctx.notifications[0].level, "warning");
129
+ } finally {
130
+ process.chdir(origCwd);
131
+ rmSync(dir, { recursive: true, force: true });
132
+ }
133
+ });
134
+
135
+ test("logs debug lists debug logs", async () => {
136
+ const dir = createTestDir();
137
+ const ctx = createMockCtx();
138
+ const origCwd = process.cwd();
139
+ process.chdir(dir);
140
+
141
+ writeDebugLog(dir, "debug-2026-03-18T10-30-00.log", [
142
+ { ts: "2026-03-18T10:30:00Z", event: "debug-start", platform: "darwin" },
143
+ { ts: "2026-03-18T10:35:00Z", event: "debug-summary", dispatches: 5 },
144
+ ]);
145
+
146
+ try {
147
+ await handleLogs("debug", ctx as any);
148
+ assert.equal(ctx.notifications.length, 1);
149
+ const msg = ctx.notifications[0].msg;
150
+ assert.ok(msg.includes("Debug Logs"), "should show debug logs header");
151
+ assert.ok(msg.includes("debug-2026-03-18T10-30-00.log"), "should show filename");
152
+ } finally {
153
+ process.chdir(origCwd);
154
+ rmSync(dir, { recursive: true, force: true });
155
+ }
156
+ });
157
+
158
+ test("logs debug <N> shows debug log summary", async () => {
159
+ const dir = createTestDir();
160
+ const ctx = createMockCtx();
161
+ const origCwd = process.cwd();
162
+ process.chdir(dir);
163
+
164
+ writeDebugLog(dir, "debug-2026-03-18T10-30-00.log", [
165
+ { ts: "2026-03-18T10:30:00Z", event: "debug-start", platform: "darwin" },
166
+ { ts: "2026-03-18T10:30:05Z", event: "dispatch-error", error: "missing plan" },
167
+ { ts: "2026-03-18T10:35:00Z", event: "debug-summary", dispatches: 5 },
168
+ ]);
169
+
170
+ try {
171
+ await handleLogs("debug 1", ctx as any);
172
+ assert.equal(ctx.notifications.length, 1);
173
+ const msg = ctx.notifications[0].msg;
174
+ assert.ok(msg.includes("Debug Log:"), "should show debug log header");
175
+ assert.ok(msg.includes("Events: 3"), "should count events");
176
+ assert.ok(msg.includes("Dispatches: 5"), "should show dispatch count");
177
+ assert.ok(msg.includes("dispatch-error"), "should show errors");
178
+ } finally {
179
+ process.chdir(origCwd);
180
+ rmSync(dir, { recursive: true, force: true });
181
+ }
182
+ });
183
+
184
+ test("logs tail shows recent activity summaries", async () => {
185
+ const dir = createTestDir();
186
+ const ctx = createMockCtx();
187
+ const origCwd = process.cwd();
188
+ process.chdir(dir);
189
+
190
+ writeActivityLog(dir, 1, "execute-task", "M001/S01/T01", [
191
+ { type: "toolCall", name: "bash", arguments: { command: "npm test" } },
192
+ ]);
193
+ writeActivityLog(dir, 2, "execute-task", "M001/S01/T02", [
194
+ { type: "toolCall", name: "bash", arguments: { command: "npm build" } },
195
+ { role: "toolResult", toolCallId: "1", toolName: "bash", isError: true },
196
+ ]);
197
+
198
+ try {
199
+ await handleLogs("tail 2", ctx as any);
200
+ assert.equal(ctx.notifications.length, 1);
201
+ const msg = ctx.notifications[0].msg;
202
+ assert.ok(msg.includes("Last 2 activity log(s)"), "should show count");
203
+ assert.ok(msg.includes("#1"), "should show first log");
204
+ assert.ok(msg.includes("#2"), "should show second log");
205
+ } finally {
206
+ process.chdir(origCwd);
207
+ rmSync(dir, { recursive: true, force: true });
208
+ }
209
+ });
210
+
211
+ test("logs clear removes old logs", async () => {
212
+ const dir = createTestDir();
213
+ const ctx = createMockCtx();
214
+ const origCwd = process.cwd();
215
+ process.chdir(dir);
216
+
217
+ // Create an old activity log (modify mtime to 10 days ago)
218
+ writeActivityLog(dir, 1, "execute-task", "M001/S01/T01", [{ type: "toolCall" }]);
219
+ const oldFile = join(dir, ".gsd", "activity", "001-execute-task-M001-S01-T01.jsonl");
220
+ const oldTime = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000);
221
+ utimesSync(oldFile, oldTime, oldTime);
222
+
223
+ // Create 6 recent activity logs so the old one is outside the "keep 5" window
224
+ for (let i = 2; i <= 7; i++) {
225
+ writeActivityLog(dir, i, "execute-task", `M001/S01/T0${i}`, [{ type: "toolCall" }]);
226
+ }
227
+
228
+ try {
229
+ await handleLogs("clear", ctx as any);
230
+ assert.equal(ctx.notifications.length, 1);
231
+ // Old log should be removed, recent ones kept
232
+ assert.ok(!existsSync(oldFile), "old log should be removed");
233
+ assert.ok(
234
+ existsSync(join(dir, ".gsd", "activity", "007-execute-task-M001-S01-T07.jsonl")),
235
+ "most recent log should be kept",
236
+ );
237
+ } finally {
238
+ process.chdir(origCwd);
239
+ rmSync(dir, { recursive: true, force: true });
240
+ }
241
+ });
@@ -1,4 +1,6 @@
1
- // Tests for the SEPARATOR_PREFIX convention used by ExtensionSelectorComponent.
1
+ // Tests for the SEPARATOR_PREFIX convention used by ExtensionSelectorComponent
2
+ // and the two-step provider→model picker in configureModels.
3
+ //
2
4
  // We cannot import the component directly in node:test because its transitive
3
5
  // dependency (countdown-timer.ts) uses TypeScript parameter properties which
4
6
  // are unsupported under --experimental-strip-types. Instead we duplicate the
@@ -69,16 +71,17 @@ describe("separator detection", () => {
69
71
  });
70
72
  });
71
73
 
72
- describe("model grouping", () => {
73
- test("groups models by provider with separator headers", () => {
74
- // Simulate the grouping logic from configureModels
75
- const availableModels = [
76
- { id: "claude-opus-4-6", provider: "anthropic" },
77
- { id: "gpt-4o", provider: "openai" },
78
- { id: "claude-sonnet-4-5", provider: "anthropic" },
79
- { id: "o3-mini", provider: "openai" },
80
- ];
74
+ describe("two-step provider→model picker", () => {
75
+ // Simulate the grouping logic from configureModels
76
+ const availableModels = [
77
+ { id: "claude-opus-4-6", provider: "anthropic" },
78
+ { id: "gpt-4o", provider: "openai" },
79
+ { id: "claude-sonnet-4-5", provider: "anthropic" },
80
+ { id: "o3-mini", provider: "openai" },
81
+ { id: "claude-haiku-4-5", provider: "anthropic" },
82
+ ];
81
83
 
84
+ function buildProviderGroups() {
82
85
  const byProvider = new Map<string, typeof availableModels>();
83
86
  for (const m of availableModels) {
84
87
  let group = byProvider.get(m.provider);
@@ -89,34 +92,53 @@ describe("model grouping", () => {
89
92
  group.push(m);
90
93
  }
91
94
  const providers = Array.from(byProvider.keys()).sort((a, b) => a.localeCompare(b));
92
-
93
- const modelOptions: string[] = [];
94
- for (const provider of providers) {
95
- const group = byProvider.get(provider)!;
96
- modelOptions.push(`${SEPARATOR_PREFIX} ${provider} (${group.length}) ${SEPARATOR_PREFIX}`);
97
- for (const m of group) {
98
- modelOptions.push(`${m.id} · ${m.provider}`);
99
- }
95
+ for (const group of byProvider.values()) {
96
+ group.sort((a, b) => a.id.localeCompare(b.id));
100
97
  }
101
- modelOptions.push("(keep current)", "(clear)");
102
-
103
- // Verify structure
104
- assert.strictEqual(modelOptions[0], `${SEPARATOR_PREFIX} anthropic (2) ${SEPARATOR_PREFIX}`);
105
- assert.strictEqual(modelOptions[1], "claude-opus-4-6 · anthropic");
106
- assert.strictEqual(modelOptions[2], "claude-sonnet-4-5 · anthropic");
107
- assert.strictEqual(modelOptions[3], `${SEPARATOR_PREFIX} openai (2) ${SEPARATOR_PREFIX}`);
108
- assert.strictEqual(modelOptions[4], "gpt-4o · openai");
109
- assert.strictEqual(modelOptions[5], "o3-mini · openai");
110
- assert.strictEqual(modelOptions[6], "(keep current)");
111
- assert.strictEqual(modelOptions[7], "(clear)");
112
-
113
- // Verify separators are correctly detected
114
- assert.ok(isSeparator(modelOptions, 0));
115
- assert.ok(!isSeparator(modelOptions, 1));
116
- assert.ok(isSeparator(modelOptions, 3));
117
- assert.ok(!isSeparator(modelOptions, 6));
118
-
119
- // Verify first selectable is index 1, not the separator at 0
120
- assert.strictEqual(nextSelectable(modelOptions, 0, 1), 1);
98
+ return { byProvider, providers };
99
+ }
100
+
101
+ test("provider menu lists providers with model counts", () => {
102
+ const { providers, byProvider } = buildProviderGroups();
103
+ const providerOptions = providers.map(p => {
104
+ const count = byProvider.get(p)!.length;
105
+ return `${p} (${count} models)`;
106
+ });
107
+ providerOptions.push("(keep current)", "(clear)", "(type manually)");
108
+
109
+ assert.strictEqual(providerOptions[0], "anthropic (3 models)");
110
+ assert.strictEqual(providerOptions[1], "openai (2 models)");
111
+ assert.strictEqual(providerOptions[2], "(keep current)");
112
+ assert.strictEqual(providerOptions[3], "(clear)");
113
+ assert.strictEqual(providerOptions[4], "(type manually)");
114
+ });
115
+
116
+ test("model menu for a provider is sorted alphabetically", () => {
117
+ const { byProvider } = buildProviderGroups();
118
+ const anthropicModels = byProvider.get("anthropic")!;
119
+ const modelOptions = anthropicModels.map(m => m.id);
120
+
121
+ assert.strictEqual(modelOptions[0], "claude-haiku-4-5");
122
+ assert.strictEqual(modelOptions[1], "claude-opus-4-6");
123
+ assert.strictEqual(modelOptions[2], "claude-sonnet-4-5");
124
+ });
125
+
126
+ test("provider name is extracted correctly from choice string", () => {
127
+ const choice = "anthropic (3 models)";
128
+ const providerName = choice.replace(/ \(\d+ models?\)$/, "");
129
+ assert.strictEqual(providerName, "anthropic");
130
+
131
+ const singleChoice = "ollama (1 model)";
132
+ const singleProvider = singleChoice.replace(/ \(\d+ models?\)$/, "");
133
+ assert.strictEqual(singleProvider, "ollama");
134
+ });
135
+
136
+ test("openai models are sorted within their group", () => {
137
+ const { byProvider } = buildProviderGroups();
138
+ const openaiModels = byProvider.get("openai")!;
139
+ const modelOptions = openaiModels.map(m => m.id);
140
+
141
+ assert.strictEqual(modelOptions[0], "gpt-4o");
142
+ assert.strictEqual(modelOptions[1], "o3-mini");
121
143
  });
122
144
  });
@@ -3,7 +3,7 @@
3
3
  // Tests the pure formatInspectOutput function with known data.
4
4
 
5
5
  import { createTestContext } from './test-helpers.ts';
6
- import { formatInspectOutput, type InspectData } from '../commands.ts';
6
+ import { formatInspectOutput, type InspectData } from '../commands-inspect.ts';
7
7
 
8
8
  const { assertEq, assertTrue, assertMatch, report } = createTestContext();
9
9