@opengsd/gsd-pi 1.1.1-dev.9f86580 → 1.1.1-dev.b2556262

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 (261) hide show
  1. package/dist/headless-recover.js +56 -1
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/browser-tools/index.js +39 -22
  4. package/dist/resources/extensions/browser-tools/state.js +12 -0
  5. package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
  6. package/dist/resources/extensions/browser-tools/utils.js +3 -3
  7. package/dist/resources/extensions/gsd/auto/loop.js +4 -2
  8. package/dist/resources/extensions/gsd/auto/phases.js +43 -10
  9. package/dist/resources/extensions/gsd/auto/session.js +20 -1
  10. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +72 -12
  12. package/dist/resources/extensions/gsd/auto-model-selection.js +128 -9
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
  14. package/dist/resources/extensions/gsd/auto-prompts.js +24 -19
  15. package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
  16. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  18. package/dist/resources/extensions/gsd/auto.js +14 -11
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +172 -65
  21. package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
  22. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
  23. package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
  24. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
  25. package/dist/resources/extensions/gsd/db-writer.js +35 -0
  26. package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
  27. package/dist/resources/extensions/gsd/gsd-db.js +480 -172
  28. package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
  29. package/dist/resources/extensions/gsd/md-importer.js +38 -3
  30. package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
  31. package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
  32. package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
  33. package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
  34. package/dist/resources/extensions/gsd/preferences-models.js +110 -43
  35. package/dist/resources/extensions/gsd/preferences-types.js +13 -0
  36. package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
  37. package/dist/resources/extensions/gsd/preferences.js +4 -1
  38. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  39. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  40. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  41. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
  42. package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
  43. package/dist/resources/extensions/gsd/source-observations.js +306 -0
  44. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
  45. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
  46. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
  47. package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
  48. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
  49. package/dist/resources/extensions/gsd/state.js +7 -3
  50. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  51. package/dist/resources/extensions/gsd/tool-presentation-plan.js +1 -9
  52. package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -6
  53. package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
  54. package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
  55. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +57 -429
  56. package/dist/resources/extensions/gsd/uat-policy.js +130 -0
  57. package/dist/resources/extensions/gsd/uat-run.js +414 -0
  58. package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
  59. package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
  60. package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
  61. package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
  62. package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
  63. package/dist/resources/extensions/subagent/agents.js +1 -0
  64. package/dist/resources/extensions/subagent/index.js +27 -12
  65. package/dist/resources/extensions/subagent/launch.js +7 -2
  66. package/dist/web/standalone/.next/BUILD_ID +1 -1
  67. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  68. package/dist/web/standalone/.next/build-manifest.json +2 -2
  69. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  70. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/index.html +1 -1
  87. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  94. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  95. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  97. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  98. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  99. package/dist/web/standalone/node_modules/@gsd/native/dist/native.js +22 -0
  100. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  101. package/package.json +4 -4
  102. package/packages/cloud-mcp-gateway/package.json +2 -2
  103. package/packages/contracts/package.json +1 -1
  104. package/packages/daemon/package.json +4 -4
  105. package/packages/gsd-agent-core/package.json +5 -5
  106. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  107. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
  108. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
  109. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -0
  110. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  111. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -0
  112. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  113. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
  114. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  115. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
  116. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  117. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  118. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
  119. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  120. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  121. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
  122. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  123. package/packages/gsd-agent-modes/package.json +7 -7
  124. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  125. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  126. package/packages/mcp-server/package.json +3 -3
  127. package/packages/native/dist/native.js +22 -0
  128. package/packages/native/package.json +1 -1
  129. package/packages/pi-agent-core/package.json +1 -1
  130. package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
  131. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  132. package/packages/pi-ai/dist/image-models.generated.js +30 -0
  133. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  134. package/packages/pi-ai/dist/models.generated.d.ts +23 -17
  135. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  136. package/packages/pi-ai/dist/models.generated.js +25 -24
  137. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  138. package/packages/pi-ai/package.json +1 -1
  139. package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
  140. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  141. package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
  142. package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
  143. package/packages/pi-coding-agent/package.json +7 -7
  144. package/packages/pi-tui/dist/utils.d.ts +11 -0
  145. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  146. package/packages/pi-tui/dist/utils.js +119 -6
  147. package/packages/pi-tui/dist/utils.js.map +1 -1
  148. package/packages/pi-tui/package.json +2 -1
  149. package/packages/rpc-client/package.json +2 -2
  150. package/pkg/dist/theme/themes.js +1 -1
  151. package/pkg/dist/theme/themes.js.map +1 -1
  152. package/pkg/package.json +1 -1
  153. package/src/resources/extensions/browser-tools/index.ts +39 -22
  154. package/src/resources/extensions/browser-tools/state.ts +13 -0
  155. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
  156. package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
  157. package/src/resources/extensions/browser-tools/utils.ts +3 -3
  158. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  159. package/src/resources/extensions/gsd/auto/loop.ts +4 -2
  160. package/src/resources/extensions/gsd/auto/phases.ts +42 -10
  161. package/src/resources/extensions/gsd/auto/session.ts +22 -1
  162. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
  163. package/src/resources/extensions/gsd/auto-dispatch.ts +85 -12
  164. package/src/resources/extensions/gsd/auto-model-selection.ts +164 -12
  165. package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
  166. package/src/resources/extensions/gsd/auto-prompts.ts +23 -20
  167. package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
  168. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  169. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  170. package/src/resources/extensions/gsd/auto.ts +13 -10
  171. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  172. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +225 -72
  173. package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
  174. package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
  175. package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
  176. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
  177. package/src/resources/extensions/gsd/db-writer.ts +38 -0
  178. package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
  179. package/src/resources/extensions/gsd/gsd-db.ts +564 -186
  180. package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
  181. package/src/resources/extensions/gsd/md-importer.ts +49 -2
  182. package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
  183. package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
  184. package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
  185. package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
  186. package/src/resources/extensions/gsd/preferences-models.ts +112 -43
  187. package/src/resources/extensions/gsd/preferences-types.ts +39 -0
  188. package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
  189. package/src/resources/extensions/gsd/preferences.ts +5 -0
  190. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  191. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  192. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  193. package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
  194. package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
  195. package/src/resources/extensions/gsd/source-observations.ts +402 -0
  196. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
  197. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
  198. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
  199. package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
  200. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
  201. package/src/resources/extensions/gsd/state.ts +7 -4
  202. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
  203. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
  204. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
  205. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
  206. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
  207. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
  208. package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
  209. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
  210. package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
  211. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +16 -2
  212. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
  213. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
  214. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
  215. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
  216. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +15 -0
  217. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
  218. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
  219. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
  220. package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
  221. package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
  222. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
  223. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +9 -0
  224. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
  225. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
  226. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +8 -0
  227. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
  228. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
  229. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
  230. package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
  231. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
  232. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
  233. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
  234. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
  235. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
  236. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  237. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
  238. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +73 -6
  239. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
  240. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
  241. package/src/resources/extensions/gsd/tool-contract.ts +28 -0
  242. package/src/resources/extensions/gsd/tool-presentation-plan.ts +1 -11
  243. package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -6
  244. package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
  245. package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
  246. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +66 -526
  247. package/src/resources/extensions/gsd/types.ts +1 -0
  248. package/src/resources/extensions/gsd/uat-policy.ts +191 -0
  249. package/src/resources/extensions/gsd/uat-run.ts +550 -0
  250. package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
  251. package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
  252. package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
  253. package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
  254. package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
  255. package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
  256. package/src/resources/extensions/subagent/agents.ts +4 -0
  257. package/src/resources/extensions/subagent/index.ts +28 -3
  258. package/src/resources/extensions/subagent/launch.ts +8 -0
  259. package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
  260. /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
  261. /package/dist/web/standalone/.next/static/{zzYMrKpPGfRQRxSFO32Jr → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
@@ -3,7 +3,8 @@
3
3
  * Handles complexity-based routing, model resolution across providers,
4
4
  * and fallback chains.
5
5
  */
6
- import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
6
+ import { clampThinkingLevel } from "@gsd/pi-ai";
7
+ import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
7
8
  import { classifyUnitComplexity, extractTaskMetadata, tierLabel } from "./complexity-classifier.js";
8
9
  import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet } from "./model-router.js";
9
10
  import { getLedger, getProjectTotals } from "./metrics.js";
@@ -228,10 +229,88 @@ function restoreToolBaseline(pi) {
228
229
  pi.setActiveTools([...baseline]);
229
230
  }
230
231
  }
231
- function reapplyThinkingLevel(pi, level) {
232
+ /**
233
+ * Apply the desired reasoning effort for the just-selected model, clamping to
234
+ * what the model actually supports (ADR-026). An unsupported level is never
235
+ * sent to the provider — it is clamped via `clampThinkingLevel` and the
236
+ * mismatch is surfaced once per (model, requested-level). Returns the level
237
+ * actually applied so callers can record it.
238
+ */
239
+ export function applyThinkingLevelForModel(pi, desired, model, ctx) {
240
+ if (!desired)
241
+ return desired;
242
+ // Capability-clamp only when we have a bare string level AND the model
243
+ // advertises reasoning capability (`reasoning` is always present on real
244
+ // registry models). Richer host snapshot shapes (e.g. `{ effort: "high" }`)
245
+ // and partial model objects are applied verbatim — we never coerce an unknown
246
+ // shape into a string or guess capability we can't see.
247
+ if (typeof desired === "string" && model != null && typeof model === "object" && "reasoning" in model) {
248
+ const clamped = clampThinkingLevel(model, desired);
249
+ pi.setThinkingLevel(clamped);
250
+ if (clamped !== desired) {
251
+ const key = `${model.provider}/${model.id}:${desired}`;
252
+ if (!_warnedThinkingClamp.has(key)) {
253
+ _warnedThinkingClamp.add(key);
254
+ ctx.ui.notify(`Thinking level '${desired}' not supported by ${model.provider}/${model.id}; using '${clamped}'.`, "warning");
255
+ }
256
+ }
257
+ return clamped;
258
+ }
259
+ pi.setThinkingLevel(desired);
260
+ return desired;
261
+ }
262
+ /** Warn-once guard for capability clamps, keyed by `provider/id:requested`. */
263
+ const _warnedThinkingClamp = new Set();
264
+ /** Warn-once guard for the execute-task floor punch-through advisory. */
265
+ let _warnedExecuteTaskFloorBypass = false;
266
+ /**
267
+ * Ascending severity order for reasoning levels (matches @gsd/pi-agent-core
268
+ * `ThinkingLevel`). Used only for floor comparisons below.
269
+ */
270
+ const THINKING_LEVEL_ORDER = [
271
+ "off",
272
+ "minimal",
273
+ "low",
274
+ "medium",
275
+ "high",
276
+ "xhigh",
277
+ ];
278
+ /**
279
+ * Minimum reasoning level for code-writing units.
280
+ *
281
+ * `execute-task` is the only unit that edits source. With a low/minimal
282
+ * thinking level a model does not plan its edits and compensates by re-reading
283
+ * the same files dozens of times per task (measured: index.html read ~49× in a
284
+ * single task on a minimal-thinking model) and shelling out to `nl`/`sed` to
285
+ * re-locate code after every edit invalidates its line numbers. Flooring the
286
+ * level for this unit type removes that read/bash thrash. Planning, research,
287
+ * and lifecycle units are unaffected.
288
+ */
289
+ const EXECUTE_TASK_MIN_THINKING_LEVEL = "medium";
290
+ function thinkingLevelRank(level) {
291
+ const idx = THINKING_LEVEL_ORDER.indexOf(level);
292
+ return idx === -1 ? 0 : idx;
293
+ }
294
+ /**
295
+ * Raise (never lower) the thinking level for code-writing units to a sane
296
+ * floor. Returns the input unchanged for non-`execute-task` units, when no
297
+ * level was captured, or when the captured level already meets the floor.
298
+ */
299
+ export function floorThinkingLevelForUnit(unitType, level) {
300
+ if (unitType !== "execute-task")
301
+ return level;
232
302
  if (!level)
233
- return;
234
- pi.setThinkingLevel(level);
303
+ return level;
304
+ // Only act on the recognized string levels. Any other shape (e.g. a richer
305
+ // host snapshot object) is passed through untouched so we never coerce an
306
+ // unknown representation into a bare string the host can't apply.
307
+ if (!THINKING_LEVEL_ORDER.includes(level)) {
308
+ return level;
309
+ }
310
+ if (thinkingLevelRank(level) >= thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL)) {
311
+ return level;
312
+ }
313
+ return EXECUTE_TASK_MIN_THINKING_LEVEL;
235
314
  }
236
315
  export function resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode = true) {
237
316
  const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
@@ -282,6 +361,32 @@ sessionModelOverride,
282
361
  /** Thinking level captured at auto-mode start and re-applied after model swaps. */
283
362
  autoModeStartThinkingLevel) {
284
363
  const uokFlags = resolveUokFlags(prefs);
364
+ // Resolve reasoning effort for this dispatch (ADR-026). An explicit per-phase
365
+ // thinking config (inline `models.<phase>.thinking` or the separate `thinking`
366
+ // block) expresses hard user intent: it bypasses the execute-task floor and is
367
+ // honored verbatim, then capability-clamped per model at apply time below.
368
+ // With no explicit level, fall back to the auto-start session level and raise
369
+ // the code-writing floor — preserving prior behavior exactly. Recomputed per
370
+ // dispatch so neither the floor nor a phase override leaks to other units.
371
+ const explicitThinkingLevel = resolveThinkingLevelForUnit(unitType);
372
+ const desiredThinkingLevel = explicitThinkingLevel
373
+ ?? floorThinkingLevelForUnit(unitType, autoModeStartThinkingLevel);
374
+ if (explicitThinkingLevel) {
375
+ if (unitType === "execute-task" &&
376
+ thinkingLevelRank(explicitThinkingLevel) < thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL) &&
377
+ !_warnedExecuteTaskFloorBypass) {
378
+ _warnedExecuteTaskFloorBypass = true;
379
+ ctx.ui.notify(`Explicit execution thinking '${explicitThinkingLevel}' is below the measured execute-task floor ` +
380
+ `(${EXECUTE_TASK_MIN_THINKING_LEVEL}); honoring it as configured. Low reasoning on code edits can ` +
381
+ `cause repeated file re-reads.`, "warning");
382
+ }
383
+ }
384
+ else if (verbose &&
385
+ desiredThinkingLevel &&
386
+ desiredThinkingLevel !== autoModeStartThinkingLevel) {
387
+ ctx.ui.notify(`Thinking level raised to ${desiredThinkingLevel} for ${unitType} (was ${autoModeStartThinkingLevel ?? "unset"})`, "info");
388
+ }
389
+ let appliedThinkingLevel = null;
285
390
  const effectiveSessionModelOverride = sessionModelOverride === undefined
286
391
  ? getSessionModelOverride(ctx.sessionManager.getSessionId())
287
392
  : (sessionModelOverride ?? undefined);
@@ -559,7 +664,7 @@ autoModeStartThinkingLevel) {
559
664
  const ok = await pi.setModel(model, { persist: false });
560
665
  if (ok) {
561
666
  appliedModel = model;
562
- reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
667
+ appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
563
668
  // ADR-005: Adjust active tool set for the selected model's provider capabilities.
564
669
  // Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
565
670
  const activeToolNames = pi.getActiveTools();
@@ -617,7 +722,7 @@ autoModeStartThinkingLevel) {
617
722
  if (!ok)
618
723
  continue;
619
724
  appliedModel = model;
620
- reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
725
+ appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
621
726
  attemptedPolicyEligible = true;
622
727
  if (verbose) {
623
728
  ctx.ui.notify(`Model policy: configured model unavailable; using ${model.provider}/${model.id}`, "info");
@@ -647,18 +752,32 @@ autoModeStartThinkingLevel) {
647
752
  const fallbackOk = await pi.setModel(byId, { persist: false });
648
753
  if (fallbackOk) {
649
754
  appliedModel = byId;
650
- reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
755
+ appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, byId, ctx);
651
756
  }
652
757
  }
653
758
  }
654
759
  else {
655
760
  appliedModel = startModel;
656
- reapplyThinkingLevel(pi, autoModeStartThinkingLevel);
761
+ appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, startModel, ctx);
657
762
  }
658
763
  }
659
764
  }
660
765
  }
661
- return { routing, appliedModel };
766
+ // If no model branch applied a thinking level (e.g. interactive guided-flow
767
+ // with a `thinking:` block but no per-phase model and no start model), still
768
+ // honor an explicitly configured phase thinking level against the current
769
+ // session model. Only the explicit path runs here — the floored session
770
+ // default is intentionally left untouched so no-config interactive runs keep
771
+ // the user's /model thinking level. (ADR-026)
772
+ if (appliedThinkingLevel == null && explicitThinkingLevel && ctx.model) {
773
+ // Prefer the full registry model (carries reasoning capability so the level
774
+ // can be clamped); fall back to ctx.model. Always route through
775
+ // applyThinkingLevelForModel so the clamp runs whenever capability metadata
776
+ // exists — never a raw verbatim setThinkingLevel that bypasses it (ADR-026).
777
+ const current = resolveModelId(`${ctx.model.provider}/${ctx.model.id}`, ctx.modelRegistry?.getAvailable?.() ?? [], ctx.model.provider) ?? ctx.model;
778
+ appliedThinkingLevel = applyThinkingLevelForModel(pi, explicitThinkingLevel, current, ctx);
779
+ }
780
+ return { routing, appliedModel, appliedThinkingLevel };
662
781
  }
663
782
  /**
664
783
  * Resolve a model ID string to a model object from the available models list.
@@ -1280,6 +1280,7 @@ export async function postUnitPreVerification(pctx, opts) {
1280
1280
  logError("engine", "triage resolution failed", { error: err.message });
1281
1281
  }
1282
1282
  }
1283
+ let blockingContentViolation = null;
1283
1284
  // ── Safety harness: post-unit validation ──
1284
1285
  try {
1285
1286
  const { loadEffectiveGSDPreferences } = await import("./preferences.js");
@@ -1399,8 +1400,15 @@ export async function postUnitPreVerification(pctx, opts) {
1399
1400
  const artifactPath = resolveArtifactForContent(s.currentUnit.type, s.currentUnit.id, s.basePath);
1400
1401
  const contentViolations = validateContent(s.currentUnit.type, artifactPath);
1401
1402
  for (const v of contentViolations) {
1402
- logWarning("safety", `content: ${v.reason}`);
1403
- ctx.ui.notify(`Content validation: ${v.reason}`, "warning");
1403
+ if (v.severity === "error") {
1404
+ blockingContentViolation ??= v.reason;
1405
+ logError("safety", `content: ${v.reason}`);
1406
+ ctx.ui.notify(`Content validation: ${v.reason}`, "error");
1407
+ }
1408
+ else {
1409
+ logWarning("safety", `content: ${v.reason}`);
1410
+ ctx.ui.notify(`Content validation: ${v.reason}`, "warning");
1411
+ }
1404
1412
  }
1405
1413
  }
1406
1414
  catch (e) {
@@ -1573,6 +1581,15 @@ export async function postUnitPreVerification(pctx, opts) {
1573
1581
  return "continue";
1574
1582
  }
1575
1583
  }
1584
+ if (blockingContentViolation && triggerArtifactVerified) {
1585
+ triggerArtifactVerified = false;
1586
+ debugLog("postUnit", {
1587
+ phase: "content-validation-blocked-artifact",
1588
+ unitType: s.currentUnit.type,
1589
+ unitId: s.currentUnit.id,
1590
+ reason: blockingContentViolation,
1591
+ });
1592
+ }
1576
1593
  // When artifact verification fails for a unit type that has a known expected
1577
1594
  // artifact, ask the caller to retry so it re-dispatches with failure context
1578
1595
  // instead of blindly re-dispatching the same unit (#1571).
@@ -8,7 +8,7 @@
8
8
  * utility.
9
9
  */
10
10
  import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection } from "./files.js";
11
- import { hasVerdict, getUatType, extractVerdict } from "./verdict-parser.js";
11
+ import { hasVerdict, extractVerdict } from "./verdict-parser.js";
12
12
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
13
13
  import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
14
14
  import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
@@ -27,11 +27,11 @@ import { logWarning } from "./workflow-logger.js";
27
27
  import { inlineGraphSubgraph } from "./graph-context.js";
28
28
  import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
29
29
  import { classifyProject } from "./detection.js";
30
- import { hasBrowserRequiredText } from "./browser-evidence.js";
31
30
  import { debugLog } from "./debug-logger.js";
32
31
  import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
33
32
  import { findMilestoneIds } from "./milestone-ids.js";
34
33
  import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
34
+ import { resolveEffectiveUatType, shouldDispatchUatForContent } from "./uat-policy.js";
35
35
  export { buildSkillActivationBlock, buildSkillDiscoveryVars };
36
36
  // ─── Preamble Cap ─────────────────────────────────────────────────────────────
37
37
  /**
@@ -228,17 +228,6 @@ function prependContextModeToBlock(unitType, base, block, renderMode = "standalo
228
228
  return contextMode;
229
229
  return `${contextMode}\n\n${block}`;
230
230
  }
231
- function resolveEffectiveUatType(content) {
232
- const uatType = getUatType(content);
233
- if (uatType === "artifact-driven" && hasBrowserRequiredText(content)) {
234
- return "browser-executable";
235
- }
236
- return uatType;
237
- }
238
- function shouldDispatchUatForContent(content, prefs) {
239
- const uatType = resolveEffectiveUatType(content);
240
- return !!prefs?.uat_dispatch || uatType !== "artifact-driven" || hasBrowserRequiredText(content);
241
- }
242
231
  // ─── Executor Constraints ─────────────────────────────────────────────────────
243
232
  /**
244
233
  * Format executor context constraints for injection into the plan-slice prompt.
@@ -3077,7 +3066,23 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
3077
3066
  });
3078
3067
  }
3079
3068
  // ─── Reactive Execute Prompt ──────────────────────────────────────────────
3080
- export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, readyTaskIds, base, subagentModel, opts) {
3069
+ /**
3070
+ * Build the `with model: "…" and thinking: "…"` suffix injected into a prompt
3071
+ * that instructs the coordinator how to dispatch a `subagent` call. Either or
3072
+ * both may be absent (ADR-026 / #508).
3073
+ */
3074
+ function subagentCallSuffix(model, thinking) {
3075
+ const parts = [];
3076
+ if (model)
3077
+ parts.push(`model: "${model}"`);
3078
+ if (thinking)
3079
+ parts.push(`thinking: "${thinking}"`);
3080
+ return parts.length > 0 ? ` with ${parts.join(" and ")}` : "";
3081
+ }
3082
+ export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, readyTaskIds, base, subagentModel,
3083
+ // Reasoning effort travels inside opts here (not as a positional param) so
3084
+ // existing positional `opts` callers don't shift (#508).
3085
+ opts) {
3081
3086
  const { loadSliceTaskIO, deriveTaskGraph, graphMetrics } = await import("./reactive-graph.js");
3082
3087
  // Build graph for context
3083
3088
  const taskIO = await loadSliceTaskIO(base, mid, sid);
@@ -3151,7 +3156,7 @@ export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, rea
3151
3156
  "",
3152
3157
  `When done, say: "Task ${tid} complete."`,
3153
3158
  ].join("\n");
3154
- const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
3159
+ const modelSuffix = subagentCallSuffix(subagentModel, opts?.subagentThinking);
3155
3160
  subagentSections.push([
3156
3161
  `### ${tid}: ${tTitle}`,
3157
3162
  "",
@@ -3217,10 +3222,10 @@ function renderGatesToCloseBlock(gates, opts) {
3217
3222
  }
3218
3223
  return lines.join("\n").trimEnd();
3219
3224
  }
3220
- export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath, subagentModel) {
3225
+ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath, subagentModel, subagentThinking) {
3221
3226
  // Build individual research-slice prompts for each slice
3222
3227
  const subagentSections = [];
3223
- const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
3228
+ const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
3224
3229
  for (const slice of slices) {
3225
3230
  const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath, { contextModeRenderMode: "nested" });
3226
3231
  subagentSections.push([
@@ -3242,7 +3247,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
3242
3247
  subagentPrompts: subagentSections.join("\n\n---\n\n"),
3243
3248
  });
3244
3249
  }
3245
- export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base, subagentModel) {
3250
+ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base, subagentModel, subagentThinking) {
3246
3251
  // Pull only the gates this turn actually owns (Q3/Q4). Filter via the
3247
3252
  // registry so that scope:"slice" gates owned by other turns (Q8) can't
3248
3253
  // leak into this prompt and can't block dispatch via silent skip.
@@ -3291,7 +3296,7 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base,
3291
3296
  "- `rationale`: one-sentence justification",
3292
3297
  "- `findings`: detailed markdown findings (or empty if omitted)",
3293
3298
  ].join("\n");
3294
- const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
3299
+ const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
3295
3300
  subagentSections.push([
3296
3301
  `### ${def.id}: ${def.question}`,
3297
3302
  "",
@@ -14,7 +14,7 @@ import { appendEvent } from "./workflow-events.js";
14
14
  import { atomicWriteSync } from "./atomic-write.js";
15
15
  import { clearParseCache } from "./files.js";
16
16
  import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
17
- import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus, insertSlice, getMilestone, getMilestoneSlices, getLatestAssessmentByScope, updateMilestoneStatus, refreshOpenDatabaseFromDisk, transaction } from "./gsd-db.js";
17
+ import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGatesForTurn, updateTaskStatus, updateSliceStatus, insertSlice, getMilestone, getMilestoneSlices, getLatestAssessmentByScope, updateMilestoneStatus, refreshOpenDatabaseFromDisk, transaction, } from "./gsd-db.js";
18
18
  import { isValidationTerminal } from "./state.js";
19
19
  import { getErrorMessage } from "./error-utils.js";
20
20
  import { logWarning, logError } from "./workflow-logger.js";
@@ -329,7 +329,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
329
329
  if (gateIds.length === 0)
330
330
  return true;
331
331
  try {
332
- const pending = getPendingGates(mid, sid, "slice");
332
+ if (!isDbAvailable())
333
+ return false;
334
+ const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
333
335
  const pendingIds = new Set(pending.map((g) => g.gate_id));
334
336
  // All dispatched gates must no longer be pending
335
337
  for (const gid of gateIds) {
@@ -41,3 +41,6 @@ export function clearToolInvocationError() {
41
41
  return;
42
42
  autoSession.lastToolInvocationError = null;
43
43
  }
44
+ export function getSourceObservationStore() {
45
+ return autoSession.sourceObservations;
46
+ }
@@ -1208,7 +1208,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
1208
1208
  s.autoStartTime = Date.now();
1209
1209
  s.resourceVersionOnStart = readResourceVersion();
1210
1210
  s.pendingQuickTasks = [];
1211
- s.currentUnit = null;
1211
+ s.clearCurrentUnit();
1212
1212
  s.currentMilestoneId ??=
1213
1213
  strandedRecoveryAction?.milestoneId ??
1214
1214
  (deepProjectStagePending ? null : state.activeMilestone?.id ?? null);
@@ -822,7 +822,7 @@ export async function cleanupAfterLoopExit(ctx) {
822
822
  const preserveStepSurface = s.preserveStepSurfaceAfterLoopExit;
823
823
  const preserveCompletionSurface = s.completionStopInProgress;
824
824
  const preservePausedSurface = s.paused;
825
- s.currentUnit = null;
825
+ s.clearCurrentUnit();
826
826
  s.active = false;
827
827
  deactivateGSD();
828
828
  clearUnitTimeout();
@@ -847,12 +847,15 @@ export async function cleanupAfterLoopExit(ctx) {
847
847
  // A transient provider-error pause intentionally leaves the paused badge
848
848
  // visible so the user still has a resumable auto-mode signal on screen.
849
849
  if (!s.paused) {
850
- if (preserveStepSurface) {
851
- s.preserveStepSurfaceAfterLoopExit = false;
852
- }
853
- else if (preserveCompletionSurface) {
850
+ if (preserveCompletionSurface) {
854
851
  ctx.ui.setStatus("gsd-auto", undefined);
855
852
  s.completionStopInProgress = false;
853
+ if (preserveStepSurface) {
854
+ s.preserveStepSurfaceAfterLoopExit = false;
855
+ }
856
+ }
857
+ else if (preserveStepSurface) {
858
+ s.preserveStepSurfaceAfterLoopExit = false;
856
859
  }
857
860
  else {
858
861
  ctx.ui.setStatus("gsd-auto", undefined);
@@ -1492,7 +1495,7 @@ export async function pauseAuto(ctx, _pi, _errorContext, options = {}) {
1492
1495
  // Non-fatal — best-effort closeout on pause
1493
1496
  logWarning("engine", `unit closeout on pause failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1494
1497
  }
1495
- s.currentUnit = null;
1498
+ s.clearCurrentUnit();
1496
1499
  }
1497
1500
  // Keep STATE.md aligned with the DB-backed state before releasing pause state.
1498
1501
  // Without this, an interrupted deep run can leave STATE.md saying "no active
@@ -2627,7 +2630,7 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
2627
2630
  s.stepMode = true;
2628
2631
  s.cmdCtx = ctx;
2629
2632
  s.autoStartTime = Date.now();
2630
- s.currentUnit = null;
2633
+ s.clearCurrentUnit();
2631
2634
  s.pendingQuickTasks = [];
2632
2635
  }
2633
2636
  // ADR-016 phase 2 / B2 (#5620): hook-trigger basePath transition. Treats
@@ -2641,23 +2644,23 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
2641
2644
  }
2642
2645
  const hookUnitType = `hook/${hookName}`;
2643
2646
  const hookStartedAt = Date.now();
2644
- s.currentUnit = {
2647
+ s.setCurrentUnit({
2645
2648
  type: triggerUnitType,
2646
2649
  id: triggerUnitId,
2647
2650
  startedAt: hookStartedAt,
2648
2651
  workspaceRoot: s.basePath,
2649
- };
2652
+ });
2650
2653
  const result = await s.cmdCtx.newSession({ workspaceRoot: s.basePath });
2651
2654
  if (result.cancelled) {
2652
2655
  await stopAuto(ctx, pi);
2653
2656
  return false;
2654
2657
  }
2655
- s.currentUnit = {
2658
+ s.setCurrentUnit({
2656
2659
  type: hookUnitType,
2657
2660
  id: triggerUnitId,
2658
2661
  startedAt: hookStartedAt,
2659
2662
  workspaceRoot: s.basePath,
2660
- };
2663
+ });
2661
2664
  if (hookModel) {
2662
2665
  const availableModels = ctx.modelRegistry.getAvailable();
2663
2666
  const match = resolveModelId(hookModel, availableModels, ctx.model?.provider);
@@ -664,7 +664,7 @@ export function registerDbTools(pi) {
664
664
  files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
665
665
  verify: Type.String({ description: "Verification command or block" }),
666
666
  inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
667
- expectedOutput: Type.Array(Type.String(), { description: "Array<string> of expected output files or artifacts; pass [\"path\"] or [], never a single string" }),
667
+ expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
668
668
  observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
669
669
  }), { description: "Planned tasks for the slice" }),
670
670
  // ── Enrichment metadata (optional — defaults to empty) ────────────
@@ -740,7 +740,7 @@ export function registerDbTools(pi) {
740
740
  files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
741
741
  verify: Type.String({ description: "Verification command or block" }),
742
742
  inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
743
- expectedOutput: Type.Array(Type.String(), { description: "Array<string> of expected output files or artifacts; pass [\"path\"] or [], never a single string" }),
743
+ expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
744
744
  observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
745
745
  // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
746
746
  actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
@@ -1069,7 +1069,7 @@ export function registerDbTools(pi) {
1069
1069
  files: Type.Array(Type.String(), { description: "Files likely touched" }),
1070
1070
  verify: Type.String({ description: "Verification command or block" }),
1071
1071
  inputs: Type.Array(Type.String(), { description: "Input files or references" }),
1072
- expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
1072
+ expectedOutput: Type.Array(Type.String(), { description: "Files this task creates or overwrites" }),
1073
1073
  }), { description: "Tasks to upsert (update existing or insert new)" }),
1074
1074
  removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }),
1075
1075
  // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.