better-dsh 0.2.3 → 0.2.4

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 (385) hide show
  1. package/cordis.patch.yml +1 -1
  2. package/docs/50_test-reports/2026-09-06-write/345/267/245/345/205/267sandbox/345/215/207/347/272/247/351/200/217/344/274/240bug/345/244/215/345/217/221/345/217/212/346/214/202/350/265/267-/344/272/213/344/273/266/346/212/245/345/221/212.md +176 -0
  3. package/docs/50_test-reports/2026-09-08-hashline-edit-E_RANGE_UNVERIFIED/350/267/250/350/275/256/344/274/232/350/257/235/351/224/256/345/244/261/346/225/210-/350/257/212/346/226/255/346/212/245/345/221/212.md +226 -0
  4. package/docs/50_test-reports/2026-09-11-control-prompt-into-eval-description/345/256/236/346/265/213/346/212/245/345/221/212.md +222 -0
  5. package/docs/50_test-reports/2026-09-12-fs-scheme-resolution-/345/256/236/346/265/213/346/212/245/345/221/212.md +81 -0
  6. package/docs/50_test-reports/2026-09-12-url-schemes-grammar-matrix/344/270/216catalog-centralize-/345/256/236/346/265/213/346/212/245/345/221/212.md +234 -0
  7. package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-design/351/252/214/350/257/201/346/212/245/345/221/212.md +160 -0
  8. package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/345/211/247/346/234/254.md +44 -0
  9. package/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/346/212/245/345/221/212.md +89 -0
  10. package/docs/50_test-reports/2026-09-12-url-schemes-/345/205/255scheme/345/206/222/347/203/237/344/270/216/350/276/271/347/225/214/345/256/236/346/265/213/346/212/245/345/221/212.md +198 -0
  11. package/docs/50_test-reports/2026-09-13-hashline-off/344/270/213scheme/345/217/257/350/276/276/346/200/247/345/267/245/345/205/267/351/235/242/344/270/215/345/257/271/347/247/260-/345/256/236/346/265/213/346/212/245/345/221/212.md +246 -0
  12. package/docs/50_test-reports/2026-09-13-preact-ui-shell/345/256/236/346/265/213/346/212/245/345/221/212.md +50 -0
  13. package/docs/50_test-reports/2026-09-14-4999-skill/346/270/205/345/215/225/344/270/216lsp-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +63 -0
  14. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-local-test-report.md +44 -0
  15. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-report.md +110 -0
  16. package/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
  17. package/docs/50_test-reports/v0.2.3b-hashline-content-locator/345/256/236/346/265/213/346/212/245/345/221/212.md +73 -0
  18. package/docs/50_test-reports/v0.2.3c-mobile-wave/345/256/236/346/265/213/346/212/245/345/221/212.md +47 -0
  19. package/docs/50_test-reports/v0.2.4-ios-focus-zoom-suppression/345/256/236/346/265/213/346/212/245/345/221/212.md +158 -0
  20. package/docs/specs/agent/spec.md +54 -0
  21. package/docs/specs/ast/spec.md +34 -0
  22. package/docs/specs/compaction-recall/spec.md +46 -0
  23. package/docs/specs/ctx/spec.md +107 -0
  24. package/docs/specs/dsh/spec.md +47 -0
  25. package/docs/specs/dvc/spec.md +87 -0
  26. package/docs/specs/escalation-guidance/spec.md +44 -0
  27. package/docs/specs/fs-scheme-resolution/spec.md +37 -0
  28. package/docs/specs/hash-edit/spec.md +41 -0
  29. package/docs/specs/http-read/spec.md +73 -0
  30. package/docs/specs/kernel-provisioning/spec.md +53 -0
  31. package/docs/specs/lsp/spec.md +121 -0
  32. package/docs/specs/mobile-layout/spec.md +108 -0
  33. package/docs/specs/model-failover/spec.md +20 -0
  34. package/docs/specs/preact-ui-shell/spec.md +22 -0
  35. package/docs/specs/repl-dispatch-resilience/spec.md +21 -0
  36. package/docs/specs/skill/spec.md +58 -0
  37. package/docs/specs/tool-surface/spec.md +222 -0
  38. package/docs/specs/url-schema/spec.md +148 -0
  39. package/docs/specs/web-trust-fence/spec.md +43 -0
  40. package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
  41. package/dsh-docs/AGENTS.md +75 -0
  42. package/dsh-docs/agent-lifecycle.md +84 -0
  43. package/dsh-docs/agent-lifecycle.zh.md +86 -0
  44. package/dsh-docs/api-gateway.md +164 -0
  45. package/dsh-docs/api-gateway.zh.md +164 -0
  46. package/dsh-docs/architecture.md +150 -0
  47. package/dsh-docs/architecture.zh.md +154 -0
  48. package/dsh-docs/capability-seams.md +543 -0
  49. package/dsh-docs/capability-seams.zh.md +545 -0
  50. package/dsh-docs/config-catalog.md +3473 -0
  51. package/dsh-docs/config-catalog.zh.md +3474 -0
  52. package/dsh-docs/cookbook/adding-a-package.md +117 -0
  53. package/dsh-docs/cookbook/adding-a-package.zh.md +119 -0
  54. package/dsh-docs/cookbook/adding-a-remote-api.md +197 -0
  55. package/dsh-docs/cookbook/adding-a-remote-api.zh.md +197 -0
  56. package/dsh-docs/cookbook/adding-a-session-format-version.md +109 -0
  57. package/dsh-docs/cookbook/adding-a-session-format-version.zh.md +109 -0
  58. package/dsh-docs/cookbook/adding-a-settings-card.md +102 -0
  59. package/dsh-docs/cookbook/adding-a-settings-card.zh.md +102 -0
  60. package/dsh-docs/cookbook/adding-a-tool.md +101 -0
  61. package/dsh-docs/cookbook/adding-a-tool.zh.md +103 -0
  62. package/dsh-docs/cookbook/adding-a-vendored-package.md +59 -0
  63. package/dsh-docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  64. package/dsh-docs/cookbook/adding-an-llm-adapter.md +43 -0
  65. package/dsh-docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  66. package/dsh-docs/cookbook/extension-cookbook.md +132 -0
  67. package/dsh-docs/cookbook/extension-cookbook.zh.md +136 -0
  68. package/dsh-docs/cookbook/maintaining-dsh-code-review.md +64 -0
  69. package/dsh-docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  70. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  71. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  72. package/dsh-docs/cordis-api/context.md +364 -0
  73. package/dsh-docs/cordis-api/context.zh.md +366 -0
  74. package/dsh-docs/cordis-api/events.md +207 -0
  75. package/dsh-docs/cordis-api/events.zh.md +209 -0
  76. package/dsh-docs/cordis-api/fiber.md +375 -0
  77. package/dsh-docs/cordis-api/fiber.zh.md +377 -0
  78. package/dsh-docs/cordis-api/inherited.md +39 -0
  79. package/dsh-docs/cordis-api/registry.md +152 -0
  80. package/dsh-docs/cordis-api/registry.zh.md +154 -0
  81. package/dsh-docs/cordis-api/service.md +102 -0
  82. package/dsh-docs/cordis-api/service.zh.md +104 -0
  83. package/dsh-docs/cordis-primer.md +45 -0
  84. package/dsh-docs/cordis-primer.zh.md +51 -0
  85. package/dsh-docs/cordis-tutorial/01-first-plugin.md +95 -0
  86. package/dsh-docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  87. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  88. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  89. package/dsh-docs/cordis-tutorial/03-services.md +98 -0
  90. package/dsh-docs/cordis-tutorial/03-services.zh.md +98 -0
  91. package/dsh-docs/cordis-tutorial/04-events.md +144 -0
  92. package/dsh-docs/cordis-tutorial/04-events.zh.md +144 -0
  93. package/dsh-docs/cordis-tutorial/05-config.md +84 -0
  94. package/dsh-docs/cordis-tutorial/05-config.zh.md +84 -0
  95. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  96. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  97. package/dsh-docs/cordis-tutorial/07-into-the-harness.md +108 -0
  98. package/dsh-docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  99. package/dsh-docs/cordis-tutorial/index.md +60 -0
  100. package/dsh-docs/cordis-tutorial/index.zh.md +62 -0
  101. package/dsh-docs/deepseek-llm-api-wire-extensions.md +163 -0
  102. package/dsh-docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  103. package/dsh-docs/defensive-patterns.md +33 -0
  104. package/dsh-docs/defensive-patterns.zh.md +35 -0
  105. package/dsh-docs/development.md +167 -0
  106. package/dsh-docs/development.zh.md +173 -0
  107. package/dsh-docs/event-producer-consumer.md +86 -0
  108. package/dsh-docs/event-producer-consumer.zh.md +88 -0
  109. package/dsh-docs/glossary.md +45 -0
  110. package/dsh-docs/glossary.zh.md +45 -0
  111. package/dsh-docs/graph-atlas.md +22 -0
  112. package/dsh-docs/graph-atlas.zh.md +24 -0
  113. package/dsh-docs/i18n/README.md +60 -0
  114. package/dsh-docs/i18n/README.zh.md +62 -0
  115. package/dsh-docs/i18n/style-samples.md +87 -0
  116. package/dsh-docs/i18n/terminology.md +214 -0
  117. package/dsh-docs/i18n/translation-prompt.md +263 -0
  118. package/dsh-docs/i18n/translation-rules.md +69 -0
  119. package/dsh-docs/i18n/translation-rules.zh.md +69 -0
  120. package/dsh-docs/module-graph.md +1411 -0
  121. package/dsh-docs/module-graph.zh.md +1413 -0
  122. package/dsh-docs/persistence-catalog.md +1075 -0
  123. package/dsh-docs/persistence-catalog.zh.md +1077 -0
  124. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  125. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  126. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  127. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  128. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  129. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  130. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  131. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  132. package/dsh-docs/postmortem/README.md +18 -0
  133. package/dsh-docs/postmortem/README.zh.md +18 -0
  134. package/dsh-docs/rescope.md +53 -0
  135. package/dsh-docs/rescope.zh.md +53 -0
  136. package/dsh-docs/session-format-status.md +47 -0
  137. package/dsh-docs/session-format-status.zh.md +47 -0
  138. package/dsh-docs/subsystems/README.md +61 -0
  139. package/dsh-docs/subsystems/README.zh.md +61 -0
  140. package/dsh-docs/subsystems/agent-team.md +207 -0
  141. package/dsh-docs/subsystems/agent-team.zh.md +207 -0
  142. package/dsh-docs/subsystems/approval.md +170 -0
  143. package/dsh-docs/subsystems/approval.zh.md +170 -0
  144. package/dsh-docs/subsystems/attachment.md +351 -0
  145. package/dsh-docs/subsystems/attachment.zh.md +351 -0
  146. package/dsh-docs/subsystems/client-modules.md +168 -0
  147. package/dsh-docs/subsystems/client-modules.zh.md +168 -0
  148. package/dsh-docs/subsystems/client-resources.md +91 -0
  149. package/dsh-docs/subsystems/client-resources.zh.md +91 -0
  150. package/dsh-docs/subsystems/code-runtime.md +195 -0
  151. package/dsh-docs/subsystems/code-runtime.zh.md +195 -0
  152. package/dsh-docs/subsystems/commands.md +219 -0
  153. package/dsh-docs/subsystems/commands.zh.md +219 -0
  154. package/dsh-docs/subsystems/compaction.md +238 -0
  155. package/dsh-docs/subsystems/compaction.zh.md +238 -0
  156. package/dsh-docs/subsystems/conversation.md +258 -0
  157. package/dsh-docs/subsystems/conversation.zh.md +258 -0
  158. package/dsh-docs/subsystems/core.md +1209 -0
  159. package/dsh-docs/subsystems/core.zh.md +1219 -0
  160. package/dsh-docs/subsystems/credentials.md +329 -0
  161. package/dsh-docs/subsystems/credentials.zh.md +329 -0
  162. package/dsh-docs/subsystems/extensions.md +382 -0
  163. package/dsh-docs/subsystems/extensions.zh.md +382 -0
  164. package/dsh-docs/subsystems/feedback.md +266 -0
  165. package/dsh-docs/subsystems/feedback.zh.md +266 -0
  166. package/dsh-docs/subsystems/filesystem.md +505 -0
  167. package/dsh-docs/subsystems/filesystem.zh.md +505 -0
  168. package/dsh-docs/subsystems/goal.md +277 -0
  169. package/dsh-docs/subsystems/goal.zh.md +277 -0
  170. package/dsh-docs/subsystems/invariants.md +88 -0
  171. package/dsh-docs/subsystems/invariants.zh.md +88 -0
  172. package/dsh-docs/subsystems/jobs.md +290 -0
  173. package/dsh-docs/subsystems/jobs.zh.md +290 -0
  174. package/dsh-docs/subsystems/llm-streaming.md +1080 -0
  175. package/dsh-docs/subsystems/llm-streaming.zh.md +1086 -0
  176. package/dsh-docs/subsystems/lsp.md +202 -0
  177. package/dsh-docs/subsystems/lsp.zh.md +202 -0
  178. package/dsh-docs/subsystems/permission-presets.md +131 -0
  179. package/dsh-docs/subsystems/permission-presets.zh.md +131 -0
  180. package/dsh-docs/subsystems/persistence.md +395 -0
  181. package/dsh-docs/subsystems/persistence.zh.md +395 -0
  182. package/dsh-docs/subsystems/plan.md +87 -0
  183. package/dsh-docs/subsystems/plan.zh.md +87 -0
  184. package/dsh-docs/subsystems/sandbox.md +220 -0
  185. package/dsh-docs/subsystems/sandbox.zh.md +220 -0
  186. package/dsh-docs/subsystems/schedule.md +192 -0
  187. package/dsh-docs/subsystems/schedule.zh.md +192 -0
  188. package/dsh-docs/subsystems/scope.md +59 -0
  189. package/dsh-docs/subsystems/scope.zh.md +59 -0
  190. package/dsh-docs/subsystems/session-projection.md +354 -0
  191. package/dsh-docs/subsystems/session-projection.zh.md +354 -0
  192. package/dsh-docs/subsystems/session-query.md +509 -0
  193. package/dsh-docs/subsystems/session-query.zh.md +509 -0
  194. package/dsh-docs/subsystems/session-reference.md +219 -0
  195. package/dsh-docs/subsystems/session-reference.zh.md +219 -0
  196. package/dsh-docs/subsystems/session-telemetry.md +194 -0
  197. package/dsh-docs/subsystems/session-telemetry.zh.md +194 -0
  198. package/dsh-docs/subsystems/session-title.md +204 -0
  199. package/dsh-docs/subsystems/session-title.zh.md +204 -0
  200. package/dsh-docs/subsystems/session.md +1155 -0
  201. package/dsh-docs/subsystems/session.zh.md +1159 -0
  202. package/dsh-docs/subsystems/settings.md +405 -0
  203. package/dsh-docs/subsystems/settings.zh.md +405 -0
  204. package/dsh-docs/subsystems/shell.md +303 -0
  205. package/dsh-docs/subsystems/shell.zh.md +303 -0
  206. package/dsh-docs/subsystems/sidebar-right.md +148 -0
  207. package/dsh-docs/subsystems/sidebar-right.zh.md +148 -0
  208. package/dsh-docs/subsystems/skills.md +354 -0
  209. package/dsh-docs/subsystems/skills.zh.md +354 -0
  210. package/dsh-docs/subsystems/slots.md +175 -0
  211. package/dsh-docs/subsystems/slots.zh.md +175 -0
  212. package/dsh-docs/subsystems/spill.md +117 -0
  213. package/dsh-docs/subsystems/spill.zh.md +117 -0
  214. package/dsh-docs/subsystems/storage.md +260 -0
  215. package/dsh-docs/subsystems/storage.zh.md +260 -0
  216. package/dsh-docs/subsystems/subagent.md +766 -0
  217. package/dsh-docs/subsystems/subagent.zh.md +770 -0
  218. package/dsh-docs/subsystems/subprocess.md +324 -0
  219. package/dsh-docs/subsystems/subprocess.zh.md +324 -0
  220. package/dsh-docs/subsystems/system-prompt.md +220 -0
  221. package/dsh-docs/subsystems/system-prompt.zh.md +220 -0
  222. package/dsh-docs/subsystems/terminal.md +184 -0
  223. package/dsh-docs/subsystems/terminal.zh.md +184 -0
  224. package/dsh-docs/subsystems/todo.md +32 -0
  225. package/dsh-docs/subsystems/todo.zh.md +32 -0
  226. package/dsh-docs/subsystems/token-meter.md +105 -0
  227. package/dsh-docs/subsystems/token-meter.zh.md +105 -0
  228. package/dsh-docs/subsystems/tools.md +720 -0
  229. package/dsh-docs/subsystems/tools.zh.md +720 -0
  230. package/dsh-docs/subsystems/typert.md +343 -0
  231. package/dsh-docs/subsystems/typert.zh.md +343 -0
  232. package/dsh-docs/subsystems/user-questions.md +178 -0
  233. package/dsh-docs/subsystems/user-questions.zh.md +178 -0
  234. package/dsh-docs/subsystems/web-client.md +95 -0
  235. package/dsh-docs/subsystems/web-client.zh.md +95 -0
  236. package/dsh-docs/subsystems/web-server.md +154 -0
  237. package/dsh-docs/subsystems/web-server.zh.md +154 -0
  238. package/dsh-docs/subsystems/web.md +206 -0
  239. package/dsh-docs/subsystems/web.zh.md +206 -0
  240. package/dsh-docs/subsystems/webhook.md +70 -0
  241. package/dsh-docs/subsystems/webhook.zh.md +70 -0
  242. package/dsh-docs/subsystems/workflow.md +278 -0
  243. package/dsh-docs/subsystems/workflow.zh.md +278 -0
  244. package/dsh-docs/subsystems/workspace.md +321 -0
  245. package/dsh-docs/subsystems/workspace.zh.md +321 -0
  246. package/dsh-docs/testing.md +54 -0
  247. package/dsh-docs/testing.zh.md +54 -0
  248. package/dsh-docs/tool-catalog.md +2225 -0
  249. package/dsh-docs/tool-catalog.zh.md +2233 -0
  250. package/dsh-docs/tool-execution-pipeline.md +62 -0
  251. package/dsh-docs/tool-execution-pipeline.zh.md +64 -0
  252. package/dsh-docs/user/develop/basic/config.md +106 -0
  253. package/dsh-docs/user/develop/basic/config.zh.md +106 -0
  254. package/dsh-docs/user/develop/basic/index.md +144 -0
  255. package/dsh-docs/user/develop/basic/index.zh.md +144 -0
  256. package/dsh-docs/user/develop/basic/publish.md +183 -0
  257. package/dsh-docs/user/develop/basic/publish.zh.md +183 -0
  258. package/dsh-docs/user/develop/basic/tool.md +52 -0
  259. package/dsh-docs/user/develop/basic/tool.zh.md +52 -0
  260. package/dsh-docs/user/develop/framework/events.md +143 -0
  261. package/dsh-docs/user/develop/framework/events.zh.md +143 -0
  262. package/dsh-docs/user/develop/framework/index.md +137 -0
  263. package/dsh-docs/user/develop/framework/index.zh.md +137 -0
  264. package/dsh-docs/user/develop/framework/service.md +148 -0
  265. package/dsh-docs/user/develop/framework/service.zh.md +150 -0
  266. package/dsh-docs/user/develop/practice/dynamic-cordis.md +15 -0
  267. package/dsh-docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  268. package/dsh-docs/user/develop/practice/index.md +155 -0
  269. package/dsh-docs/user/develop/practice/index.zh.md +155 -0
  270. package/dsh-docs/user/develop/practice/llm-adapter.md +189 -0
  271. package/dsh-docs/user/develop/practice/llm-adapter.zh.md +189 -0
  272. package/dsh-docs/user/guide/github-review.md +102 -0
  273. package/dsh-docs/user/guide/github-review.zh.md +102 -0
  274. package/dsh-docs/user/guide/index.md +30 -0
  275. package/dsh-docs/user/guide/index.zh.md +30 -0
  276. package/dsh-docs/user/guide/mcp-memory.md +101 -0
  277. package/dsh-docs/user/guide/mcp-memory.zh.md +101 -0
  278. package/dsh-docs/user/guide/network-proxy.md +85 -0
  279. package/dsh-docs/user/guide/network-proxy.zh.md +85 -0
  280. package/dsh-docs/user/guide/providers.md +190 -0
  281. package/dsh-docs/user/guide/providers.zh.md +190 -0
  282. package/dsh-docs/user/guide/python-sdk.md +150 -0
  283. package/dsh-docs/user/guide/python-sdk.zh.md +150 -0
  284. package/dsh-docs/user/guide/schedule.md +21 -0
  285. package/dsh-docs/user/guide/schedule.zh.md +21 -0
  286. package/dsh-docs/user/index.md +11 -0
  287. package/dsh-docs/user/index.zh.md +11 -0
  288. package/dsh-docs/web-styling.md +29 -0
  289. package/dsh-docs/web-styling.zh.md +29 -0
  290. package/eval-description.md +33 -0
  291. package/lib/client/index.js +327 -88
  292. package/lib/fs-aware/sandbox-plugin.d.ts +71 -0
  293. package/lib/fs-aware/sandbox-plugin.js +249 -0
  294. package/lib/index.d.ts +22 -22
  295. package/lib/index.js +3095 -3204
  296. package/lib/lsp-server-registry-DkaYmTwt.js +972 -0
  297. package/lib/lsp-server-registry-_hk-Wcia.js +3 -0
  298. package/lib/py-sdk-Chvy92MB.js +178 -0
  299. package/lib/py-sdk.d.ts +19 -2
  300. package/lib/py-sdk.js +2 -2
  301. package/lib/wrap-JFjcWwZf.js +747 -0
  302. package/package.json +9 -3
  303. package/url-schemes-instruction.md +22 -0
  304. package/control-prompt.md +0 -37
  305. package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
  306. package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  307. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  308. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  309. package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
  310. package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  311. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  312. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  313. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  314. package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  315. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  316. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  317. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  318. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  319. package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
  320. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  321. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  322. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  323. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  324. package/docs/60_exploration-and-research/cordis-research.md +0 -350
  325. package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
  326. package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
  327. package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
  328. package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
  329. package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
  330. package/docs/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +0 -110
  331. package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +0 -14
  332. package/docs/adr/0002-masking-is-presentation-only.md +0 -15
  333. package/docs/plans/A2A-messaging-channel-test-archive.md +0 -256
  334. package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +0 -137
  335. package/docs/plans/dashr-blueprint-review.md +0 -201
  336. package/docs/plans/dashr-blueprint.md +0 -561
  337. package/docs/plans/dashr-compaction-window-and-archive.md +0 -307
  338. package/docs/plans/dashr-profile-layer-feasibility.md +0 -367
  339. package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +0 -171
  340. package/docs/plans/dashr-security-sandbox-analysis.md +0 -187
  341. package/docs/plans/dashr-surface-invariant-and-omp-imports.md +0 -97
  342. package/docs/plans/ipython-kernel-interactive-interface-test-report.md +0 -152
  343. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +0 -146
  344. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +0 -50
  345. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +0 -79
  346. package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +0 -138
  347. package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +0 -161
  348. package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +0 -109
  349. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +0 -50
  350. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +0 -113
  351. package/docs/plans/recallable-compaction.md +0 -147
  352. package/docs/plans/spike-tag-repro.mjs +0 -102
  353. package/docs/plans/upstream-analysis.md +0 -128
  354. package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -142
  355. package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -193
  356. package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -96
  357. package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -127
  358. package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -150
  359. package/docs/v0.1.8d_artifacts/README.md +0 -138
  360. package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  361. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  362. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  363. package/docs/v0.1.8d_artifacts/functions.json +0 -592
  364. package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  365. package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  366. package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  367. package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  368. package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  369. package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -224
  370. package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -168
  371. package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -123
  372. package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  373. package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  374. package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  375. package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  376. package/docs/v0.2.0b_artifacts/hashline-probe.md +0 -5
  377. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  378. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  379. package/docs/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  380. package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  381. package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -110
  382. package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -86
  383. package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -66
  384. package/lib/py-sdk-BCaOGYz7.d.ts +0 -125
  385. package/lib/py-sdk-CbgYiX8O.js +0 -691
@@ -0,0 +1,121 @@
1
+ # lsp Specification
2
+
3
+ ## Purpose
4
+ `lsp` 是**双模**语言服务能力:passive push 模(插件订阅 dsh 文件事件流,替 agent 向 per-session LSP server 子进程做 `didOpen/didChange/didSave` 文本同步,缓存 server 推回的 `publishDiagnostics`)+ proactive tool 模(agent 经 `dvc://lsp` 主动要 `diagnostics`/`format`/`definition` 等)。工作单位 = agent session(cwd 即 workspace root 候选);**每 session 每语言一个 server 子进程**,不跨 session 共享。生命周期三级供给,类比 repl kernel:host start 零重物、session-start 登记零子进程、首用 lazy spawn。
5
+
6
+ ## Requirements
7
+
8
+ ### Requirement: Root-marker probing (lspMarker)
9
+ Server availability and project-root determination SHALL follow the per-language marker table(`pyrightconfig.json`/`pyproject.toml`、`tsconfig.json`/`jsconfig.json`、`Cargo.toml`、`go.mod` …配置驱动,不发明 `lsp.json`)——编辑器侧工程惯例,非 LSP 协议标准。Marker 缺席不阻断:server 仍可 spawn,root 退化为 mutation 文件所在目录。
10
+
11
+ #### Scenario: Marker present
12
+ - **WHEN** a session's cwd contains a language marker file and the language's server is locally available
13
+ - **THEN** the manager resolves project root to the marker's directory and reports availability for that language
14
+
15
+ #### Scenario: Marker absent
16
+ - **WHEN** no marker exists for the mutated file's language
17
+ - **THEN** availability is `unknown`, not `unavailable` — the gate below still offers opt-in
18
+
19
+ ### Requirement: Gated notice with explicit per-session opt-in (on/off)
20
+ The manager at session start SHALL check local availability of each language server in its table(Python/TypeScript 为必备,缺失即安装;Rust/Go 保留 nag 检测,server 缺失时按需安装). When a session performs file mutations (edit/write 落盘) in a language with availability `available` or `unknown` and the session gate is `unasked`, the tool result MAY append the availability notice (lsp 可用,`dvc://lsp` 开/关) **at most 10 times per session**(防刷屏上限). Both `on` and `off` are PER-SESSION state — the manager handles everything, and SHALL write NO repo artifact or marker file in either direction(无 `.dashr/lsp.json`,无任何落盘偏好).
21
+
22
+ #### Scenario: Mutation nag capped
23
+ - **WHEN** the agent edits `.py` files repeatedly in a session with gate `unasked`
24
+ - **THEN** at most 10 tool results carry the notice; afterwards mutations stay silent until the gate is decided
25
+
26
+ #### Scenario: Explicit on (per session)
27
+ - **WHEN** the agent sets `dvc://lsp` on
28
+ - **THEN** the session gate becomes `on` and the manager warm-starts the language server; nothing is written to the repo
29
+
30
+ #### Scenario: Explicit off (per session)
31
+ - **WHEN** the agent sets `dvc://lsp` off
32
+ - **THEN** the gate becomes `off`, no server spawns, the notice is muted for the session, and no repo marker is written
33
+
34
+ ### Requirement: Must-have servers installed, niche on demand
35
+ At session start the manager SHALL verify Python and TypeScript servers and INSTALL a missing one (pip/npm, pinned, fail-soft — 安装失败降级为该语言 `unavailable`);Rust/Go servers SHALL NOT be installed proactively — they stay in the nag-detection table and install only when the agent turns lsp on for that language.
36
+
37
+ #### Scenario: Missing pyright on a fresh host
38
+ - **WHEN** a session starts and no Python language server is installed
39
+ - **THEN** the manager installs it in the background and reports availability `available` once done(安装期间 `unknown`,nag 照常)
40
+
41
+ #### Scenario: Rust opted in on demand
42
+ - **WHEN** the agent sets lsp on in a session touching Rust files and rust-analyzer is absent
43
+ - **THEN** the manager installs rust-analyzer then spawns it — never before the opt-in
44
+
45
+ ### Requirement: Lazy spawn, session lifetime
46
+ Server subprocesses SHALL spawn lazily on first post-on use, one subprocess per (session, language), registered under the agent's own tool effect so agent dispose unwinds them via `shutdown`+`exit`; an idle timeout reclaims servers of still-live sessions.
47
+
48
+ #### Scenario: Per-session isolation
49
+ - **WHEN** two sessions work in different cwd/repo simultaneously
50
+ - **THEN** each owns independent server subprocesses with its own workspace root and document mirrors
51
+
52
+ ### Requirement: Text synchronization is post-hoc, never intercepting
53
+ The plugin SHALL feed document sync (`didOpen`/`didChange` full-text + `didSave`) from AFTER-THE-FACT dsh events only — `tools/post-execute` on successful read/edit/write, mirroring the exact landed content(EXACT content, didSave freshness, span guard)— and SHALL NOT intercept, wrap, or delay any dsh read/write/edit flow. The version ledger follows the host fs observation policy's read-before-edit accounts; no second version book is kept.
54
+
55
+ #### Scenario: Landed content is the mirror
56
+ - **WHEN** an edit lands and lsp is on for that language
57
+ - **THEN** the server receives a full-text `didChange` + `didSave` with the exact written content before diagnostics are requested, so line numbers match what the model just wrote
58
+
59
+ ### Requirement: Dual-mode results
60
+ Proactive mode (`dvc://lsp` write: `diagnostics`/`format`/`definition`/…) and passive mode (cached `publishDiagnostics` attached to tool results, e.g. hashline edit 的 post-edit summary,经注入回调而非模块内依赖) SHALL both be served from the same session manager. Every failure — no server, gate off, cold-start noise — SHALL read as "no feedback": a serverless mutation is byte-identical to stock behavior.
61
+
62
+ #### Scenario: Diagnostics ride the edit result
63
+ - **WHEN** lsp is on, an edit lands, and the server answers diagnostics
64
+ - **THEN** the edit's tool result carries the diagnostics summary; when the server is absent or slow, the result is unchanged
65
+
66
+ ### Requirement: Spin-up latency is absorbed, never blocking
67
+ Server cold-start(spawn + `initialize` + 首轮索引)SHALL be handled by three means: (1) **warm-start at opt-in** — gate on 即后台 spawn,不等首个请求; (2) **fire-and-attach** — diagnostics 请求带超时,超时/未就绪读作"no feedback",server 稍后推回的 `publishDiagnostics` 缓存并附到**下一个** mutation 的 tool result(延迟附挂,不丢不阻塞); (3) **read 预热** — session 内首个某语言文件 read 即提前 `didOpen`,使首个 edit 命中已初始化的 server. The mutation path SHALL NEVER wait on server readiness — worst case is a summary arriving one tool call late.
68
+
69
+ #### Scenario: First edit on a cold server
70
+ - **WHEN** the gate turns on and the very next mutation hits an uninitialized server
71
+ - **THEN** the edit result carries no diagnostics (no feedback), and when the server finishes indexing the diagnostics attach to the next mutation's result
72
+
73
+ #### Scenario: Read pre-warms
74
+ - **WHEN** the agent reads a `.ts` file before editing it and lsp gate is on for TypeScript
75
+ - **THEN** the read triggers `didOpen` and server initialization, so the subsequent edit usually gets same-call diagnostics
76
+
77
+ ### Requirement: Orthogonality and injection boundaries
78
+ The lsp capability SHALL be a self-contained module: no url-schemes/hashline imports; per-feature attachments (edit-result diagnostics, availability notices) arrive as injected callbacks from composition roots. Host start SHALL NOT probe markers or spawn processes — all discovery is per-session, on demand.
79
+
80
+ #### Scenario: Host boot cost
81
+ - **WHEN** the host starts with the lsp capability mounted
82
+ - **THEN** no subprocess spawns, no marker probing runs, and nothing on the boot path can fail because of lsp
83
+
84
+ ## Surface syntax (`dvc://lsp`)
85
+
86
+ The dvc contract is uniform: **bare read = roster, `<device>` read = doc/status, `<device>` write = action dispatch**. Gate state is per-session — the write dispatcher injects the calling agent's session id automatically; agents never type it.
87
+
88
+ Read-vs-write follows GET/PUT semantics — **reads never mutate, writes always do**:
89
+
90
+ - `read dvc://lsp` — the device doc: actions, args, current contract.
91
+ - `read dvc://lsp/status` — the calling session's gate (session injected from the read env; no session → an explicit pointer note).
92
+ - `read dvc://lsp/diagnostics?file=<path>&all=1` — fan-out query (read-only; spawning a lazily-managed server is the side effect of asking, not a mutation).
93
+ - `read dvc://lsp/definition?file=&line=&character=|&symbol=` (also `references`, `hover`) — position queries, 1-based.
94
+ - `write dvc://lsp` `{"action":"on"}` / `{"action":"off"}` — per-session gate decision; ack describes the effect. No repo artifact in either direction.
95
+ - `write dvc://lsp` `{"action":"reload"}` — restart the server (config re-read).
96
+ - `write dvc://lsp` `{"action":"rename",...}` / `{"action":"code_actions",...,"apply":N}` / `{"action":"format","file":...}` — workspace-mutating operations.
97
+
98
+ The write surface retains `status` for symmetry with the session-injected dispatcher, but the read form is canonical for all queries. Path-mutation forms (`dvc://lsp/on`) are NOT part of the contract: mutation never rides a read URL.
99
+
100
+ ### Requirement: Session transport is out-of-band
101
+ The per-session gate addressing SHALL ride the dvc write dispatcher's `execute(args, { session })` context — NOT the args payload — so devices with strict argument validators (browser) are unaffected; the lsp device reads `ctx.session` with a legacy in-args fallback for direct callers. The read surface receives the calling session through the resolver env the same way (`dvc://lsp/status` returns the calling session's gate).
102
+
103
+ #### Scenario: Strict-validator device unaffected
104
+ - **WHEN** the model writes `dvc://browser` with `{"action":"open","url":…}` from a session
105
+ - **THEN** the browser device's validator sees only its declared fields and the action executes (the session rides the dispatcher's out-of-band ctx)
106
+
107
+ #### Scenario: Status read is session-aware
108
+ - **WHEN** the model turns lsp on and then reads `dvc://lsp/status` from the same session
109
+ - **THEN** the status reports that session's gate (`"gate":"on"`)
110
+
111
+ ## OMP parity progress
112
+
113
+ The device vendored a trimmed upstream oh-my-pi (`packages/coding-agent/src/lsp`) surface; parity is being completed in stages, each keeping the module boundary (nothing imports hash-edit/ast/url-schemes internals):
114
+
115
+ 1. ✅ `rename` / `code_actions` / `reload` actions (apply/preview WorkspaceEdit over `changes` + `documentChanges`; code action apply by index; reload = shutdown + evict).
116
+ 2. ✅ Workspace-wide diagnostics (`{"action":"diagnostics","file":"*"}` — aggregate cached publishDiagnostics across all live servers, per-file E/W counts) + `documentDiagnostic` pull for servers advertising `diagnosticProvider` (pull wins over last push on the saved path).
117
+ 3. ✅ Per-file fan-out: `{"action":"diagnostics","file":...,"all":true}` queries every registered server covering the file and merges results tagged per server (single-coverage falls through to the primary path).
118
+ 4. ✅ `symbol` / `symbol#N` position resolution on definition/references/rename/hover (word-bounded exact first, case-insensitive fallback, structured `LSP_SYMBOL_NOT_FOUND`; explicit `character` wins).
119
+ 5. ✅ Must-have installer: registry `installServer()` runs the package-manager command (npm/pip/go/rustup, 5 min timeout, fail-soft) for missing python/ts/js primaries once per session at first nag; niche languages stay install-on-opt-in.
120
+
121
+ All five stages are in-tree; residual deltas vs upstream (lspmux, deferred-diagnostics ledger, writethrough editor integration) are IDE-side facilities without a dsh counterpart and are tracked as out of scope by the lsp spec's post-hoc sync ruling.
@@ -0,0 +1,108 @@
1
+ # mobile-layout Specification
2
+
3
+ ## Purpose
4
+ better-dsh 的移动端布局与输入契约:窄视口侧栏轨 0(注入 CSS 覆盖,桌面档零影响)、三条件滑动手势(边缘带 × 距离 × 速率,纯函数可测)、iOS focus 自动放大抑制 zoomGuard(browser=viewport meta token 改写 / standalone=16px 字号地板双形态,`'off'` 逃生门),全部随插件发布、config 门控(`mobile.enabled` / `mobile.breakpoint` / `mobile.zoomGuard`)。
5
+
6
+ ## Requirements
7
+
8
+ ### Requirement: iOS focus auto-zoom suppression on narrow viewports
9
+
10
+ The plugin's host half SHALL suppress the iOS Safari focus-triggered auto-zoom with **display-mode-dependent behavior**:
11
+
12
+ - **Browser context** (not standalone): rewrite the page's viewport meta (appending `maximum-scale=1` and `user-scalable=no`) inside the injected head boot script — before any application bundle can focus an input — with the v0.2.4 machinery (double gate iOS-class UA AND narrow viewport, breakpoint re-evaluation, provisional/reconcile single-meta invariant, early-load re-evaluation ladder, idempotent merge, byte-level restore). Real-device datum (2026-09-03): in-browser iOS Safari ignores `user-scalable=no` for pinch, so pinch zoom remains available in this mode.
13
+ - **Standalone context** (`(display-mode: standalone)` media query matches OR `navigator.standalone === true`): the plugin SHALL NOT touch the viewport meta at all (no rewrite, no provisional, no listeners, no timers — real-device datum: standalone iOS honors `user-scalable=no` and pinch would break), and SHALL instead inject a static style element (`id="ios-zoom-font-floor"`, carrying the plugin's style-claim attributes) with `@media (max-width: {breakpoint-0.02}px){ input,textarea,select,[contenteditable="true"]{ font-size:16px !important } }`, which suppresses the focus auto-zoom by the font-size mechanism.
14
+
15
+ Both branches SHALL be config-gated via `mobile.zoomGuard` (`'meta'` default = auto dual-mode behavior; `'off'` emits neither branch on any platform). Non-iOS browsers and wide viewports SHALL observe stock behavior in both display modes.
16
+
17
+ #### Scenario: iOS narrow focus does not zoom
18
+
19
+ - **WHEN** an input, select, checkbox, or contenteditable receives focus on an iOS-class browser below the breakpoint with `zoomGuard: 'meta'`
20
+ - **THEN** no auto-zoom occurs in either display mode: browser mode suppresses it via the rewritten viewport meta, standalone mode via the 16px font-floor style
21
+
22
+ #### Scenario: Rewrite lands before first possible focus
23
+
24
+ - **WHEN** the head boot script executes during page load in browser (non-standalone) display mode
25
+ - **THEN** the viewport meta rewrite is applied synchronously before any application bundle materializes, so no zoom flash can occur on an early auto-focus
26
+
27
+ #### Scenario: Browser mode rewrites meta (unchanged from v0.2.4)
28
+
29
+ - **WHEN** an iOS-class browser below the breakpoint loads in a non-standalone display mode with `zoomGuard: 'meta'`
30
+ - **THEN** the viewport meta carries `maximum-scale=1, user-scalable=no` (single meta, idempotent, restorable) and no font-floor style is injected
31
+
32
+ #### Scenario: Standalone mode never touches the viewport meta
33
+
34
+ - **WHEN** an iOS-class browser below the breakpoint loads with display-mode standalone (matched via media query or `navigator.standalone`) and `zoomGuard: 'meta'`
35
+ - **THEN** the viewport meta is byte-identical to stock, no provisional meta is created, no resize/MQ listeners or re-evaluation timers are armed, and the `ios-zoom-font-floor` style element is present with the 16px floor rules scoped to the configured breakpoint
36
+
37
+ #### Scenario: Standalone pinch zoom is preserved
38
+
39
+ - **WHEN** the user pinch-zooms in standalone display mode with the guard active
40
+ - **THEN** the viewport meta contains no zoom-restricting tokens (pinch is engine-available; suppression relies solely on the font-size floor)
41
+
42
+ #### Scenario: Font floor suppresses the focus zoom in standalone
43
+
44
+ - **WHEN** an input, textarea, select, or `[contenteditable="true"]` element receives focus in standalone mode below the breakpoint
45
+ - **THEN** its computed font-size is at least 16px and no auto-zoom occurs
46
+
47
+ #### Scenario: Non-iOS touch browsers unaffected
48
+
49
+ - **WHEN** the page loads on a non-iOS touch browser (e.g. Android Chrome) below the breakpoint, in either display mode
50
+ - **THEN** the viewport meta is not rewritten and no font-floor style is injected (Android never focus-zooms; the iOS gate avoids `maximum-scale` side effects there)
51
+
52
+ #### Scenario: Breakpoint crossing re-evaluates
53
+
54
+ - **WHEN** the viewport crosses the breakpoint after load (rotation, split-screen) in browser display mode
55
+ - **THEN** the rewrite is applied on entering the narrow band and the stock meta content is restored on leaving it; in standalone mode the font-floor style's media query naturally stops matching above the breakpoint (no JS re-evaluation exists there)
56
+
57
+ #### Scenario: Desktop and wide viewports unaffected
58
+
59
+ - **WHEN** the page loads on a desktop browser, a non-iOS browser, or at/above the breakpoint (either display mode)
60
+ - **THEN** the viewport meta is stock and no font-floor style is injected (the floor's media query does not match above the breakpoint)
61
+
62
+ #### Scenario: Config off restores stock behavior
63
+
64
+ - **WHEN** `mobile.zoomGuard` is `'off'`
65
+ - **THEN** neither the meta machinery nor the font-floor style exists in any display mode
66
+
67
+ #### Scenario: Idempotent evaluation
68
+
69
+ - **WHEN** the browser-mode re-evaluation runs multiple times within one state (load, resize storms, repeated crossings)
70
+ - **THEN** the meta content does not accumulate duplicate tokens or regress (standalone mode arms no re-evaluation machinery at all)
71
+
72
+ ### Requirement: Sidebar occupies zero width on narrow viewports
73
+
74
+ The plugin's client half SHALL hide the sidebar rail (zero-width column track) on narrow viewports via injected static CSS (media query + semantic attribute selectors, `!important` over the inline grid template), aligned with the upstream CSS-first layout paradigm and WITHOUT JavaScript geometry measurement; desktop-class rendering SHALL remain identical to the unpatched product, and the feature SHALL ship with the plugin, config-gated (`mobile.enabled`, default on).
75
+
76
+ #### Scenario: Mobile viewport hides the rail
77
+
78
+ - **WHEN** the page renders at a mobile-class viewport width below the configured breakpoint with the feature enabled
79
+ - **THEN** the sidebar column track is zero width and the conversation area spans the frame
80
+
81
+ #### Scenario: Desktop unaffected
82
+
83
+ - **WHEN** the page renders at or above the breakpoint
84
+ - **THEN** layout behavior is identical to the unpatched product
85
+
86
+ #### Scenario: Degradation is benign
87
+
88
+ - **WHEN** upstream DOM/attribute changes break the CSS override
89
+ - **THEN** the layout falls back to the native rail rendering without errors or blank areas
90
+
91
+ ### Requirement: Three-condition swipe recognition
92
+
93
+ Swipe recognition SHALL require all three of: gesture origin within the edge band, displacement at or above the distance threshold, and average velocity at or above the velocity threshold; slow press-drag gestures (text selection and similar) SHALL NOT trigger a swipe, and a recognized swipe SHALL toggle the sidebar via the layout service (`ctx.layout.toggleSidebar()`, narrow-viewport semantics), with the velocity/distance predicates implemented as pure functions under unit test.
94
+
95
+ #### Scenario: Slow text-selection drag does not toggle
96
+
97
+ - **WHEN** a pointer press-drag covers the distance threshold at sub-threshold velocity (e.g. selecting text to copy)
98
+ - **THEN** no sidebar toggle occurs
99
+
100
+ #### Scenario: Fast swipe toggles
101
+
102
+ - **WHEN** a pointer gesture starts in the edge band, exceeds the distance threshold, and meets the velocity threshold
103
+ - **THEN** the sidebar overlay state toggles (narrowExpanded flips)
104
+
105
+ #### Scenario: Interactive-element origins are ignored
106
+
107
+ - **WHEN** a gesture begins on an interactive element (link, button, input)
108
+ - **THEN** no swipe recognition runs for that gesture
@@ -0,0 +1,20 @@
1
+ # model-failover Specification
2
+
3
+ ## Purpose
4
+ TBD - created by archiving change 2026-09-02-model-failover-settings-surface. Update Purpose after archive.
5
+
6
+ ## Requirements
7
+
8
+ ### Requirement: Model Failover surface in General settings
9
+
10
+ The plugin SHALL register a Model Failover row into the Settings > General page via the `settings.general.item` slot, exposing the failover pair (primary/secondary model selectors) with persisted configuration, wherever the plugin's client bundle is built and loaded — including the source-level test instance — and the row SHALL remain functional across upstream settings-slot contract evolutions covered by the alignment process.
11
+
12
+ #### Scenario: Row renders in the source-level test instance
13
+
14
+ - **WHEN** the Dev/Test 1 instance starts with the plugin's client bundle built and the user opens Settings > General
15
+ - **THEN** the Model Failover row with both model selectors is visible and its selections persist across instance restarts
16
+
17
+ #### Scenario: Failover engages on primary failure
18
+
19
+ - **WHEN** a turn's primary model request fails and a secondary model is configured in the row
20
+ - **THEN** the host-side per-turn waterfall retries via the configured secondary and the outcome is observable in the session
@@ -0,0 +1,22 @@
1
+ # preact-ui-shell Specification
2
+
3
+ ## Purpose
4
+ 为测试线(test-line)的 `apps/web` shell 提供构建期 React 家族到 `preact/compat` 的 vite alias patch:上游 ui-* 插件 bundle 的 `require("react")` 零改动获得 Preact 实例,shell 体积随之显著缩减。该 patch 仅限测试线 checkout,随 tag 切换重放;是否随插件包发布 dist 由 ship 决策另行裁决、暂缓。
5
+
6
+ ### Requirement: Preact-shell build for the web UI
7
+ The test-line harness build SHALL support building the web shell (`apps/web`) with the React family aliased to `preact/compat` (including `react/jsx-runtime`, `react/jsx-dev-runtime`, `react-dom`, `react-dom/client` subpaths) via a build-time vite alias, so the platform module seed materializes Preact instances and every upstream client plugin bundle's `require("react")` receives Preact with zero upstream component edits. The alias SHALL be a monorepo-local build patch (documented, re-applied on tag switches), never an upstream source fork.
8
+
9
+ #### Scenario: Shell serves the UI with Preact
10
+ - **WHEN** the test-line instance is rebuilt with the alias patch and a browser loads the served UI
11
+ - **THEN** the full upstream UI corpus mounts (sidebar/workspace/settings/chat), the session reports zero `pageerror` and zero `console.error`, and the shell bundle contains no `react-dom` production banner while carrying `preact` identity
12
+
13
+ #### Scenario: Size regression is measured, not assumed
14
+ - **WHEN** the alias build completes
15
+ - **THEN** the shell `index` chunk (where the React family rides) is measured against the stock build and the delta recorded in the change report
16
+
17
+ ### Requirement: Test-line-only scope pending a ship decision
18
+ The alias patch lives in the harness checkout only. The published plugin package (`@pgmi-builds/better-dsh`) SHALL NOT silently fork the web-UI serve surface: shipping a Preact-built frontend dist through the plugin (web-runtime override rows) is a separate decision gated on the prod host version upgrade, because a shipped dist freezes the UI corpus at the fork point.
19
+
20
+ #### Scenario: Plugin publish content unchanged by this change
21
+ - **WHEN** the next plugin alpha is published after this change
22
+ - **THEN** the Preact enhancement is not part of the published artifact; the report records the ship-in-plugin option (dist + override rows) and its corpus-freeze trade-off as a pending decision tied to the prod host upgrade
@@ -0,0 +1,21 @@
1
+ # repl-dispatch-resilience Specification
2
+
3
+ ## Purpose
4
+ REPL(`eval` cell)子分派的韧性契约:分派层的任何错误——调度器缺失、工具体抛错、取消——都必须 settle 为 cell 可见的 `ToolCallError` 结果,绝不外泄为 unhandled rejection 或使宿主进程崩溃。生产组合必须把带 `TOOL_RUNTIME_SCHEDULER` symbol 的原生 `ToolRuntime` 实例解析给插件,测试组合与生产组合之间不得存在环境差异导致的静默行为分裂。
5
+
6
+ ## Requirements
7
+
8
+ ### Requirement: Dispatch errors settle as visible ToolCallError
9
+ The system SHALL resolve the plugin's tools service to the native `ToolRuntime` instance carrying the `TOOL_RUNTIME_SCHEDULER` symbol in the production composition, so REPL sub-dispatches execute through the same staged scheduler as the agent loop and return real tool results to the cell. The symbol this plugin imports SHALL be identical (`===`) to the one keying the mounted instance — a second dsh-tools module copy reachable from the deployed plugin (e.g. stray nested `@deepseek-ai` symlinks) breaks that identity and is a deployment defect (2026-09-02 corrected root cause; the plain `runtimeCtx.tools` read is the sanctioned resolution path). A mount whose tools service genuinely lacks the symbol SHALL be treated as a loud, diagnosable configuration failure — the error names the plugin's own `dsh-tools` resolution path — rather than a silent runtime crash, and that loud failure SHALL be the abnormal fallback, not the normal production state.
10
+
11
+ #### Scenario: Production mount carries the scheduler symbol
12
+ - **WHEN** the DASHR plugin mounts in the production composition and a cell dispatches a real tool call
13
+ - **THEN** the dispatch executes through `registry[TOOL_RUNTIME_SCHEDULER]` and returns the tool result to the cell without crashing the daemon
14
+
15
+ #### Scenario: Legitimate cell tool call returns its real result
16
+ - **WHEN** a cell dispatches a legitimate tool call (e.g. `tool.read({ path })`) in a live session after the fix
17
+ - **THEN** the cell receives the tool's actual result, not the `TOOL_RUNTIME_SCHEDULER` loud error
18
+
19
+ #### Scenario: Regression probes pass after the fix
20
+ - **WHEN** the four probe cells from the diagnosis matrix (`tool.subagent` background:false, `tool.subagent` background:true, `tool.bash` background:true, `tool.read`) run in a live session after the fix
21
+ - **THEN** all four return a real result (or a visible `ToolCallError` where the call is legitimately invalid) instead of truncating, and the journal contains no new daemon crash
@@ -0,0 +1,58 @@
1
+ # skill Specification
2
+
3
+ ## Purpose
4
+
5
+ Let the model address skill bodies and internal skill resources via `skill://` URLs, with discovery tied to the same workspace source that advertises skills, and replace the skill tool's body-loading role on the REPL surface.
6
+
7
+ ## Requirements
8
+
9
+ ### Requirement: Skill body addressing
10
+ The system SHALL let read accept `skill://<name>` and return that skill's SKILL.md body in full text (no default truncation; only explicit selectors page).
11
+
12
+ #### Scenario: Reading an existing skill
13
+ - **WHEN** the model reads `skill://<registered skill name>`
14
+ - **THEN** the system returns the skill's body text in full
15
+
16
+ #### Scenario: Reading an unknown skill
17
+ - **WHEN** the model reads `skill://<unregistered name>`
18
+ - **THEN** the system returns the structured `URL_SKILL_NOT_FOUND` error ("unknown or no longer available")
19
+
20
+ ### Requirement: Skill internal resource addressing
21
+ The system SHALL let read accept `skill://<name>/<path>` and return the named file inside the skill's resource directory, loaded through the sandboxed filesystem (same containment/audit rules as host reads). A skill without a filesystem resource directory returns `URL_SKILL_NO_RESOURCE_BASE`; a subpath escaping the directory returns `URL_SKILL_RESOURCE_ESCAPE`.
22
+
23
+ #### Scenario: Reading a referenced skill file
24
+ - **WHEN** the model reads `skill://foo/references/x.md`
25
+ - **THEN** the system returns the content of `references/x.md` inside foo's resource directory
26
+
27
+ #### Scenario: Resource path escapes the skill directory
28
+ - **WHEN** the model reads `skill://foo/../../etc/passwd`
29
+ - **THEN** the system returns the structured `URL_SKILL_RESOURCE_ESCAPE` error and reads nothing
30
+
31
+ ### Requirement: Workspace-cwd-sensitive discovery
32
+ The system SHALL pass the calling agent's session cwd (`{cwd: agent.session.header.cwd}`) to every skill-registry lookup — the same source `dsh-tool-skill` uses to render `<available_skills>` — so `skill://` can address exactly the skills the catalog advertises for the current workspace.
33
+
34
+ #### Scenario: Skill visible in the current workspace
35
+ - **WHEN** the model reads `skill://foo` from a session whose cwd is inside a project root that provides foo
36
+ - **THEN** the lookup succeeds and the body resolves
37
+
38
+ #### Scenario: Skill outside the workspace is unknown
39
+ - **WHEN** a skill's project roots do not cover the session cwd
40
+ - **THEN** the lookup misses and the system returns `URL_SKILL_NOT_FOUND`, matching what `<available_skills>` advertised
41
+
42
+ ### Requirement: Path-backed search view
43
+ The system SHALL expose the handler's `resolvePath`: `skill://<name>` maps to the skill's resource-directory root and `skill://<name>/<subpath>` to the joined file (same escape guard), letting grep/glob search the real files; unmappable URLs (unknown skill, non-directory resource base, escaping subpath) resolve to `undefined` so callers fall back to text resolution with its structured error.
44
+
45
+ #### Scenario: grep searches the skill's real directory
46
+ - **WHEN** the model greps a `skill://foo` URL
47
+ - **THEN** the search runs natively over foo's on-disk resource directory
48
+
49
+ ### Requirement: Skill tool masked on the REPL surface only
50
+ The system SHALL mask the upstream `skill` tool presentation-only (ADR-0002): it disappears from the REPL `tool.*` binding names and the dashr tool-catalog section, while the host-layer native `skill` tool stays registered and executable and the `<available_skills>` discovery catalog is retained.
51
+
52
+ #### Scenario: Skill absent from the REPL surface
53
+ - **WHEN** the model inspects the kernel tool bindings or the tool-catalog text
54
+ - **THEN** neither contains `skill`, and `skill://` URLs remain the addressing path for skill content
55
+
56
+ #### Scenario: Host-native skill tool survives
57
+ - **WHEN** any host-plane consumer dispatches the native `skill` tool directly
58
+ - **THEN** the tool remains registered and executable — the mask touched only presentation surfaces
@@ -0,0 +1,222 @@
1
+ # tool-surface Specification
2
+
3
+ ## Purpose
4
+ DASHR 的模型表面(model surface)契约:哪些工具出现在 registry 投影(LLM-client 协议 tools 数组、REPL 绑定)里。核心原则——掩码作用于 tool registry(被替代了呈现面的原生工具全部 visible=false);REPL 绑定对 registry 可见集做机械/透明的自动桥接(零名单维护);被掩工具的能力保留靠三桥 service 层直调(`agent` spawn/fork、`agent_message` 消息+中断、`agent_workflow` 编排),不靠 registry 豁免。全部 REPL 指引(cell 语义、调用形、非 flat 名例外、`subagent` 别名注记)只经由 `eval` 工具的 wire description 承载——system prompt 中不存在任何 DASHR 渲染的工具目录或 control-prompt section。
5
+
6
+ ## Requirements
7
+
8
+ ### Requirement: Registry masking of replaced-presentation native tools
9
+
10
+ The system SHALL remove the native tools whose presentation surface DASHR replaces(`skill`、上游 `send_message`、`report`、`list_agents`、delegation 家族 `subagent_fork`/`interrupt_agent`/`workflow`/`ralph`)from the agent's tool registry projection via an agent-scope registry restriction —— wire tools array 与 REPL bindings 同源于该 projection,移除因此均匀生效。`subagent` is deliberately NOT masked:它在每个表面保持可见,且 **`eval` 工具的 description** 注记它是 `agent` delegation tool(统一 agent-spawn 入口)的别名。The restriction MUST NOT touch the registered tool definitions themselves;DASHR preserves each masked tool's native capability at the tool-bridge level(not by registry exemption):`agent` spawns/forks subagents、`agent_message` 经 host-plane service 层传递 child-downlink/parent-uplink/interrupt、`agent_workflow` 把 script/rfc 透传给 CAPTURED native workflow/ralph definitions(workflowEngine service 是 preset delegation realm 的 entry-local 服务,任何外部 ctx 不可见——native execute closures 从内部解析);`agent://` 取代 `list_agents`、`read skill://` 取代 `skill`。
11
+
12
+ #### Scenario: Masked tool absent from every model-facing surface
13
+
14
+ - **WHEN** an agent session starts under DASHR
15
+ - **THEN** the wire tools array 与 the REPL bindings 均不含 masked 名,对 masked 名的调用返回 `UNKNOWN_TOOL`
16
+
17
+ #### Scenario: subagent stays visible as an annotated alias
18
+
19
+ - **WHEN** an agent session starts under DASHR
20
+ - **THEN** `subagent` remains present on the wire tools array 与 the REPL bindings,且 `eval` 工具 description 注明它是 `agent` delegation tool 的别名
21
+
22
+ #### Scenario: Masked capability preserved through the bridge
23
+
24
+ - **WHEN** the model sends a child-downlink, parent-uplink, or interrupt through the `agent_message` bridge
25
+ - **THEN** the service layer executes it with native delivery semantics (user-role next-turn delivery, `messageId` confirmation) and native authorization (direct-child-only lineage, ancestor authority for interrupt)
26
+
27
+ #### Scenario: DASHR's own wrappers unaffected
28
+
29
+ - **WHEN** the agent-scope restriction denies a native name that a DASHR wrapper shadows on the agent's own layer
30
+ - **THEN** the wrapper (`read`/`write`/`grep`/`glob`, `agent`/`agent_message`/`agent_workflow`) remains visible and callable on every surface
31
+
32
+ ### Requirement: Delegation bridges are registry tools
33
+
34
+ The system SHALL register the delegation bridges(`agent`、`agent_message`、`agent_workflow`)as real tools in the tool registry(与 `eval` transport 同一 host registration 层),runtime argument validation inside their execute、structured `{ error }` return values(bad input 不抛异常)。Registry projection 是**两个**模型表面的 single source:wire tools array 与 REPL `tool.*` bindings(经 mechanical auto-bridge)。两个表面 SHALL 每个 session name-by-name 相等(以 mechanical binding rule 的 flat-name 限定为界);唯一允许的例外是 `eval` 本身排除在 binding set 之外(self-call prevention)。
35
+
36
+ #### Scenario: Bridge callable directly on the wire
37
+
38
+ - **WHEN** the model sends a direct tool call `agent` with `{ description, prompt }` (no cell)
39
+ - **THEN** the call dispatches through the normal kernel pipeline and returns the same result shape the REPL binding returns, with the same audit events as any registry tool
40
+
41
+ #### Scenario: Three-surface name equality
42
+
43
+ - **WHEN** a DASHR session starts
44
+ - **THEN** 目录表面已随「Catalog section presents REPL bridge instructions」的 REMOVED 撤销,原三表面等式收敛为两表面:the wire tools array 与 the REPL binding names 在 flat-name 规则内 equal as sets,excepting only `eval`
45
+
46
+ #### Scenario: No dual-source drift
47
+
48
+ - **WHEN** a bridge's parameter surface changes
49
+ - **THEN** the wire schema 与 REPL binding 一起变化,因为两者都派生自同一注册 schema
50
+
51
+ ### Requirement: eval transport description matches runtime semantics
52
+
53
+ The system SHALL state the eval transport's top-level semantics truthfully in **the `eval` tool's model-facing description(唯一的 REPL 指引载体)**:top-level `await` works —— kernel 以 `PyCF_ALLOW_TOP_LEVEL_AWAIT` 编译 cell 并运行 module coroutine;top-level `return` is a SyntaxError(cell 运行于 module scope,globals = locals)。The description SHALL NOT claim top-level `return` is accepted.
54
+
55
+ #### Scenario: Description promises only what the kernel does
56
+
57
+ - **WHEN** the model reads the `eval` tool description
58
+ - **THEN** the text states that top-level `await` works,states that top-level `return` is a SyntaxError(module-scope cell),and contains no claim that top-level `return` is accepted
59
+
60
+ #### Scenario: Top-level return stays rejected
61
+
62
+ - **WHEN** a cell contains a top-level `return`
63
+ - **THEN** the kernel rejects it with a SyntaxError, matching the description
64
+
65
+ ### Requirement: eval description is the single REPL guidance source
66
+
67
+ The system SHALL carry ALL REPL guidance in the `eval` tool's wire description —— cell 语义、直调 vs 进 cell 的判据、非 flat 名例外、`subagent` 别名注记、**置于 description 末尾**的 mechanical bridge 调用形 —— 内容从**插件源码中的 Markdown 文件**加载、注册工具时作为 `description` 生效;system prompt 中 SHALL NOT 存在任何 DASHR 渲染的工具目录或 control-prompt section。桥接指引 SHALL 只陈述**一个**统一调用形、一句话说清:`await tool.<name>(argsObject)`,argsObject = 该工具 wire JSON-Schema 参数对象写成的 Python dict 字面量(同字段名、单个位置参数、不用 kwargs),唯一系统性语法差异为 `true`/`false`/`null` → `True`/`False`/`None`;SHALL NOT 渲染 per-tool 签名表,且 SHALL NOT 对桥接调用的返回值形态作任何陈述(不写"不保证形状/需试错"类措辞)。描述中的桥接示例 SHALL 使用与被引工具 wire schema 一致的参数名。
68
+
69
+ #### Scenario: System prompt carries no DASHR catalog or control section
70
+
71
+ - **WHEN** an agent session renders its system prompt
72
+ - **THEN** 没有 DASHR 来源的 section 枚举 per-tool 签名,也没有独立的 control-prompt section 教 cell 范式;全部 REPL 指引只经由 `eval` description 到达模型
73
+
74
+ #### Scenario: Description loads from the source Markdown
75
+
76
+ - **WHEN** the plugin registers the `eval` tool
77
+ - **THEN** 其 wire description 等于包内 Markdown 指引文件的内容——编辑该文件即改变模型可见的 description
78
+
79
+ #### Scenario: One bridge call form, one syntax delta
80
+
81
+ - **WHEN** the model reads the bridge instructions in the `eval` description
82
+ - **THEN** it sees the single positional-args-object call form 与 `True`/`False`/`None` 大小写映射,and no per-tool signature table or output-shape caveat(无任何"不保证形态/试错"措辞)
83
+
84
+ #### Scenario: Examples match wire parameter names
85
+
86
+ - **WHEN** the description shows a bridge example for `read`
87
+ - **THEN** 参数键与 `read` 的 wire schema 一致(如 `path`),而非其它工具的键名
88
+
89
+ #### Scenario: Guidance lives and dies with the tool
90
+
91
+ - **WHEN** a session's scope excludes the `eval` tool
92
+ - **THEN** 任何地方都不渲染 REPL 指引(指引即工具自身的 description);`eval` 在场时指引必然在场
93
+
94
+ #### Scenario: Alias annotation present
95
+
96
+ - **WHEN** the model reads the `eval` description
97
+ - **THEN** it states that `subagent` is an alias of the `agent` delegation tool,两者经同一 runtime delegate
98
+
99
+ #### Scenario: Non-flat exception present
100
+
101
+ - **WHEN** the model reads the `eval` description
102
+ - **THEN** it states that 含非标识符字符(如连字符)的工具名没有 `tool.<name>` member,必须以 direct tool call 调用
103
+
104
+ ### Requirement: Masking failures surface loudly
105
+
106
+ The system SHALL surface a structured error, not a silent skip, when restricting any masked tool name fails at session start;application 完成后 mask SHALL verify 每个 masked 名在 **the wire tools array 与 the REPL bindings** 中均不存在。
107
+
108
+ #### Scenario: A masked name's restriction errors and the session reports it
109
+
110
+ - **WHEN** applying the mask, a single masked name's registry restriction throws
111
+ - **THEN** the session surfaces the failure as a structured error naming the masked tool, and the name does not silently remain on any model-facing surface
112
+
113
+ #### Scenario: Masked names absent after successful application
114
+
115
+ - **WHEN** an agent session starts under DASHR with a healthy registry
116
+ - **THEN** the wire tools array 与 the REPL bindings contain none of the masked names(`skill`、`send_message`、`report`、`list_agents`、`subagent_fork`、`interrupt_agent`、`workflow`、`ralph`),and a call naming a masked tool returns `UNKNOWN_TOOL`
117
+
118
+ ### Requirement: REPL bindings bridge the visible registry mechanically
119
+ The system SHALL install REPL bindings by automatic, transparent conversion of every flat-bindable name in the registry's visible set at session start — no manual allowlist or denylist; masked names are naturally absent because the binding source and the masking act on the same projection. Non-flat names SHALL be skipped — a name is non-flat when it contains characters outside `[A-Za-z0-9_]` (e.g. hyphens); a `__` infix alone is a legal identifier and does not by itself make a name non-flat — and the bridge instructions SHALL state the name-shape limitation without enumerating affected tools.
120
+
121
+ #### Scenario: A newly registered host tool appears in the REPL without list edits
122
+ - **WHEN** the host registers a new flat-named tool after a DASHR upgrade
123
+ - **THEN** the next agent session exposes it as `tool.<name>` with no DASHR source change
124
+
125
+ #### Scenario: Non-flat MCP names documented, not listed
126
+ - **WHEN** an MCP tool named `mcp__server__tool-name` is registered
127
+ - **THEN** no binding is created for it, and the bridge instructions explain the name-shape limitation
128
+
129
+ #### Scenario: Double-underscore infix alone stays bindable
130
+ - **WHEN** a tool named `mcp__server__tool` (identifier characters only, no hyphen) is registered
131
+ - **THEN** the name is flat-bindable (`'mcp__server__tool'.isidentifier()` is true) and appears as `tool.<name>` unless separately masked
132
+
133
+ ### Requirement: llm_completion tool
134
+ The system SHALL provide an `llm_completion` tool: a one-shot, stateless LLM call — no tools, no conversation history, no agent creation. Inputs: `{ prompt, system?, maxTokens? }`; output: the model's text. The call SHALL be attributed to the calling agent's session through the normal tool-call audit (the host's auxiliary-purpose enum is closed and carries no completion class), SHALL honor the caller's abort signal, and SHALL resolve its model route from the calling agent's current model selection, and SHALL answer a structured error value — never a silent fallback route — when no selection is available. A finish other than a clean stop, or any tool-call block in the output, SHALL produce a structured error value, not a thrown exception.
135
+
136
+ #### Scenario: Zero-spawn judge step inside a cell
137
+ - **WHEN** a cell calls `await tool.llm_completion({ prompt: "<judge prompt>", system: "<rubric>" })`
138
+ - **THEN** the value returned is the model's text; no subagent is spawned, no session besides the caller's is created, and the call is auditable under its own purpose
139
+
140
+ #### Scenario: Model route follows the caller
141
+ - **WHEN** the calling agent's selected model differs from the host default
142
+ - **THEN** the completion runs on the caller's selection
143
+
144
+ #### Scenario: Degraded finish is a structured error
145
+ - **WHEN** the completion hits maxTokens or aborts
146
+ - **THEN** the tool returns `{ error: <description> }` rather than throwing
147
+
148
+ ### Requirement: REPL tool namespace introspection
149
+ The system SHALL make the REPL `tool` namespace introspectable: `dir(tool)` returns the sorted list of bound tool names — exactly the names callable as `tool.<name>(argsObject)`. The underlying injected mapping (e.g. `__dashr_injected__`) remains unchanged for compatibility; `dir()` is the documented introspection surface.
150
+
151
+ #### Scenario: dir(tool) lists the binding set
152
+ - **WHEN** a cell runs `dir(tool)`
153
+ - **THEN** the returned list equals the sorted set of names bound in the `tool` namespace for that run (dunder members aside), including the delegation bridges and `llm_completion`
154
+
155
+ ### Requirement: Hashline edit family registered on the agent's own layer
156
+
157
+ The system SHALL register the vendored hashline edit family on each agent's own scope layer at session start — `edit` (hash-anchored ordered edit tuples, shadowing the preset's built-in edit by nearest-layer resolution, no mask entry needed) and `undo_last_edit` (revert of the most recent hashline edit) — alongside the URL-aware read/write/grep/glob wrappers, unwinding with the agent. The write tool SHALL remain the upstream full-file write with its native confirmation envelope: no hook SHALL append a hashline preview to write results, and the hashline guidance SHALL NOT promise post-write anchors (the model MAY edit directly using anchors derived from the content it just wrote, or read first). The hashline guidance sections SHALL shadow the preset's built-in tool guidance on the same layer (compiled defaults when no agentPresets service or a failing override — never a failed install).
158
+
159
+ #### Scenario: A hash-anchored edit lands and is reversible
160
+
161
+ - **WHEN** the model calls `edit` with anchored edit tuples on a file whose current content matches the anchors
162
+ - **THEN** the edit applies atomically (drift-checked against current content), and a subsequent `undo_last_edit` reverts it
163
+
164
+ #### Scenario: A write result stays upstream-native
165
+
166
+ - **WHEN** the model calls `write` and it succeeds
167
+ - **THEN** the result content is the upstream confirmation envelope with no auto-read/anchor section appended, and no read is required before the next anchored `edit` on that file
168
+
169
+ #### Scenario: The shadow replaces the built-in edit without masking
170
+
171
+ - **WHEN** an agent session starts under DASHR
172
+ - **THEN** the `edit` the model sees is the hashline tool (own-layer shadow), the preset's built-in edit is unreachable for that agent, and no deny-list entry names `edit`
173
+
174
+ ### Requirement: Lsp feedback rides edit results
175
+ The system SHALL attach the same write-feedback diagnostics contract to successful edits: after a landed `edit` with an explicit path, the result content carries the diagnostics summary computed from the exact landed content (didSave freshness, timeout degradation, span guard — the `dvc` write-feedback requirement's terms apply verbatim). Anchor-only edits (path inferred from anchors) and non-edit tools pass through untouched; the write tool's feedback stays with its wrapper (no double pull).
176
+
177
+ #### Scenario: An edit that introduces a type error reports it
178
+ - **WHEN** an edit lands content introducing a type error in a file with a language server and its check completes within the budget
179
+ - **THEN** the edit result text carries the diagnostics summary for the exact landed content
180
+
181
+ ### Requirement: Hashline edit verification is content-anchored
182
+
183
+ The system SHALL verify each edit tuple's anchors against the CURRENT file content before consulting any ledger: an anchor SHALL be accepted when its hash locates a unique, consistently pairable position in the current canonical line hashes; the served ledger SHALL be advisory (echo/undo attribution) and keyed by canonical absolute path with no session identity, so anchors survive session-tree forks and continuation without a re-read. Genuine drift SHALL still fail closed with nothing written, batch atomicity SHALL be unchanged, and a multi-tuple batch failure SHALL instruct reading the file once and resubmitting the whole batch.
184
+
185
+ #### Scenario: An edit across a forked session lands without a re-read
186
+
187
+ - **WHEN** a file is written or read in one session node, the conversation continues in a forked node (new session identity), and the model submits anchored edit tuples derived from that earlier content
188
+ - **THEN** the edit applies without any intervening `read`, because verification matched current content
189
+
190
+ #### Scenario: A drifted line still fails closed
191
+
192
+ - **WHEN** an anchor's hash no longer exists in the current file (content changed or line removed externally)
193
+ - **THEN** the tuple is rejected with a drift error stating the content changed and a read is needed, and nothing is written
194
+
195
+ #### Scenario: An ambiguous anchor falls back before failing
196
+
197
+ - **WHEN** an anchor's hash occurs at multiple current positions and the served ledger cannot disambiguate the span
198
+ - **THEN** the tuple is rejected with nothing written, and the error names the ambiguity
199
+
200
+ #### Scenario: Multi-tuple failure copy is actionable
201
+
202
+ - **WHEN** any tuple in a multi-tuple batch fails verification
203
+ - **THEN** the batch aborts with zero writes and the error instructs reading the file once, then resubmitting the whole batch
204
+
205
+ ### Requirement: Hashline store centralized under DSH_HOME
206
+
207
+ The hashline store SHALL live at a single location — `$DSH_HOME/storages/dsh-better-edit/hash-store.sqlite` — for tool calls, previews, and tests alike, resolved through the harness home resolver so `DSH_HOME` isolates deployments; no per-workspace dot-directory SHALL be created. The served table SHALL be keyed by canonical absolute path (no session column), the 7-day TTL prune SHALL be retained, and the store schema version SHALL bump with a rebuild-on-mismatch gate that drops and recreates legacy session-keyed served tables.
208
+
209
+ #### Scenario: No dot-directory is created
210
+
211
+ - **WHEN** hashline tools run inside any workspace
212
+ - **THEN** state lands in the centralized store and no `<workspace>/.dsh_better_edit/` directory is created
213
+
214
+ #### Scenario: DSH_HOME isolates deployments
215
+
216
+ - **WHEN** the harness runs with a test `DSH_HOME` (e.g. the 4999 line)
217
+ - **THEN** its hashline store is a separate file under that home and never touches the production store
218
+
219
+ #### Scenario: Legacy session-keyed served tables rebuild
220
+
221
+ - **WHEN** the store opens with a schema version below the current one, or a served table still carrying a `session_id` column
222
+ - **THEN** the served table is dropped and recreated with the path-keyed schema, and the version marker is updated