@sqdr2/dsh-agent-studio-fusion 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/CHANGELOG.md +629 -0
  2. package/INSTALL.md +72 -0
  3. package/INSTALL.zh.md +73 -0
  4. package/LICENSE +201 -0
  5. package/README.en.md +207 -0
  6. package/README.md +207 -2
  7. package/RELEASING.md +136 -0
  8. package/RELEASING.zh.md +128 -0
  9. package/assets/icon.svg +10 -0
  10. package/assets/mermaid.min.js +3636 -0
  11. package/contracts/fusion.ts +422 -0
  12. package/contracts/storage.sql +86 -0
  13. package/cordis.patch.yml +3 -0
  14. package/docs/ATTRIBUTION-ACP.md +117 -0
  15. package/docs/ATTRIBUTION-AGY.md +139 -0
  16. package/docs/COMPATIBILITY.md +242 -0
  17. package/docs/EVIDENCE.md +141 -0
  18. package/docs/MIGRATION-ACP.md +195 -0
  19. package/docs/MIGRATION-AGY.md +282 -0
  20. package/dshx.yml +58 -0
  21. package/lib/assets/mermaid.min.js +3636 -0
  22. package/lib/bridge.mjs +138 -0
  23. package/lib/client.js +7130 -0
  24. package/lib/client.js.map +7 -0
  25. package/lib/dsh-agent-studio-fusion.js +26686 -0
  26. package/lib/types/activity.d.ts +34 -0
  27. package/lib/types/approval/logical.d.ts +10 -0
  28. package/lib/types/benchmark/naive.d.ts +37 -0
  29. package/lib/types/benchmark/native-run.d.ts +68 -0
  30. package/lib/types/benchmark/output-limits.d.ts +19 -0
  31. package/lib/types/bilingual.d.ts +2 -0
  32. package/lib/types/client/AcpSettingsGuide.d.ts +15 -0
  33. package/lib/types/client/ActivityRows.d.ts +8 -0
  34. package/lib/types/client/FusionCache.d.ts +4 -0
  35. package/lib/types/client/FusionHint.d.ts +9 -0
  36. package/lib/types/client/FusionHistory.d.ts +7 -0
  37. package/lib/types/client/FusionPanelIcon.d.ts +13 -0
  38. package/lib/types/client/FusionPermission.d.ts +15 -0
  39. package/lib/types/client/FusionRecovery.d.ts +5 -0
  40. package/lib/types/client/FusionSettings.d.ts +17 -0
  41. package/lib/types/client/FusionStatus.d.ts +12 -0
  42. package/lib/types/client/FusionTool.d.ts +4 -0
  43. package/lib/types/client/acp-import.d.ts +82 -0
  44. package/lib/types/client/activity-model.d.ts +14 -0
  45. package/lib/types/client/agy/AgyConsole.d.ts +42 -0
  46. package/lib/types/client/agy/brand-icons.d.ts +34 -0
  47. package/lib/types/client/agy/decisions.d.ts +23 -0
  48. package/lib/types/client/agy/images.d.ts +13 -0
  49. package/lib/types/client/agy/locale.d.ts +26 -0
  50. package/lib/types/client/agy/locales.d.ts +174 -0
  51. package/lib/types/client/agy/scroll-guard.d.ts +24 -0
  52. package/lib/types/client/agy/toolview.d.ts +169 -0
  53. package/lib/types/client/agy-activity.d.ts +49 -0
  54. package/lib/types/client/i18n.d.ts +15 -0
  55. package/lib/types/client/index.d.ts +22 -0
  56. package/lib/types/client/settings-events.d.ts +2 -0
  57. package/lib/types/client/status-polling.d.ts +13 -0
  58. package/lib/types/client/studio-brand.d.ts +12 -0
  59. package/lib/types/context/guard.d.ts +21 -0
  60. package/lib/types/context/handoff.d.ts +17 -0
  61. package/lib/types/contracts.d.ts +494 -0
  62. package/lib/types/digest.d.ts +5 -0
  63. package/lib/types/dsh-agent-studio-fusion.d.ts +27 -0
  64. package/lib/types/dsh-fusion.d.ts +1 -0
  65. package/lib/types/errors.d.ts +28 -0
  66. package/lib/types/evidence/gate.d.ts +23 -0
  67. package/lib/types/evidence/receipts.d.ts +65 -0
  68. package/lib/types/execution/write-lease.d.ts +42 -0
  69. package/lib/types/host/acp/adapter.d.ts +107 -0
  70. package/lib/types/host/acp/agent-process.d.ts +126 -0
  71. package/lib/types/host/acp/bridge-route.d.ts +13 -0
  72. package/lib/types/host/acp/bridge.d.ts +149 -0
  73. package/lib/types/host/acp/chunk-translator.d.ts +29 -0
  74. package/lib/types/host/acp/config.d.ts +21 -0
  75. package/lib/types/host/acp/context-windows.d.ts +32 -0
  76. package/lib/types/host/acp/host.d.ts +41 -0
  77. package/lib/types/host/acp/index.d.ts +33 -0
  78. package/lib/types/host/acp/permission.d.ts +28 -0
  79. package/lib/types/host/acp/prompt-capabilities.d.ts +35 -0
  80. package/lib/types/host/acp/request-image.d.ts +32 -0
  81. package/lib/types/host/acp/transcript.d.ts +33 -0
  82. package/lib/types/host/acp/types.d.ts +54 -0
  83. package/lib/types/host/agy/adapter.d.ts +347 -0
  84. package/lib/types/host/agy/agy-db.d.ts +67 -0
  85. package/lib/types/host/agy/agy-log.d.ts +13 -0
  86. package/lib/types/host/agy/agy-usage.d.ts +52 -0
  87. package/lib/types/host/agy/ask-tool.d.ts +7 -0
  88. package/lib/types/host/agy/atomic-write.d.ts +4 -0
  89. package/lib/types/host/agy/auth.d.ts +49 -0
  90. package/lib/types/host/agy/auto-updater.d.ts +38 -0
  91. package/lib/types/host/agy/commands.d.ts +39 -0
  92. package/lib/types/host/agy/config.d.ts +37 -0
  93. package/lib/types/host/agy/credential-slot.d.ts +252 -0
  94. package/lib/types/host/agy/diagnostics.d.ts +19 -0
  95. package/lib/types/host/agy/discovery.d.ts +21 -0
  96. package/lib/types/host/agy/dsh-goal.d.ts +43 -0
  97. package/lib/types/host/agy/index.d.ts +13 -0
  98. package/lib/types/host/agy/mapper.d.ts +145 -0
  99. package/lib/types/host/agy/mcp-bridge.d.ts +72 -0
  100. package/lib/types/host/agy/media-route.d.ts +23 -0
  101. package/lib/types/host/agy/media.d.ts +54 -0
  102. package/lib/types/host/agy/mirror-tool.d.ts +60 -0
  103. package/lib/types/host/agy/models.d.ts +90 -0
  104. package/lib/types/host/agy/net.d.ts +10 -0
  105. package/lib/types/host/agy/oauth.d.ts +77 -0
  106. package/lib/types/host/agy/oneshot.d.ts +35 -0
  107. package/lib/types/host/agy/parser.d.ts +42 -0
  108. package/lib/types/host/agy/pool-auth.d.ts +70 -0
  109. package/lib/types/host/agy/pool-types.d.ts +145 -0
  110. package/lib/types/host/agy/pool.d.ts +231 -0
  111. package/lib/types/host/agy/quota.d.ts +352 -0
  112. package/lib/types/host/agy/read-json-body.d.ts +15 -0
  113. package/lib/types/host/agy/recording.d.ts +199 -0
  114. package/lib/types/host/agy/runner.d.ts +192 -0
  115. package/lib/types/host/agy/sessions.d.ts +53 -0
  116. package/lib/types/host/agy/types.d.ts +425 -0
  117. package/lib/types/host/agy/warmup.d.ts +82 -0
  118. package/lib/types/host/agy/wincred.d.ts +35 -0
  119. package/lib/types/host/authority.d.ts +50 -0
  120. package/lib/types/host/bindings.d.ts +30 -0
  121. package/lib/types/host/cache-defaults.d.ts +48 -0
  122. package/lib/types/host/cache-policy.d.ts +165 -0
  123. package/lib/types/host/change-evidence.d.ts +38 -0
  124. package/lib/types/host/compaction-routing.d.ts +15 -0
  125. package/lib/types/host/coordinator.d.ts +222 -0
  126. package/lib/types/host/evidence-page.d.ts +13 -0
  127. package/lib/types/host/history.d.ts +106 -0
  128. package/lib/types/host/http.d.ts +4 -0
  129. package/lib/types/host/model-output.d.ts +13 -0
  130. package/lib/types/host/native-activity.d.ts +26 -0
  131. package/lib/types/host/native-approvals.d.ts +29 -0
  132. package/lib/types/host/native-auxiliary.d.ts +17 -0
  133. package/lib/types/host/native-budget.d.ts +33 -0
  134. package/lib/types/host/native-checks.d.ts +130 -0
  135. package/lib/types/host/native-compaction.d.ts +8 -0
  136. package/lib/types/host/native-context.d.ts +36 -0
  137. package/lib/types/host/native-effects.d.ts +120 -0
  138. package/lib/types/host/native-evidence.d.ts +4 -0
  139. package/lib/types/host/native-exploration.d.ts +15 -0
  140. package/lib/types/host/native-keepalive.d.ts +82 -0
  141. package/lib/types/host/native-model-control.d.ts +124 -0
  142. package/lib/types/host/native-on-demand-context.d.ts +39 -0
  143. package/lib/types/host/native-request.d.ts +5 -0
  144. package/lib/types/host/native-review.d.ts +11 -0
  145. package/lib/types/host/native-role-sandbox.d.ts +57 -0
  146. package/lib/types/host/native-scopes.d.ts +70 -0
  147. package/lib/types/host/native-selection.d.ts +39 -0
  148. package/lib/types/host/native-task-context.d.ts +39 -0
  149. package/lib/types/host/native-usage.d.ts +46 -0
  150. package/lib/types/host/native-worker-brief.d.ts +74 -0
  151. package/lib/types/host/native-worker-notices.d.ts +15 -0
  152. package/lib/types/host/native-worker.d.ts +44 -0
  153. package/lib/types/host/native-workflow.d.ts +41 -0
  154. package/lib/types/host/pairs.d.ts +47 -0
  155. package/lib/types/host/price-settings.d.ts +14 -0
  156. package/lib/types/host/read-tools.d.ts +22 -0
  157. package/lib/types/host/route-transport.d.ts +22 -0
  158. package/lib/types/host/settings.d.ts +58 -0
  159. package/lib/types/host/shell.d.ts +37 -0
  160. package/lib/types/host/status.d.ts +7 -0
  161. package/lib/types/host/subagent-seam.d.ts +11 -0
  162. package/lib/types/host/text-report.d.ts +56 -0
  163. package/lib/types/host/tool-table.d.ts +35 -0
  164. package/lib/types/host/worker-terminal.d.ts +94 -0
  165. package/lib/types/host/workspace-guard.d.ts +13 -0
  166. package/lib/types/host/workspace.d.ts +52 -0
  167. package/lib/types/identity.d.ts +82 -0
  168. package/lib/types/index.d.ts +34 -0
  169. package/lib/types/message-source.d.ts +35 -0
  170. package/lib/types/profile/compactor.d.ts +5 -0
  171. package/lib/types/profile/keepalive.d.ts +3 -0
  172. package/lib/types/profile/resolve.d.ts +17 -0
  173. package/lib/types/prompts.d.ts +8 -0
  174. package/lib/types/recovery/reconcile.d.ts +28 -0
  175. package/lib/types/review/dispatch.d.ts +20 -0
  176. package/lib/types/review/protocol.d.ts +51 -0
  177. package/lib/types/review/ticket.d.ts +32 -0
  178. package/lib/types/status.d.ts +145 -0
  179. package/lib/types/store-migration.d.ts +29 -0
  180. package/lib/types/task/deletion.d.ts +64 -0
  181. package/lib/types/task/reducer.d.ts +6 -0
  182. package/lib/types/task/sqlite-store.d.ts +71 -0
  183. package/lib/types/task/state.d.ts +51 -0
  184. package/lib/types/task/status-index.d.ts +28 -0
  185. package/lib/types/task/store.d.ts +48 -0
  186. package/lib/types/usage/budget.d.ts +27 -0
  187. package/lib/types/usage/cost.d.ts +77 -0
  188. package/lib/types/usage/ledger.d.ts +66 -0
  189. package/lib/types/usage/normalize.d.ts +50 -0
  190. package/lib/types/usage/price-cards.d.ts +65 -0
  191. package/lib/types/usage/pricing.d.ts +18 -0
  192. package/package.json +197 -4
  193. package/profiles/fusion-auto.example.json +45 -0
  194. package/prompts/compact.md +7 -0
  195. package/prompts/lead.md +52 -0
  196. package/prompts/model-lead.md +16 -0
  197. package/prompts/model-worker.md +9 -0
  198. package/prompts/worker.md +25 -0
  199. package/src/activity.ts +78 -0
  200. package/src/approval/logical.ts +44 -0
  201. package/src/benchmark/naive.ts +216 -0
  202. package/src/benchmark/native-run.ts +215 -0
  203. package/src/benchmark/output-limits.ts +33 -0
  204. package/src/bilingual.ts +2 -0
  205. package/src/client/AcpSettingsGuide.tsx +469 -0
  206. package/src/client/ActivityRows.tsx +73 -0
  207. package/src/client/FusionCache.tsx +130 -0
  208. package/src/client/FusionHint.tsx +46 -0
  209. package/src/client/FusionHistory.tsx +260 -0
  210. package/src/client/FusionPanelIcon.tsx +39 -0
  211. package/src/client/FusionPermission.tsx +52 -0
  212. package/src/client/FusionRecovery.tsx +69 -0
  213. package/src/client/FusionSettings.tsx +362 -0
  214. package/src/client/FusionStatus.tsx +138 -0
  215. package/src/client/FusionTool.tsx +66 -0
  216. package/src/client/acp-import.ts +303 -0
  217. package/src/client/activity-model.ts +31 -0
  218. package/src/client/agy/AgyConsole.tsx +2213 -0
  219. package/src/client/agy/brand-icons.ts +43 -0
  220. package/src/client/agy/decisions.ts +344 -0
  221. package/src/client/agy/images.ts +605 -0
  222. package/src/client/agy/locale.ts +75 -0
  223. package/src/client/agy/locales.ts +332 -0
  224. package/src/client/agy/scroll-guard.ts +106 -0
  225. package/src/client/agy/toolview.ts +1903 -0
  226. package/src/client/agy-activity.ts +174 -0
  227. package/src/client/i18n.ts +30 -0
  228. package/src/client/index.ts +89 -0
  229. package/src/client/settings-events.ts +3 -0
  230. package/src/client/status-polling.ts +93 -0
  231. package/src/client/studio-brand.ts +13 -0
  232. package/src/context/guard.ts +81 -0
  233. package/src/context/handoff.ts +28 -0
  234. package/src/contracts.ts +489 -0
  235. package/src/digest.ts +28 -0
  236. package/src/dsh-agent-studio-fusion.ts +480 -0
  237. package/src/dsh-fusion.ts +1 -0
  238. package/src/errors.ts +34 -0
  239. package/src/evidence/gate.ts +290 -0
  240. package/src/evidence/receipts.ts +175 -0
  241. package/src/execution/write-lease.ts +187 -0
  242. package/src/host/acp/adapter.ts +692 -0
  243. package/src/host/acp/agent-process.ts +621 -0
  244. package/src/host/acp/bridge-route.ts +29 -0
  245. package/src/host/acp/bridge.ts +601 -0
  246. package/src/host/acp/chunk-translator.ts +200 -0
  247. package/src/host/acp/config.ts +57 -0
  248. package/src/host/acp/context-windows.ts +89 -0
  249. package/src/host/acp/host.ts +43 -0
  250. package/src/host/acp/index.ts +186 -0
  251. package/src/host/acp/permission.ts +129 -0
  252. package/src/host/acp/prompt-capabilities.ts +112 -0
  253. package/src/host/acp/request-image.ts +68 -0
  254. package/src/host/acp/transcript.ts +200 -0
  255. package/src/host/acp/types.ts +58 -0
  256. package/src/host/agy/adapter.ts +2790 -0
  257. package/src/host/agy/agy-db.ts +682 -0
  258. package/src/host/agy/agy-log.ts +81 -0
  259. package/src/host/agy/agy-usage.ts +253 -0
  260. package/src/host/agy/ask-tool.ts +141 -0
  261. package/src/host/agy/atomic-write.ts +35 -0
  262. package/src/host/agy/auth.ts +267 -0
  263. package/src/host/agy/auto-updater.ts +127 -0
  264. package/src/host/agy/bridge.mjs +138 -0
  265. package/src/host/agy/commands.ts +628 -0
  266. package/src/host/agy/config.ts +261 -0
  267. package/src/host/agy/credential-slot.ts +1326 -0
  268. package/src/host/agy/diagnostics.ts +118 -0
  269. package/src/host/agy/discovery.ts +71 -0
  270. package/src/host/agy/dsh-goal.ts +248 -0
  271. package/src/host/agy/index.ts +1279 -0
  272. package/src/host/agy/mapper.ts +593 -0
  273. package/src/host/agy/mcp-bridge.ts +450 -0
  274. package/src/host/agy/media-route.ts +247 -0
  275. package/src/host/agy/media.ts +163 -0
  276. package/src/host/agy/mirror-tool.ts +756 -0
  277. package/src/host/agy/models.ts +404 -0
  278. package/src/host/agy/net.ts +54 -0
  279. package/src/host/agy/oauth.ts +366 -0
  280. package/src/host/agy/oneshot.ts +198 -0
  281. package/src/host/agy/parser.ts +330 -0
  282. package/src/host/agy/pool-auth.ts +304 -0
  283. package/src/host/agy/pool-types.ts +204 -0
  284. package/src/host/agy/pool.ts +1050 -0
  285. package/src/host/agy/quota.ts +1420 -0
  286. package/src/host/agy/read-json-body.ts +70 -0
  287. package/src/host/agy/recording.ts +447 -0
  288. package/src/host/agy/runner.ts +830 -0
  289. package/src/host/agy/sessions.ts +153 -0
  290. package/src/host/agy/types.ts +657 -0
  291. package/src/host/agy/warmup.ts +614 -0
  292. package/src/host/agy/wincred.ts +354 -0
  293. package/src/host/authority.ts +231 -0
  294. package/src/host/bindings.ts +91 -0
  295. package/src/host/cache-defaults.ts +103 -0
  296. package/src/host/cache-policy.ts +180 -0
  297. package/src/host/change-evidence.ts +156 -0
  298. package/src/host/compaction-routing.ts +46 -0
  299. package/src/host/coordinator.ts +2675 -0
  300. package/src/host/evidence-page.ts +25 -0
  301. package/src/host/history.ts +180 -0
  302. package/src/host/http.ts +30 -0
  303. package/src/host/model-output.ts +22 -0
  304. package/src/host/native-activity.ts +205 -0
  305. package/src/host/native-approvals.ts +196 -0
  306. package/src/host/native-auxiliary.ts +19 -0
  307. package/src/host/native-budget.ts +112 -0
  308. package/src/host/native-checks.ts +562 -0
  309. package/src/host/native-compaction.ts +34 -0
  310. package/src/host/native-context.ts +204 -0
  311. package/src/host/native-effects.ts +379 -0
  312. package/src/host/native-evidence.ts +31 -0
  313. package/src/host/native-exploration.ts +114 -0
  314. package/src/host/native-keepalive.ts +292 -0
  315. package/src/host/native-model-control.ts +343 -0
  316. package/src/host/native-on-demand-context.ts +74 -0
  317. package/src/host/native-request.ts +12 -0
  318. package/src/host/native-review.ts +51 -0
  319. package/src/host/native-role-sandbox.ts +183 -0
  320. package/src/host/native-scopes.ts +255 -0
  321. package/src/host/native-selection.ts +154 -0
  322. package/src/host/native-task-context.ts +264 -0
  323. package/src/host/native-usage.ts +121 -0
  324. package/src/host/native-worker-brief.ts +135 -0
  325. package/src/host/native-worker-notices.ts +72 -0
  326. package/src/host/native-worker.ts +215 -0
  327. package/src/host/native-workflow.ts +103 -0
  328. package/src/host/pairs.ts +180 -0
  329. package/src/host/price-settings.ts +27 -0
  330. package/src/host/read-tools.ts +34 -0
  331. package/src/host/route-transport.ts +54 -0
  332. package/src/host/settings.ts +126 -0
  333. package/src/host/shell.ts +42 -0
  334. package/src/host/status.ts +181 -0
  335. package/src/host/subagent-seam.ts +21 -0
  336. package/src/host/text-report.ts +124 -0
  337. package/src/host/tool-table.ts +56 -0
  338. package/src/host/worker-terminal.ts +145 -0
  339. package/src/host/workspace-guard.ts +17 -0
  340. package/src/host/workspace.ts +184 -0
  341. package/src/identity.ts +117 -0
  342. package/src/index.ts +50 -0
  343. package/src/message-source.ts +33 -0
  344. package/src/profile/compactor.ts +26 -0
  345. package/src/profile/keepalive.ts +13 -0
  346. package/src/profile/resolve.ts +131 -0
  347. package/src/prompts.ts +32 -0
  348. package/src/recovery/reconcile.ts +38 -0
  349. package/src/review/dispatch.ts +48 -0
  350. package/src/review/protocol.ts +212 -0
  351. package/src/review/ticket.ts +166 -0
  352. package/src/status.ts +113 -0
  353. package/src/store-migration.ts +65 -0
  354. package/src/task/deletion.ts +105 -0
  355. package/src/task/reducer.ts +684 -0
  356. package/src/task/sqlite-store.ts +386 -0
  357. package/src/task/state.ts +72 -0
  358. package/src/task/status-index.ts +198 -0
  359. package/src/task/store.ts +287 -0
  360. package/src/usage/budget.ts +88 -0
  361. package/src/usage/cost.ts +194 -0
  362. package/src/usage/ledger.ts +218 -0
  363. package/src/usage/normalize.ts +308 -0
  364. package/src/usage/price-cards.ts +122 -0
  365. package/src/usage/pricing.ts +95 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,629 @@
1
+ # Changelog
2
+
3
+ Release notes for `@sqdr2/dsh-agent-studio-fusion` (published as `@sqdr2/dsh-fusion` up to 0.3.9). Newest first.
4
+
5
+ ## Origin
6
+
7
+ This package is a fork of [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion). 0.3.0 is the
8
+ first release published under this fork, and it branches from upstream 0.2.9. Upstream 0.2.10 and 0.2.11 landed after
9
+ that point and are **not** included here.
10
+
11
+ **The name changed at 1.0.0.** Versions 0.3.0 through 0.3.9 were published as `@sqdr2/dsh-fusion`. From 1.0.0 the
12
+ package is `@sqdr2/dsh-agent-studio-fusion` and the plugin id is `dsh-agent-studio-fusion`. The 0.4.x line was never
13
+ published: it exists only in this repository's history, and 1.0.0 is its first release. Upgrading from a
14
+ `@sqdr2/dsh-fusion` install migrates the state directory automatically; see [`INSTALL.md`](INSTALL.md).
15
+
16
+ Earlier versions — `dsh-model-fusion` 0.2.0 through 0.2.11, and the pre-0.3.0 tags in this repository's history — were
17
+ not published as `@sqdr2/dsh-fusion`, so they are not listed here. Their notes live in the upstream repository, under its
18
+ own tags and releases.
19
+
20
+ Entry format: what changed, then what was actually validated. "Not claimed" lines mark what a release did *not* test —
21
+ read them before assuming a platform is covered.
22
+
23
+ ## 1.0.0 — 2026-11-13
24
+
25
+ ### Naming and upgrade
26
+ - **The package is now `@sqdr2/dsh-agent-studio-fusion`, plugin id `dsh-agent-studio-fusion`.** 1.0.0 is the first
27
+ release of that name and the first release after 0.3.9; the 0.4.x and 0.5.x numbers existed only in this
28
+ repository. `@sqdr2/dsh-fusion` stays on npm at 0.3.9 and is not updated again.
29
+ - What the rename does **not** touch: the `dsh-fusion` provider route, the `auto`/`pair-*` model ids, the `/api/fusion`
30
+ path and the `Fusion · <name>` model-menu label. An existing conversation keeps its combo.
31
+ - What moves: the state directory becomes `$DSH_HOME/plugins/dsh-agent-studio-fusion/`. `dsh-fusion`,
32
+ `dsh-model-fusion` and `dsh-agent-studio` directories are adopted on first start
33
+ (`src/dsh-agent-studio-fusion.ts`), along with the whole ledger inside them.
34
+ - Message sources are now written as `plugin:dsh-agent-studio-fusion`. The three older kinds stay readable through
35
+ `isFusionSourceKind`, so context restored into a session started under an older name is still matched.
36
+ - `docs/MIGRATION-AGY.md` and `docs/MIGRATION-ACP.md` now use the current row id in their copy-paste blocks; they had
37
+ still named `- id: dsh-fusion` / `name: '@sqdr2/dsh-fusion'`, which the loader no longer matches.
38
+
39
+ ### Client
40
+ - **The Fusion panel becomes the combined studio page**, titled `DSH Agent Studio With Fusion` (one constant,
41
+ `src/client/studio-brand.ts`). The sidebar row keeps its short label `Fusion` and the panel id stays `fusion`; the
42
+ provider route and model ids are unchanged (see the Naming section above for what did move), and no Harness-wide
43
+ branding slot is claimed — `sidebar.brand.mark` / `sidebar.brand.name` are deliberately left to the official brand
44
+ plugin.
45
+ - The page has three labelled section buttons — **Fusion combos** (default), **Antigravity**, **ACP routes** — as a
46
+ `<nav>` of plain buttons with `aria-pressed` and `aria-controls`, not `role="tab"`: no roving tabindex or arrow-key
47
+ focus management is implemented, so the page does not claim tab semantics. All three regions are always in the
48
+ document (so every `aria-controls` resolves) and are toggled with `hidden`; only their contents mount on demand.
49
+ - **Section state preservation is deliberate and asymmetric.** The Fusion region is hidden, never unmounted, so unsaved
50
+ combo edits and the selected row survive a round trip through another section. The Antigravity console *is* mounted
51
+ only while selected, because it starts a 3s status poll and reads the account pool on mount. Regression coverage:
52
+ `tests/fusion-brand.spec.ts`.
53
+ - The pairing explanation moved out of the page header into the Fusion section, and the header now describes the
54
+ combined workspace in one bilingual sentence.
55
+ - **New ACP section** (`src/client/AcpSettingsGuide.tsx`): an honest setup guide. It shows a minimal valid plugin entry
56
+ (`id`/`name` plus `acp.agents`), and states the real field rules: `command` is required and an absolute path is only
57
+ *more reliable* (a PATH command works — the route is spawned directly), `args` may be empty, and `models` may be
58
+ omitted entirely, in which case `discoverModels` asks the agent and the `default` model is the fallback. It also notes
59
+ the restart requirement, that configured routes then appear in the native and Fusion model selectors, and that an
60
+ existing `dsh-tauri-acp` must be disabled first. It offers **no** route list, model discovery, live status or save
61
+ control — the upstream configuration editor is still not ported, and
62
+ [`docs/ATTRIBUTION-ACP.md`](docs/ATTRIBUTION-ACP.md) now says so explicitly.
63
+ - `assets/icon.svg` is shipped (relative, in-package, under the 256 KiB cap) and declared as `icon` plus a `./icon`
64
+ export, so the Plugins page shows the Fusion convergence mark instead of default artwork.
65
+ - The package description now leads with the product name: `DSH Agent Studio With Fusion: one plugin for DeepSeek
66
+ Assistant, …`. No version bump.
67
+
68
+ ### Docs
69
+ - [`docs/MIGRATION-ACP.md`](docs/MIGRATION-ACP.md) (Chinese + English): manual disable/remove of `dsh-tauri-acp`, the
70
+ move into `acp.agents`, the restart requirement, and what is and is not preserved. It claims no release history (this
71
+ ACP integration is still unreleased) and states exactly one **verified** conflict — one provider route name registered
72
+ twice is refused with `DUPLICATE_ADAPTER`. Fusion's own `/api/fusion/acp-mcp` bridge is described as Fusion-specific
73
+ hardening, not as something inherited from upstream.
74
+ - [`docs/MIGRATION-AGY.md`](docs/MIGRATION-AGY.md): console location updated to the new **Antigravity** section, and the
75
+ account-pool row now says the copy is needed when the two resolved roots differ — whichever of `DSH_HOME` /
76
+ `DSH_STATE_DIR` was relocated.
77
+ - `README.md`, `README.en.md`, `INSTALL.md`, `INSTALL.zh.md`: new titles and openings describing one integrated plugin,
78
+ and no remaining claim that `dsh-agy-worker` or `dsh-tauri-acp` has to be installed separately.
79
+
80
+ ### Validation
81
+ - `pnpm typecheck` clean on Node 24.13.0.
82
+ - `pnpm test` 646 passed in 75 files, including `tests/fusion-brand.spec.ts` (page structure, draft preservation, lazy mounting, plus a
83
+ package-icon/metadata check and a client-`apply` check that exactly one `main`/`sidebar.panellist` entry is registered,
84
+ labelled `Fusion`, with no `sidebar.brand.*` claim) and the adapted `tests/fusion-settings-agy.spec.ts`.
85
+ - `DSHX_HARNESS=… pnpm test:host` 300 passed, 1 skipped, including `native-tests/agy-process.spec.ts`. The literal
86
+ `plugin:dsh-fusion` source-kind assertions in `native-tests/coordinator.spec.ts` and `native-tests/context.spec.ts`
87
+ were still pinning the pre-rename kind, so 15 of those cases failed against the renamed producer; they now use
88
+ `isFusionSourceKind`, the same guard the runtime reads with.
89
+ - `pnpm build` regenerates `lib/`.
90
+ - **Offline only.** `native-tests/agy-process.spec.ts` drives the real adapter against the fixture child at
91
+ `native-tests/fixtures/fake-agy.mjs` and replays the recorded step through the production `agy_tool` mirror — with
92
+ every home, state dir and conversations dir redirected into a temp tree, no network, no Google login and no paid
93
+ model call. It is **not** a Fusion-worker end-to-end test: no Lead, no work order, no coordinator. No live install,
94
+ Host restart, profile edit or real `agy` run happened in this stage either, and the GUI on this machine still serves
95
+ the previously published artifacts, so nothing here claims a live deployment or a screenshot.
96
+
97
+ ## 0.4.0 — 2026-11-12
98
+
99
+ ### Runtime
100
+ - **The complete Antigravity (agy CLI) capability is now built in**, ported from
101
+ [`SQDR2/dsh-agy-worker`](https://github.com/SQDR2/dsh-agy-worker) 0.6.3 (`ab49704`) under its MIT license
102
+ ([`docs/ATTRIBUTION-AGY.md`](docs/ATTRIBUTION-AGY.md)). One plugin identity: `installAgy(ctx, config.agy)` replaces the
103
+ upstream entry `apply()` and returns the disposer that unwinds every effect, so a disabled `agy` block (or an unloaded
104
+ plugin) rolls the whole capability back. `cordis.patch.yml` still inserts only `dsh-fusion`.
105
+ - Kept verbatim from upstream: the `antigravity` provider route, the `/agy` command family, `agy_ask` and the `agy_tool`
106
+ mirror (with its `tools/pre-execute` bypass), the full `/plugins/agy-worker/*` HTTP surface (status, auth, pool,
107
+ config, qr, media, assets, mermaid), the account pool and per-account credential isolation, quota polling and weekly
108
+ warmup, media staging and TTL sweep, the doctor report, and the reverse MCP bridge (`src/host/agy/bridge.mjs`, shipped
109
+ as `lib/bridge.mjs`). `src/host/route-transport.ts` is untouched: it already maps `antigravity` → `agy_tool`.
110
+ - Config moved into a `agy` subconfig on this plugin's entry; the layering is unchanged (`DSH_AGY_*` env > runtime
111
+ overrides file > the `agy` block > defaults). `qrcode` and `undici` became runtime dependencies because the build keeps
112
+ bare specifiers external, and `@types/qrcode` joined the dev dependencies.
113
+ - `enabled` is an **install-time** switch, exactly as upstream had it: `enabled: false` mounts no `antigravity` route and
114
+ no background capability (quota polling, warmup, MCP bridge, media sweep), while `/agy` and the
115
+ `/plugins/agy-worker/*` management routes stay mounted for inspection. Neither `/agy` nor `POST /config` accepts
116
+ `enabled` as a settable key, so re-enabling means changing the block and restarting the Host.
117
+ - The `installAgy` disposer now also tears down the two reactive sub-fibers (`tools`, `webServer`) it creates, so
118
+ one call removes the `agy_tool` registration and every `/plugins/agy-worker/*` route — a regression this release's
119
+ native test pins.
120
+ - State: the **work-state path is unchanged** (`$DSH_HOME/agy-worker/` for overrides, session bindings, media cache and
121
+ warmup history), while the **account pool moved** to `$DSH_HOME/agy-accounts/pool.json` (upstream resolved it from
122
+ `DSH_STATE_DIR`, falling back to `~/.dsh`). Nothing migrates user state automatically, edits a profile or uninstalls the
123
+ old package; the one manual copy — needed only when `DSH_STATE_DIR` and `DSH_HOME` name different roots — is in
124
+ [`docs/MIGRATION-AGY.md`](docs/MIGRATION-AGY.md).
125
+
126
+ ### Client
127
+ - **FusionSettings is still the only primary panel and the only sidebar entry.** The Antigravity console is a collapsible
128
+ section at the bottom of that page (`isModal: false`); the standalone plugin's own `main`, `sidebar.panellist`,
129
+ `plugins.bundle.config`, `plugins.row.config` and session-header registrations, its settings-nav icon injector and its
130
+ page-wide mermaid / reasoning / images / decisions / scroll scanners were deliberately not ported.
131
+ - Exactly two keyed `tool.call.toolview` views are registered, as upstream had them: `agy_tool` and `run_code`. The
132
+ `run_code` view recognizes the generated mirror wrapper through `mirrorStepInvocation` — the same strict two-line parser
133
+ Fusion's own activity projection uses — and renders every other Code Mode program as the ordinary code card, so
134
+ `constraints` on plain code rendering hold. Fusion's own activity cards are unchanged.
135
+ - The console's custom properties are declared on `.agy-console` instead of `:root`/`body` (and its overlay marker is
136
+ `agy-console-modal-open`), so the Antigravity palette cannot repaint Fusion's pages.
137
+
138
+ ### Docs
139
+ - [`docs/ATTRIBUTION-AGY.md`](docs/ATTRIBUTION-AGY.md) carries the upstream MIT text, the
140
+ `dsh-agy-link → dsh-agy-worker → this package` chain, what was ported, what changed, and the bundled
141
+ `mermaid.min.js` licenses. [`docs/MIGRATION-AGY.md`](docs/MIGRATION-AGY.md) documents the mandatory manual
142
+ disable/remove of the old package (duplicate route / provider / command / toolview hard-fail) and the manual account
143
+ copy, in Chinese and English. `INSTALL.md`, `INSTALL.zh.md`, `README.md`, `README.en.md` and
144
+ [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) are updated.
145
+
146
+ ### Validation
147
+ - `pnpm typecheck` clean on Node 24.13.0.
148
+ - `pnpm test` 605 passed in 72 files, including new `tests/agy-host-config.spec.ts`, `tests/agy-state-paths.spec.ts`,
149
+ `tests/agy-toolview.spec.ts`, `tests/agy-routes.spec.ts` and `tests/fusion-settings-agy.spec.ts`. The AGY cases run on a
150
+ throwaway `$DSH_HOME`, so no case can create or rewrite a user's real `agy-worker` state.
151
+ - `DSHX_HARNESS=… pnpm test:host` 293 passed, 1 skipped, including the new `native-tests/agy-routes.spec.ts` (5 cases:
152
+ provider/command/route registration against the real registries, the `/status` payload over real HTTP, the `agy_tool`
153
+ mirror in the real tool runtime, full disposer teardown, and the `enabled: false` behaviour).
154
+ - `pnpm build` emits `lib/dsh-fusion.js`, `lib/client.js`, `lib/bridge.mjs` and `lib/assets/mermaid.min.js`.
155
+ The vendored `assets/mermaid.min.js` is byte-identical to upstream (`cmp`-verified) and keeps its own bundled-license
156
+ banner; the 3.4 MiB size tradeoff and how it is packaged are recorded in
157
+ [`docs/ATTRIBUTION-AGY.md`](docs/ATTRIBUTION-AGY.md#size-tradeoff-accepted-decision).
158
+ - **Not claimed:** no live `agy` binary run, no real Google login, no real Worker turn on the `antigravity` route — the
159
+ port is verified structurally (registration/unwinding, config layering, path resolution, tool-card projection) and by
160
+ the existing suites. Windows and macOS were not exercised for this release.
161
+
162
+ ## 0.3.9 — 2026-11-11
163
+
164
+ ### Runtime
165
+ - **A Worker can report while a background process it declared is still running**, instead of stopping it first, and
166
+ the next handoff of the same work order is told what was running. `WorkOrder.preserveRuntime` (opt-in per delegation)
167
+ plus the Worker-only `fusion_declare_runtime` tool record the job's purpose, working directory, a digest of its
168
+ command (never the command text, which can carry a token) and a deadline; `NativeEffects.retain` moves the effect
169
+ row from `dispatch-started` to `retained`, so it no longer blocks `fusion_submit_result` while keeping the
170
+ `processId`/`startedAt` identity that forbids adoption. An undeclared running job still blocks the report, and the
171
+ refusal now names the tool.
172
+ - **This does not keep a server alive across handoffs, and the Host cannot make it so from here.** A Worker's jobs are
173
+ owned by its Agent scope (`tool-bash` registers `owner: exec.agent.id`), and `jobs-local` cancels every job of an
174
+ owner when that scope is disposed (`disposeOwned`), which is what a settled handoff does. Measured on the real Host:
175
+ the declared job settled `killed`, `detail: "signal: SIGTERM"`, within the same handoff; the Worker Agent was already
176
+ gone (`ctx.agents.get(acceptedChild) === undefined`) when the Lead reworked; and `ctx.jobs.get` later threw
177
+ `unknown job`. Real retention needs either job-ownership transfer in `@deepseek-ai/dsh-jobs` or a Host-owned
178
+ launcher, and a launcher would open a second process path that bypasses `tool-bash` approval and the per-session
179
+ sandbox mode — the plugin never widens a sandbox mode, so that half is deliberately not built. Evidence:
180
+ `docs/DEVIN-LOCAL-FUSION.md` §9.
181
+ - **Recovery never adopts a process it did not start.** A `retained` row written by a previous Host process is
182
+ reported by `NativeEffects.strandedRetained` (process id and start time are the only identity), appears as
183
+ `recovery/needed` at install, and `assertInspection` refuses to continue until that process is gone. Completion
184
+ (`accept`), pause, takeover, the deadline and Host shutdown all stop declared runtimes through the existing
185
+ `#stopJobs`.
186
+ - The Lead's fixed tool catalog is unchanged: `fusion_declare_runtime` is offered only inside the Worker's
187
+ implementation order, so the Lead's cached prompt prefix does not move.
188
+ - Tests: `native-tests/coordinator.spec.ts` "retained runtime across handoffs" — a declared job lets the report land
189
+ (journal `retained.purpose`/`deadlineAt`, a `runtime-handle` with a 64-hex `commandDigest` and final state `ended`,
190
+ the next Worker request carrying "Processes the previous handoff declared"), and an undeclared job is refused with a
191
+ message naming the declaration.
192
+
193
+ ### Safety
194
+ - **The Sidekick can no longer commit, push, tag, publish, release, open a pull request or trigger CI unless the work
195
+ order grants that exact action.** The write lease bounds *files* (`allowedPaths`); it never bounded what leaves the
196
+ workspace, so a delegated task could `git commit` / `git push` and the Lead's review happened afterwards. Devin draws
197
+ the same line for its sidekick ("does not own commits, pushes, pull requests or CI"); this is the Host-side half.
198
+ `src/host/authority.ts` reads a shell command's text — through `sudo`/`env`/`xargs`/`time`/…, `VAR=value` prefixes,
199
+ `git -C <dir>`-style value-taking globals, `bash -c "…"` and `$(…)` — and names the action; quoted literal data
200
+ (`grep -r 'git push' docs`) is not a command and is left alone. `src/host/coordinator.ts` refuses an ungranted one
201
+ with `FUSION_WORKER_AUTHORITY_DENIED` and tells the Worker to report it as pending, so the task still finishes.
202
+ A new optional `authority: AuthorityAction[]` on the frozen `WorkOrder` (`contracts/fusion.ts`, `src/contracts.ts`)
203
+ is how the Lead grants one — only for what the user actually asked for — and `fusion_rework` cannot widen it.
204
+ Deliberately a command-text guard, not a sandbox: a command assembled at runtime (`python -c`) or run through
205
+ `run_code` stays outside it, which is why the Worker prompt states the rule too.
206
+ - Tests: `tests/authority.spec.ts` (7 cases) covers read-only commands staying allowed, the seven action families,
207
+ launchers/assignments/segments/nested shells/command substitution, quoted data not being mistaken for a command, and
208
+ a grant allowing exactly the granted action. `native-tests/coordinator.spec.ts` "Sidekick authority boundary" (2
209
+ cases) drives a real Worker: an ungranted `git commit` and `git push` are refused while the work order still
210
+ completes and verifies, and an action granted in the work order runs.
211
+
212
+ ### Prompts
213
+ - **Measured, and the brief-shape rule was narrowed because of the measurement.** A pilot
214
+ (`benchmark/rebench/results-p5/REPORT.md`) ran the same committed code and the same Fusion pair over four tasks, varying
215
+ only `prompts/`: arm A the pre-change prompts, arm B the rules below. Arm B was clearly faster — wall time 1559 s → 869 s
216
+ median (−44%), worker tool calls 84 → 54.5 (−35%) — and resolved **less**: 3/4 → 2/4, losing
217
+ `ucfopen__canvasapi-716` on one FAIL_TO_PASS test with all 60 PASS_TO_PASS still passing (an incomplete fix, not a
218
+ regression). Cost did not move (−1%) and rework rounds rose (1 → 2), so under the plan's own admission thresholds
219
+ (`docs/DEVIN-LOCAL-FUSION.md` §7.4) the change cannot merge unchanged. The rule the data implicates is now narrower in
220
+ both Lead variants: a fenced snippet is advice about one settled spot, explicitly *not* the boundary of the change, and
221
+ the Worker still reads the surrounding code and covers the cases next to it. `tests/prompts.spec.ts` pins that scope.
222
+ Check damping, consolidated rework and mid-handoff steering stay: nothing in the pilot points at them, and the next
223
+ round (arm C) tests them without the wide snippet rule.
224
+ - **Delegation economy, aligned with the Devin rules that explain its 3.4× wall-time advantage** (measured on the same
225
+ model pair in `benchmark/rebench/results-devin-r1`: 4/4 resolved at $2.73 in 20.1 min vs 3/4 at $4.81 in 6.0 min).
226
+ `prompts/lead.md` / `prompts/model-lead.md` say to hand over the *shape* once an edit is settled — exact file,
227
+ location and a fenced snippet — instead of only stating "what must be true", with the explicit reason Devin gives:
228
+ never leave alternatives for a model to pick, because it guesses and a wrong guess costs a rework round. Open design
229
+ questions are settled before an implementation brief. Review is batched: finish the whole review, then send every
230
+ defect, gap and edge case as one consolidated rework brief. A user message that arrives mid-handoff is acted on
231
+ immediately with `fusion_rework` rather than waited out.
232
+ - `prompts/lead.md` / `prompts/model-lead.md` also gain the non-delegable authoring rule: the exact text of a query
233
+ against a shared or production data system (read-only included — the risk is a wrong number delivered as fact),
234
+ prompt/rubric/grader/eval-harness text, and scoring/threshold/sampling/pipeline configuration are the Lead's to
235
+ write. Tests do not catch a plausible wrong number.
236
+ - `prompts/worker.md` / `prompts/model-worker.md` gain check damping: while planned edits remain, do not stop between
237
+ them to run `git status`, `git diff`, lint, typecheck or tests; after the last edit run one consolidated pass with the
238
+ narrowest command, never re-run a command whose inputs did not change, and after a fix re-run only what it could
239
+ affect. They also state the publish boundary and the "report it as pending" resolution.
240
+ - Tests: `tests/prompts.spec.ts` (7 cases) pins these rules — authority boundary, non-delegable authoring, fenced
241
+ snippet with no alternatives, consolidated rework, mid-handoff user message, check damping — in both the Chinese and
242
+ the English variant, so an edit to one variant cannot silently drop a rule from the other.
243
+
244
+ ### Documentation
245
+ - `docs/DEVIN-LOCAL-FUSION.md` records the Devin Fusion evidence (binary offsets, static prompt text, `sessions.db`
246
+ records), the dsh-fusion comparison, the efficiency evidence that motivates the prompt changes, and the fixed A/B
247
+ protocol (metrics, repetitions, admission thresholds) that a later round must use before any speed claim is made.
248
+
249
+ ### Fixes
250
+ - **A skill the user invokes can now actually reach the Lead.** The Host publishes the session skill catalog and
251
+ injects a `/<name>` invocation's body as instructions, but `skill` was missing from the Lead's read-tool ceiling, so
252
+ the body arrived as an instruction to call a tool the Lead did not have. `/grill-me` reached the Lead as "Call the
253
+ Skill tool with 'grilling'" and stopped there: `grilling`'s rules — in particular that finding repository facts is
254
+ the Lead's job — never loaded, so the Lead interrogated the user from the task text alone instead of the code
255
+ (session-2a7a61bd-fb83-4697-ae44-86934c0e4556). That session's recorded Lead request advertises exactly 13 tools —
256
+ `bash`, the `fusion_*` family, `glob`, `grep`, `job_output`, `read` — and no `skill`. `skill` is now a read tool in
257
+ `src/host/read-tools.ts`, next to
258
+ `read`/`grep`/`glob`: loading one returns instructions and never writes, so it is offered in every
259
+ enforced-workflow Lead catalog and stays callable while a Worker holds the write lease. Both Lead prompts
260
+ (`prompts/lead.md`, `prompts/model-lead.md`) now also say to load a matching or user-invoked skill before acting —
261
+ including when a loaded skill names another one to load — and to find repository facts before putting a question to
262
+ the user.
263
+ - Tests: `tests/read-tools.spec.ts` covers the ceiling membership, the `str_replace_editor view` carve-out and the
264
+ Lead-table projection. The host regression in `native-tests/coordinator.spec.ts` registers the Host's global
265
+ `skill` loader, turns a `/grill-me`-shaped message into a `skill {name: 'grilling'}` call, and asserts that every
266
+ Lead request advertises `skill` and that the call returns the skill body without an error. Both ceilings covered by
267
+ that case — `enforced-v3` and the legacy one — fail before this change (the request lists `bash`,
268
+ `fusion_delegate`, … and no `skill`) and pass after it.
269
+
270
+ ### Not claimed
271
+ - `session-2a7a61bd-fb83-4697-ae44-86934c0e4556` was not replayed end to end. The evidence is the unit test plus the
272
+ host integration suite, which exercises the Host's real request assembly, tool registration and ceiling projection.
273
+ - The authority guard was not measured on a real delegation, and it is a command-text guard, not a sandbox: a command
274
+ assembled at runtime (`python -c`, a script piped on stdin) or run through `run_code` is outside it. It also does not
275
+ ask the user whether they wanted the action; the grant is the Lead's judgement, recorded in the work order.
276
+ - The prompt changes **were** A/B measured once (see the measurement entry above), and that measurement is n=1 per cell over
277
+ four public tasks: it cannot rank the two arms statistically and is reported as an observation. The narrowed snippet
278
+ rule has **not** been re-measured; the next round (arm C) is what would show whether the loss is gone.
279
+ `deepseek-v4.1-flash` has no list price in `plan-phase5.json`, so every cost figure is a lead-only lower bound.
280
+ - Preserving a Worker's background processes **across handoffs** is not achievable from the plugin: the Host cancels a
281
+ job when its owner Agent's scope is disposed, which is exactly what a settled handoff does. The shipped
282
+ `preserveRuntime` covers one handoff (report lands while the job runs, the next brief is told what it was) and never
283
+ claims more. See `docs/DEVIN-LOCAL-FUSION.md` §9 for the measurement and the two Host-side options.
284
+ - The declared runtime's `strandedRetained` recovery path is covered by unit-level reasoning and the existing
285
+ inspection gate, not by a host test that restarts the Host process with a live retained job.
286
+
287
+ ### Validation
288
+ - `pnpm test`: 504 tests in 66 files pass (15 of them new: 7 in `tests/authority.spec.ts`, 8 in
289
+ `tests/prompts.spec.ts`). `pnpm typecheck` is clean, and `pnpm build` regenerates `lib/` with the expected
290
+ `lib/dsh-fusion.js` change plus the new `lib/types/host/authority.d.ts` and the `lib/types/host/read-tools.d.ts`
291
+ from the previous entry.
292
+ - `pnpm test:host` against the pinned Harness via `DSHX_HARNESS`: 282 of 283 pass. The one skip is the Windows ACL
293
+ confinement suite, which only runs on Windows; the platform-neutral coordinator suite is 239 of 239 — the two new
294
+ "Sidekick authority boundary" cases and the two new "retained runtime across handoffs" cases.
295
+
296
+ ## 0.3.8 — 2026-11-09
297
+
298
+ ### Fixes
299
+ - **Acceptance check receipts now carry their real closing snapshot.** `runNativeChecks` recorded only
300
+ `inputSnapshot`, so `src/evidence/receipts.ts` rejected every completed check as `CHECK_SNAPSHOT_MISMATCH`: no task
301
+ with an acceptance command could reach `verified`, and the Lead could never accept it. The producer now takes the
302
+ batch's closing snapshot after every command in it finished, confirms the source did not change, and writes it into
303
+ each completed receipt; `runBaselineChecks` does the same per command. Covered by a host regression that asserts the
304
+ persisted pair, which is the only place this defect was observable.
305
+ - `WORKER_TOOLS_UNREACHABLE` is now route-aware. Only the antigravity/agy bridge route, which Fusion actually wires,
306
+ is told to check `mcpBridge` / `permissionMode` / the `agy_tool` allowlist. Every other route (an ACP agent such as
307
+ `dsh-tauri-acp`, whose `session/new` carries no MCP servers) is told the adapter itself must forward Host tools, that
308
+ no Fusion setting can do it, and that workspace work needs a direct-call route. Zero tool calls stays a
309
+ route/adapter mismatch — never a provider outage, quota limit or model capability.
310
+ - The verdict now carries the Worker's own bounded last words as `workerSaid` (`text` ≤ 2000 characters, `truncated`,
311
+ and an explicit unverified-prose note), persisted with the order mode so `fusion_wait` re-reports identical evidence
312
+ instead of the Lead telling the user the Sidekick never replied (session-6113b527).
313
+ - Per-order evidence: the tool-call count and the quoted message are now scoped to the current work order via its
314
+ `worker-request:<childId>:<turn>:<step>` rows, so a persistent Worker's earlier tool calls can no longer mask a
315
+ current order that dispatched none.
316
+
317
+ ### Added
318
+ - A strictly bounded text-report protocol for `mode: 'text'` assignments whose route cannot call Host tools at all:
319
+ one ```` ```json ```` block with `fusionTextReport: 1`, the frozen `workOrderId` / `revision`, the current
320
+ `briefRevision` (and `operationId` when present), `status`, `summary` and `unresolved`. Another order, another
321
+ revision or brief, extra fields, several blocks, an unclosed block, non-JSON or plain prose are refused with a
322
+ recorded reason, and only the captured request's complete message of the current brief may ever be adopted (rework
323
+ keeps the frozen order revision, so a stale block cannot answer again; an older step's valid block is never a
324
+ fallback, and an interrupted captured request adopts nothing). An accepted report goes through the
325
+ existing validation, review ticket and Lead acceptance path, and the review reply marks it
326
+ `submittedVia: 'text-report'` so it is never presented as a tool-verified submission. Native
327
+ `fusion_submit_result` stays preferred, and `implement` / `explore` orders still require real Host tool calls.
328
+ - The protocol is discoverable in the text-order brief, in the single repair instruction and in `prompts/worker.md` +
329
+ `prompts/model-worker.md`; a valid pending text report also skips the turn-stopping repair generation.
330
+ - `docs/WORKER-TOOLS-UNREACHABLE.md` gained the ACP half of the story: the `dsh-tauri-acp` `mcpServers: []` root cause,
331
+ what the protocol does and does not allow, and the difference between route metadata (`provider`/`model`) and a
332
+ Worker's own claim about the model it runs.
333
+ - Tests: `tests/text-report.spec.ts` (protocol parsing, binding, caps, discovery text), route-aware wording and bounded
334
+ quoting in `tests/worker-terminal.spec.ts`, and host-level cases in `native-tests/coordinator.spec.ts` (bound text
335
+ report accepted without a repair generation, prose-only route quoting + `fusion_wait` consistency, wrong-revision
336
+ rejection, per-order evidence, rework refusing the previous brief's report, a fresh report under the new brief,
337
+ a stale `briefRevision` named in the refusal, an interrupted captured request not falling back to an older step's
338
+ report, workspace order refusing a bound text block, and the check-receipt
339
+ snapshot regression).
340
+
341
+ ### Not claimed
342
+ - This is not ACP Sidekick support. An ACP route still cannot read, run or edit anything through Fusion; the missing
343
+ MCP bridge observed in `dsh-tauri-acp` lives outside this repository. Fusion does not assume every ACP adapter is
344
+ built that way.
345
+ - End-to-end verification against a live ACP route was not reproduced here; the coverage is unit tests plus the host
346
+ integration suite, which now runs green (see below).
347
+
348
+ ### Validation
349
+ - `pnpm test`: 487 tests in 63 files pass (the earlier Node 24 dangling-symlink `EEXIST` cases are fixed in the tests
350
+ with `unlinkSync`; their assertions are unchanged). `pnpm typecheck` is clean, and `pnpm build` regenerates `lib/`.
351
+ - `native-tests/coordinator.spec.ts` against the pinned Harness (`DSHX_HARNESS`): 233 of 233 tests pass, including the
352
+ new bound-text-report cases, the interrupted-request case (an older step's valid block is never adopted), the
353
+ per-order evidence case and the check-receipt snapshot regression. The whole file is green on this machine once the
354
+ pinned Harness is supplied via `DSHX_HARNESS`.
355
+
356
+ ## 0.3.7 — 2026-11-09
357
+
358
+ ### Changes
359
+
360
+ - **An agy Sidekick now shows its steps inside the parent conversation.** A bridge route (antigravity) reports every
361
+ completed agy step as a real `tool/call` on its own transport, `agy_tool`, but the inline projection only listed the
362
+ Host's built-in tools. Both the live collector and the historical replay therefore dropped those events, so a session
363
+ whose Sidekick ran on an agy model looked idle — the operations were only visible in a separate task panel that
364
+ required `dsh-composer-plus` or `dsh-better-sidebar`. The projection now accepts the registered route transports
365
+ (and the exact Code Mode `run_code` mirror wrapper, parsed from the recorded code and never evaluated), so the same
366
+ `fusion_explore` / `fusion_delegate` card lists the real steps with no extra plugin installed.
367
+ Each row names the operation the route actually ran — `run_command` with its `CommandLine`/`Command` and `Cwd`,
368
+ `view_file`, `write_to_file`, `replace_file_content`, MCP shapes — and shows its recorded output and failure state.
369
+ An unknown inner tool falls back to its readable name and raw arguments; malformed arguments stay readable instead
370
+ of crashing the card. Exit codes are read only in the producing tool's own format, so a `view_file` result that
371
+ merely quotes an exit line is not marked failed. Write and edit steps show their real path and output but never a
372
+ diff synthesized from tool input.
373
+ - **A Worker delivered before this fix still replays.** Such a task kept its durable activity link while storing no
374
+ activity rows at all, and the historical reader treated any link as "already cached", so cold history stayed blank
375
+ forever. It now falls back to the accepted message ids when the store really holds no rows, keeping the parent/child
376
+ ownership check, writing nothing and activating nothing; a genuine cache hit, including an exhausted cursor, is
377
+ unchanged.
378
+
379
+ ### Validation
380
+
381
+ - `tests/agy-activity.spec.ts`: 17 tests over the projection predicate, the wrapper parser, argument unwrapping and
382
+ the rendered rows (shell command/cwd/exit code, file path and output with no fabricated diff, unknown tool,
383
+ malformed arguments, `pwsh` and `bash` cards unchanged).
384
+ - `native-tests/coordinator.spec.ts -t agy`: 3 tests — live collection with deduplication and no re-run, historical
385
+ replay, and recovery of a legacy link-only task.
386
+ - `pnpm test`: 462 tests in 61 files pass; the only failures are the two pre-existing symlink `EEXIST` cases in
387
+ `tests/change-evidence.spec.ts` and `tests/native-boundaries.spec.ts`, which also fail on the untouched branch.
388
+ `pnpm typecheck` and `pnpm build` are clean.
389
+ - Not claimed: the cards appear when the adapter closes a step, so a running step is not shown live; and no browser or
390
+ live-provider check was run — the results above are unit, host-fixture and build evidence.
391
+
392
+ ## 0.3.6 — 2026-11-09
393
+
394
+ ### Changes
395
+
396
+ - **A timed-out Lead no longer strands its conversation.** When a Lead request failed, `NativeModelControl` recorded a
397
+ durable `waits.lead` pause (`TIMEOUT` in session-8ead78f7). Every later turn was then rejected before any request, so
398
+ the loop ended it as `blocked` with nothing in the conversation — pressing "continue" looked like the session
399
+ instantly ending, and the only apparent way forward was a new session. A human message is now the local continuation
400
+ control: an ordinary user message, and an empty "continue", lift the Lead's pause so the same conversation runs again.
401
+ Only quota and credential stops (`QUOTA`, `ACCOUNT_QUOTA`, `INVALID_CREDENTIAL`) keep the pause, because a retry
402
+ cannot fix them; a Sidekick pause stays behind the bounded `leadRecover` path so a delegation cannot silently retry.
403
+ Synthetic wakes are unaffected: a Sidekick settlement or a goal round still carries content and never lifts a pause.
404
+ - **A gated step now says why.** A gate that rejects the pre-step (a paused role, a closing runtime, an unfinished
405
+ recovery, a missing scope install) never reaches the model, so the turn ended with no trace in the conversation. The
406
+ Host now writes one durable bilingual notice into the Lead's session per gate state, naming the paused role, the
407
+ reason, and the controls that lift it ("继续一次" / "Continue once", or simply another message). Repeated attempts on
408
+ the same state stay silent; a new gate state speaks once. A gated Sidekick transcript is untouched: the Lead already
409
+ learns about it from the delegation result.
410
+
411
+ ### Validation
412
+
413
+ - `pnpm typecheck` and `pnpm test`: 455 tests in 61 files pass locally (Node 22.23.2), including the new
414
+ `tests/user-continuation.spec.ts`, which drives the real `NativeModelControl` listener over a SQLite ledger and the
415
+ real `NativeFusionScopes` pre-step gate.
416
+ - Not claimed: the fix was not exercised against a live provider against a real timeout in a running Host; the gate and
417
+ the pause lift are covered at the unit/integration level with the durable ledger.
418
+
419
+ ## 0.3.5 — 2026-11-08
420
+
421
+ ### Changes
422
+
423
+ - Every message that sent the user to **Settings → Fusion** now points at the sidebar panel, which is where that entry
424
+ has lived since 0.3.0. Thirteen strings were affected: the "configure Fusion first" refusal, the model-menu
425
+ description, the quota and budget notices (with their English copies), the unreachable-route explanation, and the
426
+ composer hint's three states. The old wording named a page that no longer exists, so the one instruction a blocked
427
+ user got was unfollowable.
428
+ - `contracts/fusion.ts` — the published `./contracts` subpath — is level with `src/contracts.ts` again. It had fallen
429
+ behind by `WorkOrder.mode` (the field that decides whether a task may write at all), `PairProfile.interactionMode`
430
+ and `workflowPolicy`, the `'auto'` cache-keepalive mode, twelve exported types (`ExplorationReport`, `ReviewResultV2`,
431
+ `OutboxRow` and others) and 22 of the 30 `FusionEvent` kinds. Nothing imports this file, which is why the drift went
432
+ unnoticed; a new parity test reads both files as text and fails on any future divergence.
433
+ - Cost is no longer a hard-coded `null`. `usage/pricing.ts` already held a ledger pricer that nothing called; the status
434
+ panel, the history view and `/fusion status` now report what a task cost, what the same tokens would have cost on the
435
+ Lead, and the difference. A model with no rate is reported as **unpriced** rather than priced at zero, and the number
436
+ of requests the figure covers travels with it. `actualBilledUsd` stays `null` on purpose: DSH exposes no per-request
437
+ billed amount, and subscription routes are not billed per token, so the panel says "estimate" and "unknown" instead of
438
+ presenting a conversion as a charge. Rates are seeded from the list prices this project's own benchmark published and
439
+ can be corrected per model from the panel.
440
+ - Acceptance commands can now overlap. A check the Lead marks `independent` runs beside one other check instead of
441
+ after it, which shortens the wait after every delivery. The default stays serial: the Host cannot see whether two
442
+ commands share a cache directory, and two runs of the same test framework that share one produce a failure that is not
443
+ about the code. The single-writer lease and the Lead-orchestration lock are deliberately unchanged — the change
444
+ manifest attributes every diff to one work order, so a second concurrent writer would make the scope and
445
+ per-requirement evidence unverifiable. The per-command before/after snapshot moved to batch granularity, because under
446
+ concurrency a sibling's cache write would otherwise fail an innocent command.
447
+ - `probeMissingPrograms` no longer assumes PowerShell 7. It spawned `pwsh` by name, so a Windows machine with only
448
+ Windows PowerShell 5.1 (present on every Windows since 7) got `ENOENT`, the probe returned "inconclusive", and the
449
+ pre-delegation check that names a missing interpreter silently stopped running. It now tries `pwsh` and then
450
+ `powershell`; the probe script was already written to the 5.1 subset, so both answer identically.
451
+
452
+ ### Validation
453
+
454
+ - `pnpm test` (60 files, 447 tests: 446 passed, 1 skipped, 0 failed) and `tsc -p tsconfig.json --noEmit`. The suite's
455
+ previous baseline was 399 passed / 1 skipped / 1 failed, the failure being `tests/check-programs.spec.ts` — that is
456
+ the case this release fixes, and it now passes on a host without PowerShell 7.
457
+ - New tests: `public-contracts.spec.ts` (parity of the published contract file, confirmed to fail when a field is
458
+ removed from it), `probe-shells.spec.ts` (the shell fallback and the probe environment filter), `cost.spec.ts` and
459
+ `cost-projection.spec.ts` (pricing arithmetic, unpriced handling, the saving, and the money reaching both read models,
460
+ including a page total that must be the clean string `0.45`), and `check-batches.spec.ts` with
461
+ `check-batches-timing.spec.ts` (the serial default, the bounded overlap, and a measured wall-time difference proving
462
+ the batches really run concurrently).
463
+ - `tests/native-boundaries.spec.ts` asserted the old `设置` wording; it now asserts that the refusal names the Fusion
464
+ panel.
465
+ - **Not claimed:** the native Host suite was not run. It needs `DSHX_HARNESS` pointing at a pinned Harness checkout,
466
+ which this machine does not have.
467
+ - **Not claimed:** `lib/` was not rebuilt in this repository. Building on Windows rewrites every committed `.d.ts` from
468
+ LF to CRLF, so the artifacts are left to CI, which builds from this tag before publishing.
469
+
470
+ ## 0.3.4 — 2026-11-07
471
+
472
+ ### Changes
473
+
474
+ - A combo that names a model the catalog no longer offers now says **which** route and **which** combo went stale.
475
+ Reading a saved combo deliberately tolerates a retired route so the row stays visible and editable, but saving the
476
+ list rejects it — and the refusal read only `lead 模型已不可用,请刷新后重选`, naming neither the route nor which combo
477
+ of several. After a provider is renamed the model itself usually still exists under the new provider id, so the
478
+ message left nothing to act on; and when the user had just edited the other role, it read like a complaint about the
479
+ role they had just changed. The Host now names the route (`lead 模型已不可用:aihub-openai/gpt-6.1-sol。请为该角色重新
480
+ 选择模型`), `validatePairs` passes the combo name through so a multi-row save says which row failed, and the page
481
+ checks the same condition before sending: the save names the combo, the role and the route, the combo list marks the
482
+ affected row, and the role's picker keeps the dropped model listed and disabled (`已不可用:provider/model`) instead
483
+ of silently falling back to the `选择已连接的模型` placeholder.
484
+
485
+ ### Validation
486
+
487
+ - `pnpm test` (54 files, 401 tests: 399 passed, 1 skipped, 1 failed) and `tsc -p tsconfig.json --noEmit`. The one
488
+ failing case is `tests/check-programs.spec.ts`, whose probe returns `undefined` on this Windows host before and after
489
+ the change, so it is not counted as a regression. The native Host suite was not re-run: it needs a harness checkout
490
+ (`DSHX_HARNESS`), which this machine does not have.
491
+ - New `tests/settings-stale-route.spec.ts` covers the route naming, the combo naming through `validatePairs`, and
492
+ `missingRoutes` ordering; a new `tests/fusion-combos.spec.ts` case covers the row marker and the save refusal. Both
493
+ were confirmed to fail against the previous source.
494
+ - Rebuilt `lib/` from the merged source and loaded both artifacts in Node: the Host module still exports
495
+ `apply`/`Config`/`name`, and the client bundle registers under `@sqdr2/dsh-fusion` and still exports
496
+ `apply`/`inject`/`name`/`FUSION_PANEL_ID`/`FusionPanelIcon`. The client bundle inlines only `missingRoutes`; it pulls
497
+ in no `node:` module.
498
+
499
+ ## 0.3.3 — 2026-11-07
500
+
501
+ ### Changes
502
+
503
+ - The combo list selects from the whole row, and no longer paints a black pill inside it. Only the name and route text
504
+ was a button, so the row's padding and the empty space beside the text ignored clicks; and the generic
505
+ `.fusion-settings button` fill (`--dsw-alias-button-primary-fill`, which is `#0f1115` in the light theme) outranked the
506
+ row's `background:none`, so the one clickable strip rendered as a black capsule. The row is now `padding:0` with the
507
+ button spanning its full width up to the Delete button (89% of the row in a headless-Chrome measurement), the button
508
+ keeps `background:none`, and Delete keeps its own hit area and stops its click from selecting. A radio-style marker,
509
+ a hover surface and a brand-tinted selected state carry the selection instead of the fill.
510
+ - The composer names the permission of the model working now. Fusion pins the conversation (Lead) session to
511
+ `read-only`, and that pair matches no configured preset, so the native permission control read `Custom` for the whole
512
+ task. A Fusion chip in the composer tool row shows `Lead · Read Only` / `Sidekick · Full access` and follows the role
513
+ that is running; `FusionStatus.task.permissions` carries the per-role modes (`lead`, `worker`) and `active` role, read
514
+ from the recorded role intent, the in-flight request and the phase. The native control keeps its slot, its selection
515
+ state and its meaning: it still sets the Sidekick's mode.
516
+ - Fusion is no longer limited to one saved pair. The sidebar panel now manages a list of combos (add, rename, delete),
517
+ and **each combo is its own entry in the native model menu** (`Fusion · <name>`), so several conversations can run
518
+ different Lead/Sidekick pairs at the same time.
519
+ - Each combo advertises its own Lead's input modalities and freezes its own profile, so a conversation keeps the pair it
520
+ selected even after the list is edited, reordered or a combo is deleted. Picking another combo inside a conversation
521
+ drains the current task and starts a new one, exactly like leaving Fusion.
522
+ - Up to 6 combos. The first combo keeps the historical model id `auto`, and a pre-combo `settings:profile` is migrated
523
+ into it (named "自动") on read, so durable selections, frozen bindings and deploy-time profile files keep working. The
524
+ first combo is still mirrored into `settings:profile` for an older tab or a downgrade.
525
+ - An existing tab running the previous bundle can still save: it sends one pair and edits the first combo, leaving the
526
+ others alone.
527
+ - The switch-notice filter now recognizes every combo id, including the bare `auto → pair-xxxxxxxx` form the native menu
528
+ emits when two combos of this provider replace each other.
529
+
530
+ ### Build
531
+
532
+ - `pnpm build` no longer requires a harness checkout with `tools/dshx`. It still uses that harness-owned builder when
533
+ `DSHX_HARNESS` provides it, and otherwise emits the same two artifacts with a local `esbuild` pass (now a
534
+ devDependency): `lib/dsh-fusion.js` as plain ESM with every package external, `lib/client.js` as the CommonJS body the
535
+ Harness module loader expects.
536
+
537
+ ### Validation
538
+
539
+ - `pnpm test` (53 files, 397 tests: 395 passed, 1 skipped, 1 failed), `tsc -p tsconfig.json --noEmit`. The native Host
540
+ suite was last run at 263 passed / 1 skipped and was not re-run for this change: nothing outside the client bundle
541
+ moved. The one failing case is `tests/check-programs.spec.ts`, whose probe returns `undefined` on this Windows host
542
+ both before and after the change, so it is not counted as a regression.
543
+ - Rebuilt `lib/` and loaded both artifacts in Node: the Host module exports `apply`/`Config`/`name`, and the client
544
+ bundle registers under `@sqdr2/dsh-fusion` and still exports `apply`/`inject`/`name`/`FUSION_PANEL_ID`/`FusionPanelIcon`.
545
+ - New `tests/pairs.spec.ts` (migration, id assignment, name/limit validation, compare-and-swap, per-combo profile
546
+ identity) and `tests/fusion-combos.spec.ts` (list/rename/add/delete and whole-list save payload).
547
+ - The combo row hit area: a new `tests/fusion-combos.spec.ts` case asserts the row carries no padding, the selection
548
+ button owns it (`flex:1 1 auto`, `padding:11px 12px`, `background:none`), the row switches selection from the row body,
549
+ and Delete removes its own row without changing which combo is selected. The same markup and CSS were rendered in
550
+ headless Chrome and hit-tested with `elementFromPoint`: the left edge, the marker, the text and the empty space right
551
+ of it all resolve to the selection button, the right edge resolves to Delete, and the selection button covers 89% of
552
+ the row width.
553
+ - The permission chip: new `tests/status.spec.ts` cases (role modes, the takeover exception and the released
554
+ conversation) and `tests/fusion-permission.spec.ts` (both roles, the Custom explanation, silence outside a
555
+ role-separated task, the fast poll, and the additive registration that never takes the native permission slot).
556
+
557
+ ## 0.3.2 — 2026-11-05
558
+
559
+ Verification release. No runtime behaviour changed from 0.3.0, and the package is identical to it apart from the version
560
+ field.
561
+
562
+ 0.3.1 was meant to be this release, but its CI run failed before publishing: `tests/status-index.spec.ts` timed out at
563
+ 5000ms while finishing in a fraction of a second locally. The fixture built 600 rows with one autocommit each, which a
564
+ CI runner's disk cannot absorb inside a limit meant for unit tests. Those fixtures now use a single transaction, and the
565
+ two tests that migrate and backfill a real database declare a 60s budget.
566
+
567
+ ## 0.3.1 — 2026-11-05
568
+
569
+ Verification release. No runtime behaviour changed from 0.3.0, and the package is byte-identical to it apart from the
570
+ version field.
571
+
572
+ 0.3.0 was published by hand with a granular token, before this repository could publish from CI: Actions are disabled by
573
+ default on forks, and a trusted publisher can only be added to a package that already exists. Both are now in place, so
574
+ 0.3.1 exists to prove the OIDC path end to end — the tag-push workflow builds, tests and publishes without any stored
575
+ token, and the result carries a provenance attestation naming the commit it was built from.
576
+
577
+ ## 0.3.0 — 2026-11-05
578
+
579
+ First release under the name `@sqdr2/dsh-fusion`, branching from upstream `dsh-model-fusion` 0.2.9. Everything 0.2.9
580
+ does is still here; the changes below are the fork's.
581
+
582
+ The package was renamed, so install `@sqdr2/dsh-fusion` once — an installed `dsh-model-fusion` is not upgraded in place.
583
+ The plugin id stays `dsh-fusion`, so the rename moves code only, not data.
584
+
585
+ ### Changes
586
+
587
+ - The Fusion entry moved from **Settings → Fusion** to its own left-sidebar panel, and the panel body scrolls inside the
588
+ main slot instead of clipping the form and history table on a short window.
589
+ - A role on a bridge route (`antigravity`, i.e. `dsh-agy-worker` / `dsh-agy-link`) can now reach the Host tools. That
590
+ route may only report a step as `agy_tool`, which the role ceiling never carried, so a delegation degraded to prose and
591
+ the Host reported `WORKER_TOOLS_UNREACHABLE`. The transport is unioned into the ceiling when this Host registers it,
592
+ for the Lead as well as the Sidekick. Full diagnosis: [docs/WORKER-TOOLS-UNREACHABLE.md](docs/WORKER-TOOLS-UNREACHABLE.md).
593
+ - A bridged Sidekick can now bind its brief and report back. Such a route runs the call in its own loop under a
594
+ bridge-local id, so `fusion_submit_result` was refused as "Worker tool requires a complete native model request" and
595
+ the task stalled. A bridged call is accepted for the message that emitted the transport; the native path is unchanged
596
+ and still preferred.
597
+ - A task whose Sidekick route cannot reach the tools at all has an exit: the verdict is recorded on the runtime record,
598
+ `fusion_wait` re-reports it, and `fusion_delegate` may replace the dead order instead of leaving the task in
599
+ `WORKER_RUNNING` with no way out.
600
+ - A frozen scope no longer deadlocks a task. A glob such as `allowedPaths: ['lib/types/**']` matched nothing, widening
601
+ was refused because the files it wanted to record already differed, and the scope could not be cleared. Globs match,
602
+ widening is compared against the delegation base, and the scope can be cleared explicitly.
603
+ - History records can be deleted again. Deletion now asks the coordinator, which is the only authority that sees live
604
+ Agents, tool calls, jobs and write leases, so a replaced process no longer leaves an undeletable `running` task and a
605
+ live task is no longer deleted out from under itself. A 409 names the resource that held it.
606
+ - Usage, the task list, cache keepalive and history are each a collapsible box, collapsed by default, so the model pair
607
+ stays above the fold.
608
+
609
+ ### Compatibility after the rename
610
+
611
+ - Message source kinds are read under both spellings (`plugin:dsh-fusion`, `plugin:dsh-model-fusion`) and written only
612
+ under the new one. Recorded history is never rewritten.
613
+ - A session that selected Fusion before the rename stored `dsh-model-fusion/auto`; it is rewritten to `dsh-fusion/auto`
614
+ when the plugin installs its selection, so the next turn dispatches under a registered provider.
615
+ - `$DSH_HOME/plugins/dsh-model-fusion/` is migrated to `$DSH_HOME/plugins/dsh-fusion/` on first start, with a copy
616
+ fallback across filesystems that removes only the files it copied.
617
+ - Durable write leases are adopted the same way, and a lock written under the old name still blocks a new writer rather
618
+ than being taken over.
619
+ - The panel's HTTP routes are now `/api/fusion`; `/api/model-fusion` stays registered for a browser tab still holding the
620
+ previous client bundle.
621
+
622
+ ### Validation
623
+
624
+ Type checking passes, all 379 unit tests pass, and `lib/` was rebuilt from the tagged source. The native Host suite passes
625
+ 263 tests with one Windows-only test skipped, on the pinned Host checkout. No model calls were made for this release, and
626
+ the plugin is not installed or activated in a running Host by this preparation.
627
+
628
+ Install with `dsh plugin --profile web add @sqdr2/dsh-fusion`, or `github:SQDR2/dsh-fusion` from the repository, which
629
+ ships the built `lib/`. See [INSTALL.md](INSTALL.md) / [INSTALL.zh.md](INSTALL.zh.md).