@dsh-workbench/shared 0.3.11 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/api/blocker-table.d.ts +3 -3
  4. package/dist/api/blocker-table.js +47 -23
  5. package/dist/api/dsh.d.ts +1 -1
  6. package/dist/api/workbench-client.js +2 -1
  7. package/dist/components/Activity.css +0 -1
  8. package/dist/components/ApprovalDetail.css +1 -2
  9. package/dist/components/ApprovalDetail.d.ts +1 -1
  10. package/dist/components/ApprovalPlan.css +0 -1
  11. package/dist/components/Card.css +0 -1
  12. package/dist/components/Card.d.ts +1 -1
  13. package/dist/components/CardBoundary.d.ts +1 -1
  14. package/dist/components/CardHead.css +0 -1
  15. package/dist/components/CardHead.d.ts +1 -1
  16. package/dist/components/ChoiceGroup.css +1 -2
  17. package/dist/components/ConfirmBar.d.ts +1 -1
  18. package/dist/components/ConfirmBar.js +1 -1
  19. package/dist/components/Form.css +1 -1
  20. package/dist/components/FormActions.js +1 -1
  21. package/dist/components/LongTaskRow.css +1 -2
  22. package/dist/components/LongTaskRow.d.ts +1 -1
  23. package/dist/components/LongTaskRow.js +1 -1
  24. package/dist/components/Note.css +0 -1
  25. package/dist/components/ResourceStates.css +0 -1
  26. package/dist/components/SettingsSection.css +0 -1
  27. package/dist/components/Spinner.css +0 -1
  28. package/dist/components/Stack.css +0 -1
  29. package/dist/components/StateBlock.css +0 -1
  30. package/dist/components/board-module.d.ts +3 -3
  31. package/dist/components/icons.d.ts +1 -1
  32. package/dist/components/icons.js +11 -4
  33. package/dist/config/constants.d.ts +2 -2
  34. package/dist/config/constants.js +2 -2
  35. package/dist/contract/adapters.d.ts +10 -0
  36. package/dist/contract/cli.d.ts +3 -0
  37. package/dist/contract/data.d.ts +126 -0
  38. package/dist/{api → contract}/facts.d.ts +12 -3
  39. package/dist/{api → contract}/facts.js +19 -1
  40. package/dist/contract/needs.d.ts +132 -0
  41. package/dist/contract/needs.js +232 -0
  42. package/dist/contract/plugin-source.d.ts +1 -0
  43. package/dist/contract/protocol/bundle-install.d.ts +136 -0
  44. package/dist/contract/protocol/bundle-install.js +12 -0
  45. package/dist/contract/protocol/config-sync.d.ts +55 -0
  46. package/dist/contract/protocol/config-sync.js +2 -0
  47. package/dist/contract/protocol/diy.d.ts +4 -0
  48. package/dist/contract/protocol/diy.js +4 -0
  49. package/dist/contract/protocol/dsh-plugins.d.ts +11 -0
  50. package/dist/contract/protocol/dsh-plugins.js +1 -0
  51. package/dist/contract/protocol/long-tasks.d.ts +13 -0
  52. package/dist/contract/protocol/long-tasks.js +1 -0
  53. package/dist/contract/protocol/market-index.d.ts +195 -0
  54. package/dist/contract/protocol/market-index.js +7 -0
  55. package/dist/contract/protocol/platform.d.ts +44 -0
  56. package/dist/contract/protocol/platform.js +1 -0
  57. package/dist/contract/protocol/preflight-wake.d.ts +7 -0
  58. package/dist/contract/protocol/preflight-wake.js +1 -0
  59. package/dist/contract/protocol/profile-create.d.ts +30 -0
  60. package/dist/contract/protocol/profile-create.js +2 -0
  61. package/dist/contract/protocol/sidebar-edition.d.ts +14 -0
  62. package/dist/contract/protocol/sidebar-edition.js +2 -0
  63. package/dist/contract/protocol/unit-manifests.d.ts +6 -0
  64. package/dist/contract/protocol/unit-manifests.js +1 -0
  65. package/dist/contract/unit-board.js +1 -0
  66. package/dist/contract/unit-capability.d.ts +34 -0
  67. package/dist/contract/unit-capability.js +1 -0
  68. package/dist/{host → contract}/unit-declaration.d.ts +7 -5
  69. package/dist/{api → contract}/unit-declaration.js +19 -13
  70. package/dist/contract/unit.d.ts +57 -0
  71. package/dist/contract/unit.js +24 -0
  72. package/dist/contract/workbench-contract.d.ts +15 -0
  73. package/dist/contract/workbench-contract.js +1 -0
  74. package/dist/host/adapter-set.d.ts +26 -0
  75. package/dist/host/adapter-set.js +243 -0
  76. package/dist/host/adapter-types.d.ts +79 -0
  77. package/dist/host/adapter-types.js +23 -0
  78. package/dist/host/adapters.d.ts +22 -0
  79. package/dist/host/adapters.js +9 -0
  80. package/dist/host/browser.d.ts +3 -0
  81. package/dist/host/browser.js +3 -0
  82. package/dist/host/changelog.d.ts +21 -0
  83. package/dist/host/changelog.js +188 -0
  84. package/dist/host/channel-plugin.d.ts +15 -0
  85. package/dist/host/channel-plugin.js +42 -0
  86. package/dist/host/cli.d.ts +4 -0
  87. package/dist/host/cli.js +7 -0
  88. package/dist/host/command-name.d.ts +1 -0
  89. package/dist/host/command-name.js +14 -0
  90. package/dist/host/data-error.d.ts +13 -0
  91. package/dist/host/data-error.js +20 -0
  92. package/dist/host/data-root.js +3 -0
  93. package/dist/host/diy-debug.js +2 -1
  94. package/dist/host/diy-record.js +2 -1
  95. package/dist/host/facts.d.ts +1 -1
  96. package/dist/host/facts.js +3 -2
  97. package/dist/host/git.js +2 -2
  98. package/dist/host/http.js +1 -1
  99. package/dist/host/lib-capabilities.d.ts +22 -0
  100. package/dist/host/lib-capabilities.js +37 -0
  101. package/dist/host/lib-install.d.ts +9 -0
  102. package/dist/host/lib-install.js +10 -0
  103. package/dist/host/long-task.d.ts +1 -1
  104. package/dist/host/long-task.js +4 -3
  105. package/dist/host/market-index.d.ts +22 -0
  106. package/dist/host/market-index.js +420 -0
  107. package/dist/host/needs.d.ts +4 -0
  108. package/dist/host/needs.js +2 -0
  109. package/dist/host/patch.d.ts +9 -0
  110. package/dist/host/patch.js +78 -0
  111. package/dist/host/paths.d.ts +12 -0
  112. package/dist/host/paths.js +28 -0
  113. package/dist/host/platform.d.ts +14 -0
  114. package/dist/host/platform.js +40 -0
  115. package/dist/host/plugin-source.d.ts +8 -6
  116. package/dist/host/plugin-source.js +43 -33
  117. package/dist/host/plugin.d.ts +4 -0
  118. package/dist/host/plugin.js +39 -0
  119. package/dist/host/port-types.d.ts +191 -0
  120. package/dist/host/port-types.js +1 -0
  121. package/dist/host/preflight.d.ts +28 -0
  122. package/dist/host/preflight.js +1 -0
  123. package/dist/host/profile-port.d.ts +4 -0
  124. package/dist/host/profile-port.js +4 -0
  125. package/dist/host/provision.d.ts +2 -2
  126. package/dist/host/provision.js +5 -3
  127. package/dist/host/recipe-rules.d.ts +5 -0
  128. package/dist/host/recipe-rules.js +382 -0
  129. package/dist/host/recipe.d.ts +14 -0
  130. package/dist/host/recipe.js +283 -0
  131. package/dist/host/shell-text.d.ts +9 -2
  132. package/dist/host/shell-text.js +15 -3
  133. package/dist/host/shell.d.ts +2 -0
  134. package/dist/host/shell.js +7 -0
  135. package/dist/host/spec.d.ts +8 -0
  136. package/dist/host/spec.js +24 -0
  137. package/dist/host/supply-index.d.ts +34 -0
  138. package/dist/host/supply-index.js +202 -0
  139. package/dist/host/supply-port.d.ts +5 -0
  140. package/dist/host/supply-port.js +39 -0
  141. package/dist/host/time.d.ts +12 -0
  142. package/dist/host/time.js +19 -0
  143. package/dist/host/tokens.d.ts +26 -0
  144. package/dist/host/tokens.js +154 -0
  145. package/dist/host/tool-kit.js +1 -1
  146. package/dist/host/unit-face.d.ts +5 -4
  147. package/dist/host/version-range.d.ts +2 -0
  148. package/dist/host/version-range.js +73 -0
  149. package/dist/host/version.d.ts +3 -0
  150. package/dist/host/version.js +29 -0
  151. package/dist/host.d.ts +47 -16
  152. package/dist/host.js +47 -16
  153. package/dist/i18n/en.js +224 -71
  154. package/dist/i18n/index.d.ts +298 -73
  155. package/dist/i18n/merge.js +1 -1
  156. package/dist/i18n/need-text.d.ts +26 -0
  157. package/dist/i18n/need-text.js +26 -0
  158. package/dist/i18n/settings.d.ts +70 -0
  159. package/dist/i18n/settings.js +136 -0
  160. package/dist/i18n/zh.d.ts +297 -72
  161. package/dist/i18n/zh.js +226 -73
  162. package/dist/index.d.ts +23 -7
  163. package/dist/index.js +23 -7
  164. package/dist/{api → lib}/dsh-client.d.ts +11 -1
  165. package/dist/lib/dsh-client.js +1 -0
  166. package/dist/lib/market-index.d.ts +7 -0
  167. package/dist/lib/market-index.js +25 -0
  168. package/dist/lib/react.d.ts +0 -40
  169. package/dist/lib/react.js +0 -36
  170. package/dist/lib/ui.js +3 -9
  171. package/dist/testing/data.d.ts +13 -0
  172. package/dist/testing/data.js +46 -0
  173. package/dist/testing/declaration.d.ts +1 -1
  174. package/dist/testing/declaration.js +1 -1
  175. package/dist/testing/host-fakes.d.ts +0 -13
  176. package/dist/testing/host-fakes.js +0 -24
  177. package/dist/testing/needs.d.ts +16 -0
  178. package/dist/testing/needs.js +46 -0
  179. package/dist/testing.d.ts +2 -0
  180. package/dist/testing.js +2 -0
  181. package/package.json +18 -2
  182. package/src/api/__tests__/blocker-table.test.ts +135 -86
  183. package/src/api/blocker-table.ts +52 -26
  184. package/src/api/dsh.ts +1 -1
  185. package/src/api/host-write.ts +0 -1
  186. package/src/api/workbench-client.test.ts +2 -2
  187. package/src/api/workbench-client.ts +2 -1
  188. package/src/components/Activity.css +0 -1
  189. package/src/components/ApprovalDetail.css +1 -2
  190. package/src/components/ApprovalDetail.tsx +1 -1
  191. package/src/components/ApprovalPlan.css +0 -1
  192. package/src/components/Card.css +0 -1
  193. package/src/components/Card.tsx +1 -1
  194. package/src/components/CardAnchor.test.tsx +1 -1
  195. package/src/components/CardBoundary.tsx +1 -1
  196. package/src/components/CardHead.css +0 -1
  197. package/src/components/CardHead.tsx +1 -1
  198. package/src/components/ChoiceGroup.css +1 -2
  199. package/src/components/ConfirmBar.tsx +1 -1
  200. package/src/components/Form.css +1 -1
  201. package/src/components/Form.tsx +1 -1
  202. package/src/components/FormActions.tsx +1 -1
  203. package/src/components/LongTaskRow.css +1 -2
  204. package/src/components/LongTaskRow.tsx +1 -1
  205. package/src/components/Note.css +0 -1
  206. package/src/components/ResourceStates.css +0 -1
  207. package/src/components/SelectFieldNodes.tsx +0 -1
  208. package/src/components/SettingsSection.css +0 -1
  209. package/src/components/Spinner.css +0 -1
  210. package/src/components/Stack.css +0 -1
  211. package/src/components/StateBlock.css +0 -1
  212. package/src/components/__tests__/long-task-row.test.ts +1 -1
  213. package/src/components/board-module.ts +3 -3
  214. package/src/components/icons.tsx +16 -8
  215. package/src/config/constants.ts +2 -2
  216. package/src/{api → contract}/__tests__/facts.test.ts +73 -25
  217. package/src/{api → contract}/__tests__/long-task.test.ts +3 -3
  218. package/src/contract/__tests__/needs.test.ts +74 -0
  219. package/src/{host → contract}/__tests__/unit-declaration.test.ts +1 -1
  220. package/src/contract/__tests__/unit.test.ts +43 -0
  221. package/src/contract/adapters.ts +9 -0
  222. package/src/contract/cli.ts +3 -0
  223. package/src/contract/data.ts +145 -0
  224. package/src/{api → contract}/facts.ts +34 -4
  225. package/src/contract/needs.ts +331 -0
  226. package/src/contract/plugin-source.ts +1 -0
  227. package/src/contract/protocol/bundle-install.ts +198 -0
  228. package/src/contract/protocol/config-sync.ts +65 -0
  229. package/src/contract/protocol/diy.ts +4 -0
  230. package/src/contract/protocol/dsh-plugins.ts +13 -0
  231. package/src/contract/protocol/long-tasks.ts +16 -0
  232. package/src/contract/protocol/market-index.ts +246 -0
  233. package/src/contract/protocol/platform.ts +47 -0
  234. package/src/contract/protocol/preflight-wake.ts +17 -0
  235. package/src/contract/protocol/profile-create.ts +36 -0
  236. package/src/contract/protocol/sidebar-edition.ts +19 -0
  237. package/src/contract/protocol/unit-manifests.ts +8 -0
  238. package/src/{api → contract}/unit-board.ts +0 -1
  239. package/src/contract/unit-capability.ts +37 -0
  240. package/src/{host → contract}/unit-declaration.ts +22 -18
  241. package/src/contract/unit.ts +76 -0
  242. package/src/contract/workbench-contract.ts +30 -0
  243. package/src/host/__tests__/adapter-set.test.ts +228 -0
  244. package/src/host/__tests__/adapters.test.ts +27 -0
  245. package/src/host/__tests__/changelog.test.ts +102 -0
  246. package/src/host/__tests__/command-name.test.ts +16 -0
  247. package/src/host/__tests__/diy-record.test.ts +3 -3
  248. package/src/host/__tests__/facts.test.ts +5 -5
  249. package/src/host/__tests__/long-task.test.ts +1 -1
  250. package/src/host/__tests__/market-index.test.ts +179 -0
  251. package/src/host/__tests__/plugin-ledger.test.ts +10 -10
  252. package/src/host/__tests__/provision.test.ts +7 -6
  253. package/src/host/__tests__/shell-text.test.ts +16 -1
  254. package/src/host/__tests__/supply-index.test.ts +137 -0
  255. package/src/host/__tests__/tokens.test.ts +110 -0
  256. package/src/host/__tests__/version-range.test.ts +21 -0
  257. package/src/host/adapter-set.ts +298 -0
  258. package/src/host/adapter-types.ts +105 -0
  259. package/src/host/adapters.ts +44 -0
  260. package/src/host/browser.ts +3 -0
  261. package/src/host/changelog.ts +212 -0
  262. package/src/host/channel-plugin.ts +55 -0
  263. package/src/host/cli.ts +11 -0
  264. package/src/host/command-name.ts +15 -0
  265. package/src/host/data-error.ts +21 -0
  266. package/src/host/data-root.ts +2 -0
  267. package/src/host/diy-debug.ts +2 -1
  268. package/src/host/diy-record.ts +2 -1
  269. package/src/host/facts.ts +4 -3
  270. package/src/host/git.ts +2 -2
  271. package/src/host/http.ts +1 -1
  272. package/src/host/lib-capabilities.ts +52 -0
  273. package/src/host/lib-install.ts +18 -0
  274. package/src/host/long-task.ts +4 -3
  275. package/src/host/market-index.ts +413 -0
  276. package/src/host/needs.ts +6 -0
  277. package/src/host/patch.ts +93 -0
  278. package/src/host/paths.ts +37 -0
  279. package/src/host/platform.ts +48 -0
  280. package/src/host/plugin-source.ts +48 -56
  281. package/src/host/plugin.ts +39 -0
  282. package/src/host/port-types.ts +222 -0
  283. package/src/host/preflight.ts +31 -0
  284. package/src/host/profile-port.ts +9 -0
  285. package/src/host/provision.ts +7 -4
  286. package/src/host/recipe-rules.ts +330 -0
  287. package/src/host/recipe.test.ts +334 -0
  288. package/src/host/recipe.ts +323 -0
  289. package/src/host/shell-text.ts +15 -3
  290. package/src/host/shell.ts +9 -0
  291. package/src/host/spec.ts +32 -0
  292. package/src/host/supply-index.ts +256 -0
  293. package/src/host/supply-port.ts +45 -0
  294. package/src/host/time.ts +22 -0
  295. package/src/host/tokens.ts +186 -0
  296. package/src/host/tool-kit.ts +1 -1
  297. package/src/host/unit-face.ts +5 -4
  298. package/src/host/version-range.ts +71 -0
  299. package/src/host/version.ts +30 -0
  300. package/src/host.ts +47 -16
  301. package/src/i18n/en.ts +224 -71
  302. package/src/i18n/merge.test.ts +6 -6
  303. package/src/i18n/merge.ts +1 -1
  304. package/src/i18n/need-text.ts +27 -0
  305. package/src/i18n/settings.ts +141 -0
  306. package/src/i18n/zh.ts +227 -73
  307. package/src/index.ts +23 -7
  308. package/src/lib/blocker-action.ts +0 -1
  309. package/src/{api → lib}/dsh-client.ts +12 -1
  310. package/src/lib/market-index.ts +36 -0
  311. package/src/lib/react.ts +0 -40
  312. package/src/lib/text.test.ts +2 -2
  313. package/src/lib/ui.test.ts +6 -5
  314. package/src/lib/ui.ts +3 -9
  315. package/src/testing/__tests__/declaration.test.ts +1 -1
  316. package/src/testing/data.ts +66 -0
  317. package/src/testing/declaration.ts +2 -2
  318. package/src/testing/host-fakes.ts +0 -38
  319. package/src/testing/needs.ts +80 -0
  320. package/src/testing.ts +2 -0
  321. package/dist/api/unit-declaration.d.ts +0 -65
  322. package/dist/api/unit.d.ts +0 -85
  323. package/dist/api/unit.js +0 -8
  324. package/dist/api/workbench-contract.d.ts +0 -44
  325. package/dist/components/MockStrip.css +0 -39
  326. package/dist/components/MockStrip.d.ts +0 -15
  327. package/dist/components/MockStrip.js +0 -8
  328. package/dist/components/SaveBar.css +0 -7
  329. package/dist/host/browser-find.d.ts +0 -38
  330. package/dist/host/browser-find.js +0 -242
  331. package/dist/host/browser-read.d.ts +0 -28
  332. package/dist/host/browser-read.js +0 -243
  333. package/dist/host/opencli-runtime.d.ts +0 -25
  334. package/dist/host/opencli-runtime.js +0 -56
  335. package/dist/host/opencli-window.d.ts +0 -2
  336. package/dist/host/opencli-window.js +0 -8
  337. package/dist/host/opencli.d.ts +0 -37
  338. package/dist/host/opencli.js +0 -155
  339. package/dist/host/unit-declaration.js +0 -213
  340. package/dist/host/unit-libs.d.ts +0 -37
  341. package/dist/lib/diy-debug.d.ts +0 -80
  342. package/dist/lib/diy-debug.js +0 -88
  343. package/dist/lib/diy-record.d.ts +0 -135
  344. package/dist/lib/diy-record.js +0 -162
  345. package/dist/lib/lint-probe.d.ts +0 -1
  346. package/dist/lib/lint-probe.js +0 -6
  347. package/dist/lib/panel-state.d.ts +0 -120
  348. package/dist/lib/panel-state.js +0 -176
  349. package/src/api/__tests__/unit.test.ts +0 -38
  350. package/src/api/unit.ts +0 -93
  351. package/src/api/workbench-contract.ts +0 -59
  352. package/src/host/__tests__/browser-find.test.ts +0 -330
  353. package/src/host/__tests__/browser-read.test.ts +0 -228
  354. package/src/host/__tests__/opencli-runtime.test.ts +0 -46
  355. package/src/host/browser-find.ts +0 -311
  356. package/src/host/browser-read.ts +0 -311
  357. package/src/host/opencli-runtime.ts +0 -79
  358. package/src/host/opencli-window.ts +0 -11
  359. package/src/host/opencli.ts +0 -213
  360. package/src/host/unit-libs.ts +0 -41
  361. /package/dist/{api/blocker.js → contract/adapters.js} +0 -0
  362. /package/dist/{api → contract}/blocker.d.ts +0 -0
  363. /package/dist/{api/dsh-client.js → contract/blocker.js} +0 -0
  364. /package/dist/{api/unit-board.js → contract/cli.js} +0 -0
  365. /package/dist/{api/workbench-contract.js → contract/data.js} +0 -0
  366. /package/dist/{api → contract}/long-task.d.ts +0 -0
  367. /package/dist/{api → contract}/long-task.js +0 -0
  368. /package/dist/{host/unit-libs.js → contract/plugin-source.js} +0 -0
  369. /package/dist/{api → contract}/unit-board.d.ts +0 -0
  370. /package/src/{api → contract}/blocker.ts +0 -0
  371. /package/src/{api → contract}/long-task.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import type { Translate } from '../dsh-client.js';
3
- import type { CapabilityPayload } from '../workbench-contract.js';
2
+ import type { Translate } from '../../lib/dsh-client.js';
3
+ import type { CapabilityPayload } from '../../contract/workbench-contract.js';
4
+ import type { NeedState } from '../../contract/unit-capability.js';
4
5
  import { blockerOfCapability, blockerOfError } from '../blocker-table.js';
5
6
 
6
7
  const t: Translate = (key, params) => (params === undefined ? key : `${key}(${JSON.stringify(params)})`);
@@ -8,7 +9,7 @@ const t: Translate = (key, params) => (params === undefined ? key : `${key}(${JS
8
9
  describe('blockerOfError', () => {
9
10
  it('未登录 + 有登录页地址 → 行内「去登录 ↗」+ 一颗手动「重试」(不安排自动重试)', () => {
10
11
  const blocker = blockerOfError(
11
- { code: 'auth-required', message: '未登录 CODING', helpUrl: 'https://x.coding.net/login' },
12
+ { code: 'auth-required', message: '未登录 Acme', helpUrl: 'https://example.com/login' },
12
13
  t,
13
14
  );
14
15
 
@@ -18,7 +19,7 @@ describe('blockerOfError', () => {
18
19
  {
19
20
  kind: 'open-url',
20
21
  label: 'blocker.login.go',
21
- url: 'https://x.coding.net/login',
22
+ url: 'https://example.com/login',
22
23
  inline: true,
23
24
  },
24
25
  { kind: 'retry', label: 'blocker.retry' },
@@ -27,20 +28,20 @@ describe('blockerOfError', () => {
27
28
  });
28
29
 
29
30
  it('平台名由**调用方**给(同一个"未登录"能服务不同平台)', () => {
30
- const coding = blockerOfError(
31
- { code: 'auth-required', message: '未登录', helpUrl: 'https://x.coding.net/login' },
31
+ const demo = blockerOfError(
32
+ { code: 'auth-required', message: '未登录', helpUrl: 'https://example.com/login' },
32
33
  t,
33
- { platform: 'Coding' },
34
+ { platform: 'Acme' },
34
35
  );
35
- const cmdb = blockerOfError(
36
- { code: 'auth-required', message: '未登录', helpUrl: 'https://cmdb.example.cn/login' },
36
+ const inventory = blockerOfError(
37
+ { code: 'auth-required', message: '未登录', helpUrl: 'https://inventory.example.cn/login' },
37
38
  t,
38
- { platform: 'CMDB' },
39
+ { platform: 'Inventory' },
39
40
  );
40
41
 
41
- expect(coding.title).toContain('"platform":"Coding"');
42
- expect(cmdb.title).toContain('"platform":"CMDB"');
43
- expect(cmdb.actions[0]).toMatchObject({ kind: 'open-url', url: 'https://cmdb.example.cn/login' });
42
+ expect(demo.title).toContain('"platform":"Acme"');
43
+ expect(inventory.title).toContain('"platform":"Inventory"');
44
+ expect(inventory.actions[0]).toMatchObject({ kind: 'open-url', url: 'https://inventory.example.cn/login' });
44
45
  });
45
46
 
46
47
  it('没给平台名 → 用不带名字的文案(不猜平台)', () => {
@@ -58,15 +59,15 @@ describe('blockerOfError', () => {
58
59
 
59
60
  it('权限不足 → block,主动作「打开权限页」(地址同样来自信封)', () => {
60
61
  const blocker = blockerOfError(
61
- { code: 'permission-denied', message: '没有权限', helpUrl: 'https://x.coding.net/p/x/settings' },
62
+ { code: 'permission-denied', message: '没有权限', helpUrl: 'https://example.com/p/x/settings' },
62
63
  t,
63
- { platform: 'Coding' },
64
+ { platform: 'Acme' },
64
65
  );
65
66
 
66
67
  expect(blocker.id).toBe('permission-denied');
67
68
  expect(blocker.severity).toBe('block');
68
- expect(blocker.title).toContain('"platform":"Coding"');
69
- expect(blocker.actions[0]).toMatchObject({ kind: 'open-url', url: 'https://x.coding.net/p/x/settings' });
69
+ expect(blocker.title).toContain('"platform":"Acme"');
70
+ expect(blocker.actions[0]).toMatchObject({ kind: 'open-url', url: 'https://example.com/p/x/settings' });
70
71
  });
71
72
 
72
73
  it('权限不足但没有地址 → 只给重试(不编一个页面出来)', () => {
@@ -102,33 +103,38 @@ describe('blockerOfError', () => {
102
103
  });
103
104
  });
104
105
 
106
+ function needOf(patch: Partial<NeedState> & { kind: NeedState['kind']; name: string }): NeedState {
107
+ return { id: patch.id ?? `${patch.kind}:${patch.name}`, status: 'ok', detail: '', ...patch };
108
+ }
109
+
105
110
  function capability(patch: Partial<CapabilityPayload>): CapabilityPayload {
106
- return {
107
- unit: 'issues',
108
- status: 'ok',
109
- required: [],
110
- missing: [],
111
- detail: '',
112
- ...patch,
113
- };
111
+ return { unit: 'issues', status: 'ok', needs: [], ...patch };
114
112
  }
115
113
 
116
114
  describe('blockerOfCapability', () => {
117
115
  it('就绪 → 没有阻断', () => {
118
116
  expect(blockerOfCapability(capability({}), t)).toBeUndefined();
119
- });
120
-
121
- it('就绪 → 没有阻断(**没有**"能凑合用但提示一下"的中间态了,见 ADR-0016)', () => {
122
- expect(blockerOfCapability(capability({ status: 'ok', plugin: 'coding' }), t)).toBeUndefined();
117
+ expect(
118
+ blockerOfCapability(
119
+ capability({ needs: [needOf({ kind: 'extension', name: 'demo', status: 'ok' })] }),
120
+ t,
121
+ ),
122
+ ).toBeUndefined();
123
123
  });
124
124
 
125
125
  it('★ 缺哪些命令只出现在 detail(排障区),标题里没有命令名', () => {
126
126
  const blocker = blockerOfCapability(
127
127
  capability({
128
- status: 'missing-commands',
129
- plugin: 'coding',
130
- missing: ['issue-detail'],
131
- detail: '1 份安装都在(缺必需:issue-detail)',
128
+ status: 'missing',
129
+ needs: [
130
+ needOf({
131
+ kind: 'extension',
132
+ name: 'demo',
133
+ status: 'missing',
134
+ missing: ['issue-detail'],
135
+ detail: '1 份安装都在(缺必需:issue-detail)',
136
+ }),
137
+ ],
132
138
  }),
133
139
  t,
134
140
  );
@@ -137,11 +143,7 @@ describe('blockerOfCapability', () => {
137
143
  expect(blocker?.detail).toContain('issue-detail');
138
144
  });
139
145
 
140
- it('降级那一档已经不存在(`ok` 就是没阻断)', () => {
141
- expect(blockerOfCapability(capability({ status: 'ok', plugin: 'coding' }), t)).toBeUndefined();
142
- });
143
-
144
- it('★ 起不来(模块自己装配炸了)→ 只说"起不来" + 把宿主给的原因原样附上,不给装/卸的按钮', () => {
146
+ it('★ 起不来(模块自己装配炸了)→ 只说"起不来" + 原样附原因,不给装/卸按钮', () => {
145
147
  const blocker = blockerOfCapability(
146
148
  capability({ status: 'failed', detail: '模块自己的 bug:kit.components.StateBlock 取不到' }),
147
149
  t,
@@ -154,46 +156,99 @@ describe('blockerOfCapability', () => {
154
156
  expect(blocker?.actions.map((action) => action.kind)).toEqual(['retry']);
155
157
  });
156
158
 
157
- it('★ 没装好 → 标题只说"这个模块还没装好",**不点名插件**(用户不认识插件)', () => {
159
+ it('★ 未知 kind(模块跑在更新的工作台上)→ 单独一档,叫升级工作台,不猜怎么修', () => {
160
+ const blocker = blockerOfCapability(
161
+ capability({ status: 'unsupported', detail: 'needs[0].kind 不认识 —— "dsh-bundle"' }),
162
+ t,
163
+ );
164
+
165
+ expect(blocker?.id).toBe('unit-unsupported');
166
+ expect(blocker?.title).toBe('env.unit.unsupported');
167
+ expect(blocker?.severity).toBe('block');
168
+ expect(blocker?.actions.map((action) => action.kind)).toEqual(['retry']);
169
+ });
170
+
171
+ it('★ 可选的没装(required: false)→ notice,不挡卡片', () => {
172
+ const blocker = blockerOfCapability(
173
+ capability({
174
+ status: 'degraded',
175
+ needs: [needOf({ kind: 'bin', name: 'gitops', status: 'missing', detail: '这台机器上找不到 gitops' })],
176
+ }),
177
+ t,
178
+ );
179
+
180
+ expect(blocker?.id).toBe('unit-degraded');
181
+ expect(blocker?.severity).toBe('notice');
182
+ expect(blocker?.detail).toContain('gitops');
183
+ });
184
+
185
+ it('★ 缺二进制命令 → 标题按 kind 出(不是"缺插件"),并给复制命令', () => {
158
186
  const blocker = blockerOfCapability(
159
187
  capability({
160
- status: 'missing-plugin',
161
- plugin: 'coding',
162
- missing: ['issues'],
163
- command: 'opencli plugin install <coding 插件源>',
188
+ status: 'missing',
189
+ needs: [needOf({ kind: 'bin', name: 'gitops', status: 'missing', command: 'brew install gitops' })],
164
190
  }),
165
191
  t,
166
192
  );
167
193
 
168
- expect(blocker?.id).toBe('unit-missing-plugin');
169
- expect(blocker?.title).toBe('env.unit.missingPlugin');
170
- expect(blocker?.title).not.toContain('coding');
171
- expect(blocker?.hint).not.toContain('插件');
194
+ expect(blocker?.id).toBe('unit-need-bin-missing');
195
+ expect(blocker?.title).toBe('env.need.bin.missing');
172
196
  expect(blocker?.actions.map((action) => action.kind)).toEqual(['copy', 'retry']);
173
197
  });
174
198
 
175
- it('能一键修时,主动作是「帮我升级」并带上 { action, unit }(命令由宿主侧决定)', () => {
199
+ it('extension 装了但版本旧 → 标题是「版本旧了」那一档,不是「没装」', () => {
200
+ const blocker = blockerOfCapability(
201
+ capability({
202
+ status: 'outdated',
203
+ needs: [needOf({ kind: 'extension', name: 'demo', status: 'outdated' })],
204
+ }),
205
+ t,
206
+ );
207
+
208
+ expect(blocker?.id).toBe('unit-need-extension-outdated');
209
+ expect(blocker?.title).toBe('env.need.extension.outdated');
210
+ });
211
+
212
+ it('来源解析得出 → 主动作是「帮我安装」+ 复制命令', () => {
176
213
  const blocker = blockerOfCapability(
177
- capability({ status: 'missing-commands', plugin: 'coding', missing: ['issue-detail'], fix: 'update' }),
214
+ capability({
215
+ status: 'missing',
216
+ needs: [
217
+ needOf({
218
+ kind: 'extension',
219
+ name: 'demo',
220
+ status: 'missing',
221
+ provision: 'ready',
222
+ command: 'opencli plugin install /some/path',
223
+ }),
224
+ ],
225
+ }),
178
226
  t,
179
227
  );
180
228
 
229
+ expect(blocker?.actions.map((action) => action.kind)).toEqual(['run-fix', 'copy', 'retry']);
181
230
  expect(blocker?.actions[0]).toEqual({
182
231
  kind: 'run-fix',
183
- label: 'blocker.fix.update',
232
+ label: 'blocker.fix.install',
184
233
  unit: 'issues',
185
- fix: 'update',
234
+ fix: 'install',
186
235
  });
187
236
  });
188
237
 
189
- it('★ 来源解析不出(宿主给了 install 但不是 ready)→ 给「去模块市场」,不给注定失败的按钮', () => {
238
+ it('★ 来源解析不出(provision 不是 ready)→ 给「去模块市场」,不给注定失败的按钮', () => {
190
239
  for (const install of ['env-missing', 'not-declared', 'malformed'] as const) {
191
240
  const blocker = blockerOfCapability(
192
241
  capability({
193
- status: 'missing-plugin',
194
- plugin: 'coding',
195
- command: 'opencli plugin install <coding 插件源>',
196
- install,
242
+ status: 'missing',
243
+ needs: [
244
+ needOf({
245
+ kind: 'extension',
246
+ name: 'demo',
247
+ status: 'missing',
248
+ command: 'opencli plugin install <demo 插件源>',
249
+ provision: install,
250
+ }),
251
+ ],
197
252
  }),
198
253
  t,
199
254
  );
@@ -203,57 +258,52 @@ describe('blockerOfCapability', () => {
203
258
  }
204
259
  });
205
260
 
206
- it('来源解析得出时仍然给「帮我安装」+ 复制命令(open-market 不该抢戏)', () => {
261
+ it('共用依赖版本不对 → 那一档标题', () => {
207
262
  const blocker = blockerOfCapability(
208
263
  capability({
209
- status: 'missing-plugin',
210
- plugin: 'coding',
211
- command: 'opencli plugin install /some/path',
212
- install: 'ready',
213
- fix: 'install',
264
+ status: 'missing',
265
+ needs: [needOf({ kind: 'lib', name: 'opencli-workflow', status: 'unsatisfied' })],
214
266
  }),
215
267
  t,
216
268
  );
217
269
 
218
- expect(blocker?.actions.map((action) => action.kind)).toEqual(['run-fix', 'copy', 'retry']);
270
+ expect(blocker?.title).toBe('env.need.lib.unsatisfied');
219
271
  });
220
272
 
221
- it('缺插件且有来源 → 主动作是「帮我安装」', () => {
273
+ it('环境变量没设 → 只提醒,不给复制值', () => {
222
274
  const blocker = blockerOfCapability(
223
- capability({ status: 'missing-plugin', plugin: 'coding', fix: 'install' }),
224
- t,
225
- );
226
-
227
- expect(blocker?.actions[0]?.kind).toBe('run-fix');
228
- expect(blocker?.actions[0]?.label).toBe('blocker.fix.install');
229
- expect(blocker?.actions[0]).toMatchObject({ fix: 'install', unit: 'issues' });
230
- });
231
-
232
- it('缺命令(版本旧)→ 也给「帮我升级」', () => {
233
- const blocker = blockerOfCapability(
234
- capability({ status: 'missing-commands', plugin: 'coding', missing: ['issue-detail'], fix: 'update' }),
275
+ capability({
276
+ status: 'missing',
277
+ needs: [needOf({ kind: 'env', name: 'DSH_TOKEN', status: 'missing' })],
278
+ }),
235
279
  t,
236
280
  );
237
281
 
238
- expect(blocker?.actions[0]?.kind).toBe('run-fix');
239
- expect(blocker?.actions[0]?.label).toBe('blocker.fix.update');
282
+ expect(blocker?.title).toBe('env.need.env.missing');
283
+ expect(blocker?.actions.map((action) => action.kind)).toEqual(['retry']);
240
284
  });
241
285
 
242
- it('缺命令 → 列出缺哪几个,并提示多半是版本旧', () => {
286
+ it('★ 只看第一条非 ok 的 need(顺序即优先级)', () => {
243
287
  const blocker = blockerOfCapability(
244
- capability({ status: 'missing-commands', plugin: 'coding', missing: ['issue-detail'] }),
288
+ capability({
289
+ status: 'missing',
290
+ needs: [
291
+ needOf({ kind: 'bin', name: 'gitops', status: 'missing' }),
292
+ needOf({ kind: 'extension', name: 'demo', status: 'missing' }),
293
+ ],
294
+ }),
245
295
  t,
246
296
  );
247
297
 
248
- expect(blocker?.id).toBe('unit-missing-commands');
249
- expect(blocker?.title).toBe('env.unit.missingCommands');
250
- expect(blocker?.title).not.toContain('issue-detail');
251
- expect(blocker?.hint).toBe('env.unit.missingCommandsHint');
298
+ expect(blocker?.title).toBe('env.need.bin.missing');
252
299
  });
253
300
 
254
301
  it('探不动 → notice,**绝不**说成缺命令/缺插件,也不给"复制安装命令"', () => {
255
302
  const blocker = blockerOfCapability(
256
- capability({ status: 'unchecked', plugin: 'coding', missing: ['issues', 'issue-detail'], detail: '拿不到执行通道' }),
303
+ capability({
304
+ status: 'unchecked',
305
+ needs: [needOf({ kind: 'extension', name: 'demo', status: 'unchecked', detail: '拿不到执行通道' })],
306
+ }),
257
307
  t,
258
308
  );
259
309
 
@@ -261,6 +311,5 @@ describe('blockerOfCapability', () => {
261
311
  expect(blocker?.severity).toBe('notice');
262
312
  expect(blocker?.title).toBe('env.unit.unchecked');
263
313
  expect(blocker?.actions.map((action) => action.kind)).toEqual(['retry']);
264
- expect(blocker?.title).not.toContain('issue-detail');
265
314
  });
266
315
  });
@@ -1,7 +1,7 @@
1
- import type { Translate } from './dsh-client.js';
2
- import type { CapabilityPayload } from './workbench-contract.js';
1
+ import type { Translate } from '../lib/dsh-client.js';
2
+ import type { CapabilityPayload } from '../contract/workbench-contract.js';
3
3
  import type { ApiError } from './workbench-client.js';
4
- import type { BlockerAction, ModuleBlocker } from './blocker.js';
4
+ import type { BlockerAction, ModuleBlocker } from '../contract/blocker.js';
5
5
  import { shortenPath } from '../lib/ui.js';
6
6
 
7
7
  function retryAction(t: Translate): BlockerAction {
@@ -119,21 +119,24 @@ export function blockerOfError(
119
119
  export function blockerOfCapability(capability: CapabilityPayload, t: Translate): ModuleBlocker | undefined {
120
120
  if (capability.status === 'ok') return undefined;
121
121
 
122
+ const problem = capability.needs.find((need) => need.status !== 'ok');
123
+ const fix = problem?.provision === 'ready' ? 'install' : undefined;
122
124
  const fixAction: BlockerAction | undefined =
123
- capability.fix === undefined
125
+ fix === undefined
124
126
  ? undefined
125
127
  : {
126
128
  kind: 'run-fix',
127
- label: capability.fix === 'install' ? t('blocker.fix.install') : t('blocker.fix.update'),
129
+ label: t('blocker.fix.install'),
128
130
  unit: capability.unit,
129
- fix: capability.fix,
131
+ fix,
130
132
  };
131
- const sourceUnknown = capability.fix === undefined && capability.install !== undefined && capability.install !== 'ready';
133
+ const sourceUnknown = problem?.provision !== undefined && problem.provision !== 'ready';
132
134
  const install: readonly BlockerAction[] = [
133
135
  ...(fixAction === undefined ? [] : [fixAction]),
134
136
  ...(sourceUnknown ? [{ kind: 'open-market' as const, label: t('blocker.market.open'), unit: capability.unit }] : []),
135
- ...(capability.command === undefined || sourceUnknown ? [] : [copyAction(t, capability.command)]),
137
+ ...(problem?.command === undefined || sourceUnknown ? [] : [copyAction(t, problem.command)]),
136
138
  ];
139
+ const detail = problem?.detail ?? capability.detail;
137
140
 
138
141
  if (capability.status === 'failed') {
139
142
  return {
@@ -146,34 +149,57 @@ export function blockerOfCapability(capability: CapabilityPayload, t: Translate)
146
149
  };
147
150
  }
148
151
 
149
- if (capability.status === 'missing-plugin') {
152
+ if (capability.status === 'unsupported') {
150
153
  return {
151
- id: 'unit-missing-plugin',
154
+ id: 'unit-unsupported',
152
155
  severity: 'block',
153
- title: t('env.unit.missingPlugin'),
154
- hint: t('env.unit.hint'),
155
- ...(capability.detail === undefined ? {} : { detail: capability.detail }),
156
- actions: [...install, retryAction(t)],
156
+ title: t('env.unit.unsupported'),
157
+ hint: t('env.unit.unsupportedHint'),
158
+ ...(detail === undefined ? {} : { detail }),
159
+ actions: [retryAction(t)],
157
160
  };
158
161
  }
159
162
 
160
- if (capability.status === 'missing-commands') {
163
+ if (capability.status === 'degraded') {
161
164
  return {
162
- id: 'unit-missing-commands',
163
- severity: 'block',
164
- title: t('env.unit.missingCommands'),
165
- hint: t('env.unit.missingCommandsHint'),
165
+ id: 'unit-degraded',
166
+ severity: 'notice',
167
+ title: t('env.unit.degraded'),
168
+ hint: t('env.unit.degradedHint'),
169
+ ...(detail === undefined ? {} : { detail }),
170
+ actions: [retryAction(t)],
171
+ };
172
+ }
173
+
174
+ if (problem === undefined) {
175
+ return {
176
+ id: 'unit-unchecked',
177
+ severity: 'notice',
178
+ title: t('env.unit.unchecked'),
179
+ hint: t('env.unit.uncheckedHint'),
166
180
  ...(capability.detail === undefined ? {} : { detail: capability.detail }),
167
- actions: [...install, retryAction(t)],
181
+ actions: [retryAction(t)],
182
+ };
183
+ }
184
+
185
+ if (problem.status === 'unchecked') {
186
+ return {
187
+ id: 'unit-unchecked',
188
+ severity: 'notice',
189
+ title: t('env.unit.unchecked'),
190
+ hint: t('env.unit.uncheckedHint'),
191
+ ...(detail === undefined ? {} : { detail }),
192
+ actions: [retryAction(t)],
168
193
  };
169
194
  }
170
195
 
196
+ const kindTitle = `env.need.${problem.kind}.${problem.status}`;
171
197
  return {
172
- id: 'unit-unchecked',
173
- severity: 'notice',
174
- title: t('env.unit.unchecked'),
175
- hint: t('env.unit.uncheckedHint'),
176
- ...(capability.detail === undefined ? {} : { detail: capability.detail }),
177
- actions: [retryAction(t)],
198
+ id: `unit-need-${problem.kind}-${problem.status}`,
199
+ severity: 'block',
200
+ title: t(kindTitle),
201
+ hint: t(`env.need.${problem.kind}.hint`),
202
+ ...(detail === undefined ? {} : { detail }),
203
+ actions: [...install, retryAction(t)],
178
204
  };
179
205
  }
package/src/api/dsh.ts CHANGED
@@ -126,7 +126,7 @@ export interface DshHostContext {
126
126
  ) => Promise<{ kind: string; messages?: readonly unknown[] }>,
127
127
  ): (() => void) | undefined;
128
128
  };
129
- get<T = unknown>(name: string): T | undefined;
129
+ get<T = unknown>(name: string, strict?: boolean): T | undefined;
130
130
  provide(name: string, value: unknown): () => void;
131
131
  effect(effect: () => void | (() => void), label?: string): () => void;
132
132
  inject(names: readonly string[], effect: (scoped: DshHostContext) => void): () => void;
@@ -19,4 +19,3 @@ export type WriteOutcome<T> =
19
19
  readonly detail?: string;
20
20
  readonly helpUrl?: string;
21
21
  };
22
-
@@ -66,11 +66,11 @@ describe('apiGet', () => {
66
66
 
67
67
  it('宿主的 {ok:false} 信封原样返回,不抛异常', async () => {
68
68
  stubFetch({
69
- body: { ok: false, error: { code: 'coding-not-logged-in', message: '登录态失效' } },
69
+ body: { ok: false, error: { code: 'demo-not-logged-in', message: '登录态失效' } },
70
70
  });
71
71
  const result = await apiGet('issues');
72
72
  expect(result.ok).toBe(false);
73
- expect(result.ok === false && result.error.code).toBe('coding-not-logged-in');
73
+ expect(result.ok === false && result.error.code).toBe('demo-not-logged-in');
74
74
  });
75
75
 
76
76
  it('HTTP 非 2xx 也走结构化错误(不读 body)', async () => {
@@ -46,8 +46,9 @@ export async function apiGet<T>(
46
46
  if (value !== undefined) search.set(key, String(value));
47
47
  }
48
48
  const suffix = search.toString();
49
+ const target = suffix === '' ? `${API_PREFIX}/${route}` : `${API_PREFIX}/${route}?${suffix}`;
49
50
 
50
- const response = await fetch(`${API_PREFIX}/${route}${suffix ? `?${suffix}` : ''}`, {
51
+ const response = await fetch(target, {
51
52
  method: 'GET',
52
53
  headers: { accept: 'application/json' },
53
54
  ...(signal === undefined ? {} : { signal }),
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-activityBlock {
3
2
  display: flex;
4
3
  flex-direction: column;
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-approvalCommand {
3
2
  max-width: 100%;
4
- }
3
+ }
@@ -1,4 +1,4 @@
1
- import type { Translate } from '../api/dsh-client.js';
1
+ import type { Translate } from '../lib/dsh-client.js';
2
2
  import type { ApprovalInput, UnitClientFace } from '../components/board-module.js';
3
3
  import { Fragment, h, type ReactNode } from '../lib/react.js';
4
4
  import { CodeBlock } from '@deepseek-ai/dsh-client-ui-primitives';
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-approvalPlan {
3
2
  display: flex;
4
3
  flex-direction: column;
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-card {
3
2
  border: 0.5px solid var(--dsw-alias-border-l3);
4
3
  border-radius: var(--dsw-radius-xl);
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from '../lib/react.js';
2
- import type { Translate } from '../api/dsh-client.js';
2
+ import type { Translate } from '../lib/dsh-client.js';
3
3
  import { h } from '../lib/react.js';
4
4
  import { CardHead } from './CardHead.js';
5
5
  import './Card.css';
@@ -31,6 +31,6 @@ describe('外壳给每张卡盖的锚点', () => {
31
31
  it('★ 名字由 unit 拼出来:空 unit 不给 id(一个页面里 id 必须唯一)', () => {
32
32
  expect(cardIdOf(null)).toBeUndefined();
33
33
  expect(cardIdOf('')).toBeUndefined();
34
- expect(cardIdOf('cmdb')).toBe('wb-card-cmdb');
34
+ expect(cardIdOf('inventory')).toBe('wb-card-inventory');
35
35
  });
36
36
  });
@@ -1,5 +1,5 @@
1
1
  import { Button } from '@deepseek-ai/dsh-client-ui-primitives';
2
- import type { Translate } from '../api/dsh-client.js';
2
+ import type { Translate } from '../lib/dsh-client.js';
3
3
  import type { ReactNode } from '../lib/react.js';
4
4
  import { Component, h } from '../lib/react.js';
5
5
  import { Note } from './Note.js';
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-cardHead {
3
2
  display: flex;
4
3
  align-items: center;
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from '../lib/react.js';
2
- import type { Translate } from '../api/dsh-client.js';
2
+ import type { Translate } from '../lib/dsh-client.js';
3
3
  import {
4
4
  Button,
5
5
  IconRefreshOutlineRegular,
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-choiceMenu {
3
2
  display: flex;
4
3
  flex-direction: column;
@@ -180,4 +179,4 @@
180
179
  .wb-radio:focus-visible {
181
180
  outline: var(--dsw-focus-ring-width, var(--wb-len-2)) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));
182
181
  outline-offset: 2px;
183
- }
182
+ }
@@ -29,7 +29,7 @@ export interface ConfirmBarProps {
29
29
 
30
30
  /**
31
31
  * 「先问一句再动手」那一条:标题 + 说明 + 键值 + 失败那句 + 动作区,形状一次收口。
32
- * **要不要问**归调用点(ADR-0054 §2 规则三),这一件只回答"问的时候长什么样"。
32
+ * **要不要问**归调用点,这一件只回答"问的时候长什么样"。
33
33
  * @param props.title - 那一句问话("发布到 prod?")。
34
34
  * @param props.hint - 标题下面那句说明或正文;不给不占位。
35
35
  * @param props.rows - 键值两格(键值列宽与分隔线归 `Rows` / `Row`);不给或空数组不渲染。值那一格可以放控件。
@@ -3,4 +3,4 @@
3
3
  flex-direction: column;
4
4
  gap: var(--wb-len-12);
5
5
  width: 100%;
6
- }
6
+ }
@@ -77,4 +77,4 @@ export function Form<Values extends object = FormValues>(props: FormProps<Values
77
77
  />
78
78
  </form>
79
79
  );
80
- }
80
+ }
@@ -46,7 +46,7 @@ function reportExtraPrimaries(actions: readonly FormAction[]): void {
46
46
  if (keys.length < 2) return;
47
47
  console.error(
48
48
  `[dsh-workbench] FormActions 一个区里出现了 ${keys.length} 颗 primary(${keys.join('、')})—— ` +
49
- '一个区只许一颗主操作(ADR-0054 §2 规则二):多余的这颗该改成 default',
49
+ '一个区只许一颗主操作:多余的这颗该改成 default',
50
50
  );
51
51
  }
52
52
 
@@ -1,4 +1,3 @@
1
-
2
1
  .wb-longTask {
3
2
  padding-top: var(--wb-len-12);
4
3
  border-top: 0.5px solid var(--dsw-alias-border-l2);
@@ -97,4 +96,4 @@
97
96
  line-height: var(--wb-line-16);
98
97
  color: var(--dsw-alias-state-error-primary);
99
98
  overflow-wrap: anywhere;
100
- }
99
+ }
@@ -1,4 +1,4 @@
1
- import { longTaskDot, longTaskStopPress, longTaskStopStage, LONG_TASK_STOP_ARM_MS, type LongTaskStatus } from '../api/long-task.js';
1
+ import { longTaskDot, longTaskStopPress, longTaskStopStage, LONG_TASK_STOP_ARM_MS, type LongTaskStatus } from '../contract/long-task.js';
2
2
  import { Link } from './Link.js';
3
3
  import { Fragment, h, useEffect, useState } from '../lib/react.js';
4
4
  import {