better-dsh 0.2.4 → 0.2.5

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 (1235) hide show
  1. package/cordis.patch.yml +58 -16
  2. package/docs/10_plans/2026-09-23-remote-execution-framework.md +236 -0
  3. package/docs/10_plans/2026-09-23-remote-framework-impl.md +2083 -0
  4. package/docs/10_plans/2026-09-26-lsp-ast-reminder.md +64 -0
  5. package/docs/20_specs/agent/spec.md +54 -0
  6. package/docs/20_specs/ast/spec.md +34 -0
  7. package/docs/20_specs/compaction-recall/spec.md +46 -0
  8. package/docs/20_specs/ctx/spec.md +107 -0
  9. package/docs/20_specs/dsh/spec.md +47 -0
  10. package/docs/20_specs/dvc/spec.md +87 -0
  11. package/docs/20_specs/escalation-guidance/spec.md +44 -0
  12. package/docs/20_specs/fs-scheme-resolution/spec.md +37 -0
  13. package/docs/20_specs/hash-edit/spec.md +41 -0
  14. package/docs/20_specs/http-read/spec.md +73 -0
  15. package/docs/20_specs/kernel-provisioning/spec.md +53 -0
  16. package/docs/20_specs/lsp/spec.md +121 -0
  17. package/docs/20_specs/mobile-layout/spec.md +108 -0
  18. package/docs/20_specs/model-failover/spec.md +20 -0
  19. package/docs/20_specs/plugins-page-components/spec.md +79 -0
  20. package/docs/20_specs/preact-ui-shell/spec.md +22 -0
  21. package/docs/20_specs/repl-dispatch-resilience/spec.md +21 -0
  22. package/docs/20_specs/skill/spec.md +58 -0
  23. package/docs/20_specs/tool-surface/spec.md +222 -0
  24. package/docs/20_specs/url-schema/spec.md +148 -0
  25. package/docs/20_specs/web-trust-fence/spec.md +43 -0
  26. package/docs/50_test-reports/2026-09-17-plugins/351/241/265/345/205/255/347/273/204/344/273/266/346/213/206/345/210/206/345/256/236/346/265/213/346/212/245/345/221/212.md +76 -0
  27. package/docs/50_test-reports/2026-09-22-4988/345/217/214/345/271/263/351/235/242/345/220/257/345/212/250/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +76 -0
  28. package/docs/50_test-reports/2026-09-22-better-dsh/347/273/204/344/273/266/347/203/255/346/217/222/346/213/224/344/270/216/344/276/235/350/265/226/347/272/247/350/201/224/345/256/236/346/265/213/346/212/245/345/221/212.md +134 -0
  29. package/docs/50_test-reports/2026-09-23-remote-framework/345/256/236/346/265/213/346/212/245/345/221/212.md +92 -0
  30. package/docs/50_test-reports/2026-09-23-remote-framework/347/254/254/344/270/200/344/272/272/347/247/260/345/244/215/346/265/213/346/212/245/345/221/212.md +125 -0
  31. package/docs/50_test-reports/2026-09-23-ssh/345/267/245/345/205/267assisted-pty/344/274/232/350/257/235framing/345/256/236/346/265/213/346/212/245/345/221/212.md +207 -0
  32. package/docs/50_test-reports/2026-09-24-v0.1.7-rc.1/345/257/271/351/275/220/350/275/256-compaction/344/270/216failover/350/256/276/347/275/256/351/235/242/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +65 -0
  33. package/docs/50_test-reports/2026-09-27-lsp-ast-reminder-4999/345/256/236/346/265/213/346/212/245/345/221/212.md +53 -0
  34. package/docs/50_test-reports/2026-09-28-ctx-scheme/351/225/277/344/274/232/350/257/235utility/345/256/236/346/265/213/346/212/245/345/221/212.md +155 -0
  35. package/docs/50_test-reports/2026-10-01-v0.2.4d-web-password-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +105 -0
  36. package/docs/50_test-reports/2026-10-02-ctx-navigation/345/256/236/346/265/213/346/212/245/345/221/212.md +137 -0
  37. package/docs/50_test-reports/2026-10-02-v0.2.0-rc.2/345/257/271/351/275/220/350/275/256/345/256/236/346/265/213/346/212/245/345/221/212.md +38 -0
  38. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/MdxPage-CTY7atqe.js +11 -0
  39. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/extract_omp.mjs +42 -0
  40. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/fetch_pi.py +52 -0
  41. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/jsx-runtime-BHwPObl3.js +13 -0
  42. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/omp_extracted.json +1 -0
  43. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/omp_pages.txt +35 -0
  44. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/package.json +1 -0
  45. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/pi_convert.py +49 -0
  46. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/pi_pages.txt +30 -0
  47. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/.tools/serialize_omp.py +250 -0
  48. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/README.md +80 -0
  49. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/Overview.md +88 -0
  50. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/acp.md +151 -0
  51. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/advisor.md +185 -0
  52. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/agents-and-roles.md +168 -0
  53. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/approvals.md +200 -0
  54. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/cli.md +381 -0
  55. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/code-intelligence.md +225 -0
  56. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/collab.md +207 -0
  57. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/commit.md +169 -0
  58. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/compaction.md +195 -0
  59. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/computer.md +224 -0
  60. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/context-files.md +184 -0
  61. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/custom-models.md +284 -0
  62. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/custom-tools.md +248 -0
  63. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/debugging.md +254 -0
  64. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/editing.md +157 -0
  65. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/env.md +552 -0
  66. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/extension-authoring.md +378 -0
  67. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/files.md +144 -0
  68. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/github.md +175 -0
  69. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/goal.md +156 -0
  70. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/handoff.md +139 -0
  71. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/hooks.md +257 -0
  72. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/keybindings.md +204 -0
  73. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/magic-keywords.md +135 -0
  74. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/marketplace.md +269 -0
  75. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/mcp-authoring.md +243 -0
  76. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/mcp.md +260 -0
  77. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/memory.md +306 -0
  78. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/modes.md +214 -0
  79. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/pages.txt +56 -0
  80. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/plan.md +126 -0
  81. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/plugins.md +287 -0
  82. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/prewalk.md +122 -0
  83. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/prompt-templates.md +149 -0
  84. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/providers.md +229 -0
  85. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/quickstart.md +117 -0
  86. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/review.md +248 -0
  87. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/roles.md +247 -0
  88. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/rpc.md +523 -0
  89. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/sdk.md +260 -0
  90. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/secrets.md +199 -0
  91. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/security.md +260 -0
  92. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/session-format.md +254 -0
  93. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/session-tree.md +135 -0
  94. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/sessions.md +223 -0
  95. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/settings.md +290 -0
  96. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/skills.md +187 -0
  97. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/slash.md +328 -0
  98. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/subagent-authoring.md +165 -0
  99. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/subagents.md +149 -0
  100. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/themes.md +230 -0
  101. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/tools.md +120 -0
  102. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/ttsr.md +242 -0
  103. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/using.md +214 -0
  104. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/vibe.md +187 -0
  105. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/omp/web.md +233 -0
  106. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/compaction.md +427 -0
  107. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/containerization.md +162 -0
  108. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/custom-provider.md +782 -0
  109. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/development.md +96 -0
  110. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/environment-variables.md +104 -0
  111. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/extensions.md +3058 -0
  112. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/index.md +89 -0
  113. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/json.md +105 -0
  114. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/keybindings.md +244 -0
  115. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/llama-cpp.md +106 -0
  116. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/models.md +587 -0
  117. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/packages.md +234 -0
  118. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/pages.txt +30 -0
  119. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/prompt-templates.md +101 -0
  120. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/providers.md +327 -0
  121. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/quickstart.md +172 -0
  122. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/rpc.md +1679 -0
  123. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/sdk.md +1239 -0
  124. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/security.md +64 -0
  125. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/session-format.md +454 -0
  126. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/sessions.md +150 -0
  127. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/settings.md +374 -0
  128. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/shell-aliases.md +18 -0
  129. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/skills.md +241 -0
  130. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/terminal-setup.md +199 -0
  131. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/termux.md +135 -0
  132. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/themes.md +328 -0
  133. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/tmux.md +68 -0
  134. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/tui.md +965 -0
  135. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/usage.md +315 -0
  136. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/pi-and-omp/pi/windows.md +44 -0
  137. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/SKILL.md +147 -0
  138. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch01-user-guide.md +123 -0
  139. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch02-plugin-basics.md +127 -0
  140. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch03-plugin-framework-practice.md +120 -0
  141. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch04-cordis-fundamentals.md +129 -0
  142. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch05-cordis-api.md +115 -0
  143. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch06-architecture.md +109 -0
  144. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch07-capability-seams.md +97 -0
  145. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch08-internals-pipelines.md +111 -0
  146. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch09-api-gateway.md +106 -0
  147. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch10-config-catalog.md +97 -0
  148. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch11-tool-catalog.md +121 -0
  149. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch12-persistence-catalog.md +109 -0
  150. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch13-subsystems-core-session.md +106 -0
  151. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch14-subsystems-agent-loop.md +111 -0
  152. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch15-subsystems-tool-execution.md +106 -0
  153. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch16-subsystems-session-data.md +132 -0
  154. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch17-subsystems-llm-streaming.md +128 -0
  155. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch18-subsystems-web-ui.md +142 -0
  156. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch19-cookbook.md +149 -0
  157. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch20-development-testing.md +87 -0
  158. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch21-postmortems.md +82 -0
  159. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch22-i18n.md +86 -0
  160. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/cheatsheet.md +67 -0
  161. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/glossary.md +57 -0
  162. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/patterns.md +88 -0
  163. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/AGENTS.md +75 -0
  164. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/agent-lifecycle.md +84 -0
  165. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/agent-lifecycle.zh.md +86 -0
  166. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/api-gateway.md +164 -0
  167. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/api-gateway.zh.md +164 -0
  168. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/architecture.md +150 -0
  169. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/architecture.zh.md +154 -0
  170. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/capability-seams.md +543 -0
  171. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/capability-seams.zh.md +545 -0
  172. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/config-catalog.md +3473 -0
  173. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/config-catalog.zh.md +3474 -0
  174. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-package.md +117 -0
  175. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-package.zh.md +119 -0
  176. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-remote-api.md +197 -0
  177. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-remote-api.zh.md +197 -0
  178. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-settings-card.md +102 -0
  179. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-settings-card.zh.md +102 -0
  180. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-tool.md +101 -0
  181. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-tool.zh.md +103 -0
  182. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-vendored-package.md +59 -0
  183. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  184. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-an-llm-adapter.md +43 -0
  185. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  186. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/extension-cookbook.md +132 -0
  187. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/extension-cookbook.zh.md +136 -0
  188. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/maintaining-dsh-code-review.md +64 -0
  189. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  190. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  191. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  192. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/context.md +364 -0
  193. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/context.zh.md +366 -0
  194. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/events.md +207 -0
  195. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/events.zh.md +209 -0
  196. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/fiber.md +375 -0
  197. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/fiber.zh.md +377 -0
  198. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/inherited.md +39 -0
  199. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/registry.md +152 -0
  200. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/registry.zh.md +154 -0
  201. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/service.md +102 -0
  202. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/service.zh.md +104 -0
  203. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-primer.md +45 -0
  204. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-primer.zh.md +51 -0
  205. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/01-first-plugin.md +95 -0
  206. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  207. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  208. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  209. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/03-services.md +98 -0
  210. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/03-services.zh.md +98 -0
  211. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/04-events.md +144 -0
  212. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/04-events.zh.md +144 -0
  213. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/05-config.md +84 -0
  214. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/05-config.zh.md +84 -0
  215. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  216. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  217. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/07-into-the-harness.md +108 -0
  218. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  219. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/index.md +60 -0
  220. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/index.zh.md +62 -0
  221. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/deepseek-llm-api-wire-extensions.md +163 -0
  222. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  223. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/defensive-patterns.md +33 -0
  224. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/defensive-patterns.zh.md +35 -0
  225. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/development.md +167 -0
  226. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/development.zh.md +173 -0
  227. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/event-producer-consumer.md +86 -0
  228. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/event-producer-consumer.zh.md +88 -0
  229. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/glossary.md +45 -0
  230. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/glossary.zh.md +45 -0
  231. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/graph-atlas.md +22 -0
  232. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/graph-atlas.zh.md +24 -0
  233. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/README.md +60 -0
  234. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/README.zh.md +62 -0
  235. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/style-samples.md +87 -0
  236. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/terminology.md +214 -0
  237. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-prompt.md +263 -0
  238. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-rules.md +69 -0
  239. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-rules.zh.md +69 -0
  240. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/module-graph.md +1411 -0
  241. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/module-graph.zh.md +1413 -0
  242. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/persistence-catalog.md +1075 -0
  243. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/persistence-catalog.zh.md +1077 -0
  244. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  245. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  246. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  247. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  248. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  249. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  250. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  251. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  252. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/README.md +18 -0
  253. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/README.zh.md +18 -0
  254. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/rescope.md +53 -0
  255. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/rescope.zh.md +53 -0
  256. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/README.md +61 -0
  257. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/README.zh.md +61 -0
  258. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/agent-team.md +207 -0
  259. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/agent-team.zh.md +207 -0
  260. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/approval.md +170 -0
  261. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/approval.zh.md +170 -0
  262. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/attachment.md +351 -0
  263. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/attachment.zh.md +351 -0
  264. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/client-modules.md +168 -0
  265. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/client-modules.zh.md +168 -0
  266. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/code-runtime.md +195 -0
  267. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/code-runtime.zh.md +195 -0
  268. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/commands.md +219 -0
  269. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/commands.zh.md +219 -0
  270. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/compaction.md +238 -0
  271. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/compaction.zh.md +238 -0
  272. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/conversation.md +258 -0
  273. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/conversation.zh.md +258 -0
  274. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/core.md +1209 -0
  275. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/core.zh.md +1219 -0
  276. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/credentials.md +329 -0
  277. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/credentials.zh.md +329 -0
  278. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/extensions.md +382 -0
  279. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/extensions.zh.md +382 -0
  280. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/feedback.md +266 -0
  281. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/feedback.zh.md +266 -0
  282. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/filesystem.md +505 -0
  283. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/filesystem.zh.md +505 -0
  284. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/goal.md +277 -0
  285. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/goal.zh.md +277 -0
  286. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/invariants.md +88 -0
  287. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/invariants.zh.md +88 -0
  288. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/jobs.md +290 -0
  289. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/jobs.zh.md +290 -0
  290. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/llm-streaming.md +1080 -0
  291. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/llm-streaming.zh.md +1086 -0
  292. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/lsp.md +202 -0
  293. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/lsp.zh.md +202 -0
  294. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/permission-presets.md +131 -0
  295. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/permission-presets.zh.md +131 -0
  296. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/persistence.md +395 -0
  297. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/persistence.zh.md +395 -0
  298. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/plan.md +87 -0
  299. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/plan.zh.md +87 -0
  300. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/sandbox.md +220 -0
  301. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/sandbox.zh.md +220 -0
  302. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/schedule.md +192 -0
  303. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/schedule.zh.md +192 -0
  304. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/scope.md +59 -0
  305. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/scope.zh.md +59 -0
  306. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-projection.md +354 -0
  307. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-projection.zh.md +354 -0
  308. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-query.md +509 -0
  309. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-query.zh.md +509 -0
  310. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-reference.md +219 -0
  311. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-reference.zh.md +219 -0
  312. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-telemetry.md +194 -0
  313. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-telemetry.zh.md +194 -0
  314. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-title.md +204 -0
  315. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-title.zh.md +204 -0
  316. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session.md +1155 -0
  317. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session.zh.md +1159 -0
  318. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/settings.md +405 -0
  319. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/settings.zh.md +405 -0
  320. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/shell.md +303 -0
  321. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/shell.zh.md +303 -0
  322. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/skills.md +354 -0
  323. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/skills.zh.md +354 -0
  324. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/slots.md +175 -0
  325. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/slots.zh.md +175 -0
  326. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/spill.md +117 -0
  327. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/spill.zh.md +117 -0
  328. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/storage.md +260 -0
  329. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/storage.zh.md +260 -0
  330. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subagent.md +766 -0
  331. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subagent.zh.md +770 -0
  332. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subprocess.md +324 -0
  333. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subprocess.zh.md +324 -0
  334. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/system-prompt.md +220 -0
  335. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/system-prompt.zh.md +220 -0
  336. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/terminal.md +184 -0
  337. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/terminal.zh.md +184 -0
  338. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/todo.md +32 -0
  339. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/todo.zh.md +32 -0
  340. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/token-meter.md +105 -0
  341. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/token-meter.zh.md +105 -0
  342. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/tools.md +720 -0
  343. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/tools.zh.md +720 -0
  344. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/typert.md +343 -0
  345. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/typert.zh.md +343 -0
  346. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/user-questions.md +178 -0
  347. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/user-questions.zh.md +178 -0
  348. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-client.md +95 -0
  349. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-client.zh.md +95 -0
  350. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-server.md +154 -0
  351. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-server.zh.md +154 -0
  352. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web.md +206 -0
  353. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web.zh.md +206 -0
  354. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/webhook.md +70 -0
  355. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/webhook.zh.md +70 -0
  356. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workflow.md +278 -0
  357. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workflow.zh.md +278 -0
  358. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workspace.md +321 -0
  359. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workspace.zh.md +321 -0
  360. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/testing.md +54 -0
  361. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/testing.zh.md +54 -0
  362. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-catalog.md +2225 -0
  363. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-catalog.zh.md +2233 -0
  364. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-execution-pipeline.md +62 -0
  365. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-execution-pipeline.zh.md +64 -0
  366. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/config.md +106 -0
  367. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/config.zh.md +106 -0
  368. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/index.md +144 -0
  369. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/index.zh.md +144 -0
  370. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/publish.md +183 -0
  371. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/publish.zh.md +183 -0
  372. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/tool.md +52 -0
  373. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/tool.zh.md +52 -0
  374. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/events.md +143 -0
  375. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/events.zh.md +143 -0
  376. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/index.md +137 -0
  377. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/index.zh.md +137 -0
  378. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/service.md +148 -0
  379. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/service.zh.md +150 -0
  380. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/dynamic-cordis.md +15 -0
  381. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  382. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/index.md +155 -0
  383. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/index.zh.md +155 -0
  384. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/llm-adapter.md +189 -0
  385. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/llm-adapter.zh.md +189 -0
  386. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/github-review.md +102 -0
  387. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/github-review.zh.md +102 -0
  388. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/index.md +30 -0
  389. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/index.zh.md +30 -0
  390. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/mcp-memory.md +101 -0
  391. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/mcp-memory.zh.md +101 -0
  392. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/network-proxy.md +85 -0
  393. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/network-proxy.zh.md +85 -0
  394. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/providers.md +190 -0
  395. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/providers.zh.md +190 -0
  396. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/python-sdk.md +150 -0
  397. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/python-sdk.zh.md +150 -0
  398. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/schedule.md +21 -0
  399. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/schedule.zh.md +21 -0
  400. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/index.md +11 -0
  401. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/index.zh.md +11 -0
  402. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/web-styling.md +29 -0
  403. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/web-styling.zh.md +29 -0
  404. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/site-pages-map.txt +234 -0
  405. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/site-pages.json +232 -0
  406. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-README.md +63 -0
  407. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-scripts/crawl.py +103 -0
  408. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-scripts/docs-tree.json +82965 -0
  409. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-scripts/download.py +56 -0
  410. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-scripts/gen_mapping.py +125 -0
  411. package/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-scripts/pages.json +232 -0
  412. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/api-plugins.json +1 -0
  413. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/api-skills.json +4 -0
  414. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/_category_.json +8 -0
  415. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/acp-internals.md +181 -0
  416. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/adding-platform-adapters.md +788 -0
  417. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/adding-providers.md +464 -0
  418. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/adding-tools.md +211 -0
  419. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/agent-loop.md +242 -0
  420. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/architecture.md +279 -0
  421. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/billing-lifecycle.md +184 -0
  422. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/browser-provider-plugin.md +153 -0
  423. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/browser-supervisor.md +198 -0
  424. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/chronos-managed-cron-contract.md +227 -0
  425. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/cli-internals.md +85 -0
  426. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/codebase-ownership.md +34 -0
  427. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/completion-backlog-delivery.md +52 -0
  428. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/context-compression-and-caching.md +642 -0
  429. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/context-engine-plugin.md +272 -0
  430. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/contributing.md +303 -0
  431. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/creating-skills.md +438 -0
  432. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/cron-internals.md +380 -0
  433. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/desktop-plugin-sdk.md +952 -0
  434. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/egress-internals.md +319 -0
  435. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/extending-the-cli.md +192 -0
  436. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/gateway-internals.md +297 -0
  437. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/gateway-monitoring.md +309 -0
  438. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/gateway-session-lifecycle.md +621 -0
  439. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/image-gen-provider-plugin.md +316 -0
  440. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/memory-provider-plugin.md +452 -0
  441. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/micro-compaction.md +406 -0
  442. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/middleware.md +266 -0
  443. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/model-provider-plugin.md +327 -0
  444. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/multiplexing-gateway.md +228 -0
  445. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/observer-hooks.md +331 -0
  446. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/plugin-llm-access.md +506 -0
  447. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/plugins/index.md +1775 -0
  448. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/programmatic-integration.md +212 -0
  449. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/prompt-assembly.md +328 -0
  450. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/provider-runtime.md +222 -0
  451. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/relay-connector-contract.md +790 -0
  452. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/relay-shared-metrics.md +487 -0
  453. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/secret-source-plugin.md +192 -0
  454. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/session-storage.md +523 -0
  455. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/state-db-recovery.md +107 -0
  456. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/streaming-tts.md +98 -0
  457. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/subagent-lifecycle-api.md +61 -0
  458. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/terminal-environment-plugin.md +140 -0
  459. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/tools-runtime.md +250 -0
  460. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/trajectory-format.md +232 -0
  461. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/video-gen-provider-plugin.md +231 -0
  462. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/web-search-provider-plugin.md +260 -0
  463. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/developer-guide/worktree-ui-dev.md +168 -0
  464. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/_category_.json +8 -0
  465. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/installation.md +200 -0
  466. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/learning-path.md +169 -0
  467. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/nix-setup.md +1234 -0
  468. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/platform-support.md +50 -0
  469. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/quickstart.md +399 -0
  470. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/termux.md +301 -0
  471. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/getting-started/updating.md +374 -0
  472. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/_category_.json +6 -0
  473. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/agent-email-address.md +93 -0
  474. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/automate-with-cron.md +292 -0
  475. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/automation-blueprints.md +595 -0
  476. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/aws-bedrock.md +196 -0
  477. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/azure-foundry.md +334 -0
  478. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/cron-script-only.md +247 -0
  479. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/cron-troubleshooting.md +235 -0
  480. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/daily-briefing-bot.md +272 -0
  481. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/delegation-patterns.md +242 -0
  482. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/desktop-native-signin.md +125 -0
  483. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/github-pr-review-agent.md +303 -0
  484. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/google-gemini.md +270 -0
  485. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/google-vertex.md +148 -0
  486. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/local-llm-on-mac.md +252 -0
  487. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/local-ollama-setup.md +338 -0
  488. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/manage-hermes-cloud-with-mcp.md +176 -0
  489. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/microsoft-graph-app-registration.md +180 -0
  490. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/migrate-from-openclaw.md +252 -0
  491. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/minimax-oauth.md +226 -0
  492. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/oauth-over-ssh.md +172 -0
  493. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/operate-teams-meeting-pipeline.md +295 -0
  494. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/pipe-script-output.md +249 -0
  495. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/python-library.md +333 -0
  496. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/run-hermes-with-nous-portal.md +276 -0
  497. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/run-nemotron-3-ultra-free.md +123 -0
  498. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/secure-hermes-on-a-work-machine.md +182 -0
  499. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/team-telegram-assistant.md +441 -0
  500. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/tips.md +238 -0
  501. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/troubleshooting-agent-quality.md +145 -0
  502. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/use-mcp-with-hermes.md +541 -0
  503. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/use-soul-with-hermes.md +264 -0
  504. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/use-voice-mode-with-hermes.md +473 -0
  505. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/webhook-github-pr-review.md +336 -0
  506. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/work-with-skills.md +290 -0
  507. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/guides/xai-grok-oauth.md +243 -0
  508. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/index.mdx +155 -0
  509. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/integrations/buzz.md +57 -0
  510. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/integrations/index.md +126 -0
  511. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/integrations/nous-portal.md +286 -0
  512. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/integrations/providers.md +1681 -0
  513. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/_category_.json +8 -0
  514. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/automation-blueprints-catalog.mdx +36 -0
  515. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/cli-commands.md +1900 -0
  516. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/cli-symbols.md +126 -0
  517. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/environment-variables.md +952 -0
  518. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/faq.md +874 -0
  519. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/mcp-config-reference.md +439 -0
  520. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/model-catalog.md +121 -0
  521. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/optional-skills-catalog.md +303 -0
  522. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/profile-commands.md +544 -0
  523. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/skills-catalog.md +132 -0
  524. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/slash-commands.md +336 -0
  525. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/tools-reference.md +399 -0
  526. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/reference/toolsets-reference.md +171 -0
  527. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/_category_.json +8 -0
  528. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/bot-mode.md +309 -0
  529. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/checkpoints-and-rollback.md +283 -0
  530. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/cli.md +591 -0
  531. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/configuration.md +2901 -0
  532. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/configuring-models.md +414 -0
  533. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/desktop.md +728 -0
  534. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/docker.md +896 -0
  535. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/egress/index.md +10 -0
  536. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/egress/iron-proxy.md +570 -0
  537. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/egress/network-isolation.md +201 -0
  538. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/_category_.json +8 -0
  539. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/acp.md +407 -0
  540. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/api-server.md +810 -0
  541. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/batch-processing.md +230 -0
  542. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/browser.md +901 -0
  543. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/built-in-plugins.md +366 -0
  544. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/code-execution.md +319 -0
  545. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/codex-app-server-runtime.md +460 -0
  546. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/computer-use.md +636 -0
  547. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/context-files.md +237 -0
  548. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/context-references.md +142 -0
  549. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/credential-pools.md +308 -0
  550. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/credential-vault.md +122 -0
  551. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/cron.md +1262 -0
  552. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/curator.md +409 -0
  553. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/delegation.md +664 -0
  554. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/deliverable-mode.md +134 -0
  555. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/document-extraction.md +58 -0
  556. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/extending-the-dashboard.md +927 -0
  557. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/fallback-providers.md +444 -0
  558. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/goals.md +293 -0
  559. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/heartbeat.md +68 -0
  560. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/honcho.md +276 -0
  561. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/hooks.md +2007 -0
  562. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/image-generation.md +347 -0
  563. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/kanban-multi-gateway.md +52 -0
  564. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/kanban-tutorial.md +310 -0
  565. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/kanban-worker-lanes.md +142 -0
  566. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/kanban.md +1327 -0
  567. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/loops.md +122 -0
  568. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/lsp.md +307 -0
  569. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/mcp.md +957 -0
  570. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/memory-providers.md +699 -0
  571. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/memory.md +466 -0
  572. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/mixture-of-agents.md +246 -0
  573. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/overview.md +57 -0
  574. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/personality.md +289 -0
  575. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/pets.md +236 -0
  576. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/plugin-catalog.md +212 -0
  577. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/plugins.md +847 -0
  578. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/provider-routing.md +229 -0
  579. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/skills.md +1112 -0
  580. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/skins.md +271 -0
  581. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/spotify.md +279 -0
  582. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/subscription-proxy.md +203 -0
  583. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/tool-gateway.md +223 -0
  584. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/tool-search.md +277 -0
  585. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/tools.md +261 -0
  586. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/tts.md +744 -0
  587. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/vision.md +214 -0
  588. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/voice-mode.md +608 -0
  589. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/wake-word.md +343 -0
  590. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/web-dashboard.md +1206 -0
  591. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/web-search.md +506 -0
  592. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/features/x-search.md +167 -0
  593. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/git-worktrees.md +196 -0
  594. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/import-from-other-agents.md +74 -0
  595. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/local-models.md +140 -0
  596. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/managed-scope.md +157 -0
  597. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/_category_.json +8 -0
  598. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/a2a.md +130 -0
  599. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/bluebubbles.md +171 -0
  600. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/buzz.md +162 -0
  601. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/dingtalk.md +283 -0
  602. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/discord.md +936 -0
  603. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/email.md +223 -0
  604. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/feishu.md +599 -0
  605. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/google_chat.md +430 -0
  606. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/homeassistant.md +269 -0
  607. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/index.md +859 -0
  608. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/irc.md +78 -0
  609. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/line.md +201 -0
  610. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/matrix.md +910 -0
  611. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/mattermost.md +340 -0
  612. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/msgraph-webhook.md +142 -0
  613. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/ntfy.md +157 -0
  614. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/open-webui.md +296 -0
  615. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/photon.md +255 -0
  616. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/qqbot.md +123 -0
  617. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/raft.md +70 -0
  618. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/relay.md +212 -0
  619. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/signal.md +262 -0
  620. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/simplex.md +151 -0
  621. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/slack.md +1093 -0
  622. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/sms.md +203 -0
  623. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/teams-meetings.md +242 -0
  624. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/teams.md +288 -0
  625. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/telegram.md +1373 -0
  626. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/webhooks.md +694 -0
  627. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/wecom-callback.md +179 -0
  628. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/wecom.md +306 -0
  629. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/weixin.md +333 -0
  630. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/whatsapp-cloud.md +417 -0
  631. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/whatsapp.md +283 -0
  632. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/messaging/yuanbao.md +342 -0
  633. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/multi-connection-desktop.md +361 -0
  634. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/multi-profile-gateways.md +1062 -0
  635. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/profile-distributions.md +757 -0
  636. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/profiles.md +418 -0
  637. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/secrets/bitwarden.md +155 -0
  638. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/secrets/command.md +50 -0
  639. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/secrets/index.md +50 -0
  640. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/secrets/onepassword.md +169 -0
  641. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/security.md +892 -0
  642. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/sessions.md +990 -0
  643. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/apple/apple-apple-notes.md +110 -0
  644. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/apple/apple-apple-reminders.md +146 -0
  645. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/apple/apple-findmy.md +149 -0
  646. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/apple/apple-imessage.md +118 -0
  647. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-claude-code.md +763 -0
  648. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-codex.md +169 -0
  649. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-computer-use.md +355 -0
  650. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md +230 -0
  651. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-merge-reconciler.md +176 -0
  652. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-opencode.md +237 -0
  653. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-architecture-diagram.md +165 -0
  654. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-ascii-art.md +338 -0
  655. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-ascii-video.md +265 -0
  656. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-baoyu-infographic.md +256 -0
  657. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-claude-design.md +668 -0
  658. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-comfyui.md +616 -0
  659. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-design-md.md +238 -0
  660. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-excalidraw.md +212 -0
  661. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-humanizer.md +663 -0
  662. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-manim-video.md +292 -0
  663. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-p5js.md +576 -0
  664. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-popular-web-designs.md +223 -0
  665. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-pretext.md +238 -0
  666. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-sketch.md +240 -0
  667. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music.md +319 -0
  668. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/devops/devops-sdlc-review.md +195 -0
  669. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/email/email-email-inbox-triage.md +115 -0
  670. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/email/email-himalaya.md +319 -0
  671. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-codebase-inspection.md +132 -0
  672. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-auth.md +265 -0
  673. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-code-review.md +499 -0
  674. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-issue-to-pr.md +95 -0
  675. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-issues.md +388 -0
  676. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-pr-workflow.md +385 -0
  677. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/github/github-github-repo-management.md +534 -0
  678. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/media/media-gif-search.md +106 -0
  679. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/media/media-songsee.md +98 -0
  680. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/media/media-youtube-content.md +100 -0
  681. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/mlops/mlops-evaluation-evaluating-llms-harness.md +512 -0
  682. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/mlops/mlops-evaluation-weights-and-biases.md +613 -0
  683. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/mlops/mlops-huggingface-hub.md +100 -0
  684. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/mlops/mlops-inference-llama-cpp.md +267 -0
  685. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/mlops/mlops-inference-serving-llms-vllm.md +387 -0
  686. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/note-taking/note-taking-obsidian.md +85 -0
  687. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-airtable.md +243 -0
  688. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-box.md +132 -0
  689. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-document-to-action-items.md +99 -0
  690. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-docx.md +213 -0
  691. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-google-workspace.md +348 -0
  692. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-maps.md +210 -0
  693. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-meeting-action-items.md +105 -0
  694. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-nano-pdf.md +70 -0
  695. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-notion.md +463 -0
  696. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-ocr-and-documents.md +193 -0
  697. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-pdf.md +142 -0
  698. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-powerpoint.md +237 -0
  699. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-product-price-monitor.md +97 -0
  700. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-session-librarian.md +122 -0
  701. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-teams-meeting-pipeline.md +129 -0
  702. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-weekly-review-planning.md +99 -0
  703. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/productivity/productivity-xlsx.md +213 -0
  704. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-arxiv.md +300 -0
  705. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-blocked-page-recovery.md +155 -0
  706. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-blogwatcher.md +152 -0
  707. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-competitor-news-monitor.md +106 -0
  708. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-grounded-citations.md +274 -0
  709. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-llm-wiki.md +526 -0
  710. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/research/research-research-paper-writing.md +1645 -0
  711. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/smart-home/smart-home-openhue.md +127 -0
  712. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/social-media/social-media-xurl.md +450 -0
  713. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-codebase-inspection.md +132 -0
  714. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-dogfood.md +183 -0
  715. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-github.md +73 -0
  716. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-hermes-agent-skill-authoring.md +230 -0
  717. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-inspecting-hermes-desktop-dom.md +177 -0
  718. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-node-inspect-debugger.md +337 -0
  719. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-python-debugpy.md +391 -0
  720. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review.md +298 -0
  721. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-simplify-code.md +288 -0
  722. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-spike.md +217 -0
  723. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging.md +429 -0
  724. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development.md +380 -0
  725. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/bundled/web/web-blocked-page-recovery.md +155 -0
  726. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/google-workspace.md +191 -0
  727. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-antigravity-cli.md +259 -0
  728. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-blackbox.md +161 -0
  729. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-dynamic-workflow.md +198 -0
  730. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-grok.md +326 -0
  731. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-honcho.md +446 -0
  732. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-openhands.md +167 -0
  733. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/blockchain/blockchain-evm.md +227 -0
  734. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/blockchain/blockchain-hyperliquid.md +228 -0
  735. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/blockchain/blockchain-solana.md +225 -0
  736. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/communication/communication-one-three-one-rule.md +114 -0
  737. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-ai-presenter-video.md +211 -0
  738. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-archify.md +66 -0
  739. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-ascii-art.md +338 -0
  740. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-audiocraft-audio-generation.md +588 -0
  741. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-auteur.md +195 -0
  742. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-baoyu-article-illustrator.md +225 -0
  743. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-baoyu-comic.md +264 -0
  744. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-comfyui.md +616 -0
  745. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-concept-diagrams.md +379 -0
  746. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-creative-ideation.md +192 -0
  747. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-draw-your-font.md +169 -0
  748. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-dream-loop.md +297 -0
  749. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-excalidraw.md +212 -0
  750. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-heartmula.md +191 -0
  751. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-hyperframes.md +222 -0
  752. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-impeccable.md +56 -0
  753. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-ip-as-logo.md +171 -0
  754. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md +220 -0
  755. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-meme-generation.md +147 -0
  756. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-mono-color.md +158 -0
  757. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-pixel-art.md +234 -0
  758. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-pretext.md +238 -0
  759. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-simple-english.md +362 -0
  760. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-sketch.md +240 -0
  761. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-social-media-content-calendar.md +88 -0
  762. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-system-atlas.md +105 -0
  763. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-tldraw-offline.md +294 -0
  764. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/creative/creative-unreal-mcp.md +269 -0
  765. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/data-science/data-science-jupyter-notebook.md +195 -0
  766. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-actual-setup.md +164 -0
  767. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-docker-management.md +298 -0
  768. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-hermes-s6-container-supervision.md +198 -0
  769. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-inference-sh-cli.md +173 -0
  770. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-pinggy-tunnel.md +326 -0
  771. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-setup-wizard-generator.md +133 -0
  772. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/devops/devops-watchers.md +126 -0
  773. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/dogfood/dogfood-adversarial-ux-test.md +209 -0
  774. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/email/email-agentmail.md +104 -0
  775. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-3-statement-model.md +451 -0
  776. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-comps-analysis.md +682 -0
  777. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-dcf-model.md +1288 -0
  778. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-excel-author.md +262 -0
  779. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-lbo-model.md +309 -0
  780. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-merger-model.md +162 -0
  781. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-polymarket.md +97 -0
  782. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-pptx-author.md +191 -0
  783. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/finance/finance-stocks.md +112 -0
  784. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/gaming/gaming-minecraft-modpack-server.md +209 -0
  785. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/gaming/gaming-pokemon-player.md +240 -0
  786. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/health/health-fitness-nutrition.md +259 -0
  787. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/health/health-neuroskill-bci.md +470 -0
  788. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mcp/mcp-fastmcp.md +315 -0
  789. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mcp/mcp-mcp-oauth-remote-gateway.md +389 -0
  790. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mcp/mcp-mcporter.md +138 -0
  791. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/migration/migration-openclaw-migration.md +316 -0
  792. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-accelerate.md +366 -0
  793. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-chroma.md +425 -0
  794. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-clip.md +272 -0
  795. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-evaluation-evaluating-llms-harness.md +512 -0
  796. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-evaluation-weights-and-biases.md +613 -0
  797. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-faiss.md +240 -0
  798. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-flash-attention.md +388 -0
  799. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-guidance.md +595 -0
  800. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-huggingface-tokenizers.md +535 -0
  801. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-inference-llama-cpp.md +267 -0
  802. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-inference-outlines.md +679 -0
  803. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-inference-serving-llms-vllm.md +387 -0
  804. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-instructor.md +759 -0
  805. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-lambda-labs.md +568 -0
  806. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-llava.md +323 -0
  807. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-modal.md +368 -0
  808. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-models-huggingface-hub.md +100 -0
  809. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-models-segment-anything-model.md +525 -0
  810. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-nemo-curator.md +415 -0
  811. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-obliteratus.md +360 -0
  812. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-peft.md +452 -0
  813. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-pinecone.md +396 -0
  814. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-pytorch-fsdp.md +97 -0
  815. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-pytorch-lightning.md +365 -0
  816. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-qdrant.md +522 -0
  817. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-research-dspy.md +609 -0
  818. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-saelens.md +439 -0
  819. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-simpo.md +237 -0
  820. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-slime.md +486 -0
  821. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-stable-diffusion.md +542 -0
  822. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-tensorrt-llm.md +208 -0
  823. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-torchtitan.md +404 -0
  824. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-training-axolotl.md +181 -0
  825. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-training-trl-fine-tuning.md +512 -0
  826. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-training-unsloth.md +98 -0
  827. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/mlops/mlops-whisper.md +336 -0
  828. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/payments/payments-mpp-agent.md +142 -0
  829. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/payments/payments-stripe-link-cli.md +202 -0
  830. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/payments/payments-stripe-projects.md +138 -0
  831. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-canvas.md +114 -0
  832. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-decision-questionnaire.md +133 -0
  833. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-here-now.md +231 -0
  834. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-live-dashboard.md +126 -0
  835. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-memento-flashcards.md +336 -0
  836. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-property-listings.md +121 -0
  837. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-shop.md +238 -0
  838. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-shopify.md +377 -0
  839. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-siyuan.md +305 -0
  840. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/productivity/productivity-telephony.md +435 -0
  841. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-bioinformatics.md +254 -0
  842. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-blogwatcher.md +162 -0
  843. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-darwinian-evolver.md +217 -0
  844. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-domain-intel.md +121 -0
  845. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-drug-discovery.md +237 -0
  846. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-duckduckgo-search.md +255 -0
  847. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-gitnexus-explorer.md +232 -0
  848. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-osint-investigation.md +295 -0
  849. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-parallel-cli.md +411 -0
  850. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-pinecone-research.md +125 -0
  851. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-qmd.md +459 -0
  852. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-research-paper-writing.md +1645 -0
  853. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-rss-feeds.md +114 -0
  854. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-scrapling.md +351 -0
  855. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/research/research-searxng-search.md +212 -0
  856. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-1password.md +173 -0
  857. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-godmode.md +421 -0
  858. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-oss-forensics.md +426 -0
  859. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-sherlock.md +208 -0
  860. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-unbroker.md +331 -0
  861. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/security/security-web-pentest.md +337 -0
  862. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/smart-home/smart-home-openhue.md +127 -0
  863. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/social-media/social-media-reddit-reading.md +146 -0
  864. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-ast-grep.md +307 -0
  865. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-code-wiki.md +463 -0
  866. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-grill-me.md +135 -0
  867. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-pr-lens.md +160 -0
  868. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-rest-graphql-debug.md +532 -0
  869. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development.md +370 -0
  870. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/web-development/web-development-cloudflare-temporary-deploy.md +144 -0
  871. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/web-development/web-development-har-derived-api-client.md +180 -0
  872. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/web-development/web-development-page-agent.md +207 -0
  873. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/web-development/web-development-publish-site.md +174 -0
  874. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/web-development/web-development-scrollcraft.md +257 -0
  875. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/skills/optional/yuanbao/yuanbao-yuanbao.md +127 -0
  876. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/tui.md +313 -0
  877. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/which-file-does-what.md +57 -0
  878. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/windows-native.md +326 -0
  879. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-guide/windows-wsl-quickstart.md +358 -0
  880. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docs/user-stories.mdx +10 -0
  881. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/docusaurus.config.ts +210 -0
  882. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/acp-internals.md +181 -0
  883. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/adding-platform-adapters.md +686 -0
  884. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/adding-providers.md +459 -0
  885. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/adding-tools.md +209 -0
  886. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/agent-loop.md +239 -0
  887. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/architecture.md +277 -0
  888. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/browser-supervisor.md +160 -0
  889. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/context-compression-and-caching.md +328 -0
  890. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/context-engine-plugin.md +193 -0
  891. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/contributing.md +253 -0
  892. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/creating-skills.md +375 -0
  893. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/cron-internals.md +236 -0
  894. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/extending-the-cli.md +192 -0
  895. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/gateway-internals.md +267 -0
  896. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/image-gen-provider-plugin.md +288 -0
  897. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/memory-provider-plugin.md +258 -0
  898. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/model-provider-plugin.md +267 -0
  899. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/plugin-llm-access.md +401 -0
  900. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/plugins/index.md +1156 -0
  901. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/programmatic-integration.md +126 -0
  902. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/prompt-assembly.md +273 -0
  903. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/provider-runtime.md +208 -0
  904. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/session-storage.md +420 -0
  905. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/tools-runtime.md +236 -0
  906. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/trajectory-format.md +222 -0
  907. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/video-gen-provider-plugin.md +231 -0
  908. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/developer-guide/web-search-provider-plugin.md +260 -0
  909. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/installation.md +204 -0
  910. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/learning-path.md +154 -0
  911. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/nix-setup.md +975 -0
  912. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/quickstart.md +352 -0
  913. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/termux.md +236 -0
  914. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/getting-started/updating.md +231 -0
  915. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/automate-with-cron.md +266 -0
  916. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/automation-blueprints.md +595 -0
  917. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/aws-bedrock.md +170 -0
  918. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/azure-foundry.md +334 -0
  919. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/cron-script-only.md +247 -0
  920. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/cron-troubleshooting.md +227 -0
  921. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/daily-briefing-bot.md +268 -0
  922. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/delegation-patterns.md +239 -0
  923. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/github-pr-review-agent.md +303 -0
  924. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/google-gemini.md +254 -0
  925. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/local-llm-on-mac.md +240 -0
  926. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/local-ollama-setup.md +317 -0
  927. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/microsoft-graph-app-registration.md +180 -0
  928. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/migrate-from-openclaw.md +244 -0
  929. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/minimax-oauth.md +228 -0
  930. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/oauth-over-ssh.md +96 -0
  931. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/operate-teams-meeting-pipeline.md +288 -0
  932. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/pipe-script-output.md +217 -0
  933. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/python-library.md +333 -0
  934. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/run-hermes-with-nous-portal.md +273 -0
  935. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/team-telegram-assistant.md +441 -0
  936. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/tips.md +234 -0
  937. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/use-mcp-with-hermes.md +490 -0
  938. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/use-soul-with-hermes.md +264 -0
  939. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/use-voice-mode-with-hermes.md +469 -0
  940. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/webhook-github-pr-review.md +329 -0
  941. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/work-with-skills.md +290 -0
  942. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/guides/xai-grok-oauth.md +243 -0
  943. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/index.mdx +117 -0
  944. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/integrations/buzz.md +57 -0
  945. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/integrations/index.md +100 -0
  946. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/integrations/nous-portal.md +272 -0
  947. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/integrations/providers.md +1433 -0
  948. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/cli-commands.md +1259 -0
  949. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/environment-variables.md +678 -0
  950. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/faq.md +859 -0
  951. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/mcp-config-reference.md +250 -0
  952. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/model-catalog.md +103 -0
  953. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/optional-skills-catalog.md +220 -0
  954. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/profile-commands.md +467 -0
  955. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/skills-catalog.md +156 -0
  956. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/slash-commands.md +272 -0
  957. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/tools-reference.md +261 -0
  958. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/reference/toolsets-reference.md +162 -0
  959. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/checkpoints-and-rollback.md +251 -0
  960. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/cli.md +445 -0
  961. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/configuration.md +1746 -0
  962. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/configuring-models.md +239 -0
  963. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/docker.md +595 -0
  964. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/acp.md +341 -0
  965. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/api-server.md +456 -0
  966. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/batch-processing.md +229 -0
  967. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/browser.md +629 -0
  968. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/built-in-plugins.md +269 -0
  969. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/code-execution.md +240 -0
  970. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/codex-app-server-runtime.md +441 -0
  971. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/computer-use.md +144 -0
  972. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/context-files.md +218 -0
  973. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/context-references.md +142 -0
  974. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/credential-pools.md +240 -0
  975. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/cron.md +761 -0
  976. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/curator.md +248 -0
  977. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/delegation.md +355 -0
  978. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/deliverable-mode.md +91 -0
  979. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/extending-the-dashboard.md +907 -0
  980. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/fallback-providers.md +408 -0
  981. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/goals.md +180 -0
  982. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/honcho.md +233 -0
  983. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/hooks.md +1388 -0
  984. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/image-generation.md +150 -0
  985. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/kanban-tutorial.md +308 -0
  986. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/kanban-worker-lanes.md +117 -0
  987. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/kanban.md +863 -0
  988. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/lsp.md +217 -0
  989. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/mcp.md +591 -0
  990. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/memory-providers.md +570 -0
  991. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/memory.md +233 -0
  992. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/overview.md +52 -0
  993. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/personality.md +271 -0
  994. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/plugins.md +346 -0
  995. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/provider-routing.md +200 -0
  996. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/skills.md +760 -0
  997. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/skins.md +271 -0
  998. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/spotify.md +279 -0
  999. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/subscription-proxy.md +163 -0
  1000. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/tool-gateway.md +187 -0
  1001. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/tools.md +223 -0
  1002. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/tts.md +456 -0
  1003. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/vision.md +210 -0
  1004. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/voice-mode.md +521 -0
  1005. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/web-dashboard.md +351 -0
  1006. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/web-search.md +422 -0
  1007. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/features/x-search.md +147 -0
  1008. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/git-worktrees.md +173 -0
  1009. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/bluebubbles.md +143 -0
  1010. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/dingtalk.md +283 -0
  1011. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/discord.md +843 -0
  1012. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/email.md +190 -0
  1013. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/feishu.md +538 -0
  1014. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/google_chat.md +283 -0
  1015. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/homeassistant.md +252 -0
  1016. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/index.md +569 -0
  1017. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/line.md +199 -0
  1018. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/matrix.md +677 -0
  1019. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/mattermost.md +340 -0
  1020. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/msgraph-webhook.md +137 -0
  1021. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/ntfy.md +155 -0
  1022. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/open-webui.md +296 -0
  1023. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/qqbot.md +123 -0
  1024. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/signal.md +257 -0
  1025. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/simplex.md +98 -0
  1026. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/slack.md +614 -0
  1027. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/sms.md +203 -0
  1028. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/teams-meetings.md +233 -0
  1029. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/teams.md +255 -0
  1030. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/telegram.md +1241 -0
  1031. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/webhooks.md +601 -0
  1032. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/wecom-callback.md +149 -0
  1033. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/wecom.md +292 -0
  1034. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/weixin.md +312 -0
  1035. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/whatsapp.md +236 -0
  1036. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/messaging/yuanbao.md +341 -0
  1037. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/profile-distributions.md +573 -0
  1038. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/profiles.md +272 -0
  1039. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/secrets/bitwarden.md +143 -0
  1040. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/secrets/index.md +9 -0
  1041. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/security.md +664 -0
  1042. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/sessions.md +609 -0
  1043. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/apple/apple-apple-notes.md +106 -0
  1044. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/apple/apple-apple-reminders.md +114 -0
  1045. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/apple/apple-findmy.md +147 -0
  1046. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/apple/apple-imessage.md +118 -0
  1047. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/apple/apple-macos-computer-use.md +175 -0
  1048. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-claude-code.md +763 -0
  1049. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-codex.md +143 -0
  1050. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md +947 -0
  1051. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-opencode.md +237 -0
  1052. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-architecture-diagram.md +165 -0
  1053. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-ascii-art.md +338 -0
  1054. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-ascii-video.md +261 -0
  1055. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-baoyu-infographic.md +256 -0
  1056. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-claude-design.md +609 -0
  1057. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-comfyui.md +547 -0
  1058. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-design-md.md +189 -0
  1059. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-excalidraw.md +210 -0
  1060. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-humanizer.md +594 -0
  1061. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-manim-video.md +289 -0
  1062. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-p5js.md +574 -0
  1063. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-popular-web-designs.md +211 -0
  1064. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-pretext.md +238 -0
  1065. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-sketch.md +238 -0
  1066. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/creative/creative-songwriting-and-ai-music.md +305 -0
  1067. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/email/email-himalaya.md +305 -0
  1068. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-codebase-inspection.md +132 -0
  1069. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-github-auth.md +265 -0
  1070. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-github-code-review.md +499 -0
  1071. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-github-issues.md +388 -0
  1072. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-github-pr-workflow.md +385 -0
  1073. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/github/github-github-repo-management.md +534 -0
  1074. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/media/media-gif-search.md +106 -0
  1075. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/media/media-songsee.md +98 -0
  1076. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/media/media-youtube-content.md +93 -0
  1077. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/mlops/mlops-evaluation-evaluating-llms-harness.md +512 -0
  1078. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/mlops/mlops-evaluation-weights-and-biases.md +609 -0
  1079. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/mlops/mlops-huggingface-hub.md +100 -0
  1080. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/mlops/mlops-inference-llama-cpp.md +267 -0
  1081. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/mlops/mlops-inference-serving-llms-vllm.md +386 -0
  1082. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/note-taking/note-taking-obsidian.md +81 -0
  1083. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-airtable.md +243 -0
  1084. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-google-workspace.md +325 -0
  1085. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-maps.md +196 -0
  1086. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-nano-pdf.md +69 -0
  1087. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-notion.md +463 -0
  1088. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-ocr-and-documents.md +190 -0
  1089. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-powerpoint.md +257 -0
  1090. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/productivity/productivity-teams-meeting-pipeline.md +127 -0
  1091. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/research/research-arxiv.md +300 -0
  1092. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/research/research-blogwatcher.md +152 -0
  1093. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/research/research-llm-wiki.md +469 -0
  1094. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/research/research-research-paper-writing.md +2395 -0
  1095. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/smart-home/smart-home-openhue.md +124 -0
  1096. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/social-media/social-media-xurl.md +428 -0
  1097. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-dogfood.md +181 -0
  1098. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-hermes-agent-skill-authoring.md +183 -0
  1099. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-node-inspect-debugger.md +337 -0
  1100. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-python-debugpy.md +391 -0
  1101. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-requesting-code-review.md +287 -0
  1102. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-spike.md +217 -0
  1103. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-systematic-debugging.md +385 -0
  1104. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/bundled/software-development/software-development-test-driven-development.md +361 -0
  1105. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/google-workspace.md +191 -0
  1106. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-blackbox.md +162 -0
  1107. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-honcho.md +446 -0
  1108. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/blockchain/blockchain-evm.md +227 -0
  1109. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/blockchain/blockchain-hyperliquid.md +210 -0
  1110. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/blockchain/blockchain-solana.md +206 -0
  1111. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/communication/communication-one-three-one-rule.md +114 -0
  1112. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-audiocraft-audio-generation.md +588 -0
  1113. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-concept-diagrams.md +379 -0
  1114. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-heartmula.md +189 -0
  1115. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-hyperframes.md +205 -0
  1116. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-kanban-video-orchestrator.md +173 -0
  1117. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/creative/creative-meme-generation.md +147 -0
  1118. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/data-science/data-science-jupyter-notebook.md +180 -0
  1119. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/devops/devops-docker-management.md +297 -0
  1120. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/devops/devops-inference-sh-cli.md +173 -0
  1121. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/devops/devops-pinggy-tunnel.md +327 -0
  1122. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/devops/devops-watchers.md +126 -0
  1123. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/dogfood/dogfood-adversarial-ux-test.md +209 -0
  1124. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/email/email-agentmail.md +143 -0
  1125. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-3-statement-model.md +451 -0
  1126. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-comps-analysis.md +682 -0
  1127. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-dcf-model.md +1288 -0
  1128. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-excel-author.md +262 -0
  1129. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-lbo-model.md +309 -0
  1130. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-merger-model.md +162 -0
  1131. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-polymarket.md +94 -0
  1132. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-pptx-author.md +191 -0
  1133. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/finance/finance-stocks.md +108 -0
  1134. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/health/health-fitness-nutrition.md +255 -0
  1135. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/health/health-neuroskill-bci.md +431 -0
  1136. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mcp/mcp-fastmcp.md +315 -0
  1137. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mcp/mcp-mcporter.md +138 -0
  1138. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/migration/migration-openclaw-migration.md +316 -0
  1139. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-accelerate.md +350 -0
  1140. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-chroma.md +425 -0
  1141. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-clip.md +272 -0
  1142. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-faiss.md +240 -0
  1143. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-flash-attention.md +381 -0
  1144. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-guidance.md +591 -0
  1145. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-huggingface-tokenizers.md +535 -0
  1146. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-inference-outlines.md +671 -0
  1147. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-instructor.md +759 -0
  1148. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-lambda-labs.md +568 -0
  1149. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-llava.md +323 -0
  1150. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-modal.md +362 -0
  1151. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-models-segment-anything-model.md +525 -0
  1152. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-nemo-curator.md +401 -0
  1153. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-peft.md +452 -0
  1154. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-pinecone.md +377 -0
  1155. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-pytorch-fsdp.md +145 -0
  1156. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-pytorch-lightning.md +365 -0
  1157. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-qdrant.md +514 -0
  1158. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-saelens.md +407 -0
  1159. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-simpo.md +237 -0
  1160. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-slime.md +486 -0
  1161. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-stable-diffusion.md +542 -0
  1162. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-tensorrt-llm.md +206 -0
  1163. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-torchtitan.md +378 -0
  1164. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-training-axolotl.md +181 -0
  1165. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-training-trl-fine-tuning.md +477 -0
  1166. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-training-unsloth.md +98 -0
  1167. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/mlops/mlops-whisper.md +336 -0
  1168. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-canvas.md +114 -0
  1169. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-here-now.md +231 -0
  1170. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-memento-flashcards.md +336 -0
  1171. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-shop.md +354 -0
  1172. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-shopify.md +377 -0
  1173. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-siyuan.md +305 -0
  1174. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/productivity/productivity-telephony.md +435 -0
  1175. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-bioinformatics.md +252 -0
  1176. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-darwinian-evolver.md +188 -0
  1177. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-domain-intel.md +117 -0
  1178. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-drug-discovery.md +237 -0
  1179. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-duckduckgo-search.md +255 -0
  1180. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-gitnexus-explorer.md +213 -0
  1181. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-osint-investigation.md +243 -0
  1182. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-parallel-cli.md +411 -0
  1183. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-qmd.md +435 -0
  1184. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-scrapling.md +351 -0
  1185. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/research/research-searxng-search.md +229 -0
  1186. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/security/security-1password.md +173 -0
  1187. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/security/security-oss-forensics.md +421 -0
  1188. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/security/security-sherlock.md +208 -0
  1189. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/software-development/software-development-rest-graphql-debug.md +531 -0
  1190. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/web-development/web-development-page-agent.md +207 -0
  1191. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/skills/optional/yuanbao/yuanbao-yuanbao.md +125 -0
  1192. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/tui.md +256 -0
  1193. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/windows-native.md +325 -0
  1194. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-guide/windows-wsl-quickstart.md +332 -0
  1195. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/i18n/zh-Hans/user-stories.mdx +10 -0
  1196. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/llms-full.txt +88833 -0
  1197. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/llms.txt +267 -0
  1198. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/site-pages-map.txt +928 -0
  1199. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src/site-pages.json +4218 -0
  1200. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-README.md +101 -0
  1201. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-scripts/clone_repo.sh +17 -0
  1202. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-scripts/crawl.py +82 -0
  1203. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-scripts/gen_mapping.py +112 -0
  1204. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-scripts/retry-none.json +305 -0
  1205. package/docs/80_upstream-docs-and-skills/hermes-dev-skill/src-scripts/verify_orphans.py +53 -0
  1206. package/docs/specs/ctx/spec.md +78 -6
  1207. package/docs/specs/model-picker-ios-blur/spec.md +168 -0
  1208. package/docs/specs/plugins-page-components/spec.md +79 -0
  1209. package/docs/superpowers/plans/2026-10-02-ctx-navigation.md +319 -0
  1210. package/docs/superpowers/specs/2026-10-02-ctx-navigation-design.md +209 -0
  1211. package/lib/client/index.js +20 -20
  1212. package/lib/compaction/index.d.ts +57 -0
  1213. package/lib/compaction/index.js +145 -0
  1214. package/lib/failover/index.d.ts +59 -0
  1215. package/lib/failover/index.js +147 -0
  1216. package/lib/fs-aware/sandbox-plugin.js +3 -3
  1217. package/lib/index.d.ts +1 -32
  1218. package/lib/index.js +193 -8034
  1219. package/lib/{lsp-server-registry-_hk-Wcia.js → lsp-server-registry-XU6aHSqZ.js} +1 -1
  1220. package/lib/mobile/plugin.d.ts +29 -0
  1221. package/lib/mobile/plugin.js +54 -0
  1222. package/lib/native-capture-x_Hos2e8.js +68 -0
  1223. package/lib/remote/plugin.d.ts +24 -0
  1224. package/lib/remote/plugin.js +1095 -0
  1225. package/lib/url-schemes/index.d.ts +88 -0
  1226. package/lib/url-schemes/index.js +7461 -0
  1227. package/lib/web-password.d.ts +156 -0
  1228. package/lib/web-password.js +562 -0
  1229. package/lib/web-trust-BO66y72w.js +361 -0
  1230. package/lib/web-trust-BihHCelF.d.ts +106 -0
  1231. package/lib/web-trust.d.ts +2 -0
  1232. package/lib/web-trust.js +3 -0
  1233. package/lib/{wrap-JFjcWwZf.js → wrap-Bzdimp4p.js} +112 -112
  1234. package/package.json +101 -56
  1235. /package/lib/{lsp-server-registry-DkaYmTwt.js → lsp-server-registry-946ysdqg.js} +0 -0
@@ -0,0 +1,2083 @@
1
+ # Remote 执行框架(`remote` 工具)Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** 落地 2026-09-23 设计文档的全新阶段——一个 `remote` 工具(`dashr-remote` composition row),双轨执行(oneshot 默认 / pty opt-in)、CLI 子进程 transports(ssh / docker / incus)、BYO-PTY `spawn` 通道、随机 Nonce 收帧、10min 空闲 TTL、断联透明冷启——在 4999 系 dev 实例第一人称验收。
6
+
7
+ **Architecture:** 全新实现(不基于 RM0 分支——RM0 的 ssh2 库 + 连接池 + 准备层路线被本设计否决,分支存档不动)。新代码在 `better-dsh/src/remote/` 下:纯模块(framing / target 路由 / argv builders)先行 TDD, runners(oneshot 子进程、pty 会话池)用本地真 `bash` 与 `script(1)` 夹具测试,零网络依赖;工具面与插件行复用 RM0 已验证的注册形态(`defineTool` + `- id: dashr-remote` bundle patch 行)。零新增 npm 依赖(ssh2 移出依赖面;只加 `node:child_process` / `node:crypto` stdlib)。
8
+
9
+ **Tech Stack:** TypeScript(ESM,`.ts` import specifiers)、node:child_process、node:crypto、util-linux `script(1)`(宿主 PTY 托管)、schemastery row config、vitest(serial suite)。
10
+
11
+ **Spec:** `docs/10_plans/2026-09-23-remote-execution-framework.md`(本计划论证之源;设计文档为约束权威,本计划在其留白处以 Rulings 裁决)。
12
+
13
+ ## Global Constraints(spec 逐条摘录,全部任务隐含遵守)
14
+
15
+ - **双轨收敛**:One-shot = 第 2 层(`bash -lc` 经 CLI 传输,进程退出码即收尾,**零字符串扫描**);Persistent = 第 4 层(PTY + Nonce 收帧)。每阵营严格各一,不做第 1/3 层。
16
+ - **One-shot argv 形态(§五.1 原文)**:SSH = `ssh -o BatchMode=yes <target> "bash -lc '<cmd>'"`(不分配 tty);Docker = `docker exec -i <target> bash -lc "<cmd>"`(不加 `-t`);Incus = `incus exec <target> -- bash -lc "<cmd>"`(不加 `-t`)。
17
+ - **Nonce 收帧(§五.2)**:每次下发前 Host 生成 8 字节随机串 `$NONCE`;命令末尾收帧指令 `printf "\033]133;D;%s;%s\007" "$NONCE" "$?"`;**只有匹配当前轮次 Nonce 才收帧**;远端偶然打印的静态 `\033]133;D;` 一律当普通输出,不得截断流或窜改退出码。
18
+ - **空闲 TTL = 10 分钟**(默认 600s,可配),到期自动关连接释放资源;下次调用透明冷启动。
19
+ - **断联自愈**:底层绝不重建 shell 内存状态;统一行为 = 重建干净初始会话并返回明确提示 `[remote: session reconnected to fresh shell; cwd reset to default]`(此字符串逐字使用)。
20
+ - **Strict Non-Goals(§六)**:① 后台进程输出不隔离、不清洗(使用者显式 `cmd > log 2>&1 &`);② 不快照/回放 shell 临时环境变量;③ 不暴露终端行列调整接口(内部固定 40×120)。
21
+ - **错误透明**:连接失败 / 找不到容器 / 权限拒绝,原生 stderr 原样返回,不过度包裹(Soft Fail-close)。
22
+ - **便利性而非保姆性(§三)**:参数面 = `{target?, spawn?, cmd, mode?, stdin?, timeout?}`;target 与 spawn 二选一;spawn 时 mode 锁定 `'pty'`;无静态注册要求。
23
+ - **Target 智能路由(§二.2)**:容器前缀 `docker:x` / `incus:x` → 容器传输;普通名称 / IP / 域名 → SSH;URL 形态(`ws://`)本期不做。
24
+ - **测试纪律**:vitest 全绿;新增规格先测后码(TDD);单测不得要求外网或真实远端主机。
25
+ - **交付形态**:`dashr-remote` 为 better-dsh 内 composition row(subpath export + tsdown entry + bundle patch insert),插件管理器可开关,不新建 npm 包。
26
+ - **发布红线**:npm publish 需 4999 第一人称实测 + 报告 + user 放行(Development Operation Contract);本计划只到 dev 实例验收。
27
+
28
+ ## Rulings(本计划对 spec 留白的裁决)
29
+
30
+ 1. **基座分支**:`remote-framework` 分支自 `main`(已核验 `main` 与 `dashr-bun-port-m1` 的 `better-dsh/` 零差异);worktree `.worktrees/remote-framework`。RM0 分支(`remote-tool-rm0` / `arch/…`)存档不动,其代码不合并、不 import——但 `src/remote/tool.ts` 的注册形态(defineTool + 审计事件)与 `plugin.ts` 的行形态被本计划照抄结构。
31
+ 2. **传输 = 系统 CLI,宿主无 PTY 库**:ssh pty = `ssh -tt -o BatchMode=yes -- <host> bash` 走宿主管道(远端 pty 的行规程吃 `\x03` 成 SIGINT——与 ssh2 pty channel 同构);incus pty = `incus exec --force-interactive`(API 代理容器侧 pty,宿主管道);**docker pty 与一切 `spawn`(BYO-PTY)= util-linux `script -qfec '…' /dev/null` 托管宿主 PTY**(docker CLI 对 `-t` 要求 stdin 是 TTY;node-pty 是原生模块,违反零 lifecycle-script 包红线,否决)。script 命令串前置 `stty -echo 2>/dev/null ; exec ` 关掉本地 pty 回显。
32
+ 3. **marker 为三字段超集**:`\x1b]133;D;<nonce>;<exit>;<cwd>\x07`(spec 两字段 + cwd 只读回传)。cwd 是状态**报告**不是状态重建(Non-Goal ② 不破)——`cd` 后 Agent 需要知道自己在哪。终止符收 BEL 与 ST(`\x1b\\`)两种。nonce = `crypto.randomBytes(8).toString('hex')`(16 hex 字符)。
33
+ 4. **无 C 标记**:nonce 门控使 OSC 133 C(PS0)不必要——init 之后的流里,帧间内容只可能是本轮输出(PS1/PS2 已哑)。比 RM0 少一个解析维度。
34
+ 5. **init 协议**:会话冷启后先发 `stty -echo 2>/dev/null ; stty rows 40 cols 120 2>/dev/null ; PS1='' ; PS2='' ; export TERM=dumb ; printf '\033]133;D;<INIT_NONCE>;0;%s\007' "$PWD"\n`,INIT_NONCE 帧到达 = ready;帧前字节(回显残响/ssh banner)全部丢弃。固定 40×120 在此落位(Non-Goal ③)。
35
+ 6. **会话键与 Agent 隔离**:pty 会话键 = `<agentSessionKey>|t:<target>` 或 `|s:<spawn>`;agentSessionKey 默认 `exec.agent?.id`(无 agent 用常量 `no-session`)。同一 Agent 跨 turn 保持状态(spec 场景 2),并发 Agent 互不污染(RM0 Ruling 7 先例)。同键命令串行排队,不同键天然并发。
36
+ 7. **意外死亡 vs TTL**:进程死亡(EOF/被杀)后会话对象**留在池内**(state=dead),下次 dispatch 同对象重启并置 `reconnected: true`(带提示行);TTL/row dispose 才出池(出池后重建是新对象 = 透明冷启,无提示)。
37
+ 8. **超时语义**:默认 120s(row `execTimeoutSec`)。pty 超时 = 写 `\x03` + **紧随注入同 nonce 的 130-marker 行**(`printf '\033]133;D;<NONCE>;130;%s\007' "$PWD"`——交互 bash 被打断后放弃当前命令行剩余部分,尾部 marker 不再执行,注入行在 bash 回到读取态后补帧;若 bash 续行则原 marker 先帧、注入行帧被 parser 丢弃——两路皆 exit 130,会话存活)→ 3s 宽限无帧则 kill 进程组,`exit: null`。oneshot 超时 = SIGTERM → 2s → SIGKILL(**进程组杀**——后台子进程占管道时 close 永不触发,实测必挂),`timedOut: true`。超时秒数非正/非有限 → dispatch 前 `E_BAD_TIMEOUT` 拒绝。
38
+ 9. **杀进程纪律**:全部子进程 `detached: true` 起进程组,杀 = `process.kill(-pid, SIGTERM)` → 2s → SIGKILL(script 会连带 docker CLI 一并收掉)。
39
+ 10. **输出纪律**:回模型前机械剥残余 ANSI + CRLF→LF(RM0 连续性);超帽保留尾窗 + 前置 `[truncated: showing last N of M chars]`(row `maxOutputChars` 默认 30000)。oneshot stdout/stderr 分离保留;pty 合流是诚实代价(spec §4.2 精神)。
40
+ 11. **stdin 语义**:oneshot = 管道直写后 close;pty = 紧随命令行裸写(REPL 式 best-effort——cmd 不读则残行被 bash 当下一条命令执行、输出计入本轮,Agent 看到后自纠)。工具层校验 `stdin` 依赖 `cmd` 在场。
41
+ 12. **别名注册**:row config `containers: { 'ctr-1': 'incus:ctr-1' }` 形态(裸名 → 容器传输的"已知容器"判定);别名值必须是 `docker:`/`incus:` 前缀形态,否则 `E_TARGET_FORMAT`。裸名无别名命中 → ssh(本机 `~/.ssh/config` 里 ctr-1 同时是 ssh Host,显式前缀/别名优先于 ssh)。
42
+ 13. **审计**:engine 回调 → 工具层 append session 事件 `dashr/remote-exec`(对齐 RM0 Ruling 10 / `tool/ptc-dispatch` 先例,成功与失败都记,best-effort 不破坏命令路径)。
43
+ 14. **oneshot ssh 单层机械转义**:`bash -lc <shQuote(cmd)>` 作为 host 后的**单个 argv**(ssh 拼接 argv 后远端 sh 只做一次解析);shQuote = POSIX 单引号包裹。docker/incus 的 argv 直传无二次解析。
44
+ 15. **不做的**:ControlMaster 复用(oneshot 天然并发,握手成本可接受,YAGNI);`ws://` 传输;forward/tmux/WebUI 终端(RM2 线);host key 管理(ssh CLI 的 known_hosts 即正道,RM0 的 TOFU pin 文件随 ssh2 路线一并退役);targets 列表面(发现是 agent 自己的活:`cat ~/.ssh/config`、`docker ps`、`incus list`——工具不做保姆注册表)。
45
+ 16. **状态词汇表(user 2026-09-23 裁决,禁止歧义)**:本工具面向 LLM agent——它有语义理解与自愈能力,前提是不被误导。状态必须如实、无死灭暗示:**禁止 `offline`**(无人发起过连接当然是"未连接",该词零信息且诱导 agent 误判配置已死——实测 reasoning log 里 agent 确实困惑过)。词汇表:探测面 `reachable (in Nms)` / `unreachable — <原生 stderr 单行>` / 容器事实态(`running`/`stopped`/`exited`…来自 inspect/list,不臆造)/ `error — <原生错误>`;会话层 `session: idle Ns (connected)`(连接存在、当前无 activity)/ `session: busy (a command is running)` / `session: none — dials on first exec`(明说"未拨号"而非任何可达性断言)/ `session: died — next exec cold-starts a fresh shell`。
46
+ 17. **status 探测时机 = on-demand**(user 两选项中选此):`remote({target})`(无 cmd)= 调用瞬间拨一次探测,**双重超时**:ssh `ConnectTimeout=5` + 外层 hard timeout 10s(防个别机器永不回复卡死 agent);探测结果即当时事实,永不启动期扫描、永不缓存(启动扫描会立即过期且拖慢 boot)。status 只报探测面 + 会话层两行,不含任何注册表断言。
47
+
48
+ ---
49
+
50
+ ### Task 0: worktree 与基座
51
+
52
+ **Files:**
53
+ - Create: `.worktrees/remote-framework/`(git worktree,branch `remote-framework` off `main`)
54
+ - Create(分支内): `docs/10_plans/2026-09-23-remote-execution-framework.md`(spec 副本)、`docs/10_plans/2026-09-23-remote-framework-impl.md`(本计划副本)
55
+
56
+ - [ ] **Step 1: 建 worktree + 分支**
57
+
58
+ ```bash
59
+ cd /home/u1/workspaces/dashr
60
+ git worktree add .worktrees/remote-framework -b remote-framework main
61
+ ```
62
+
63
+ - [ ] **Step 2: spec + 本计划入库(分支自包含,executor 只读 worktree)**
64
+
65
+ ```bash
66
+ cp docs/10_plans/2026-09-23-remote-execution-framework.md docs/10_plans/2026-09-23-remote-framework-impl.md \
67
+ .worktrees/remote-framework/docs/10_plans/
68
+ cd .worktrees/remote-framework && git add docs/10_plans/ && git commit -m "docs(remote): framework spec + implementation plan (2026-09-23 stage)"
69
+ ```
70
+
71
+ - [ ] **Step 3: node_modules 软链**(worktree 不带 untracked 文件;canonical 的 dev 依赖树直接复用,本计划零新增依赖故版本面一致;⚠ 勿与 canonical 同时跑 vitest——`.vite` 缓存会撞)
72
+
73
+ ```bash
74
+ ln -s /home/u1/workspaces/dashr/better-dsh/node_modules /home/u1/workspaces/dashr/.worktrees/remote-framework/better-dsh/node_modules
75
+ ```
76
+
77
+ - [ ] **Step 4: 基线绿**
78
+
79
+ ```bash
80
+ cd /home/u1/workspaces/dashr/.worktrees/remote-framework/better-dsh && npm test
81
+ ```
82
+ Expected: 全绿(main 基线)。
83
+
84
+ ---
85
+
86
+ ### Task 1: Nonce 收帧纯模块 `nonce-framing.ts`
87
+
88
+ **Files:**
89
+ - Create: `better-dsh/src/remote/nonce-framing.ts`
90
+ - Test: `better-dsh/test/remote/nonce-framing.spec.ts`
91
+
92
+ **Interfaces(后续任务消费):**
93
+ ```ts
94
+ export interface PtyFrame { exit: number; cwd: string | null }
95
+ export function genNonce(bytes?: number): string // 16 hex chars
96
+ export function wrapPtyCommand(cmd: string, nonce: string): string // 含尾 \n 的整行下发串
97
+ export function buildInitCommand(nonce: string): string // init 串含尾 \n
98
+ export function stripAnsi(s: string): string
99
+ export function normalizePtyText(s: string): string // stripAnsi + CRLF→LF + 孤 CR 删除
100
+ export function tailWindow(text: string, cap: number): { text: string; truncated?: number }
101
+ export interface FrameParserEvents { onOutput?(text: string): void; onFrame(frame: PtyFrame): void }
102
+ export interface NonceFrameParser { feed(chunk: string): void; flush(): void }
103
+ export function createNonceFrameParser(nonce: string, events: FrameParserEvents): NonceFrameParser
104
+ ```
105
+
106
+ - [ ] **Step 1: 写失败测试**
107
+
108
+ ```ts
109
+ import { describe, expect, it } from 'vitest'
110
+ import {
111
+ buildInitCommand, createNonceFrameParser, genNonce, normalizePtyText, tailWindow, wrapPtyCommand,
112
+ } from '../../src/remote/nonce-framing.ts'
113
+
114
+ describe('command builders', () => {
115
+ it('wrapPtyCommand braces cmd and bakes nonce marker with $?/$PWD', () => {
116
+ const s = wrapPtyCommand('echo hi', 'abcd1234abcd1234')
117
+ expect(s).toContain('{\necho hi\n} ; printf')
118
+ expect(s).toContain(`'\\033]133;D;abcd1234abcd1234;%s;%s\\007' "$?" "$PWD"`)
119
+ expect(s.endsWith('\n')).toBe(true)
120
+ })
121
+ it('buildInitCommand silences the terminal and ends with the init marker', () => {
122
+ const s = buildInitCommand('ffffffffffffffff')
123
+ for (const frag of ["stty -echo 2>/dev/null", "stty rows 40 cols 120", "PS1=''", "PS2=''", 'export TERM=dumb'])
124
+ expect(s).toContain(frag)
125
+ expect(s).toContain(`'\\033]133;D;ffffffffffffffff;0;%s\\007' "$PWD"`)
126
+ })
127
+ it('genNonce is 16 hex chars and unique', () => {
128
+ expect(genNonce()).toMatch(/^[0-9a-f]{16}$/)
129
+ expect(new Set([genNonce(), genNonce(), genNonce(), genNonce()]).size).toBe(4)
130
+ })
131
+ })
132
+
133
+ describe('createNonceFrameParser', () => {
134
+ const MARK = (nonce: string, exit: number, cwd: string) =>
135
+ `\x1b]133;D;${nonce};${exit};${cwd}\x07`
136
+
137
+ it('emits pre-marker output normalized and parses exit + cwd', () => {
138
+ const out: string[] = []
139
+ const frames: Array<{ exit: number; cwd: string | null }> = []
140
+ const nonce = genNonce()
141
+ const p = createNonceFrameParser(nonce, { onOutput: (t) => out.push(t), onFrame: (f) => frames.push(f) })
142
+ p.feed(`hello\r\nworld\r\n${MARK(nonce, 3, '/data')}`)
143
+ expect(out.join('')).toBe('hello\nworld\n')
144
+ expect(frames).toEqual([{ exit: 3, cwd: '/data' }])
145
+ })
146
+
147
+ it('survives the marker split at every chunk boundary', () => {
148
+ const nonce = genNonce()
149
+ const stream = `out${MARK(nonce, 0, '/tmp')}tail-is-dropped`
150
+ for (let split = 1; split < stream.length; split++) {
151
+ const frames: Array<{ exit: number; cwd: string | null }> = []
152
+ const p = createNonceFrameParser(nonce, { onFrame: (f) => frames.push(f) })
153
+ p.feed(stream.slice(0, split)); p.feed(stream.slice(split))
154
+ expect(frames, `split at ${split}`).toEqual([{ exit: 0, cwd: '/tmp' }])
155
+ }
156
+ })
157
+
158
+ it('a forged marker with a WRONG nonce is ordinary output, never frames', () => {
159
+ const nonce = genNonce()
160
+ const out: string[] = []
161
+ const frames: Array<{ exit: number; cwd: string | null }> = []
162
+ const p = createNonceFrameParser(nonce, { onOutput: (t) => out.push(t), onFrame: (f) => frames.push(f) })
163
+ p.feed(`ok\n${MARK('deadbeefdeadbeef', 99, '/pwn')}${MARK(nonce, 0, '/')}`)
164
+ expect(frames).toEqual([{ exit: 0, cwd: '/' }])
165
+ expect(out.join('')).toBe('ok\n') // forged OSC stripped as ANSI residue
166
+ })
167
+
168
+ it('accepts ST (ESC backslash) terminator and empty cwd -> null', () => {
169
+ const nonce = genNonce()
170
+ const frames: Array<{ exit: number; cwd: string | null }> = []
171
+ const p = createNonceFrameParser(nonce, { onFrame: (f) => frames.push(f) })
172
+ p.feed(`\x1b]133;D;${nonce};7;\x1b\\`)
173
+ expect(frames).toEqual([{ exit: 7, cwd: null }])
174
+ })
175
+ it('frames a cwd containing ; (terminal field — only BEL/ST end it)', () => {
176
+ const nonce = genNonce()
177
+ const frames: Array<{ exit: number; cwd: string | null }> = []
178
+ const p = createNonceFrameParser(nonce, { onFrame: (f) => frames.push(f) })
179
+ p.feed(`\x1b]133;D;${nonce};2;/pa;th\x07`)
180
+ expect(frames).toEqual([{ exit: 2, cwd: '/pa;th' }])
181
+ })
182
+ it('the spec\'s literal static 133-D marker (no nonce field) is ordinary output', () => {
183
+ const nonce = genNonce()
184
+ const out: string[] = []
185
+ const frames: Array<{ exit: number; cwd: string | null }> = []
186
+ const p = createNonceFrameParser(nonce, { onOutput: (t) => out.push(t), onFrame: (f) => frames.push(f) })
187
+ p.feed(`ok\n\x1b]133;D;0\x07text${MARK(nonce, 0, '/')}`)
188
+ expect(frames).toEqual([{ exit: 0, cwd: '/' }])
189
+ expect(out.join('')).toBe('ok\ntext') // 静态 marker 被 ANSI 剥洗当噪音清掉,正文保留
190
+ })
191
+
192
+ it('holds back a partial marker prefix at buffer end; flush releases it', () => {
193
+ const nonce = genNonce()
194
+ const out: string[] = []
195
+ const frames: Array<{ exit: number; cwd: string | null }> = []
196
+ const p = createNonceFrameParser(nonce, { onOutput: (t) => out.push(t), onFrame: (f) => frames.push(f) })
197
+ p.feed(`ok\n\x1b]133;D;${nonce.slice(0, 5)}`)
198
+ expect(out.join('')).toBe('ok\n')
199
+ p.flush()
200
+ expect(out.join('')).toContain(nonce.slice(0, 5))
201
+ expect(frames).toEqual([])
202
+ })
203
+
204
+ it('ignores everything after the first frame (post-frame bytes are next turn\'s business)', () => {
205
+ const nonce = genNonce()
206
+ const frames: Array<{ exit: number; cwd: string | null }> = []
207
+ const p = createNonceFrameParser(nonce, { onFrame: (f) => frames.push(f) })
208
+ p.feed(`${MARK(nonce, 1, '/a')}noise${MARK(nonce, 2, '/b')}`)
209
+ expect(frames).toEqual([{ exit: 1, cwd: '/a' }])
210
+ })
211
+ })
212
+
213
+ describe('text hygiene', () => {
214
+ it('normalizePtyText strips CSI/OSC and normalizes line endings', () => {
215
+ expect(normalizePtyText('a\r\nb\rc \x1b[31mred\x1b[0m\x1b]0;title\x07end')).toBe('a\nbc redend')
216
+ })
217
+ it('tailWindow caps from the tail with a disclosure header', () => {
218
+ const r = tailWindow('x'.repeat(100), 10)
219
+ expect(r.truncated).toBe(100)
220
+ expect(r.text).toBe('[truncated: showing last 10 of 100 chars]\n' + 'x'.repeat(10))
221
+ expect(tailWindow('short', 10)).toEqual({ text: 'short' })
222
+ })
223
+ })
224
+ ```
225
+
226
+ - [ ] **Step 2: 跑测试确认失败**
227
+
228
+ Run: `cd better-dsh && npm test -- test/remote/nonce-framing.spec.ts`
229
+ Expected: FAIL(模块不存在)。
230
+
231
+ - [ ] **Step 3: 最小实现**
232
+
233
+ ```ts
234
+ import { randomBytes } from 'node:crypto'
235
+
236
+ /** 收帧帧体:退出码 + 只读回传的 cwd(Non-Goal ②:报告不重建)。 */
237
+ export interface PtyFrame { exit: number; cwd: string | null }
238
+
239
+ /** 8 字节随机串的 hex 形(spec §五.2:每次下发前生成)。 */
240
+ export function genNonce(bytes = 8): string {
241
+ return randomBytes(bytes).toString('hex')
242
+ }
243
+
244
+ /** 命令整行:花括号复合体 + Nonce 收帧尾(spec §五.2 的 printf 逐字落地 + cwd 第三字段)。 */
245
+ export function wrapPtyCommand(cmd: string, nonce: string): string {
246
+ return `{\n${cmd}\n} ; printf '\\033]133;D;${nonce};%s;%s\\007' "$?" "$PWD"\n`
247
+ }
248
+
249
+ /** init 整行:哑终端(echo/PS1/PS2/TERM)+ 固定 40×120(Non-Goal ③)+ INIT 帧。 */
250
+ export function buildInitCommand(nonce: string): string {
251
+ return `stty -echo 2>/dev/null ; stty rows 40 cols 120 2>/dev/null ; PS1='' ; PS2='' ; export TERM=dumb ; printf '\\033]133;D;${nonce};0;%s\\007' "$PWD"\n`
252
+ }
253
+
254
+ const ANSI_RE = /\x1b(?:\][^\x07\x1b]*(?:\x07|\x1b\\)?|\[[0-9;?]*[ -/]*[@-~]|[@-Z\\-_])/g
255
+
256
+ export function stripAnsi(s: string): string {
257
+ return s.replace(ANSI_RE, '')
258
+ }
259
+
260
+ export function normalizePtyText(s: string): string {
261
+ return stripAnsi(s).replace(/\r\n/g, '\n').replace(/\r/g, '')
262
+ }
263
+
264
+ export function tailWindow(text: string, cap: number): { text: string; truncated?: number } {
265
+ if (text.length <= cap) return { text }
266
+ return { text: `[truncated: showing last ${cap} of ${text.length} chars]\n${text.slice(text.length - cap)}`, truncated: text.length }
267
+ }
268
+
269
+ export interface FrameParserEvents {
270
+ /** 输出文本:feed 路径经 normalize(剥 ANSI/规整换行);flush 路径为**裸放出**(残余字节原样,勿假设已剥洗)。 */
271
+ onOutput?(text: string): void
272
+ onFrame(frame: PtyFrame): void
273
+ }
274
+
275
+ export interface NonceFrameParser { feed(chunk: string): void; flush(): void }
276
+
277
+ const FRAME_BODY_RE = /^(\d+);([^\x07\x1b]*)(?:\x07|\x1b\\)/ // cwd 是尾字段:合法路径可含 `;`,只有 BEL/ESC 终止它
278
+
279
+ /**
280
+ * 单 nonce、单帧解析器:一轮 dispatch 一个实例。只认 `\x1b]133;D;<nonce>;`,
281
+ * 错误 nonce 的静态/伪造 marker 永不匹配,按普通输出流过(再经 ANSI 剥洗)。
282
+ * 缓冲尾若可能是 marker 前缀则扣留,flush() 时作为输出放出。
283
+ */
284
+ export function createNonceFrameParser(nonce: string, events: FrameParserEvents): NonceFrameParser {
285
+ const prefix = `\x1b]133;D;${nonce};`
286
+ let buf = ''
287
+ let done = false
288
+
289
+ const emit = (raw: string): void => {
290
+ const text = normalizePtyText(raw)
291
+ if (text.length > 0) events.onOutput?.(text)
292
+ }
293
+
294
+ const holdback = (): number => {
295
+ const max = Math.min(buf.length, prefix.length - 1)
296
+ for (let k = max; k > 0; k--) if (buf.endsWith(prefix.slice(0, k))) return k
297
+ return 0
298
+ }
299
+
300
+ const consume = (): void => {
301
+ if (done) return
302
+ const i = buf.indexOf(prefix)
303
+ if (i < 0) {
304
+ const keep = holdback()
305
+ emit(buf.slice(0, buf.length - keep))
306
+ buf = buf.slice(buf.length - keep)
307
+ return
308
+ }
309
+ emit(buf.slice(0, i))
310
+ const rest = buf.slice(i + prefix.length)
311
+ const m = FRAME_BODY_RE.exec(rest)
312
+ if (m === null) { buf = buf.slice(i); return } // 帧体未到齐,整段扣留
313
+ events.onFrame({ exit: Number(m[1]!), cwd: m[2]!.length > 0 ? m[2]! : null })
314
+ done = true // 帧后字节一律丢弃(下一轮是新解析器)
315
+ buf = ''
316
+ }
317
+
318
+ return {
319
+ feed(chunk: string): void { buf += chunk; consume() },
320
+ // 流结束 = 裸放出扣留的残余(含未完成的 marker 前缀):不经过 ANSI 剥洗——
321
+ // stripAnsi 会把未闭合 OSC 整段吃掉,扣留字节就此蒸发,违背 flush 语义。
322
+ flush(): void { if (buf.length > 0) events.onOutput?.(buf); buf = '' },
323
+ }
324
+ }
325
+ ```
326
+
327
+ - [ ] **Step 4: 跑测试确认通过** — `npm test -- test/remote/nonce-framing.spec.ts` → PASS。
328
+
329
+ - [ ] **Step 5: Commit**
330
+
331
+ ```bash
332
+ git add src/remote/nonce-framing.ts test/remote/nonce-framing.spec.ts
333
+ git commit -m "feat(remote): nonce-gated framing module — wrap/init/parse/strip/tail-window"
334
+ ```
335
+
336
+ ---
337
+
338
+ ### Task 2: Target 智能路由 `target.ts`
339
+
340
+ **Files:**
341
+ - Create: `better-dsh/src/remote/target.ts`
342
+ - Test: `better-dsh/test/remote/target.spec.ts`
343
+
344
+ **Interfaces:**
345
+ ```ts
346
+ export type TargetPlan = { kind: 'ssh'; host: string } | { kind: 'docker' | 'incus'; container: string }
347
+ export class TargetFormatError extends Error { readonly code = 'E_TARGET_FORMAT' }
348
+ export function resolveTarget(target: string, containerAliases?: Record<string, string>): TargetPlan
349
+ ```
350
+
351
+ - [ ] **Step 1: 写失败测试**
352
+
353
+ ```ts
354
+ import { describe, expect, it } from 'vitest'
355
+ import { resolveTarget, TargetFormatError } from '../../src/remote/target.ts'
356
+
357
+ describe('resolveTarget', () => {
358
+ it('routes plain names / IPs / domains to ssh', () => {
359
+ expect(resolveTarget('dev4')).toEqual({ kind: 'ssh', host: 'dev4' })
360
+ expect(resolveTarget('137.131.54.174')).toEqual({ kind: 'ssh', host: '137.131.54.174' })
361
+ expect(resolveTarget('mac.example.com')).toEqual({ kind: 'ssh', host: 'mac.example.com' })
362
+ })
363
+ it('routes explicit container prefixes', () => {
364
+ expect(resolveTarget('docker:corti')).toEqual({ kind: 'docker', container: 'corti' })
365
+ expect(resolveTarget('incus:ctr-1')).toEqual({ kind: 'incus', container: 'ctr-1' })
366
+ })
367
+ it('registered bare container names beat ssh (ctr-1 is also an ssh Host)', () => {
368
+ expect(resolveTarget('ctr-1', { 'ctr-1': 'incus:ctr-1' })).toEqual({ kind: 'incus', container: 'ctr-1' })
369
+ })
370
+ it('ssh: explicit selector forces ssh even when an alias would match (Ruling P16)', () => {
371
+ expect(resolveTarget('ssh:ctr-1', { 'ctr-1': 'incus:ctr-1' })).toEqual({ kind: 'ssh', host: 'ctr-1' })
372
+ expect(resolveTarget('ssh:dev4')).toEqual({ kind: 'ssh', host: 'dev4' })
373
+ })
374
+ it('explicit prefix beats the alias map', () => {
375
+ expect(resolveTarget('incus:ctr-1', { 'ctr-1': 'docker:other' })).toEqual({ kind: 'incus', container: 'ctr-1' })
376
+ })
377
+ it('bad alias value and empty target fail loud', () => {
378
+ expect(() => resolveTarget('x', { x: 'dev4' })).toThrowError(TargetFormatError)
379
+ expect(() => resolveTarget(' ')).toThrowError(/E_TARGET_FORMAT/)
380
+ })
381
+ })
382
+ ```
383
+
384
+ - [ ] **Step 2: 跑测试确认失败** — `npm test -- test/remote/target.spec.ts` → FAIL。
385
+
386
+ - [ ] **Step 3: 最小实现**
387
+
388
+ ```ts
389
+ /** 解析后的传输计划:三种 CLI 传输之一。 */
390
+ export type TargetPlan =
391
+ | { kind: 'ssh'; host: string }
392
+ | { kind: 'docker'; container: string }
393
+ | { kind: 'incus'; container: string }
394
+
395
+ export class TargetFormatError extends Error {
396
+ readonly code = 'E_TARGET_FORMAT'
397
+ constructor(message: string) { super(message); this.name = 'TargetFormatError' }
398
+ }
399
+
400
+ /** 显式协议选择器(Ruling P16):可扩展新协议——加一个词即一条新传输腿。 */
401
+ const PREFIX_RE = /^(docker|incus|ssh):(.+)$/
402
+ /** 别名表值只接受容器形态(ssh 无别名意义——裸名即 ssh)。 */
403
+ const CONTAINER_PREFIX_RE = /^(docker|incus):(.+)$/
404
+
405
+ /** spec §二.2 智能路由(Ruling 12 + P16):显式选择器 > 别名表(人工 pin,撞名时赢)> ssh 缺省。 */
406
+ export function resolveTarget(target: string, containerAliases: Record<string, string> = {}): TargetPlan {
407
+ const raw = target.trim()
408
+ if (raw.length === 0) throw new TargetFormatError('[E_TARGET_FORMAT] remote: empty target')
409
+ const direct = PREFIX_RE.exec(raw)
410
+ if (direct !== null) {
411
+ if (direct[1] === 'ssh') return { kind: 'ssh', host: direct[2]! }
412
+ return { kind: direct[1] as 'docker' | 'incus', container: direct[2]! }
413
+ }
414
+ const aliased = containerAliases[raw]
415
+ if (aliased !== undefined) {
416
+ const m = CONTAINER_PREFIX_RE.exec(aliased)
417
+ if (m === null)
418
+ throw new TargetFormatError(
419
+ `[E_TARGET_FORMAT] remote: container alias '${raw}' must map to 'docker:<name>' or 'incus:<name>' (got ${JSON.stringify(aliased)})`)
420
+ return { kind: m[1] as 'docker' | 'incus', container: m[2]! }
421
+ }
422
+ return { kind: 'ssh', host: raw }
423
+ }
424
+ ```
425
+
426
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
427
+
428
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): smart target routing — prefix/alias/ssh"`(含 add)。
429
+
430
+ ---
431
+
432
+ ### Task 3: 传输 argv builders `transports.ts`
433
+
434
+ **Files:**
435
+ - Create: `better-dsh/src/remote/transports.ts`
436
+ - Test: `better-dsh/test/remote/transports.spec.ts`
437
+
438
+ **Interfaces:**
439
+ ```ts
440
+ export function shQuote(s: string): string
441
+ export function buildOneShotArgv(plan: TargetPlan, cmd: string): string[]
442
+ export function buildPtyArgv(plan: TargetPlan): string[]
443
+ export function buildSpawnArgv(spawnCommand: string): string[]
444
+ ```
445
+
446
+ - [ ] **Step 1: 写失败测试**
447
+
448
+ ```ts
449
+ import { describe, expect, it } from 'vitest'
450
+ import { buildOneShotArgv, buildPtyArgv, buildSpawnArgv, shQuote } from '../../src/remote/transports.ts'
451
+
452
+ describe('shQuote', () => {
453
+ it('wraps in single quotes and escapes embedded quotes POSIX-style', () => {
454
+ expect(shQuote('ls -la')).toBe(`'ls -la'`)
455
+ expect(shQuote("it's")).toBe(`'it'\\''s'`)
456
+ expect(shQuote('a\nb')).toBe(`'a\nb'`)
457
+ })
458
+ })
459
+
460
+ describe('buildOneShotArgv (spec §五.1 verbatim shapes)', () => {
461
+ it('ssh: BatchMode, no tty, one mechanically-quoted argv after the host', () => {
462
+ expect(buildOneShotArgv({ kind: 'ssh', host: 'dev4' }, "git status | head -1"))
463
+ .toEqual(['ssh', '-o', 'BatchMode=yes', '-T', '--', 'dev4', `bash -lc 'git status | head -1'`])
464
+ })
465
+ it('ssh survives a cmd containing single quotes (one mechanical layer)', () => {
466
+ const argv = buildOneShotArgv({ kind: 'ssh', host: 'dev4' }, "echo 'hi'")
467
+ expect(argv.at(-1)).toBe(`bash -lc 'echo '\\''hi'\\'''`)
468
+ })
469
+ it('docker: exec -i, argv-direct (no -t, no re-parse)', () => {
470
+ expect(buildOneShotArgv({ kind: 'docker', container: 'c1' }, 'echo x'))
471
+ .toEqual(['docker', 'exec', '-i', '--', 'c1', 'bash', '-lc', 'echo x'])
472
+ })
473
+ it('incus: exec without -t semantics (--force-noninteractive)', () => {
474
+ expect(buildOneShotArgv({ kind: 'incus', container: 'ctr-1' }, 'echo x'))
475
+ .toEqual(['incus', 'exec', '--force-noninteractive', 'ctr-1', '--', 'bash', '-lc', 'echo x'])
476
+ })
477
+ })
478
+
479
+ describe('buildPtyArgv', () => {
480
+ it('ssh: force-tty over host pipes, BatchMode', () => {
481
+ expect(buildPtyArgv({ kind: 'ssh', host: 'dev4' }))
482
+ .toEqual(['ssh', '-tt', '-o', 'BatchMode=yes', '--', 'dev4', 'bash'])
483
+ })
484
+ it('docker: script(1) hosts the PTY, local echo pre-silenced, exec replaces the shell', () => {
485
+ expect(buildPtyArgv({ kind: 'docker', container: 'my c' }))
486
+ .toEqual(['script', '-qfec', `stty -echo 2>/dev/null ; exec docker exec -it -- 'my c' bash`, '/dev/null'])
487
+ })
488
+ it('incus: force-interactive over host pipes', () => {
489
+ expect(buildPtyArgv({ kind: 'incus', container: 'ctr-1' }))
490
+ .toEqual(['incus', 'exec', '--force-interactive', 'ctr-1', '--', 'bash'])
491
+ })
492
+ })
493
+
494
+ describe('buildSpawnArgv (BYO-PTY)', () => {
495
+ it('hosts any spawn command under script with echo pre-silenced', () => {
496
+ expect(buildSpawnArgv('docker exec -it temp-worker bash'))
497
+ .toEqual(['script', '-qfec', 'stty -echo 2>/dev/null ; exec docker exec -it temp-worker bash', '/dev/null'])
498
+ })
499
+ })
500
+ ```
501
+
502
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
503
+
504
+ - [ ] **Step 3: 最小实现**
505
+
506
+ ```ts
507
+ import type { TargetPlan } from './target.ts'
508
+
509
+ /** POSIX 单引号机械转义(唯一一层转义,spec §三"一层机械转义")。 */
510
+ export function shQuote(s: string): string {
511
+ return `'${s.replaceAll("'", `'\\''`)}'`
512
+ }
513
+
514
+ /** One-shot(§五.1):不分配 tty,收尾 = 子进程退出码,零字符串扫描。 */
515
+ export function buildOneShotArgv(plan: TargetPlan, cmd: string): string[] {
516
+ switch (plan.kind) {
517
+ case 'ssh':
518
+ // ssh 把 host 后的 argv 用空格拼接交远端 shell 解析——预先整体 shQuote,
519
+ // 远端只做这一层解析,bash -lc 拿到原样 cmd。
520
+ return ['ssh', '-o', 'BatchMode=yes', '-T', '--', plan.host, `bash -lc ${shQuote(cmd)}`]
521
+ case 'docker':
522
+ return ['docker', 'exec', '-i', '--', plan.container, 'bash', '-lc', cmd]
523
+ case 'incus':
524
+ return ['incus', 'exec', '--force-noninteractive', plan.container, '--', 'bash', '-lc', cmd]
525
+ }
526
+ }
527
+
528
+ /** Persistent pty(Ruling 2):ssh/incus 走宿主管道,docker 经 script(1) 托管宿主 PTY。 */
529
+ export function buildPtyArgv(plan: TargetPlan): string[] {
530
+ switch (plan.kind) {
531
+ case 'ssh':
532
+ return ['ssh', '-tt', '-o', 'BatchMode=yes', '--', plan.host, 'bash']
533
+ case 'docker':
534
+ return ['script', '-qfec', `stty -echo 2>/dev/null ; exec docker exec -it -- ${shQuote(plan.container)} bash`, '/dev/null']
535
+ case 'incus':
536
+ return ['incus', 'exec', '--force-interactive', plan.container, '--', 'bash']
537
+ }
538
+ }
539
+
540
+ /** BYO-PTY(§三 spawn):工具只提供 PTY 托管 + Nonce 注入 + 收帧。 */
541
+ export function buildSpawnArgv(spawnCommand: string): string[] {
542
+ return ['script', '-qfec', `stty -echo 2>/dev/null ; exec ${spawnCommand}`, '/dev/null']
543
+ }
544
+ ```
545
+
546
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
547
+
548
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): CLI transport argv builders (ssh/docker/incus + script-hosted BYO-PTY)"`。
549
+
550
+ ---
551
+
552
+ ### Task 4: One-shot runner `oneshot.ts`
553
+
554
+ **Files:**
555
+ - Create: `better-dsh/src/remote/oneshot.ts`
556
+ - Test: `better-dsh/test/remote/oneshot.spec.ts`
557
+
558
+ **Interfaces:**
559
+ ```ts
560
+ export interface OneShotOptions { stdin?: string; timeoutSec?: number }
561
+ export interface OneShotResult { exit: number | null; timedOut: boolean; stdout: string; stderr: string; durationMs: number }
562
+ export async function runOneShot(argv: string[], opts?: OneShotOptions): Promise<OneShotResult>
563
+ ```
564
+
565
+ - [ ] **Step 1: 写失败测试**(本地真 `bash` 当 CLI 夹具,零网络)
566
+
567
+ ```ts
568
+ import { describe, expect, it } from 'vitest'
569
+ import { runOneShot } from '../../src/remote/oneshot.ts'
570
+
571
+ const BASH = (cmd: string): string[] => ['bash', '-c', cmd]
572
+
573
+ describe('runOneShot', () => {
574
+ it('captures stdout, stderr and the binary exit code', async () => {
575
+ const r = await runOneShot(BASH('echo out; echo err >&2; exit 42'))
576
+ expect(r.exit).toBe(42)
577
+ expect(r.stdout).toBe('out\n')
578
+ expect(r.stderr).toBe('err\n')
579
+ expect(r.timedOut).toBe(false)
580
+ })
581
+ it('pipes stdin and closes it', async () => {
582
+ const r = await runOneShot(BASH('cat'), { stdin: 'line1\nline2\n' })
583
+ expect(r.exit).toBe(0)
584
+ expect(r.stdout).toBe('line1\nline2\n')
585
+ })
586
+ it('preserves utf8 across chunk boundaries', async () => {
587
+ const r = await runOneShot(BASH("printf '中%.0s' $(seq 1 20000); echo"))
588
+ expect(r.stdout).toBe('中'.repeat(20_000) + '\n')
589
+ expect(r.exit).toBe(0)
590
+ })
591
+ it('timeout: TERM ignored -> KILL escalation observable (exit null, >2s), flagged, bounded', async () => {
592
+ const r = await runOneShot(BASH('trap "" TERM; sleep 30'), { timeoutSec: 1 })
593
+ expect(r.timedOut).toBe(true)
594
+ expect(r.exit).toBe(null)
595
+ expect(r.durationMs).toBeGreaterThan(2_500)
596
+ expect(r.durationMs).toBeLessThan(8_000)
597
+ })
598
+ it('timeout bounds completion when a background descendant holds the pipes (process-group kill)', async () => {
599
+ const r = await runOneShot(BASH('sleep 8 & sleep 8'), { timeoutSec: 1 })
600
+ expect(r.timedOut).toBe(true)
601
+ expect(r.durationMs).toBeLessThan(5_000)
602
+ })
603
+ it('spawn failure surfaces the OS error verbatim (error transparency)', async () => {
604
+ const r = await runOneShot(['definitely-not-a-real-cli-xyz', '--version'])
605
+ expect(r.exit).toBe(null)
606
+ expect(r.stderr).toContain('spawn failed')
607
+ expect(r.stderr).toContain('ENOENT')
608
+ })
609
+ })
610
+ ```
611
+
612
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
613
+
614
+ - [ ] **Step 3: 最小实现**
615
+
616
+ ```ts
617
+ import { spawn } from 'node:child_process'
618
+
619
+ export interface OneShotOptions { stdin?: string; timeoutSec?: number }
620
+ export interface OneShotResult { exit: number | null; timedOut: boolean; stdout: string; stderr: string; durationMs: number }
621
+
622
+ /** 单流硬收集帽(4M UTF-16 code units,ASCII≈4MB):防失控输出吃内存;模型面截断由上层 tailWindow 负责。 */
623
+ const HARD_CAP = 4_000_000
624
+
625
+ /** One-shot:子进程退出码即收尾(spec §五.1),stdout/stderr 分离保留。 */
626
+ export async function runOneShot(argv: string[], opts: OneShotOptions = {}): Promise<OneShotResult> {
627
+ const started = Date.now()
628
+ // detached+进程组:超时杀整组——后台子进程若仍占着管道,只杀直接子进程会让 close
629
+ // 永不触发(实测 `sleep 30 &` 场景无限挂起);组杀与 Ruling 9 的 pty 杀法同构。
630
+ const child = spawn(argv[0]!, argv.slice(1), { stdio: ['pipe', 'pipe', 'pipe'], detached: true })
631
+ let stdout = ''
632
+ let stderr = ''
633
+ let timedOut = false
634
+ child.stdout.setEncoding('utf8').on('data', (d: string) => {
635
+ if (stdout.length < HARD_CAP) stdout = (stdout + d).slice(0, HARD_CAP)
636
+ })
637
+ child.stderr.setEncoding('utf8').on('data', (d: string) => {
638
+ if (stderr.length < HARD_CAP) stderr = (stderr + d).slice(0, HARD_CAP)
639
+ })
640
+ child.stdin.on('error', () => {}) // EPIPE on early exit is not ours to raise
641
+ if (opts.stdin !== undefined) child.stdin.write(opts.stdin)
642
+ child.stdin.end()
643
+
644
+ let termTimer: NodeJS.Timeout | undefined
645
+ let killTimer: NodeJS.Timeout | undefined
646
+ const clearTimers = (): void => {
647
+ if (termTimer !== undefined) clearTimeout(termTimer)
648
+ if (killTimer !== undefined) clearTimeout(killTimer)
649
+ }
650
+ if (opts.timeoutSec !== undefined) {
651
+ const killGroup = (sig: NodeJS.Signals): void => {
652
+ if (child.pid === undefined) { child.kill(sig); return }
653
+ try { process.kill(-child.pid, sig) } catch { /* group already gone */ }
654
+ }
655
+ termTimer = setTimeout(() => {
656
+ timedOut = true
657
+ killGroup('SIGTERM')
658
+ killTimer = setTimeout(() => killGroup('SIGKILL'), 2_000)
659
+ }, opts.timeoutSec * 1_000)
660
+ }
661
+
662
+ const exit = await new Promise<number | null>((resolve) => {
663
+ child.once('close', (code) => resolve(code))
664
+ child.once('error', (err) => {
665
+ stderr += `\n[remote: spawn failed: ${err.message}]`
666
+ resolve(null)
667
+ })
668
+ })
669
+ clearTimers()
670
+ return { exit, timedOut, stdout, stderr, durationMs: Date.now() - started }
671
+ }
672
+ ```
673
+
674
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
675
+
676
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): one-shot runner — exit code only, split streams, TERM/KILL timeout"`。
677
+
678
+ ---
679
+
680
+ ### Task 5: Persistent PTY 会话与池 `pty-session.ts`
681
+
682
+ **Files:**
683
+ - Create: `better-dsh/src/remote/pty-session.ts`
684
+ - Test: `better-dsh/test/remote/pty-session.spec.ts`
685
+
686
+ **Interfaces:**
687
+ ```ts
688
+ export const RECONNECT_NOTICE = '[remote: session reconnected to fresh shell; cwd reset to default]'
689
+ export interface PtySessionOptions { key: string; argv: string[]; idleTtlSec: number; initTimeoutSec?: number; onDead?: () => void }
690
+ export interface PtyDispatchOptions { stdin?: string; timeoutSec?: number }
691
+ export interface PtyDispatchResult { output: string; exit: number | null; cwd: string | null; timedOut: boolean; reconnected: boolean; durationMs: number }
692
+ export type PtyState = 'cold' | 'starting' | 'ready' | 'dead' | 'disposed'
693
+ /** 会话运行时快照(status 面消费,Ruling 16 词汇源)。 */
694
+ export interface SessionSnapshot { state: PtyState; busy: boolean; idleMs: number | null; pid: number | null }
695
+ export class PtySession {
696
+ constructor(opts: PtySessionOptions)
697
+ get sessionState(): PtyState
698
+ get snapshot(): SessionSnapshot
699
+ dispatch(cmd: string, opts?: PtyDispatchOptions): Promise<PtyDispatchResult>
700
+ dispose(): Promise<void>
701
+ }
702
+ export interface PtyPoolDefaults { idleTtlSec: number; initTimeoutSec?: number }
703
+ export class PtyPool {
704
+ constructor(defaults: PtyPoolDefaults)
705
+ getOrCreate(key: string, argv: string[]): PtySession
706
+ get size(): number
707
+ inspect(key: string): SessionSnapshot | undefined
708
+ disposeAll(): Promise<void>
709
+ }
710
+ ```
711
+
712
+ - [ ] **Step 1: 写失败测试**(本地 `bash` 与 `script -qfec bash /dev/null` 当传输夹具——真协议、真 init、真帧,零网络)
713
+
714
+ ```ts
715
+ import { describe, expect, it } from 'vitest'
716
+ import { PtyPool, PtySession } from '../../src/remote/pty-session.ts'
717
+
718
+ const OPTS = { idleTtlSec: 600 }
719
+
720
+ describe('PtySession over plain local bash', () => {
721
+ it('cold starts, frames output/exit/cwd', async () => {
722
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
723
+ const r = await s.dispatch('echo hello && cd /tmp && pwd')
724
+ expect(r.output.trim()).toBe('hello\n/tmp')
725
+ expect(r.exit).toBe(0)
726
+ expect(r.cwd).toBe('/tmp')
727
+ expect(r.reconnected).toBe(false)
728
+ await s.dispose()
729
+ })
730
+ it('multi-line cmd = one compound frame, exit is the last command\'s', async () => {
731
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
732
+ const r = await s.dispatch('echo a\necho b\nfalse')
733
+ expect(r.output).toBe('a\nb\n')
734
+ expect(r.exit).toBe(1)
735
+ await s.dispose()
736
+ })
737
+ it('state persists across dispatches (cwd/env)', async () => {
738
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
739
+ await s.dispatch('export FOO=bar && cd /tmp')
740
+ const r = await s.dispatch('echo "$FOO" && pwd')
741
+ expect(r.output).toBe('bar\n/tmp\n')
742
+ await s.dispose()
743
+ })
744
+ it('snapshot feeds the status face: ready+idle after dispatch, disposed after dispose', async () => {
745
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
746
+ await s.dispatch('echo hi')
747
+ expect(s.snapshot).toMatchObject({ state: 'ready', busy: false })
748
+ expect(s.snapshot.idleMs).toBeGreaterThanOrEqual(0)
749
+ const pool = new PtyPool({ idleTtlSec: 600 })
750
+ const s2 = pool.getOrCreate('t:x', ['bash'])
751
+ expect(pool.inspect('t:x')?.state).toBe('cold')
752
+ expect(pool.inspect('missing')).toBeUndefined()
753
+ await s2.dispatch('echo y')
754
+ expect(pool.inspect('t:x')).toMatchObject({ state: 'ready', busy: false })
755
+ await s.dispose(); await pool.disposeAll()
756
+ })
757
+ it('serializes concurrent dispatches on one session (clean A/B output = no stdin interleave)', async () => {
758
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
759
+ const [r1, r2] = await Promise.all([
760
+ s.dispatch('sleep 0.4 ; echo A'),
761
+ s.dispatch('echo B'),
762
+ ])
763
+ expect(r1.output.trim()).toBe('A')
764
+ expect(r2.output.trim()).toBe('B')
765
+ expect(r1.durationMs).toBeGreaterThan(300)
766
+ await s.dispose()
767
+ })
768
+ it('unexpected shell death: partial + null exit; next dispatch reconnects with the notice', async () => {
769
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
770
+ const r1 = await s.dispatch('kill -9 $$')
771
+ expect(r1.exit).toBe(null)
772
+ const r2 = await s.dispatch('echo back')
773
+ expect(r2.reconnected).toBe(true)
774
+ expect(r2.output.trim()).toBe('back')
775
+ expect(r2.exit).toBe(0)
776
+ await s.dispose()
777
+ })
778
+ it('idle TTL disposes the session and drops it from the pool (transparent cold start, no notice)', async () => {
779
+ const pool = new PtyPool({ idleTtlSec: 1 })
780
+ const s = pool.getOrCreate('t:x', ['bash'])
781
+ await s.dispatch('echo hi')
782
+ await new Promise((r) => setTimeout(r, 1_800))
783
+ expect(s.sessionState).toBe('disposed')
784
+ expect(pool.size).toBe(0)
785
+ const s2 = pool.getOrCreate('t:x', ['bash'])
786
+ const r = await s2.dispatch('echo again')
787
+ expect(r.reconnected).toBe(false)
788
+ await pool.disposeAll()
789
+ })
790
+ })
791
+
792
+ describe('PtySession over script(1)-hosted PTY (BYO-PTY shape)', () => {
793
+ it('timeout sends ^C through the pty line discipline: framed exit 130, flagged interrupted', async () => {
794
+ const s = new PtySession({ key: 'k', argv: ['script', '-qfec', 'bash', '/dev/null'], ...OPTS })
795
+ const r = await s.dispatch('sleep 30', { timeoutSec: 1 })
796
+ expect(r.timedOut).toBe(true)
797
+ expect(r.durationMs).toBeLessThan(8_000)
798
+ expect(r.exit).toBe(130)
799
+ const r2 = await s.dispatch('echo alive') // session survived the interrupt
800
+ expect(r2.exit).toBe(0)
801
+ await s.dispose()
802
+ }, 20_000)
803
+ it('timeout kill fallback on a transport without interrupt (plain bash over pipes)', async () => {
804
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
805
+ const r = await s.dispatch('trap "" INT; sleep 30', { timeoutSec: 1 })
806
+ expect(r.timedOut).toBe(true)
807
+ expect(r.exit).toBe(null)
808
+ expect(r.durationMs).toBeLessThan(10_000)
809
+ await s.dispose()
810
+ }, 20_000)
811
+ it('forged static 133-D marker with wrong nonce never truncates the stream', async () => {
812
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
813
+ const r = await s.dispatch(`printf '\\x1b]133;D;deadbeefdeadbeef;99;/pwn\\x07' ; echo real`)
814
+ expect(r.exit).toBe(0)
815
+ expect(r.output.trim()).toBe('real')
816
+ await s.dispose()
817
+ })
818
+ it('caps dispatch output collection (tail ring) — runaway output cannot eat host memory', async () => {
819
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
820
+ const r = await s.dispatch("printf 'x%.0s' $(seq 1 5000000) ; echo ; echo TAILMARK")
821
+ expect(r.output.length).toBeLessThanOrEqual(4_000_001)
822
+ expect(r.output.trim().endsWith('TAILMARK')).toBe(true)
823
+ await s.dispose()
824
+ }, 30_000)
825
+ it('grace-expiry kill fallback reaps the process group (snapshot pid null, group gone)', async () => {
826
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
827
+ await s.dispatch('echo warm')
828
+ const pid = s.snapshot.pid
829
+ expect(pid).toBeTypeOf('number')
830
+ const r = await s.dispatch('trap "" INT; sleep 30', { timeoutSec: 1 })
831
+ expect(r.exit).toBe(null)
832
+ expect(r.timedOut).toBe(true)
833
+ expect(s.snapshot.pid).toBe(null)
834
+ await new Promise((r) => setTimeout(r, 1_200)) // 等组长异步收割(zombie 保留 PGID,同 tick 断言必假阴)
835
+ expect(() => process.kill(-pid!, 0)).toThrow()
836
+ await s.dispose()
837
+ }, 20_000)
838
+ it('dispose is terminal: stale-reference dispatch rejects E_SESSION_DISPOSED', async () => {
839
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
840
+ await s.dispatch('echo hi')
841
+ await s.dispose()
842
+ await expect(s.dispatch('echo late')).rejects.toThrow(/E_SESSION_DISPOSED/)
843
+ })
844
+ it('dispose mid-flight settles the in-flight dispatch promptly (exit null, not timedOut)', async () => {
845
+ const s = new PtySession({ key: 'k', argv: ['bash'], ...OPTS })
846
+ const p = s.dispatch('sleep 30', { timeoutSec: 30 })
847
+ await new Promise((r) => setTimeout(r, 300))
848
+ await s.dispose()
849
+ const r = await p
850
+ expect(r.exit).toBe(null)
851
+ expect(r.timedOut).toBe(false)
852
+ expect(r.durationMs).toBeLessThan(5_000)
853
+ await new Promise((r2) => setTimeout(r2, 1_200)) // 等 dispose 的 killTree 兑现,防组泄漏到下一测试
854
+ }, 20_000)
855
+ })
856
+ ```
857
+
858
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
859
+
860
+ - [ ] **Step 3: 最小实现**
861
+
862
+ ```ts
863
+ import { spawn, type ChildProcess } from 'node:child_process'
864
+ import { buildInitCommand, createNonceFrameParser, genNonce, wrapPtyCommand } from './nonce-framing.ts'
865
+
866
+ /** spec §五.2 逐字。 */
867
+ export const RECONNECT_NOTICE = '[remote: session reconnected to fresh shell; cwd reset to default]'
868
+
869
+ export interface PtySessionOptions {
870
+ key: string
871
+ argv: string[]
872
+ idleTtlSec: number
873
+ initTimeoutSec?: number
874
+ /** 池回调:会话彻底出池(dispose)时触发;进程意外死亡不出池(Ruling 7)。 */
875
+ onDead?: () => void
876
+ }
877
+
878
+ export interface PtyDispatchOptions { stdin?: string; timeoutSec?: number }
879
+ export interface PtyDispatchResult {
880
+ output: string
881
+ exit: number | null
882
+ cwd: string | null
883
+ timedOut: boolean
884
+ reconnected: boolean
885
+ durationMs: number
886
+ }
887
+
888
+ export type PtyState = 'cold' | 'starting' | 'ready' | 'dead' | 'disposed'
889
+
890
+ const DEFAULT_INIT_TIMEOUT_SEC = 30
891
+ const INTERRUPT_GRACE_MS = 3_000
892
+ /** pty 收集内存安全帽(Ruling P15,与 oneshot HARD_CAP 对齐):模型面只见尾窗,保留尾部。 */
893
+ const OUTPUT_HARD_CAP = 4_000_000
894
+
895
+ export class PtySession {
896
+ private proc: ChildProcess | null = null
897
+ private state: PtyState = 'cold'
898
+ private startPromise: Promise<void> | null = null
899
+ private queue: Promise<unknown> = Promise.resolve()
900
+ private idleTimer: NodeJS.Timeout | null = null
901
+ private onChunk: ((c: string) => void) | null = null
902
+ private deathWaiters: Array<() => void> = []
903
+ private diag = ''
904
+ private inFlight = 0
905
+ private lastSettleAt = 0
906
+
907
+ constructor(private readonly opts: PtySessionOptions) {}
908
+
909
+ get sessionState(): PtyState { return this.state }
910
+
911
+ /** status 面快照:state + busy(有命令在跑)+ idleMs(上次 settle 至今)+ pid(进程组头,kill 兜底可观测)。 */
912
+ get snapshot(): SessionSnapshot {
913
+ return { state: this.state, busy: this.inFlight > 0, idleMs: this.lastSettleAt > 0 ? Date.now() - this.lastSettleAt : null, pid: this.proc?.pid ?? null }
914
+ }
915
+
916
+ /** 同一会话命令严格串行(FIFO);死亡/冷态先重启。 */
917
+ dispatch(cmd: string, dOpts: PtyDispatchOptions = {}): Promise<PtyDispatchResult> {
918
+ const attempt = async (): Promise<PtyDispatchResult> => {
919
+ const started = Date.now()
920
+ const reconnected = this.state === 'dead'
921
+ if (this.state !== 'ready') await this.start()
922
+ this.inFlight++
923
+ return await new Promise<PtyDispatchResult>((resolve) => {
924
+ const nonce = genNonce()
925
+ let output = ''
926
+ let interrupted = false
927
+ let settled = false
928
+ let interruptTimer: NodeJS.Timeout | undefined
929
+ let killTimer: NodeJS.Timeout | undefined
930
+ const deathWaiter = (): void => finish({ output, exit: null, cwd: null, timedOut: interrupted })
931
+ const cleanup = (): void => {
932
+ this.onChunk = null
933
+ // I1(终审):已结算 dispatch 的死亡等待必须摘除——否则闭包钉住整段 output,
934
+ // 长命会话每调用累积一个 waiter(init 路径的 filter 同款形态)
935
+ this.deathWaiters = this.deathWaiters.filter((w) => w !== deathWaiter)
936
+ if (interruptTimer !== undefined) clearTimeout(interruptTimer)
937
+ if (killTimer !== undefined) clearTimeout(killTimer)
938
+ }
939
+ const finish = (r: Omit<PtyDispatchResult, 'durationMs' | 'reconnected'>): void => {
940
+ if (settled) return
941
+ settled = true
942
+ cleanup()
943
+ this.inFlight--
944
+ this.lastSettleAt = Date.now()
945
+ this.resetIdleTimer()
946
+ resolve({ ...r, reconnected, durationMs: Date.now() - started })
947
+ }
948
+ const parser = createNonceFrameParser(nonce, {
949
+ onOutput: (t) => {
950
+ output += t
951
+ // C1(终审):内存安全帽——无帽时一条 cat /dev/urandom 能在 120s 看门狗内
952
+ // 吃垮宿主 daemon。帽上切片避开代理对(首字符为低位代理则让出一字符)。
953
+ if (output.length > OUTPUT_HARD_CAP) {
954
+ output = output.slice(output.length - OUTPUT_HARD_CAP)
955
+ if (output.charCodeAt(0) >= 0xdc00 && output.charCodeAt(0) <= 0xdfff) output = output.slice(1)
956
+ }
957
+ },
958
+ onFrame: ({ exit, cwd }) => finish({ output, exit, cwd, timedOut: interrupted }),
959
+ })
960
+ this.onChunk = (c) => parser.feed(c)
961
+ this.write(wrapPtyCommand(cmd, nonce))
962
+ if (dOpts.stdin !== undefined) this.write(dOpts.stdin) // Ruling 11: REPL 式紧随
963
+ interruptTimer = setTimeout(() => {
964
+ interrupted = true
965
+ // P8 两段打断:\x03 中断前台作业后,交互 bash 会放弃当前命令行的剩余部分
966
+ // (尾部 marker 不再执行);紧随注入的同 nonce 130-marker 行在 bash 回到
967
+ // 读取态后被执行。无论 bash 弃行还是续行,帧都在宽限内到达且 exit=130,
968
+ // 会话存活;若命令 trap 掉 SIGINT,原 marker 先帧、注入行帧后字节被丢弃。
969
+ this.write('\x03')
970
+ this.write(`printf '\\033]133;D;${nonce};130;%s\\007' "$PWD"\n`)
971
+ killTimer = setTimeout(() => {
972
+ // Ruling 8 的 kill 兜底:宽限无帧 = 会话不可恢复,杀整组后收尸
973
+ // (否则 trap-INT 的卡死进程永生,重连后旧组再不可达)
974
+ this.killTree()
975
+ this.markDead()
976
+ finish({ output, exit: null, cwd: null, timedOut: true })
977
+ }, INTERRUPT_GRACE_MS)
978
+ }, dOpts.timeoutSec === undefined ? 120_000 : dOpts.timeoutSec * 1_000)
979
+ this.deathWaiters.push(deathWaiter)
980
+ })
981
+ }
982
+ const run = this.queue.then(attempt, attempt)
983
+ this.queue = run.then(() => undefined, () => undefined)
984
+ return run
985
+ }
986
+
987
+ /** TTL / row teardown:尽力 exit,1s 后杀组,出池。 */
988
+ async dispose(): Promise<void> {
989
+ if (this.state === 'disposed') return
990
+ this.clearIdleTimer()
991
+ this.state = 'disposed'
992
+ this.startPromise = null
993
+ this.write('exit\n')
994
+ setTimeout(() => this.killTree(), 1_000).unref()
995
+ this.opts.onDead?.()
996
+ }
997
+
998
+ private write(s: string): void {
999
+ if (this.proc?.stdin?.writable !== true) return
1000
+ try { this.proc.stdin.write(s) } catch { /* dead: death waiter settles the dispatch */ }
1001
+ }
1002
+
1003
+ private async start(): Promise<void> {
1004
+ if (this.state === 'disposed')
1005
+ throw new Error(`[E_SESSION_DISPOSED] remote pty session '${this.opts.key}' was disposed — the pool replaces disposed sessions; this reference is stale`)
1006
+ if (this.startPromise === null) {
1007
+ this.state = 'starting'
1008
+ this.startPromise = this.doStart().catch((err: unknown) => {
1009
+ this.startPromise = null
1010
+ this.markDead()
1011
+ throw err
1012
+ })
1013
+ }
1014
+ return this.startPromise
1015
+ }
1016
+
1017
+ private async doStart(): Promise<void> {
1018
+ const proc = spawn(this.opts.argv[0]!, this.opts.argv.slice(1), {
1019
+ stdio: ['pipe', 'pipe', 'pipe'],
1020
+ detached: true, // Ruling 9: 进程组杀法
1021
+ })
1022
+ this.proc = proc
1023
+ proc.stdout.setEncoding('utf8')
1024
+ proc.stdout.on('data', (d: string) => { this.onChunk?.(d) })
1025
+ proc.stderr.setEncoding('utf8').on('data', (d: string) => { this.diag = (this.diag + d).slice(-2_000) })
1026
+ proc.once('close', () => this.markDead())
1027
+ proc.once('error', (err) => { this.diag = (this.diag + `\n[remote: spawn failed: ${err.message}]`).slice(-2_000) })
1028
+
1029
+ const initTimeoutSec = this.opts.initTimeoutSec ?? DEFAULT_INIT_TIMEOUT_SEC
1030
+ const initNonce = genNonce()
1031
+ await new Promise<void>((resolve, reject) => {
1032
+ const timer = setTimeout(() => {
1033
+ this.killTree()
1034
+ reject(new Error(
1035
+ `[E_SESSION_START] remote pty session '${this.opts.key}' did not initialize in ${initTimeoutSec}s` +
1036
+ (this.diag.length > 0 ? `; transport stderr tail: ${this.diag}` : '')))
1037
+ }, initTimeoutSec * 1_000)
1038
+ const waiter = (): void => {
1039
+ clearTimeout(timer)
1040
+ reject(new Error(
1041
+ `[E_SESSION_DIED] remote pty session '${this.opts.key}' died before initializing` +
1042
+ (this.diag.length > 0 ? `; transport stderr tail: ${this.diag}` : '')))
1043
+ }
1044
+ this.deathWaiters.push(waiter)
1045
+ const parser = createNonceFrameParser(initNonce, {
1046
+ onFrame: () => {
1047
+ clearTimeout(timer)
1048
+ this.deathWaiters = this.deathWaiters.filter((w) => w !== waiter)
1049
+ if (this.state === 'disposed') {
1050
+ // dispose 竞态 init:不得复活已终态会话(否则重挂 idle timer + 幽灵 ready)
1051
+ reject(new Error(`[E_SESSION_DISPOSED] remote pty session '${this.opts.key}' disposed during init`))
1052
+ return
1053
+ }
1054
+ this.state = 'ready'
1055
+ this.resetIdleTimer()
1056
+ resolve()
1057
+ },
1058
+ })
1059
+ this.onChunk = (c) => parser.feed(c)
1060
+ this.write(buildInitCommand(initNonce))
1061
+ })
1062
+ }
1063
+
1064
+ private markDead(): void {
1065
+ if (this.state === 'disposed') {
1066
+ // dispose 是终态:不再翻转 state,但在飞 dispatch 的死亡等待仍需立即结算
1067
+ // (row teardown 不是超时——不得等 123s 看门狗,也不得错标 timedOut)
1068
+ const waiters = this.deathWaiters
1069
+ this.deathWaiters = []
1070
+ for (const w of waiters) w()
1071
+ return
1072
+ }
1073
+ this.state = 'dead'
1074
+ this.startPromise = null
1075
+ this.clearIdleTimer()
1076
+ const waiters = this.deathWaiters
1077
+ this.deathWaiters = []
1078
+ for (const w of waiters) w()
1079
+ }
1080
+
1081
+ private resetIdleTimer(): void {
1082
+ this.clearIdleTimer()
1083
+ this.idleTimer = setTimeout(() => void this.dispose(), this.opts.idleTtlSec * 1_000)
1084
+ this.idleTimer.unref()
1085
+ }
1086
+
1087
+ private clearIdleTimer(): void {
1088
+ if (this.idleTimer !== null) { clearTimeout(this.idleTimer); this.idleTimer = null }
1089
+ }
1090
+
1091
+ private killTree(): void {
1092
+ const pid = this.proc?.pid
1093
+ this.proc = null
1094
+ if (pid === undefined) return
1095
+ try { process.kill(-pid, 'SIGTERM') } catch { /* already gone */ }
1096
+ setTimeout(() => { try { process.kill(-pid, 'SIGKILL') } catch { /* already gone */ } }, 2_000).unref()
1097
+ }
1098
+ }
1099
+
1100
+ export interface PtyPoolDefaults { idleTtlSec: number; initTimeoutSec?: number }
1101
+
1102
+ /** 会话池:键 → 会话。意外死亡的会话留在池内(下次 dispatch 带 reconnect 提示)。 */
1103
+ export class PtyPool {
1104
+ private readonly sessions = new Map<string, PtySession>()
1105
+
1106
+ constructor(private readonly defaults: PtyPoolDefaults) {}
1107
+
1108
+ get size(): number { return this.sessions.size }
1109
+
1110
+ /** status 面:键上的会话快照(无会话 = undefined → "none — dials on first exec")。 */
1111
+ inspect(key: string): SessionSnapshot | undefined {
1112
+ return this.sessions.get(key)?.snapshot
1113
+ }
1114
+
1115
+ getOrCreate(key: string, argv: string[]): PtySession {
1116
+ let s = this.sessions.get(key)
1117
+ if (s === undefined || s.sessionState === 'disposed') {
1118
+ s = new PtySession({ key, argv, ...this.defaults, onDead: () => this.sessions.delete(key) })
1119
+ this.sessions.set(key, s)
1120
+ }
1121
+ return s
1122
+ }
1123
+
1124
+ async disposeAll(): Promise<void> {
1125
+ await Promise.all([...this.sessions.values()].map((s) => s.dispose()))
1126
+ this.sessions.clear()
1127
+ }
1128
+ }
1129
+ ```
1130
+
1131
+ - [ ] **Step 4: 跑测试确认通过** → PASS(130 断言由 Ruling P8 两段打断保证确定性:交互 bash 弃行→注入行补帧 130;续行→原 marker 报 130;trap INT 忽略→宽限后 kill 兜底 exit null,走另一测试)。
1132
+
1133
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): persistent pty session pool — init protocol, serial dispatch, ^C interrupt, TTL, reconnect notice"`。
1134
+
1135
+ ---
1136
+
1137
+ ### Task 6: `RemoteDriver` 调度器 `driver.ts`
1138
+
1139
+ **Files:**
1140
+ - Create: `better-dsh/src/remote/driver.ts`
1141
+ - Test: `better-dsh/test/remote/driver.spec.ts`
1142
+
1143
+ **Interfaces:**
1144
+ ```ts
1145
+ export interface RemoteCallParams { target?: string; spawn?: string; cmd: string; mode?: 'oneshot' | 'pty'; stdin?: string; timeout?: number }
1146
+ export interface RemoteCallResult {
1147
+ mode: 'oneshot' | 'pty'; target: string; exit: number | null; cwd: string | null
1148
+ timedOut: boolean; reconnected: boolean; stdout: string; stderr?: string
1149
+ durationMs: number; truncated?: number
1150
+ }
1151
+ export interface RemoteAuditRecord { target: string; cmd: string; cwd?: string; exit?: number | null; durationMs?: number; error?: string }
1152
+ export interface RemoteDriverOptions {
1153
+ containers?: Record<string, string>
1154
+ execTimeoutSec?: number // default 120
1155
+ idleTtlSec?: number // default 600 (spec: 10min)
1156
+ maxOutputChars?: number // default 30000
1157
+ onAudit?: (r: RemoteAuditRecord) => void
1158
+ /** 测试缝:覆写 argv 构造(默认走 buildOneShotArgv / buildPtyArgv / buildSpawnArgv)。 */
1159
+ oneshotArgvFor?: (plan: TargetPlan, cmd: string) => string[]
1160
+ ptyArgvFor?: (plan: TargetPlan) => string[]
1161
+ spawnArgvFor?: (spawnCommand: string) => string[]
1162
+ }
1163
+ export class RemoteDriver {
1164
+ constructor(opts?: RemoteDriverOptions)
1165
+ call(params: RemoteCallParams, callCtx?: { sessionKey?: string }): Promise<RemoteCallResult>
1166
+ dispose(): Promise<void>
1167
+ }
1168
+ ```
1169
+
1170
+ - [ ] **Step 1: 写失败测试**(测试缝把 argv 指到本地 bash,其余全真)
1171
+
1172
+ ```ts
1173
+ import { describe, expect, it } from 'vitest'
1174
+ import { RemoteDriver, type RemoteAuditRecord } from '../../src/remote/driver.ts'
1175
+
1176
+ const driverWith = (over: Partial<ConstructorParameters<typeof RemoteDriver>[0]> = {}): RemoteDriver =>
1177
+ new RemoteDriver({
1178
+ oneshotArgvFor: () => ['bash', '-lc', 'echo fixed'],
1179
+ ptyArgvFor: () => ['bash'],
1180
+ spawnArgvFor: () => ['bash'],
1181
+ idleTtlSec: 600,
1182
+ ...over,
1183
+ })
1184
+
1185
+ describe('RemoteDriver validation', () => {
1186
+ it('rejects target+spawn and neither (E_PARAMS), and bad timeout (E_BAD_TIMEOUT)', async () => {
1187
+ const d = driverWith()
1188
+ await expect(d.call({ target: 'dev4', spawn: 'bash', cmd: 'x' })).rejects.toThrow(/E_PARAMS/)
1189
+ await expect(d.call({ cmd: 'x' })).rejects.toThrow(/E_PARAMS/)
1190
+ await expect(d.call({ target: 'dev4', cmd: 'x', timeout: 0 })).rejects.toThrow(/E_BAD_TIMEOUT/)
1191
+ await expect(d.call({ target: 'dev4', cmd: 'x', timeout: Number.POSITIVE_INFINITY })).rejects.toThrow(/E_BAD_TIMEOUT/)
1192
+ })
1193
+ it('spawn locks mode to pty even if oneshot was asked', async () => {
1194
+ const d = driverWith()
1195
+ const r = await d.call({ spawn: 'docker exec -it x bash', cmd: 'echo hi', mode: 'oneshot' })
1196
+ expect(r.mode).toBe('pty')
1197
+ await d.dispose()
1198
+ })
1199
+ })
1200
+
1201
+ describe('RemoteDriver routing', () => {
1202
+ it('oneshot default: runs the transport argv, returns binary exit + split stderr', async () => {
1203
+ const seen: string[][] = []
1204
+ const d = new RemoteDriver({
1205
+ oneshotArgvFor: (_plan, cmd) => { seen.push(['oneshot', cmd]); return ['bash', '-c', 'echo out; echo err >&2; exit 3'] },
1206
+ })
1207
+ const r = await d.call({ target: 'dev4', cmd: 'git status' })
1208
+ expect(r.mode).toBe('oneshot')
1209
+ expect(r.exit).toBe(3)
1210
+ expect(r.stdout).toBe('out\n')
1211
+ expect(r.stderr).toBe('err\n')
1212
+ expect(seen).toEqual([['oneshot', 'git status']])
1213
+ await d.dispose()
1214
+ })
1215
+ it('pty mode: session key isolates agents, state persists per key', async () => {
1216
+ const d = driverWith()
1217
+ await d.call({ target: 'dev4', mode: 'pty', cmd: 'cd /tmp' }, { sessionKey: 'a1' })
1218
+ const r = await d.call({ target: 'dev4', mode: 'pty', cmd: 'pwd' }, { sessionKey: 'a1' })
1219
+ expect(r.cwd).toBe('/tmp')
1220
+ const r2 = await d.call({ target: 'dev4', mode: 'pty', cmd: 'pwd' }, { sessionKey: 'a2' })
1221
+ expect(r2.cwd).not.toBe('/tmp') // different agent, fresh session
1222
+ await d.dispose()
1223
+ })
1224
+ it('truncates oversized output to the tail window with disclosure', async () => {
1225
+ const d = new RemoteDriver({
1226
+ maxOutputChars: 10,
1227
+ oneshotArgvFor: () => ['bash', '-c', 'printf "x%.0s" $(seq 1 100)'],
1228
+ })
1229
+ const r = await d.call({ target: 'dev4', cmd: 'x' })
1230
+ expect(r.truncated).toBe(100)
1231
+ expect(r.stdout).toContain('[truncated: showing last 10 of 100 chars]')
1232
+ await d.dispose()
1233
+ })
1234
+ it('emits one audit record per attempt (success, nonzero exit, and error paths)', async () => {
1235
+ const audit: RemoteAuditRecord[] = []
1236
+ const d = driverWith({ onAudit: (r) => audit.push(r) })
1237
+ await d.call({ target: 'dev4', cmd: 'echo ok' })
1238
+ const d255 = new RemoteDriver({
1239
+ onAudit: (r) => audit.push(r),
1240
+ oneshotArgvFor: () => ['bash', '-c', 'exit 255'],
1241
+ })
1242
+ await d255.call({ target: 'no-such-host-xyz', cmd: 'echo no' }).catch(() => {})
1243
+ await expect(d.call({ target: 'a', spawn: 'b', cmd: 'x' })).rejects.toThrow(/E_PARAMS/)
1244
+ expect(audit[0]).toMatchObject({ target: 'dev4', cmd: 'echo ok', exit: 0 })
1245
+ expect(audit[1]).toMatchObject({ target: 'no-such-host-xyz', exit: 255 })
1246
+ expect(audit[2]).toMatchObject({ target: 'a', cmd: 'x', error: expect.stringContaining('E_PARAMS') })
1247
+ await d.dispose(); await d255.dispose()
1248
+ })
1249
+ })
1250
+ ```
1251
+
1252
+ 注:`no-such-host-xyz` 用例经 `exit 255` 缝走**非零退出的成功分支**审计(`runOneShot` 把 exit 收集为数据、不抛错);真正的 catch 审计路径用 `E_PARAMS` 拒绝断言(`target ?? spawn ?? '?'` 回退)。
1253
+
1254
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
1255
+
1256
+ - [ ] **Step 3: 最小实现**
1257
+
1258
+ ```ts
1259
+ import { runOneShot } from './oneshot.ts'
1260
+ import { PtyPool } from './pty-session.ts'
1261
+ import { tailWindow } from './nonce-framing.ts'
1262
+ import { resolveTarget, type TargetPlan } from './target.ts'
1263
+ import { buildOneShotArgv, buildPtyArgv, buildSpawnArgv } from './transports.ts'
1264
+
1265
+ export interface RemoteCallParams {
1266
+ target?: string
1267
+ spawn?: string
1268
+ cmd: string
1269
+ mode?: 'oneshot' | 'pty'
1270
+ stdin?: string
1271
+ timeout?: number
1272
+ }
1273
+
1274
+ export interface RemoteCallResult {
1275
+ mode: 'oneshot' | 'pty'
1276
+ target: string
1277
+ exit: number | null
1278
+ cwd: string | null
1279
+ timedOut: boolean
1280
+ reconnected: boolean
1281
+ stdout: string
1282
+ stderr?: string
1283
+ durationMs: number
1284
+ truncated?: number
1285
+ }
1286
+
1287
+ export interface RemoteAuditRecord {
1288
+ target: string
1289
+ cmd: string
1290
+ cwd?: string
1291
+ exit?: number | null
1292
+ durationMs?: number
1293
+ error?: string
1294
+ }
1295
+
1296
+ export interface RemoteDriverOptions {
1297
+ containers?: Record<string, string>
1298
+ execTimeoutSec?: number
1299
+ idleTtlSec?: number
1300
+ maxOutputChars?: number
1301
+ onAudit?: (r: RemoteAuditRecord) => void
1302
+ oneshotArgvFor?: (plan: TargetPlan, cmd: string) => string[]
1303
+ ptyArgvFor?: (plan: TargetPlan) => string[]
1304
+ spawnArgvFor?: (spawnCommand: string) => string[]
1305
+ }
1306
+
1307
+ /** 双轨调度器(spec §七 Phase 2):参数校验 → 路由 → oneshot 子进程 / pty 会话池。 */
1308
+ export class RemoteDriver {
1309
+ private readonly pool: PtyPool
1310
+ constructor(private readonly opts: RemoteDriverOptions = {}) {
1311
+ this.pool = new PtyPool({ idleTtlSec: opts.idleTtlSec ?? 600 })
1312
+ }
1313
+
1314
+ async call(params: RemoteCallParams, callCtx: { sessionKey?: string } = {}): Promise<RemoteCallResult> {
1315
+ const started = Date.now()
1316
+ try {
1317
+ const routing = this.route(params)
1318
+ const result = await this.execute(params, routing, callCtx)
1319
+ this.audit({
1320
+ target: routing.display, cmd: params.cmd, cwd: result.cwd ?? undefined,
1321
+ exit: result.exit, durationMs: Date.now() - started,
1322
+ })
1323
+ return result
1324
+ } catch (error) {
1325
+ this.audit({
1326
+ target: params.target ?? params.spawn ?? '?', cmd: params.cmd,
1327
+ error: error instanceof Error ? error.message : String(error), durationMs: Date.now() - started,
1328
+ })
1329
+ throw error
1330
+ }
1331
+ }
1332
+
1333
+ /** Ruling 13:审计 best-effort——钩子抛错不得影响命令路径(成功被毒化成失败+双重审计)。 */
1334
+ private audit(r: RemoteAuditRecord): void {
1335
+ try { this.opts.onAudit?.(r) } catch { /* audit hook failure is never the command's failure */ }
1336
+ }
1337
+
1338
+ private route(params: RemoteCallParams): { mode: 'oneshot' | 'pty'; display: string; plan?: TargetPlan; spawn?: string } {
1339
+ const hasTarget = params.target !== undefined && params.target.length > 0
1340
+ const hasSpawn = params.spawn !== undefined && params.spawn.length > 0
1341
+ if (hasTarget && hasSpawn)
1342
+ throw new Error('[E_PARAMS] remote: pass exactly one of target or spawn, not both')
1343
+ if (!hasTarget && !hasSpawn)
1344
+ throw new Error('[E_PARAMS] remote: target or spawn is required (e.g. { target: "dev4", cmd: "git status" })')
1345
+ if (params.timeout !== undefined && (!Number.isFinite(params.timeout) || params.timeout <= 0))
1346
+ throw new Error(`[E_BAD_TIMEOUT] remote: timeout must be a positive number of seconds (got ${JSON.stringify(params.timeout)})`)
1347
+ if (params.stdin !== undefined && (params.cmd === undefined || params.cmd.length === 0))
1348
+ throw new Error('[E_STDIN_WITHOUT_CMD] remote: stdin requires cmd')
1349
+ const mode: 'oneshot' | 'pty' = hasSpawn ? 'pty' : params.mode ?? 'oneshot'
1350
+ if (hasSpawn) return { mode, display: params.spawn!, spawn: params.spawn }
1351
+ return { mode, display: params.target!, plan: resolveTarget(params.target!, this.opts.containers ?? {}) }
1352
+ }
1353
+
1354
+ private async execute(params: RemoteCallParams, routing: { mode: 'oneshot' | 'pty'; display: string; plan?: TargetPlan; spawn?: string }, callCtx: { sessionKey?: string }): Promise<RemoteCallResult> {
1355
+ const timeoutSec = params.timeout ?? this.opts.execTimeoutSec ?? 120
1356
+ const cap = this.opts.maxOutputChars ?? 30_000
1357
+ if (routing.mode === 'oneshot') {
1358
+ const argv = (this.opts.oneshotArgvFor ?? buildOneShotArgv)(routing.plan!, params.cmd)
1359
+ const r = await runOneShot(argv, { stdin: params.stdin, timeoutSec })
1360
+ const out = tailWindow(r.stdout, cap)
1361
+ const err = r.stderr.length > 0 ? tailWindow(r.stderr, cap) : undefined
1362
+ return {
1363
+ mode: 'oneshot', target: routing.display, exit: r.exit, cwd: null,
1364
+ timedOut: r.timedOut, reconnected: false, stdout: out.text,
1365
+ ...(err !== undefined ? { stderr: err.text } : {}), durationMs: r.durationMs,
1366
+ ...(out.truncated !== undefined ? { truncated: out.truncated } : {}),
1367
+ }
1368
+ }
1369
+ const argv = routing.spawn !== undefined
1370
+ ? (this.opts.spawnArgvFor ?? buildSpawnArgv)(routing.spawn)
1371
+ : (this.opts.ptyArgvFor ?? buildPtyArgv)(routing.plan!)
1372
+ const key = `${callCtx.sessionKey ?? 'no-session'}|${routing.spawn !== undefined ? `s:${routing.spawn}` : `t:${routing.display}`}`
1373
+ const session = this.pool.getOrCreate(key, argv)
1374
+ const r = await session.dispatch(params.cmd, { stdin: params.stdin, timeoutSec })
1375
+ const out = tailWindow(r.output, cap)
1376
+ return {
1377
+ mode: 'pty', target: routing.display, exit: r.exit, cwd: r.cwd,
1378
+ timedOut: r.timedOut, reconnected: r.reconnected, stdout: out.text,
1379
+ durationMs: r.durationMs, ...(out.truncated !== undefined ? { truncated: out.truncated } : {}),
1380
+ }
1381
+ }
1382
+
1383
+ async dispose(): Promise<void> { await this.pool.disposeAll() }
1384
+ }
1385
+ ```
1386
+
1387
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
1388
+
1389
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): two-track driver — routing matrix, agent-scoped session keys, audit hook"`。
1390
+
1391
+ ---
1392
+
1393
+ ### Task 7: 状态面 `status.ts`(诚实词汇表 + on-demand 探测)
1394
+
1395
+ **Files:**
1396
+ - Create: `better-dsh/src/remote/status.ts`
1397
+ - Test: `better-dsh/test/remote/status.spec.ts`
1398
+
1399
+ **Interfaces:**
1400
+ ```ts
1401
+ export type ProbeOutcome =
1402
+ | { state: 'reachable'; rttMs: number }
1403
+ | { state: 'unreachable'; detail: string } // 含原生 stderr 单行 / 超时标注
1404
+ | { state: 'container'; status: string } // running / stopped / exited …(事实态)
1405
+ | { state: 'error'; detail: string } // CLI 级错误(No such object 等,原样)
1406
+ export interface ProbeOptions {
1407
+ connectTimeoutSec?: number // default 5(ssh ConnectTimeout)
1408
+ hardTimeoutSec?: number // default 10(外层硬顶,Ruling 17 双重超时)
1409
+ runner?: typeof runOneShot // 测试缝
1410
+ }
1411
+ export async function probeTarget(plan: TargetPlan, opts?: ProbeOptions): Promise<ProbeOutcome>
1412
+ export function renderProbe(p: ProbeOutcome): string
1413
+ /** Ruling P12:renderSession 只消费 state/busy/idleMs 三字段(Pick 超集,测试字面量无需 pid)。 */
1414
+ export function renderSession(s: Pick<SessionSnapshot, 'state' | 'busy' | 'idleMs'> | undefined): string
1415
+ ```
1416
+
1417
+ - [ ] **Step 1: 写失败测试**
1418
+
1419
+ ```ts
1420
+ import { describe, expect, it } from 'vitest'
1421
+ import { probeTarget, renderProbe, renderSession } from '../../src/remote/status.ts'
1422
+ import type { OneShotResult } from '../../src/remote/oneshot.ts'
1423
+
1424
+ const R = (over: Partial<OneShotResult>): OneShotResult =>
1425
+ ({ exit: 0, timedOut: false, stdout: '', stderr: '', durationMs: 10, ...over })
1426
+
1427
+ describe('probeTarget vocabulary (Ruling 16 — offline is banned)', () => {
1428
+ it('ssh exit 0 -> reachable with rtt', async () => {
1429
+ const p = await probeTarget({ kind: 'ssh', host: 'dev4' }, { runner: async () => R({}) })
1430
+ expect(p).toMatchObject({ state: 'reachable' })
1431
+ expect(p.state === 'reachable' && p.rttMs).toBeGreaterThanOrEqual(0)
1432
+ expect(renderProbe(p)).toContain('reachable')
1433
+ })
1434
+ it('ssh failure -> unreachable + native stderr verbatim, never "offline"', async () => {
1435
+ const p = await probeTarget({ kind: 'ssh', host: 'x' }, {
1436
+ runner: async () => R({ exit: 255, stderr: 'ssh: connect to host x port 22: Connection timed out\r\n' }),
1437
+ })
1438
+ expect(p.state).toBe('unreachable')
1439
+ expect(p.state === 'unreachable' && p.detail).toContain('Connection timed out')
1440
+ const text = renderProbe(p)
1441
+ expect(text).toContain('unreachable')
1442
+ expect(text).not.toContain('offline')
1443
+ })
1444
+ it('ssh hang -> hard timeout labeled', async () => {
1445
+ const p = await probeTarget({ kind: 'ssh', host: 'x' }, {
1446
+ runner: async () => R({ exit: null, timedOut: true }),
1447
+ })
1448
+ expect(p).toMatchObject({ state: 'unreachable', detail: expect.stringContaining('probe timed out after 10s') })
1449
+ })
1450
+ it('docker inspect -> factual container state; native error passes through', async () => {
1451
+ const p1 = await probeTarget({ kind: 'docker', container: 'c1' }, { runner: async () => R({ stdout: 'running\n' }) })
1452
+ expect(p1).toEqual({ state: 'container', status: 'running' })
1453
+ const p2 = await probeTarget({ kind: 'docker', container: 'nope' }, {
1454
+ runner: async () => R({ exit: 1, stderr: 'Error: No such object: nope\n' }),
1455
+ })
1456
+ expect(p2).toMatchObject({ state: 'error', detail: expect.stringContaining('No such object') })
1457
+ })
1458
+ it('incus csv -> exact-name row status; missing name -> explicit error', async () => {
1459
+ const out = 'ctr-1,RUNNING\nctr-11,STOPPED\n'
1460
+ const p1 = await probeTarget({ kind: 'incus', container: 'ctr-1' }, { runner: async () => R({ stdout: out }) })
1461
+ expect(p1).toEqual({ state: 'container', status: 'RUNNING' })
1462
+ const p2 = await probeTarget({ kind: 'incus', container: 'zz' }, { runner: async () => R({ stdout: out }) })
1463
+ expect(p2).toMatchObject({ state: 'error', detail: expect.stringContaining("no container named 'zz'") })
1464
+ })
1465
+ })
1466
+
1467
+ describe('renderSession (session layer, Ruling 16)', () => {
1468
+ it('undefined -> none, says dial-on-first-exec, no reachability claim', () => {
1469
+ expect(renderSession(undefined)).toBe('session: none — dials on first exec')
1470
+ })
1471
+ it('ready+quiet -> idle with age; busy -> busy; dead -> died notice', () => {
1472
+ expect(renderSession({ state: 'ready', busy: false, idleMs: 45_000 })).toBe('session: idle 45s (connected)')
1473
+ expect(renderSession({ state: 'ready', busy: true, idleMs: 0 })).toBe('session: busy (a command is running)')
1474
+ expect(renderSession({ state: 'dead', busy: false, idleMs: null })).toBe('session: died — next exec cold-starts a fresh shell')
1475
+ })
1476
+ })
1477
+ ```
1478
+
1479
+ - [ ] **Step 2: 跑测试确认失败** — `npm test -- test/remote/status.spec.ts` → FAIL。
1480
+
1481
+ - [ ] **Step 3: 最小实现**
1482
+
1483
+ ```ts
1484
+ import { runOneShot, type OneShotOptions, type OneShotResult } from './oneshot.ts'
1485
+ import type { SessionSnapshot } from './pty-session.ts'
1486
+ import type { TargetPlan } from './target.ts'
1487
+
1488
+ /** Ruling 16 词汇表的机器面。 */
1489
+ export type ProbeOutcome =
1490
+ | { state: 'reachable'; rttMs: number }
1491
+ | { state: 'unreachable'; detail: string }
1492
+ | { state: 'container'; status: string }
1493
+ | { state: 'error'; detail: string }
1494
+
1495
+ export interface ProbeOptions {
1496
+ connectTimeoutSec?: number
1497
+ hardTimeoutSec?: number
1498
+ runner?: (argv: string[], opts?: OneShotOptions) => Promise<OneShotResult>
1499
+ }
1500
+
1501
+ function oneLine(s: string): string {
1502
+ return s.trim().split(/\r?\n/).filter(Boolean).at(-1) ?? ''
1503
+ }
1504
+
1505
+ /**
1506
+ * On-demand 探测(Ruling 17):调用瞬间拨一次,双重超时(ssh ConnectTimeout
1507
+ * 5s + 外层 hard 10s),结果即当时事实。绝不缓存、绝不在 boot 时扫。
1508
+ */
1509
+ export async function probeTarget(plan: TargetPlan, opts: ProbeOptions = {}): Promise<ProbeOutcome> {
1510
+ const ct = opts.connectTimeoutSec ?? 5
1511
+ const hard = opts.hardTimeoutSec ?? 10
1512
+ const runner = opts.runner ?? runOneShot
1513
+ const started = Date.now()
1514
+ const argv =
1515
+ plan.kind === 'ssh'
1516
+ ? ['ssh', '-o', 'BatchMode=yes', '-o', `ConnectTimeout=${ct}`, '-T', '--', plan.host, 'true']
1517
+ : plan.kind === 'docker'
1518
+ ? ['docker', 'inspect', '--format', '{{.State.Status}}', plan.container]
1519
+ : ['incus', 'list', plan.container, '--format', 'csv', '--columns', 'ns']
1520
+ const r = await runner(argv, { timeoutSec: hard })
1521
+ if (plan.kind === 'ssh') {
1522
+ if (r.exit === 0 && !r.timedOut) return { state: 'reachable', rttMs: Date.now() - started }
1523
+ const detail = r.timedOut
1524
+ ? `probe timed out after ${hard}s`
1525
+ : oneLine(r.stderr) || `ssh exited ${r.exit}`
1526
+ return { state: 'unreachable', detail }
1527
+ }
1528
+ if (plan.kind === 'docker') {
1529
+ if (r.exit === 0 && !r.timedOut) return { state: 'container', status: r.stdout.trim() }
1530
+ return { state: 'error', detail: oneLine(r.stderr) || `docker inspect exited ${r.exit}` }
1531
+ }
1532
+ const row = r.stdout.trim().split(/\r?\n/).find((l) => l.split(',')[0] === plan.container)
1533
+ if (r.exit === 0 && !r.timedOut && row !== undefined) return { state: 'container', status: row.split(',')[1]?.trim() ?? 'unknown' }
1534
+ if (r.exit === 0 && !r.timedOut) return { state: 'error', detail: `incus list has no container named '${plan.container}'` }
1535
+ return { state: 'error', detail: oneLine(r.stderr) || `incus exited ${r.exit}` }
1536
+ }
1537
+
1538
+ export function renderProbe(p: ProbeOutcome): string {
1539
+ switch (p.state) {
1540
+ case 'reachable': return `probe: reachable in ${p.rttMs}ms (just now, on demand)`
1541
+ case 'unreachable': return `probe: unreachable — ${p.detail}`
1542
+ case 'error': return `probe: error — ${p.detail}`
1543
+ case 'container': return `probe: container ${p.status} (just now, on demand)`
1544
+ }
1545
+ }
1546
+
1547
+ export function renderSession(s: Pick<SessionSnapshot, 'state' | 'busy' | 'idleMs'> | undefined): string {
1548
+ if (s === undefined || s.state === 'cold' || s.state === 'starting' || s.state === 'disposed')
1549
+ return 'session: none — dials on first exec'
1550
+ if (s.state === 'dead') return 'session: died — next exec cold-starts a fresh shell'
1551
+ if (s.busy) return 'session: busy (a command is running)'
1552
+ return `session: idle ${Math.round((s.idleMs ?? 0) / 1000)}s (connected)`
1553
+ }
1554
+ ```
1555
+
1556
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
1557
+
1558
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): on-demand status probe — honest vocabulary (reachable/unreachable/container fact), session layer render"`。
1559
+
1560
+ ---
1561
+
1562
+ ### Task 8: driver 状态集成 + 模型面工具 `tool.ts`
1563
+
1564
+ **Files:**
1565
+ - Create: `better-dsh/src/remote/tool.ts`
1566
+ - Modify: `better-dsh/src/remote/driver.ts`(增 `status()` 方法 + `probeRunner` 测试缝)
1567
+ - Test: `better-dsh/test/remote/tool.spec.ts`
1568
+
1569
+ **Interfaces:**
1570
+ ```ts
1571
+ // driver.ts 增量:
1572
+ export interface RemoteDriverOptions { /* …Task 6 全部字段… */ probeRunner?: ProbeOptions['runner'] }
1573
+ export class RemoteDriver { /* …Task 6 全部成员… */ status(target: string, callCtx?: { sessionKey?: string }): Promise<string> }
1574
+ // tool.ts:
1575
+ export function createRemoteTool(driver: RemoteDriver, opts?: { getSessionKey?: (exec: ToolRunContext) => string }): ToolDefinition
1576
+ ```
1577
+ (`defineTool` / `ToolRunContext` 来自 `@deepseek-ai/dsh-tools`,`ContentBlock` 来自 `@deepseek-ai/dsh-llm`——照 RM0 `src/remote/tool.ts` 的 import 面;RM0 文件在 `.worktrees/remote-tool-rm0/better-dsh/src/remote/tool.ts`,结构样板。)
1578
+
1579
+ > **Ruling P13(2026-09-23,Task 8 实测裁决)**:本 Task 代码块以"tsc 零新增"门为准做 6 处**类型层** harmonization(RM0 形态):①value 信封 `cwd?: string` 且**非 null 才置键**(置 `cwd: null` 会越工具自身声明的 output schema——计划原稿 bug);②guard 后 `args.target as string` / `args.cmd as string`(带注释);③spec 的 execute 结果 cast(`Promise<unknown>` 面);④driver 增量 import 补 `type ProbeOptions`。运行时语义与断言逐字不变。
1580
+
1581
+ **driver.ts 增量代码(并入 Task 6 骨架):**
1582
+
1583
+ ```ts
1584
+ import { probeTarget, renderProbe, renderSession } from './status.ts'
1585
+ // RemoteDriverOptions 增一个测试缝字段:
1586
+ // probeRunner?: ProbeOptions['runner']
1587
+
1588
+ /** Ruling 16/17:on-demand 探测 + 会话层,两行如实陈述。 */
1589
+ async status(target: string, callCtx: { sessionKey?: string } = {}): Promise<string> {
1590
+ const plan = resolveTarget(target, this.opts.containers ?? {})
1591
+ const head = `${target} — ${plan.kind === 'ssh' ? 'ssh host' : `${plan.kind} container`}`
1592
+ const probe = await probeTarget(plan, { runner: this.opts.probeRunner })
1593
+ const key = `${callCtx.sessionKey ?? 'no-session'}|t:${target}`
1594
+ return [head, renderProbe(probe), renderSession(this.pool.inspect(key))].join('\n')
1595
+ }
1596
+ ```
1597
+
1598
+ - [ ] **Step 1: 写失败测试**
1599
+
1600
+ ```ts
1601
+ import { describe, expect, it, vi } from 'vitest'
1602
+ import { createRemoteTool } from '../../src/remote/tool.ts'
1603
+ import { RemoteDriver } from '../../src/remote/driver.ts'
1604
+ import type { ToolRunContext } from '@deepseek-ai/dsh-tools'
1605
+
1606
+ const fakeDriver = (): RemoteDriver =>
1607
+ new RemoteDriver({
1608
+ oneshotArgvFor: () => ['bash', '-c', 'echo out'],
1609
+ ptyArgvFor: () => ['bash'],
1610
+ spawnArgvFor: () => ['bash'],
1611
+ })
1612
+
1613
+ const fakeExec = (): { exec: ToolRunContext; appended: Array<[string, unknown]> } => {
1614
+ const appended: Array<[string, unknown]> = []
1615
+ const exec = {
1616
+ agent: { id: 'agent-1', session: { append: (k: string, v: unknown) => appended.push([k, v]) } },
1617
+ } as unknown as ToolRunContext
1618
+ return { exec, appended }
1619
+ }
1620
+
1621
+ describe('createRemoteTool', () => {
1622
+ it('registers under the name "remote"', () => {
1623
+ expect(createRemoteTool(fakeDriver()).name).toBe('remote')
1624
+ })
1625
+ it('executes through the driver and returns the value envelope', async () => {
1626
+ const tool = createRemoteTool(fakeDriver())
1627
+ const { exec, appended } = fakeExec()
1628
+ const v = await tool.execute!({ target: 'dev4', cmd: 'echo out' } as never, exec)
1629
+ expect(v.text).toBe('out\n')
1630
+ expect(v.exit).toBe(0)
1631
+ expect(appended).toHaveLength(1)
1632
+ expect(appended[0]![0]).toBe('dashr/remote-exec')
1633
+ })
1634
+ it('renders output + footer (+cwd), stderr block, and the reconnect notice line', async () => {
1635
+ const tool = createRemoteTool(fakeDriver())
1636
+ const blocks = tool.output!.render!({} as never, {
1637
+ kind: 'exec', text: 'hello', exit: 0, durationMs: 1500, cwd: '/data', reconnected: true,
1638
+ } as never)
1639
+ const text = (blocks[0] as { type: string; text: string }).text
1640
+ expect(text).toContain('[remote: session reconnected to fresh shell; cwd reset to default]')
1641
+ expect(text).toContain('hello')
1642
+ expect(text).toContain('[exit 0 · 1.5s · cwd /data]')
1643
+ const blocks2 = tool.output!.render!({} as never, {
1644
+ kind: 'exec', text: 'x', exit: 1, durationMs: 100, stderr: 'boom', timedOut: true, truncated: 999,
1645
+ } as never)
1646
+ const text2 = (blocks2[0] as { type: string; text: string }).text
1647
+ expect(text2).toContain('interrupted')
1648
+ expect(text2).toContain('truncated, original 999 chars')
1649
+ expect(text2).toContain('[stderr]\nboom')
1650
+ })
1651
+ it('parameter violations fail before any execution', async () => {
1652
+ const tool = createRemoteTool(fakeDriver())
1653
+ const { exec } = fakeExec()
1654
+ await expect(tool.execute!({ target: 'a', spawn: 'b', cmd: 'x' } as never, exec)).rejects.toThrow(/E_PARAMS/)
1655
+ await expect(tool.execute!({ cmd: 'x' } as never, exec)).rejects.toThrow(/E_PARAMS/)
1656
+ await expect(tool.execute!({ spawn: 'docker exec -it x bash' } as never, exec)).rejects.toThrow(/E_PARAMS/)
1657
+ await expect(tool.execute!({} as never, exec)).rejects.toThrow(/discovery is yours/)
1658
+ })
1659
+ it('cmd-less target call = on-demand status, honest vocabulary, never "offline"', async () => {
1660
+ const d = new RemoteDriver({
1661
+ probeRunner: async () => ({ exit: 0, timedOut: false, stdout: '', stderr: '', durationMs: 240 }),
1662
+ })
1663
+ const tool = createRemoteTool(d)
1664
+ const { exec } = fakeExec()
1665
+ const v = await tool.execute!({ target: 'dev4' } as never, exec)
1666
+ expect(v.kind).toBe('status')
1667
+ expect(v.text).toContain('dev4 — ssh host')
1668
+ expect(v.text).toContain('reachable')
1669
+ expect(v.text).toContain('session: none — dials on first exec')
1670
+ expect(v.text).not.toContain('offline')
1671
+ })
1672
+ it('failed exec attempts append an error audit record before rethrowing', async () => {
1673
+ const tool = createRemoteTool(fakeDriver())
1674
+ const { exec, appended } = fakeExec()
1675
+ await expect(tool.execute!({ target: 'a', spawn: 'b', cmd: 'x' } as never, exec)).rejects.toThrow(/E_PARAMS/)
1676
+ expect(appended).toHaveLength(1)
1677
+ expect(appended[0]![1]).toMatchObject({ target: 'a', cmd: 'x', error: expect.stringContaining('E_PARAMS') })
1678
+ })
1679
+ it('garbage mode and stdin-without-cmd fail loud before any execution', async () => {
1680
+ const tool = createRemoteTool(fakeDriver())
1681
+ const { exec } = fakeExec()
1682
+ await expect(tool.execute!({ target: 'dev4', cmd: 'x', mode: 'pty ' } as never, exec)).rejects.toThrow(/E_BAD_MODE/)
1683
+ await expect(tool.execute!({ target: 'dev4', stdin: 's' } as never, exec)).rejects.toThrow(/E_STDIN_WITHOUT_CMD/)
1684
+ })
1685
+ })
1686
+ ```
1687
+
1688
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
1689
+
1690
+ - [ ] **Step 3: 最小实现**(骨架照 RM0 tool.ts;description 按 spec §三/§四 范式写全)
1691
+
1692
+ ```ts
1693
+ import { defineTool, type ToolDefinition, type ToolRunContext } from '@deepseek-ai/dsh-tools'
1694
+ import type { ContentBlock } from '@deepseek-ai/dsh-llm'
1695
+ import type {} from '@deepseek-ai/dsh-session/types'
1696
+ import { RECONNECT_NOTICE } from './pty-session.ts'
1697
+ import type { RemoteCallResult, RemoteDriver } from './driver.ts'
1698
+
1699
+ /** 会话审计记录(RM0 Ruling 10 形态连续)。 */
1700
+ export interface RemoteExecAudit {
1701
+ target?: string
1702
+ cmd?: string
1703
+ cwd?: string
1704
+ exit?: number | null
1705
+ durationMs?: number
1706
+ error?: string
1707
+ }
1708
+
1709
+ declare module '@deepseek-ai/dsh-session/types' {
1710
+ interface SessionEventMap {
1711
+ 'dashr/remote-exec': RemoteExecAudit
1712
+ }
1713
+ }
1714
+
1715
+ interface RemoteToolValue {
1716
+ kind: 'exec' | 'status'
1717
+ text: string
1718
+ exit: number | null
1719
+ durationMs: number
1720
+ /** P13:schema 推断为 string——非 null 才置键(`cwd: null` 会越 output schema)。 */
1721
+ cwd?: string
1722
+ stderr?: string
1723
+ timedOut?: boolean
1724
+ reconnected?: boolean
1725
+ truncated?: number
1726
+ }
1727
+
1728
+ const NO_SESSION_KEY = 'remote:no-session'
1729
+
1730
+ export function createRemoteTool(
1731
+ driver: RemoteDriver,
1732
+ opts: { getSessionKey?: (exec: ToolRunContext) => string } = {},
1733
+ ): ToolDefinition {
1734
+ const getSessionKey = opts.getSessionKey ?? ((exec: ToolRunContext) => exec.agent?.id ?? NO_SESSION_KEY)
1735
+ return defineTool({
1736
+ name: 'remote',
1737
+ description:
1738
+ 'Run a command on a remote host or container. Two tracks: oneshot (default) runs `bash -lc` statelessly — fast, ' +
1739
+ 'parallel, zero residue, the exit code is the process\'s own; mode "pty" keeps one persistent terminal session ' +
1740
+ 'per (agent, target): cwd/env survive across calls, Ctrl-C interrupts work, sudo password prompts are possible. ' +
1741
+ '`target` routes smartly: an ssh host name/IP/domain goes over ssh; "docker:<name>" / "incus:<name>" (or a ' +
1742
+ 'server-registered alias) go to that container; an explicit "ssh:<name>" selector always forces ssh — use it ' +
1743
+ 'when a bare name is ambiguous (e.g. registered as a container alias but also an ssh host). ' +
1744
+ '`spawn` is the BYO-PTY escape hatch: give the full command that ' +
1745
+ 'starts an interactive shell (e.g. "docker exec -it img bash" or "ssh -t jump \'docker exec -it runner bash\'") ' +
1746
+ 'and the tool hosts its PTY with nonce framing (mode locks to pty). Nested hops are dumb pipes — only the ' +
1747
+ 'innermost bash frames. `stdin` feeds the command\'s input; `timeout` (seconds) interrupts then kills. Native ' +
1748
+ 'transport errors pass through verbatim — self-correct from them. Background processes must redirect their own ' +
1749
+ 'output (`cmd > log 2>&1 &`): the shared terminal is POSIX behavior, not a tool defect. ' +
1750
+ 'Omit `cmd` (with `target`) for an on-demand status probe: the tool dials once right then, bounded (5s connect / ' +
1751
+ '10s hard), and reports honestly — "reachable"/"unreachable — <native error>" for ssh, the factual container ' +
1752
+ 'state for docker/incus, plus the session layer ("idle Ns", "busy", or "none — dials on first exec"). It never ' +
1753
+ 'reports "offline": a connection not existing says nothing about the target. Probes run at call time, never ' +
1754
+ 'cached from boot. Discovery of valid names is yours: read ~/.ssh/config, `docker ps`, `incus list` with your ' +
1755
+ 'local tools.',
1756
+ parameters: {
1757
+ target: { type: 'string', description: 'SSH host / IP / domain, or docker:<name> / incus:<name> container, or a registered alias. Omit when using spawn.' },
1758
+ spawn: { type: 'string', description: 'BYO-PTY: full command starting an interactive shell; the tool hosts the PTY + framing. Mode locks to pty.' },
1759
+ cmd: { type: 'string', description: 'One raw shell string parsed by the remote bash (multi-line = one compound; exit = last command\'s). Omit (with target) for an on-demand status probe.' },
1760
+ mode: { type: 'string', description: "'oneshot' (default) or 'pty' (persistent session)." },
1761
+ stdin: { type: 'string', description: 'Optional input fed to the command (oneshot pipe, or written right after it on the pty).' },
1762
+ timeout: { type: 'number', description: 'Per-command timeout in seconds (default 120). pty: Ctrl-C then kill.' },
1763
+ },
1764
+ output: {
1765
+ schema: {
1766
+ type: 'object',
1767
+ additionalProperties: false,
1768
+ properties: {
1769
+ kind: { type: 'string', required: true, enum: ['exec', 'status'] },
1770
+ text: { type: 'string', required: true },
1771
+ exit: { oneOf: [{ type: 'integer' }, { type: 'null' }] },
1772
+ durationMs: { type: 'integer' },
1773
+ cwd: { type: 'string' },
1774
+ stderr: { type: 'string' },
1775
+ timedOut: { type: 'boolean' },
1776
+ reconnected: { type: 'boolean' },
1777
+ truncated: { type: 'integer' },
1778
+ },
1779
+ },
1780
+ render: (_args, value): ContentBlock[] => [{ type: 'text', text: renderValue(value as RemoteToolValue) }],
1781
+ },
1782
+ async execute(args, exec): Promise<RemoteToolValue> {
1783
+ const hasCmd = typeof args.cmd === 'string' && args.cmd.length > 0
1784
+ const hasTarget = typeof args.target === 'string' && args.target.length > 0
1785
+ const hasSpawn = typeof args.spawn === 'string' && args.spawn.length > 0
1786
+ // fail-loud 三闸:垃圾 mode 不静默降级;status 面不吃 stdin。
1787
+ if (args.mode !== undefined && args.mode !== 'oneshot' && args.mode !== 'pty')
1788
+ throw new Error(`[E_BAD_MODE] remote: mode must be 'oneshot' or 'pty' (got ${JSON.stringify(args.mode)})`)
1789
+ // cmd 缺省 + target 在场 = on-demand status(Ruling 16/17);spawn 无可探测物。
1790
+ if (!hasCmd) {
1791
+ if (args.stdin !== undefined)
1792
+ throw new Error('[E_STDIN_WITHOUT_CMD] remote: stdin requires cmd — status probes take no input')
1793
+ if (hasSpawn)
1794
+ throw new Error('[E_PARAMS] remote: spawn is an exec channel — pass cmd (there is nothing to probe for BYO-PTY)')
1795
+ if (!hasTarget)
1796
+ throw new Error(
1797
+ '[E_PARAMS] remote: target or spawn is required; discovery is yours — read ~/.ssh/config, ' +
1798
+ '`docker ps`, `incus list` with your local tools')
1799
+ const text = await driver.status(args.target as string, { sessionKey: getSessionKey(exec) })
1800
+ return { kind: 'status', text, exit: null, durationMs: 0 }
1801
+ }
1802
+ try {
1803
+ const r: RemoteCallResult = await driver.call(
1804
+ {
1805
+ target: args.target, spawn: args.spawn, cmd: args.cmd as string,
1806
+ mode: args.mode === 'oneshot' || args.mode === 'pty' ? args.mode : undefined,
1807
+ stdin: args.stdin, timeout: args.timeout,
1808
+ },
1809
+ { sessionKey: getSessionKey(exec) },
1810
+ )
1811
+ appendAudit(exec, { target: r.target, cmd: args.cmd, cwd: r.cwd ?? undefined, exit: r.exit, durationMs: r.durationMs })
1812
+ const v: RemoteToolValue = { kind: 'exec', text: r.stdout, exit: r.exit, durationMs: r.durationMs }
1813
+ if (r.cwd !== null) v.cwd = r.cwd
1814
+ if (r.stderr !== undefined) v.stderr = r.stderr
1815
+ if (r.timedOut) v.timedOut = true
1816
+ if (r.reconnected) v.reconnected = true
1817
+ if (r.truncated !== undefined) v.truncated = r.truncated
1818
+ return v
1819
+ } catch (error) {
1820
+ // Ruling 13:失败的 exec 尝试同样落审计(RM0 Ruling 10 形态),随后原样重抛
1821
+ appendAudit(exec, {
1822
+ target: args.target ?? args.spawn, cmd: args.cmd,
1823
+ error: error instanceof Error ? error.message : String(error),
1824
+ })
1825
+ throw error
1826
+ }
1827
+ },
1828
+ })
1829
+ }
1830
+
1831
+ function renderValue(v: RemoteToolValue): string {
1832
+ if (v.kind === 'status') return v.text
1833
+ const parts: string[] = []
1834
+ if (v.reconnected === true) parts.push(RECONNECT_NOTICE)
1835
+ parts.push(v.text)
1836
+ const secs = ((v.durationMs ?? 0) / 1_000).toFixed(1)
1837
+ const markers: string[] = []
1838
+ if (v.timedOut === true) markers.push('interrupted')
1839
+ if (v.truncated !== undefined) markers.push(`truncated, original ${v.truncated} chars`)
1840
+ const suffix = markers.length > 0 ? ` · ${markers.join(' · ')}` : ''
1841
+ const cwdTag = typeof v.cwd === 'string' && v.cwd.length > 0 ? ` · cwd ${v.cwd}` : ''
1842
+ parts.push(`[exit ${v.exit} · ${secs}s${suffix}${cwdTag}]`)
1843
+ if (v.stderr !== undefined && v.stderr.length > 0) parts.push('[stderr]', v.stderr)
1844
+ return parts.join('\n')
1845
+ }
1846
+
1847
+ function appendAudit(exec: ToolRunContext, data: RemoteExecAudit): void {
1848
+ try { exec.agent?.session.append('dashr/remote-exec', data) } catch { /* best-effort by contract */ }
1849
+ }
1850
+ ```
1851
+
1852
+ - [ ] **Step 4: 跑测试确认通过** → PASS。
1853
+
1854
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): model-facing remote tool — exec + on-demand status face, transparent errors, audit event"`。
1855
+
1856
+ ---
1857
+
1858
+ ### Task 9: `dashr-remote` 插件行接线 `plugin.ts` + 全量绿
1859
+
1860
+ **Files:**
1861
+ - Create: `better-dsh/src/remote/plugin.ts`
1862
+ - Modify: `better-dsh/package.json`(exports 增 `"./remote"`,紧随 `"./mobile"` 后)
1863
+ - Modify: `better-dsh/tsdown.config.ts`(entry 增 `'src/remote/plugin.ts'`)
1864
+ - Modify: `better-dsh/cordis.patch.yml`(bundles 段落内、`compaction-basic` 行之前插 `- id: dashr-remote` 行,注释风格对齐 RM0)
1865
+ - Test: `better-dsh/test/remote/plugin.spec.ts`
1866
+
1867
+ **Interfaces:**
1868
+ ```ts
1869
+ export const name = 'dashr-remote'
1870
+ export const Config: z<RemoteRowConfig> // { containers: Record<string,string>; execTimeoutSec: number; idleTtlSec: number; maxOutputChars: number }
1871
+ export const apply = (ctx: Context, config: RemoteRowConfig): (() => void) | void
1872
+ export default { name, inject: [], Config, apply }
1873
+ ```
1874
+
1875
+ - [ ] **Step 1: 写失败测试**
1876
+
1877
+ ```ts
1878
+ import { describe, expect, it } from 'vitest'
1879
+ import { apply, Config, name } from '../../src/remote/plugin.ts'
1880
+ import type { Context } from '@deepseek-ai/cordis'
1881
+
1882
+ describe('dashr-remote row', () => {
1883
+ it('Config defaults: no containers, 120s exec, 600s TTL, 30000 chars', () => {
1884
+ const c = Config(undefined) as { containers: unknown; execTimeoutSec: number; idleTtlSec: number; maxOutputChars: number }
1885
+ expect(c).toMatchObject({ containers: {}, execTimeoutSec: 120, idleTtlSec: 600, maxOutputChars: 30_000 })
1886
+ })
1887
+ it('mounts dormant without tools, registers the remote tool when tools compose, disposer is safe', () => {
1888
+ expect(name).toBe('dashr-remote')
1889
+ const registered: Array<{ name: string }> = []
1890
+ const fakeCtx = {
1891
+ inject: (_deps: string[], fn: (c: unknown) => void) => {
1892
+ fn({ tools: { register: (t: { name: string }) => registered.push(t) } })
1893
+ },
1894
+ } as unknown as Context
1895
+ const disposer = apply(fakeCtx, Config(undefined) as never) as () => void
1896
+ expect(registered).toHaveLength(1)
1897
+ expect(registered[0]!.name).toBe('remote')
1898
+ expect(() => disposer()).not.toThrow()
1899
+ })
1900
+ it('patch row and build wiring are in place', async () => {
1901
+ const patch = await import('node:fs').then((fs) => fs.readFileSync(new URL('../../cordis.patch.yml', import.meta.url), 'utf8'))
1902
+ expect(patch).toContain('- id: dashr-remote')
1903
+ expect(patch).toContain("name: 'better-dsh/remote'")
1904
+ const pkg = JSON.parse(await import('node:fs').then((fs) => fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')))
1905
+ expect(pkg.exports['./remote']).toEqual({ types: './lib/remote/plugin.d.ts', default: './lib/remote/plugin.js' })
1906
+ const tsd = await import('node:fs').then((fs) => fs.readFileSync(new URL('../../tsdown.config.ts', import.meta.url), 'utf8'))
1907
+ expect(tsd).toContain("'src/remote/plugin.ts'")
1908
+ })
1909
+ })
1910
+ ```
1911
+
1912
+ - [ ] **Step 2: 跑测试确认失败** → FAIL。
1913
+
1914
+ - [ ] **Step 3: 最小实现**
1915
+
1916
+ ```ts
1917
+ /**
1918
+ * `dashr-remote` — the remote-execution-framework row (plan
1919
+ * docs/10_plans/2026-09-23-remote-framework-impl.md Task 9; spec
1920
+ * docs/10_plans/2026-09-23-remote-execution-framework.md). Same row shape as
1921
+ * `src/mobile/plugin.ts` / the archived RM0 row: one bundle-patch row that,
1922
+ * when a `tools` service is composed, boots one RemoteDriver and registers
1923
+ * the model-facing `remote` tool. The driver (pty session pool + idle timers)
1924
+ * is disposed with the row's fiber. Zero static injects: loads dormant in
1925
+ * compositions without tools.
1926
+ */
1927
+ import { Context } from '@deepseek-ai/cordis'
1928
+ import z from '@deepseek-ai/schemastery'
1929
+ import { RemoteDriver } from './driver.ts'
1930
+ import { createRemoteTool } from './tool.ts'
1931
+
1932
+ export const name = 'dashr-remote'
1933
+ export const inject: string[] = []
1934
+
1935
+ /** 已知容器裸名 → 'docker:<name>' / 'incus:<name>'(Ruling 12)。 */
1936
+ export interface RemoteRowConfig {
1937
+ containers: Record<string, string>
1938
+ execTimeoutSec: number
1939
+ idleTtlSec: number
1940
+ maxOutputChars: number
1941
+ }
1942
+
1943
+ export const Config: z<RemoteRowConfig> = z
1944
+ .object({
1945
+ containers: z.dict(z.string()).default({}),
1946
+ execTimeoutSec: z.natural().min(1).default(120),
1947
+ idleTtlSec: z.natural().min(1).default(600),
1948
+ maxOutputChars: z.natural().min(1).default(30_000),
1949
+ })
1950
+ .default({ containers: {}, execTimeoutSec: 120, idleTtlSec: 600, maxOutputChars: 30_000 }) as unknown as z<RemoteRowConfig>
1951
+
1952
+ /** MUST stay an arrow(RM0 plugin.ts 同注:function 声明会被 cordis 当构造器 new 掉,返回的 disposer 丢失)。 */
1953
+ export const apply = (ctx: Context, config: RemoteRowConfig): (() => void) => {
1954
+ const driver = new RemoteDriver({
1955
+ containers: config.containers,
1956
+ execTimeoutSec: config.execTimeoutSec,
1957
+ idleTtlSec: config.idleTtlSec,
1958
+ maxOutputChars: config.maxOutputChars,
1959
+ })
1960
+ ctx.inject(['tools'], (toolsCtx: Context) => {
1961
+ toolsCtx.tools.register(
1962
+ createRemoteTool(driver, { getSessionKey: (exec) => exec.agent?.id ?? 'remote:no-session' }),
1963
+ )
1964
+ })
1965
+ return () => void driver.dispose()
1966
+ }
1967
+
1968
+ export default { name, inject, Config, apply }
1969
+ ```
1970
+
1971
+ package.json exports(`"./mobile"` 条目后插):
1972
+ ```json
1973
+ "./remote": {
1974
+ "types": "./lib/remote/plugin.d.ts",
1975
+ "default": "./lib/remote/plugin.js"
1976
+ },
1977
+ ```
1978
+
1979
+ tsdown.config.ts entry 数组 `'src/mobile/plugin.ts'` 后插 `'src/remote/plugin.ts'`。
1980
+
1981
+ cordis.patch.yml(RM0 同位、同注释风格):
1982
+ ```yaml
1983
+ # Remote execution framework (plan 2026-09-23-remote-framework-impl.md):
1984
+ # `remote` tool face — two-track (oneshot default / pty opt-in), CLI
1985
+ # transports (ssh/docker/incus), BYO-PTY spawn, nonce framing, 10min TTL.
1986
+ # All config defaults, so the row carries no config block.
1987
+ - id: dashr-remote
1988
+ name: 'better-dsh/remote'
1989
+ ```
1990
+
1991
+ - [ ] **Step 4: 全量绿 + 类型零**
1992
+
1993
+ ```bash
1994
+ cd better-dsh
1995
+ npm test # 全量(含既有套件)
1996
+ npx tsc --noEmit # 0 errors
1997
+ ```
1998
+
1999
+ - [ ] **Step 5: Commit** — `git commit -m "feat(remote): dashr-remote composition row — driver + tool wiring, exports/entry/patch"`。
2000
+
2001
+ ---
2002
+
2003
+ ### Task 10: Phase-4 实测回归(真 targets + 第一人称)与报告
2004
+
2005
+ **Files:**
2006
+ - Create: `docs/50_test-reports/2026-09-23-remote-framework实测报告.md`
2007
+
2008
+ **前置事实(已勘)**:`dev4` BatchMode SSH 可达(bash 5.2.21);本机 `incus` 有运行中 `ctr-1`;`docker` 有 `corti`/`jellyfin`(**勿动这两个**——临时容器自起自清);`/usr/bin/script` 在位;`~/.ssh/config` 的 `ctr-1` Host 与容器别名同名(别名优先路由是设计内行为)。
2009
+
2010
+ - [ ] **Step 1: rsync 进 monorepo + 双半构建**(AGENTS.md §二 日常回归循环,注意 lib/client 清洗陷阱)
2011
+
2012
+ ```bash
2013
+ rsync -a --delete --exclude node_modules --exclude lib --exclude .venv-kernel --exclude .uv-cache --exclude docs \
2014
+ ~/workspaces/dashr/.worktrees/remote-framework/better-dsh/ \
2015
+ ~/workspaces/dashr/upstream/deepseek-harness/packages/better-dsh/better-dsh/
2016
+ cd ~/workspaces/dashr/upstream/deepseek-harness
2017
+ pnpm --filter better-dsh exec tsdown
2018
+ cd packages/better-dsh/better-dsh && ../../../node_modules/.bin/tsx scripts/build-client.ts && cd ../../..
2019
+ ```
2020
+
2021
+ - [ ] **Step 2: 起 dev 实例**(`bash .tests/dsh-test1/start-4999.sh PORT=4986`;端口被占则换;boot 必须走构建产物 `apps/cli/lib/bin.js`——脚本已内置)
2022
+
2023
+ - [ ] **Step 3: 配置面冒烟**
2024
+
2025
+ ```bash
2026
+ DSH_HOME=/home/u1/workspaces/dashr/.dsh-test node apps/cli/src/bin.ts web --dump-config | grep -B1 -A6 'dashr-remote'
2027
+ ```
2028
+ Expected: `dashr-remote` 行在位(默认 config 生效)。鉴权拉 shell 页 → boot graph 含 `"id":"better-dsh"` 与 `/plugins/??better-dsh/remote/client 无关`(本 row 无 client 半——只验 lib 产物 `/lib/remote/plugin.js` 在 dist 内)。
2029
+
2030
+ - [ ] **Step 4: 第一人称实测矩阵**(真实 agent session 通过 web 界面调 `remote` 工具;每项记 exit/cwd/时长/原始输出):
2031
+
2032
+ | # | case | 调用 | 判据 |
2033
+ |---|---|---|---|
2034
+ | 1 | ssh oneshot | `{target:'dev4', cmd:'echo ok && git --version'}` | exit 0,输出含 ok 与 git 版本 |
2035
+ | 2 | ssh oneshot 退出码透传 | `{target:'dev4', cmd:'exit 42'}` | exit 42(无字符串解析) |
2036
+ | 3 | ssh oneshot 复合语法 | `{target:'dev4', cmd:'ls | head -1 && echo $HOME'}` | 管道+变量展开正常(单层转义证明) |
2037
+ | 4 | ssh pty 状态保持 | 两连击:`{target:'dev4',mode:'pty',cmd:'cd /tmp && export F=1'}` → `{target:'dev4',mode:'pty',cmd:'pwd && echo $F'}` | 第二击 `/tmp` + `1` |
2038
+ | 5 | ssh pty 多行单帧 | `{target:'dev4',mode:'pty',cmd:'echo a\necho b'}` | 一帧,a/b,exit 0 |
2039
+ | 6 | ssh pty 伪 marker 免疫 | `{target:'dev4',mode:'pty',cmd:"printf '\\x1b]133;D;deadbeefdeadbeef;99;/pwn\\x07'; echo real"}` | exit 0,输出 real,无 99 |
2040
+ | 7 | ssh pty 超时打断 | `{target:'dev4',mode:'pty',cmd:'sleep 300',timeout:2}` | interrupted,秒级返回,会话存活(后续 echo 正常) |
2041
+ | 8 | incus oneshot | `{target:'incus:ctr-1', cmd:'cat /etc/os-release | head -1'}` | exit 0 |
2042
+ | 9 | incus pty + 别名路由 | home 层 patch 加 `containers: {'ctr-1':'incus:ctr-1'}` 后 `{target:'ctr-1',mode:'pty',cmd:'cd / && pwd'}` | cwd `/` |
2043
+ | 10 | docker oneshot | 临时容器 `docker run -d --name dashr-remote-t1 ubuntu:24.04 sleep 600` → `{target:'docker:dashr-remote-t1', cmd:'echo in-docker'}` | exit 0 |
2044
+ | 11 | docker pty(script 托管) | `{target:'docker:dashr-remote-t1', mode:'pty', cmd:'cd /root && pwd'}` | cwd `/root` |
2045
+ | 12 | BYO-PTY spawn | `{spawn:'docker exec -it dashr-remote-t1 bash', cmd:'echo spawned'}` | exit 0,输出 spawned |
2046
+ | 13 | 错误透明 | `{target:'no-such-host-xyz', cmd:'echo x'}`(预期 ssh 原生报错)与 `{target:'docker:no-such-ctr', cmd:'x'}` | 原生 stderr 原样可见,agent 可自愈 |
2047
+ | 14 | 断联自愈 | pty 会话中 `{target:'dev4',mode:'pty',cmd:'kill -9 $$'}` → 再 `{target:'dev4',mode:'pty',cmd:'echo back'}` | 第二击含 `[remote: session reconnected to fresh shell; cwd reset to default]` 行 |
2048
+ | 15 | 后台输出 Non-Goal | `{target:'dev4',cmd:'nohup sleep 5 >/dev/null 2>&1 & echo bg-ok'}` | 输出干净 bg-ok(使用者重定向职责示范) |
2049
+ | 16 | status 可达探测 | `{target:'dev4'}`(无 cmd) | `probe: reachable in Nms`;**全文无 "offline" 字样** |
2050
+ | 17 | status 会话层 | case 4 之后 `{target:'dev4'}` | `session: idle Ns (connected)` |
2051
+ | 18 | status 容器事实/错误 | `{target:'docker:no-such-ctr'}` | `probe: error —` 行含 docker 原生 No such object |
2052
+
2053
+ 结束清理:`docker rm -f dashr-remote-t1`;移除 home 层别名 patch(若加了)。
2054
+
2055
+ - [ ] **Step 5: 审计抽查** — 实测 session 的存储里 `dashr/remote-exec` 事件在案(target/cmd/exit/durationMs)。
2056
+
2057
+ - [ ] **Step 6: 写报告** — `docs/50_test-reports/2026-09-23-remote-framework实测报告.md`:环境(端口/sha/矩阵表)、18 case 结果、四层模型映射核对表、状态词汇表行为证据(矩阵 16-18:无 offline 歧义)、Non-Goal 三条的行为证据、遗留清单(如 130 断言环境差异、dev4 无 docker 的嵌套穿透未测等如实记录)。
2058
+
2059
+ - [ ] **Step 7: Commit** — `git add docs/50_test-reports/… && git commit -m "test(remote): phase-4 acceptance matrix report at dev instance (ssh/incus/docker/spawn)"`。
2060
+
2061
+ ---
2062
+
2063
+ ### Task 11: 收尾(finishing-a-development-branch)
2064
+
2065
+ - [ ] 全量 `npm test` + `npx tsc --noEmit` 最后一遍确认。
2066
+ - [ ] REQUIRED SUB-SKILL: `superpowers:finishing-a-development-branch` — 按 skill 走验证与选项呈现(merge / PR / 保留分支),**等 user 选择**;npm publish 不在本计划范围(Development Operation Contract:需 user 单次明确放行)。
2067
+
2068
+ ---
2069
+
2070
+ ## Self-Review 记录
2071
+
2072
+ - **Spec 覆盖**:§一 四层模型→双轨(Task 4/5);§二 命名与智能路由(Task 2);§三 API 契约 target/spawn/cmd/mode/stdin/timeout + 错误透明(Task 6/8);§四 场景 1-4(Task 10 矩阵 1-14);§五 oneshot 流水线 argv 逐字(Task 3)、nonce 收帧/TTL/断联自愈(Task 1/5 + 矩阵 6/7/14);§六 Non-Goals(矩阵 15 + Ruling 5 固定 40×120 + 无状态回放);§七 Phase 1-4(Task 1 / 4-5 / 2-3+6-9 / 10)。**user 2026-09-23 状态词汇裁决**(禁 offline;reachable/unreachable/容器事实态/idle/busy/none;on-demand 双重超时探测)→ Ruling 16/17 + Task 5 snapshot + Task 7 全任务 + Task 8 status 面 + 矩阵 16-18。无缺task。
2073
+ - **类型一致性**:`PtyFrame{exit,cwd}`(Task 1 定义,Task 5 消费);`TargetPlan`(Task 2 定义,Task 3/6/7 消费);`OneShotResult`(Task 4,Task 7 runner 缝消费);`PtyDispatchResult`(Task 5)在 Task 6 `execute` 合成 `RemoteCallResult`(Task 8 消费);`SessionSnapshot`(Task 5 定义,Task 7 `renderSession` / Task 8 `driver.status` 消费);`ProbeOutcome`(Task 7 定义,Task 8 消费);`RECONNECT_NOTICE`(Task 5 定义,Task 8 render 消费);`RemoteRowConfig`(Task 9)。已复核命名一致。
2074
+ - **占位符扫描**:各 Step 均含实码/实命令;Task 10 步骤 4 矩阵为实测脚本性步骤(验收性质,非代码占位)。
2075
+ - **已知测试环境风险**:130 断言确定性由 Ruling P8 两段打断(\x03 + 注入 130-marker 行)保证——两路(弃行/续行)皆 exit 130;trap INT 场景走 kill 兜底测试。若 CI 型环境无 /dev/ptmx,`script` 夹具会挂——本仓测试恒在真 Linux 跑,可接受。
2076
+
2077
+ ## Post-acceptance 增量记录
2078
+
2079
+ - **Ruling P16**(user 2026-09-23 选 A):补 `ssh:` 显式协议选择器(与 docker:/incus: 组成可扩展选择器族,未来新传输加一词即成);撞名优先级维持"别名 override 赢"(人工显式意图),裸名缺省仍走 ssh;别名表值只接受容器形态(CONTAINER_PREFIX_RE 单独校验,ssh 无别名意义)。工具描述同步补 selector 消歧指引。若错:代价=极小(选择器仅显式路径)。
2080
+ - **Ruling P17**(user 实测发现,2026-09-23):session log 的自定义类型事件**不可持久化**——`KNOWN_SESSION_EVENT_TYPES` 为冻结原生集(catalog 刻意独立于插件),`Session.append()` 无 ignorable 通道,`tool/ptc-dispatch` 先例是原生类型而非插件自定义。审计迁出 session log → 插件自有存储 `$DSH_HOME/storages/better-dsh/remote-exec-audit.jsonl`(hashline/hostkeys 同款先例);tool 面改注入式 audit sink;被毒化会话以 `ignorable: true` 信封标记手术修复(loader 契约内合法,事件以无表面语义的 opaque 形态保留)。若错:代价=审计从 session 视图消失(改回即恢复),但 session-log 通道本就非法。
2081
+ - **Ruling P18**(user 2026-09-23,实测后裁决):**删除别名机制整条腿**。插件环境数据不得上 cordis 配置面(行重述热插是对组合平面的误用,env-var 级需求用了系统级 YAML);别名本身伪需求——显式选择器已全覆盖,发现走 on-demand probe(当下事实 > 任何别名表/定时扫盘;扫描器亦不建,运行态无人改配置)。`resolveTarget(target)` 单参化(裸名恒 ssh);行 config 只留运行旋钮(execTimeoutSec/idleTtlSec/maxOutputChars)。若错:代价=裸名容器便利消失,补插件私有 JSON 即可(P18 明确不走 cordis 面)。
2082
+ - **Ruling P19**(user 2026-09-23,attention 裁决):`remote({})` 空调用 = **roster 面(注意力第一现场)**。区分两个概念:roster = 把名字放进上下文(读 ~/.ssh/config hosts + docker ps -a + incus list + 池内活会话,纯本地廉价扫描,零可达性检查);probe = 单点验证(既有 on-demand status,第二现场)。"模型自己会发现"只在 attention 已存在后成立——工具 catalog 是 attention 的注入点,便利性(spec §三宗旨)要求入口自带清单。E_PARAMS 发现指引退役;描述文本改为 no-args 列清单。若错:代价=多一个只读面(几行渲染),可删。
2083
+ - **Ruling P20**(user 2026-09-24,name-first 策略):裸名**先按名匹配**——ssh config 字面 host → docker → incus(与 roster 同源的本地廉价扫描,撞名 ssh 优先,查无 → 默认 ssh 交原生错误);选择器(ssh:/docker:/incus:)降级为显式消歧备用,描述不再当主路径宣传。修正 P18 的过度矫正(裸名 ≠ 恒 ssh,容器名裸传即可达)。若错:代价=裸名多一次本地扫描(亚秒),回退为恒 ssh 一行。