gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.ffbcc03

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 (403) hide show
  1. package/dist/resources/extensions/gsd/activity-log.js +16 -0
  2. package/dist/resources/extensions/gsd/auto/loop.js +147 -10
  3. package/dist/resources/extensions/gsd/auto/phases.js +113 -3
  4. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  5. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
  6. package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
  8. package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
  9. package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
  10. package/dist/resources/extensions/gsd/auto-verification.js +100 -2
  11. package/dist/resources/extensions/gsd/auto.js +28 -2
  12. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  13. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
  14. package/dist/resources/extensions/gsd/cache.js +16 -5
  15. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  16. package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
  17. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  18. package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  19. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  20. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  21. package/dist/resources/extensions/gsd/git-service.js +49 -1
  22. package/dist/resources/extensions/gsd/graph-context.js +98 -7
  23. package/dist/resources/extensions/gsd/gsd-db.js +260 -2
  24. package/dist/resources/extensions/gsd/guided-flow.js +24 -1
  25. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  26. package/dist/resources/extensions/gsd/journal.js +27 -0
  27. package/dist/resources/extensions/gsd/metrics.js +19 -0
  28. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  29. package/dist/resources/extensions/gsd/preferences-models.js +20 -3
  30. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  31. package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
  32. package/dist/resources/extensions/gsd/preferences.js +26 -0
  33. package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
  34. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  35. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  36. package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
  37. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  38. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  39. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  40. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  41. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  42. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  43. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  44. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  45. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  46. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  47. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  48. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  49. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  50. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  51. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  52. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  53. package/dist/web/standalone/.next/BUILD_ID +1 -1
  54. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  55. package/dist/web/standalone/.next/build-manifest.json +2 -2
  56. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/index.html +1 -1
  79. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  86. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  87. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  89. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  90. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  91. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  92. package/package.json +1 -1
  93. package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
  94. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
  95. package/packages/mcp-server/dist/readers/graph.js +107 -0
  96. package/packages/mcp-server/dist/readers/graph.js.map +1 -1
  97. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  98. package/packages/mcp-server/dist/workflow-tools.js +88 -6
  99. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  100. package/packages/mcp-server/src/readers/graph.test.ts +178 -0
  101. package/packages/mcp-server/src/readers/graph.ts +148 -1
  102. package/packages/mcp-server/src/workflow-tools.ts +95 -10
  103. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  104. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  105. package/packages/pi-ai/dist/index.d.ts +1 -9
  106. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  107. package/packages/pi-ai/dist/index.js +1 -9
  108. package/packages/pi-ai/dist/index.js.map +1 -1
  109. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  110. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  111. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  112. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  113. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  114. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  115. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  116. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  117. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  118. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  120. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  121. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  122. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  123. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  124. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  125. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  126. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  127. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  128. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  129. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  130. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  131. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  132. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  133. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  134. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  135. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  136. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  137. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  138. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  139. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  140. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  141. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  142. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  143. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  144. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  145. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  146. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  147. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  148. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  149. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  150. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  151. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  152. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  153. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  154. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  155. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  156. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  157. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  158. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  159. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  160. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  161. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  162. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  163. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  164. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  165. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  166. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  167. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  168. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  169. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  170. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  172. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  173. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  174. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  175. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  176. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  177. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  178. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  179. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  180. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  181. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  182. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  184. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  185. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  186. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  187. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  188. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  189. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  190. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  191. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  192. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  193. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  194. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  195. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  196. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  197. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  198. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  199. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  200. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  201. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  202. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  203. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  204. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  205. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  206. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  207. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  208. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  209. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  210. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  212. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  213. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  214. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  215. package/packages/pi-ai/dist/models/index.js +80 -0
  216. package/packages/pi-ai/dist/models/index.js.map +1 -0
  217. package/packages/pi-ai/dist/models.d.ts +1 -36
  218. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  219. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  220. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  221. package/packages/pi-ai/dist/models.js +3 -112
  222. package/packages/pi-ai/dist/models.js.map +1 -1
  223. package/packages/pi-ai/dist/models.test.js +6 -5
  224. package/packages/pi-ai/dist/models.test.js.map +1 -1
  225. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  226. package/packages/pi-ai/src/index.ts +1 -9
  227. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  228. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  229. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  230. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  231. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  232. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  233. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  234. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  235. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  236. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  237. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  238. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  239. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  240. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  241. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  242. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  243. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  244. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  245. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  246. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  247. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  248. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  249. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  250. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  251. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  252. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  253. package/packages/pi-ai/src/models/index.ts +106 -0
  254. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  255. package/packages/pi-ai/src/models.test.ts +6 -5
  256. package/packages/pi-ai/src/models.ts +3 -153
  257. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  258. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  260. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
  262. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  264. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  265. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  266. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  267. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  269. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  288. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
  289. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
  297. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  298. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  299. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
  300. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  301. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  302. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
  303. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
  304. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
  305. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
  306. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  307. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
  308. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
  309. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
  310. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  311. package/packages/pi-coding-agent/tsconfig.json +2 -2
  312. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  313. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  314. package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
  315. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  316. package/src/resources/extensions/gsd/auto/phases.ts +123 -3
  317. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  318. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
  319. package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
  320. package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
  321. package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
  322. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  323. package/src/resources/extensions/gsd/auto-verification.ts +129 -2
  324. package/src/resources/extensions/gsd/auto.ts +34 -2
  325. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  326. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
  327. package/src/resources/extensions/gsd/cache.ts +16 -5
  328. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  329. package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
  330. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  331. package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  332. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  333. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  334. package/src/resources/extensions/gsd/git-service.ts +68 -0
  335. package/src/resources/extensions/gsd/graph-context.ts +139 -12
  336. package/src/resources/extensions/gsd/gsd-db.ts +321 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +33 -1
  338. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  339. package/src/resources/extensions/gsd/journal.ts +30 -0
  340. package/src/resources/extensions/gsd/metrics.ts +26 -0
  341. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  342. package/src/resources/extensions/gsd/preferences-models.ts +20 -3
  343. package/src/resources/extensions/gsd/preferences-types.ts +32 -0
  344. package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
  345. package/src/resources/extensions/gsd/preferences.ts +28 -0
  346. package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
  347. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  348. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  349. package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  350. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
  351. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
  352. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  353. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  354. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
  355. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  356. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
  357. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  358. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  359. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  360. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  361. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  362. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  363. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  364. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  365. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  366. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  367. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  368. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
  369. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  370. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  372. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  373. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  374. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  375. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  376. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  377. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  378. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  379. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  380. package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
  381. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  382. package/src/resources/extensions/gsd/types.ts +14 -1
  383. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  384. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  385. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  386. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  387. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  388. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  389. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  390. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  391. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  392. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  393. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  394. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  395. package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
  396. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  397. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  398. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  399. package/packages/pi-ai/dist/models.generated.js +0 -14343
  400. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  401. package/packages/pi-ai/src/models.generated.ts +0 -14345
  402. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
  403. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
@@ -0,0 +1,201 @@
1
+ // GSD2 — Ecosystem extension loader for ./.gsd/extensions/
2
+ // Discovers and registers single-file extensions that consume GSDExtensionAPI.
3
+ // Trust-gated (mirrors pi's `.pi/extensions/` model) and isolated from pi's
4
+ // own loader chain — handlers run in GSD's own dispatch step, not pi's.
5
+
6
+ import * as fs from "node:fs";
7
+ import * as path from "node:path";
8
+ import { pathToFileURL } from "node:url";
9
+
10
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
11
+ import { getAgentDir } from "@gsd/pi-coding-agent";
12
+
13
+ import { logWarning } from "../workflow-logger.js";
14
+ import {
15
+ createGSDExtensionAPI,
16
+ type GSDEcosystemBeforeAgentStartHandler,
17
+ type GSDExtensionAPI,
18
+ } from "./gsd-extension-api.js";
19
+
20
+ // ─── Trust check (inlined; pi does not export isProjectTrusted from its
21
+ // package root, and constraint forbids modifying packages/pi-coding-agent/) ─
22
+
23
+ const TRUSTED_PROJECTS_FILE = "trusted-projects.json";
24
+
25
+ function isProjectTrusted(projectPath: string, agentDir: string): boolean {
26
+ const canonical = path.resolve(projectPath);
27
+ const trustedPath = path.join(agentDir, TRUSTED_PROJECTS_FILE);
28
+ try {
29
+ const content = fs.readFileSync(trustedPath, "utf-8");
30
+ const parsed = JSON.parse(content);
31
+ if (Array.isArray(parsed)) {
32
+ return parsed.includes(canonical);
33
+ }
34
+ } catch {
35
+ // missing or malformed — treat as untrusted
36
+ }
37
+ return false;
38
+ }
39
+
40
+ // ─── Ready-promise singleton ────────────────────────────────────────────
41
+
42
+ let _readyPromise: Promise<void> | null = null;
43
+ let _untrustedWarned = false;
44
+
45
+ /**
46
+ * Discover and register ecosystem extensions from `./.gsd/extensions/`.
47
+ * Idempotent: subsequent calls with the same arguments return the same
48
+ * pending promise (no double-load).
49
+ */
50
+ export function loadEcosystemExtensions(
51
+ pi: ExtensionAPI,
52
+ sharedHandlers: GSDEcosystemBeforeAgentStartHandler[],
53
+ cwd: string = process.cwd(),
54
+ ): Promise<void> {
55
+ if (_readyPromise) return _readyPromise;
56
+ _readyPromise = _loadEcosystemExtensionsImpl(pi, sharedHandlers, cwd);
57
+ return _readyPromise;
58
+ }
59
+
60
+ /**
61
+ * Returns a promise that resolves when ecosystem loading has completed.
62
+ * If loading was never kicked off this returns a resolved promise so the
63
+ * `before_agent_start` handler can `await` unconditionally.
64
+ */
65
+ export function getEcosystemReadyPromise(): Promise<void> {
66
+ return _readyPromise ?? Promise.resolve();
67
+ }
68
+
69
+ /** Test-only: clear the singleton so tests can re-run loading. */
70
+ export function _resetEcosystemLoader(): void {
71
+ _readyPromise = null;
72
+ _untrustedWarned = false;
73
+ }
74
+
75
+ // ─── Implementation ─────────────────────────────────────────────────────
76
+
77
+ async function _loadEcosystemExtensionsImpl(
78
+ pi: ExtensionAPI,
79
+ sharedHandlers: GSDEcosystemBeforeAgentStartHandler[],
80
+ cwd: string,
81
+ ): Promise<void> {
82
+ const extDir = path.join(cwd, ".gsd", "extensions");
83
+ if (!fs.existsSync(extDir)) return;
84
+
85
+ // Trust gate: refuse to load arbitrary code from untrusted project dirs.
86
+ if (!isProjectTrusted(cwd, getAgentDir())) {
87
+ if (!_untrustedWarned) {
88
+ _untrustedWarned = true;
89
+ logWarning(
90
+ "ecosystem",
91
+ ".gsd/extensions present but project is not trusted — skipping ecosystem extensions. Run `pi trust` to opt in.",
92
+ );
93
+ }
94
+ return;
95
+ }
96
+
97
+ // Resolve realpath ONCE so symlink-escape detection has a stable anchor.
98
+ let realExtDir: string;
99
+ try {
100
+ realExtDir = fs.realpathSync(extDir);
101
+ } catch (err) {
102
+ logWarning(
103
+ "ecosystem",
104
+ `failed to resolve extensions dir: ${err instanceof Error ? err.message : String(err)}`,
105
+ );
106
+ return;
107
+ }
108
+
109
+ let entries: string[];
110
+ try {
111
+ entries = fs
112
+ .readdirSync(extDir)
113
+ .filter((f) => f.endsWith(".js") || f.endsWith(".ts"))
114
+ .sort(); // deterministic load order
115
+ } catch (err) {
116
+ logWarning(
117
+ "ecosystem",
118
+ `failed to read extensions dir: ${err instanceof Error ? err.message : String(err)}`,
119
+ );
120
+ return;
121
+ }
122
+
123
+ // The wrapper api is built once per loader run and shared by all extensions
124
+ // so they all read from the same module-level snapshot.
125
+ const api: GSDExtensionAPI = createGSDExtensionAPI(pi, sharedHandlers);
126
+
127
+ for (const entry of entries) {
128
+ await _loadOne(extDir, realExtDir, entry, api);
129
+ }
130
+ }
131
+
132
+ async function _loadOne(
133
+ extDir: string,
134
+ realExtDir: string,
135
+ entry: string,
136
+ api: GSDExtensionAPI,
137
+ ): Promise<void> {
138
+ const fullPath = path.join(extDir, entry);
139
+
140
+ // Symlink-escape guard: reject entries whose realpath is not under realExtDir.
141
+ let realFullPath: string;
142
+ try {
143
+ realFullPath = fs.realpathSync(fullPath);
144
+ } catch (err) {
145
+ logWarning(
146
+ "ecosystem",
147
+ `failed to resolve ${entry}: ${err instanceof Error ? err.message : String(err)}`,
148
+ );
149
+ return;
150
+ }
151
+ const realExtDirWithSep = realExtDir.endsWith(path.sep) ? realExtDir : realExtDir + path.sep;
152
+ if (
153
+ realFullPath !== realExtDir &&
154
+ !realFullPath.startsWith(realExtDirWithSep)
155
+ ) {
156
+ logWarning("ecosystem", `rejecting ${entry}: realpath escapes extensions dir`);
157
+ return;
158
+ }
159
+
160
+ // For .ts files, require a sibling compiled .js — we do not run a TS loader
161
+ // in production. Drop mtime heuristics: if .js exists, prefer it; otherwise warn.
162
+ let importPath = realFullPath;
163
+ if (entry.endsWith(".ts")) {
164
+ const jsSibling = realFullPath.slice(0, -3) + ".js";
165
+ if (fs.existsSync(jsSibling)) {
166
+ importPath = jsSibling;
167
+ } else {
168
+ logWarning(
169
+ "ecosystem",
170
+ `${entry}: TypeScript source has no compiled .js sibling — compile it first`,
171
+ );
172
+ return;
173
+ }
174
+ }
175
+
176
+ let mod: any;
177
+ try {
178
+ mod = await import(pathToFileURL(importPath).href);
179
+ } catch (err) {
180
+ logWarning(
181
+ "ecosystem",
182
+ `failed to import ${entry}: ${err instanceof Error ? err.message : String(err)}`,
183
+ );
184
+ return;
185
+ }
186
+
187
+ const factory = mod?.default;
188
+ if (typeof factory !== "function") {
189
+ logWarning("ecosystem", `${entry}: default export is not a function`);
190
+ return;
191
+ }
192
+
193
+ try {
194
+ await factory(api);
195
+ } catch (err) {
196
+ logWarning(
197
+ "ecosystem",
198
+ `factory threw for ${entry}: ${err instanceof Error ? err.message : String(err)}`,
199
+ );
200
+ }
201
+ }
@@ -34,6 +34,7 @@ import {
34
34
  nativeAddPaths,
35
35
  nativeResetSoft,
36
36
  nativeCommitSubject,
37
+ _resetHasChangesCache,
37
38
  } from "./native-git-bridge.js";
38
39
  import { GSDError, GSD_MERGE_CONFLICT, GSD_GIT_ERROR } from "./errors.js";
39
40
  import { getErrorMessage } from "./error-utils.js";
@@ -93,6 +94,17 @@ export interface CommitOptions {
93
94
  allowEmpty?: boolean;
94
95
  }
95
96
 
97
+ export type TurnGitActionMode = "commit" | "snapshot" | "status-only";
98
+
99
+ export interface TurnGitActionResult {
100
+ action: TurnGitActionMode;
101
+ status: "ok" | "failed";
102
+ commitMessage?: string;
103
+ snapshotLabel?: string;
104
+ dirty?: boolean;
105
+ error?: string;
106
+ }
107
+
96
108
  // ─── Meaningful Commit Message Generation ───────────────────────────────────
97
109
 
98
110
  /** Context for generating a meaningful commit message from task execution results. */
@@ -822,6 +834,62 @@ export function createGitService(basePath: string): GitServiceImpl {
822
834
  return new GitServiceImpl(basePath, gitPrefs);
823
835
  }
824
836
 
837
+ function buildTurnSnapshotLabel(unitType: string, unitId: string): string {
838
+ const raw = `${unitType}/${unitId}`.trim();
839
+ if (!raw) return "turn";
840
+ return raw
841
+ .replace(/[^a-zA-Z0-9._/-]/g, "-")
842
+ .replace(/\/{2,}/g, "/")
843
+ .replace(/-{2,}/g, "-")
844
+ .replace(/^[-/]+|[-/]+$/g, "") || "turn";
845
+ }
846
+
847
+ export function runTurnGitAction(args: {
848
+ basePath: string;
849
+ action: TurnGitActionMode;
850
+ unitType: string;
851
+ unitId: string;
852
+ taskContext?: TaskCommitContext;
853
+ }): TurnGitActionResult {
854
+ try {
855
+ // Force fresh working-tree status per turn; nativeHasChanges caches briefly.
856
+ _resetHasChangesCache();
857
+ if (args.action === "status-only") {
858
+ return {
859
+ action: args.action,
860
+ status: "ok",
861
+ dirty: nativeHasChanges(args.basePath),
862
+ };
863
+ }
864
+
865
+ const git = createGitService(args.basePath);
866
+ if (args.action === "snapshot") {
867
+ const label = buildTurnSnapshotLabel(args.unitType, args.unitId);
868
+ git.createSnapshot(label);
869
+ return {
870
+ action: args.action,
871
+ status: "ok",
872
+ snapshotLabel: label,
873
+ dirty: nativeHasChanges(args.basePath),
874
+ };
875
+ }
876
+
877
+ const commitMessage = git.autoCommit(args.unitType, args.unitId, [], args.taskContext) ?? undefined;
878
+ return {
879
+ action: args.action,
880
+ status: "ok",
881
+ commitMessage,
882
+ dirty: nativeHasChanges(args.basePath),
883
+ };
884
+ } catch (err) {
885
+ return {
886
+ action: args.action,
887
+ status: "failed",
888
+ error: getErrorMessage(err),
889
+ };
890
+ }
891
+ }
892
+
825
893
  // ─── Commit Type Inference ─────────────────────────────────────────────────
826
894
 
827
895
  /**
@@ -7,13 +7,144 @@
7
7
  */
8
8
 
9
9
  import { logWarning } from "./workflow-logger.js";
10
- import type { GraphQueryResult, GraphStatusResult } from "@gsd-build/mcp-server";
10
+ import { readFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+
13
+ interface GraphNode {
14
+ id: string;
15
+ label: string;
16
+ type: string;
17
+ confidence: string;
18
+ description?: string;
19
+ }
20
+
21
+ interface GraphEdge {
22
+ from: string;
23
+ to: string;
24
+ type: string;
25
+ }
26
+
27
+ interface GraphQueryResult {
28
+ nodes: GraphNode[];
29
+ edges: GraphEdge[];
30
+ }
31
+
32
+ interface GraphStatusResult {
33
+ exists: boolean;
34
+ stale: boolean;
35
+ ageHours?: number;
36
+ }
37
+
38
+ interface GraphApi {
39
+ graphQuery: (projectDir: string, term: string, budget?: number) => Promise<GraphQueryResult>;
40
+ graphStatus: (projectDir: string) => Promise<GraphStatusResult>;
41
+ }
42
+
43
+ interface GraphFileShape {
44
+ nodes: GraphNode[];
45
+ edges: GraphEdge[];
46
+ builtAt?: string;
47
+ }
48
+
49
+ let cachedGraphApi: GraphApi | null = null;
50
+ let resolvedGraphApi = false;
11
51
 
12
52
  export interface GraphSubgraphOptions {
13
53
  /** Budget in tokens passed to graphQuery (1 node ≈ 20 tokens, 1 edge ≈ 10 tokens) */
14
54
  budget: number;
15
55
  }
16
56
 
57
+ function readGraphFile(projectDir: string): GraphFileShape | null {
58
+ try {
59
+ const graphPath = join(projectDir, ".gsd", "graphs", "graph.json");
60
+ const raw = readFileSync(graphPath, "utf-8");
61
+ const parsed = JSON.parse(raw) as Partial<GraphFileShape>;
62
+ const nodes = Array.isArray(parsed.nodes) ? parsed.nodes : [];
63
+ const edges = Array.isArray(parsed.edges) ? parsed.edges : [];
64
+ return { nodes, edges, builtAt: typeof parsed.builtAt === "string" ? parsed.builtAt : undefined };
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+
70
+ async function fallbackGraphQuery(projectDir: string, term: string, budget = 3000): Promise<GraphQueryResult> {
71
+ const graph = readGraphFile(projectDir);
72
+ if (!graph) return { nodes: [], edges: [] };
73
+
74
+ const needle = term.trim().toLowerCase();
75
+ const matches = graph.nodes.filter((node) => {
76
+ const hay = [node.id, node.label, node.description].filter(Boolean).join(" ").toLowerCase();
77
+ return hay.includes(needle);
78
+ });
79
+
80
+ const maxNodes = Math.max(1, Math.floor(Math.max(1, budget) / 20));
81
+ const selectedIds = new Set(matches.slice(0, maxNodes).map((node) => node.id));
82
+ const nodeById = new Map(graph.nodes.map((node) => [node.id, node] as const));
83
+
84
+ // Pull one-hop neighbors so relation context survives even when the term
85
+ // matches only one side of an edge.
86
+ for (const edge of graph.edges) {
87
+ if (selectedIds.size >= maxNodes) break;
88
+ const touchesSelection = selectedIds.has(edge.from) || selectedIds.has(edge.to);
89
+ if (!touchesSelection) continue;
90
+ if (selectedIds.has(edge.from) && !selectedIds.has(edge.to) && nodeById.has(edge.to)) {
91
+ selectedIds.add(edge.to);
92
+ } else if (selectedIds.has(edge.to) && !selectedIds.has(edge.from) && nodeById.has(edge.from)) {
93
+ selectedIds.add(edge.from);
94
+ }
95
+ }
96
+
97
+ const nodes = graph.nodes.filter((node) => selectedIds.has(node.id));
98
+
99
+ const remainingBudget = Math.max(0, budget - nodes.length * 20);
100
+ const maxEdges = Math.floor(remainingBudget / 10);
101
+ const edges = graph.edges
102
+ .filter((edge) => selectedIds.has(edge.from) && selectedIds.has(edge.to))
103
+ .slice(0, maxEdges);
104
+
105
+ return { nodes, edges };
106
+ }
107
+
108
+ async function fallbackGraphStatus(projectDir: string): Promise<GraphStatusResult> {
109
+ const graph = readGraphFile(projectDir);
110
+ if (!graph) return { exists: false, stale: false };
111
+ if (!graph.builtAt) return { exists: true, stale: false };
112
+
113
+ const builtAtMs = Date.parse(graph.builtAt);
114
+ if (!Number.isFinite(builtAtMs)) return { exists: true, stale: false };
115
+
116
+ const ageHours = (Date.now() - builtAtMs) / (1000 * 60 * 60);
117
+ return { exists: true, stale: ageHours > 24, ageHours };
118
+ }
119
+
120
+ function isGraphApi(mod: unknown): mod is GraphApi {
121
+ if (!mod || typeof mod !== "object") return false;
122
+ const candidate = mod as Record<string, unknown>;
123
+ return typeof candidate.graphQuery === "function" && typeof candidate.graphStatus === "function";
124
+ }
125
+
126
+ async function resolveGraphApi(): Promise<GraphApi> {
127
+ if (resolvedGraphApi && cachedGraphApi) return cachedGraphApi;
128
+
129
+ resolvedGraphApi = true;
130
+ try {
131
+ const imported = await import("@gsd-build/mcp-server");
132
+ if (isGraphApi(imported)) {
133
+ cachedGraphApi = imported;
134
+ return cachedGraphApi;
135
+ }
136
+ logWarning("prompt", "@gsd-build/mcp-server graph exports unavailable; using local graph fallback");
137
+ } catch {
138
+ // Fall back to local reader implementation.
139
+ }
140
+
141
+ cachedGraphApi = {
142
+ graphQuery: fallbackGraphQuery,
143
+ graphStatus: fallbackGraphStatus,
144
+ };
145
+ return cachedGraphApi;
146
+ }
147
+
17
148
  /**
18
149
  * Query the knowledge graph for nodes related to the given term and format
19
150
  * the result as an inlined context block.
@@ -33,18 +164,14 @@ export async function inlineGraphSubgraph(
33
164
  if (!term || !term.trim()) return null;
34
165
 
35
166
  try {
36
- const { graphQuery, graphStatus } = await import("@gsd-build/mcp-server") as {
37
- graphQuery: (projectDir: string, term: string, budget?: number) => Promise<GraphQueryResult>;
38
- graphStatus: (projectDir: string) => Promise<GraphStatusResult>;
39
- };
40
-
41
- const result = await graphQuery(projectDir, term, opts.budget);
167
+ const graphApi = await resolveGraphApi();
168
+ const result = await graphApi.graphQuery(projectDir, term, opts.budget);
42
169
  if (result.nodes.length === 0) return null;
43
170
 
44
171
  // Check staleness for annotation
45
172
  let staleAnnotation = "";
46
173
  try {
47
- const status = await graphStatus(projectDir);
174
+ const status = await graphApi.graphStatus(projectDir);
48
175
  if (status.exists && status.stale && status.ageHours !== undefined) {
49
176
  const hours = Math.round(status.ageHours);
50
177
  staleAnnotation = `\n> ⚠ Graph last built ${hours}h ago — context may be outdated`;
@@ -54,14 +181,14 @@ export async function inlineGraphSubgraph(
54
181
  }
55
182
 
56
183
  // Format nodes as a compact list
57
- const nodeLines = result.nodes.map((n) => {
58
- const desc = n.description ? ` — ${n.description}` : "";
59
- return `- **${n.label}** (\`${n.type}\`, ${n.confidence})${desc}`;
184
+ const nodeLines = result.nodes.map((node) => {
185
+ const desc = node.description ? ` — ${node.description}` : "";
186
+ return `- **${node.label}** (\`${node.type}\`, ${node.confidence})${desc}`;
60
187
  });
61
188
 
62
189
  // Format edges as relations (only if present)
63
190
  const edgeLines = result.edges.length > 0
64
- ? result.edges.map((e) => `- \`${e.from}\` →[${e.type}]→ \`${e.to}\``)
191
+ ? result.edges.map((edge) => `- \`${edge.from}\` →[${edge.type}]→ \`${edge.to}\``)
65
192
  : [];
66
193
 
67
194
  const sections: string[] = [