create-principles-disciple 1.146.3 → 1.146.6

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 (311) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/console/dist/web/assets/app.js +26 -26
  3. package/console/package.json +1 -1
  4. package/package.json +3 -3
  5. package/pd-cli/package.json +1 -1
  6. package/release-manager/package.json +3 -3
  7. package/console/dist/ui/App.d.ts +0 -1
  8. package/console/dist/ui/App.js +0 -172
  9. package/console/dist/ui/api.d.ts +0 -611
  10. package/console/dist/ui/api.js +0 -1094
  11. package/console/dist/ui/components/auth/login-form.d.ts +0 -4
  12. package/console/dist/ui/components/auth/login-form.js +0 -142
  13. package/console/dist/ui/components/auth/splash-screen.d.ts +0 -9
  14. package/console/dist/ui/components/auth/splash-screen.js +0 -22
  15. package/console/dist/ui/components/error-boundary.d.ts +0 -15
  16. package/console/dist/ui/components/error-boundary.js +0 -30
  17. package/console/dist/ui/components/focus/daily-thought-card.d.ts +0 -1
  18. package/console/dist/ui/components/focus/daily-thought-card.js +0 -41
  19. package/console/dist/ui/components/language-switcher.d.ts +0 -2
  20. package/console/dist/ui/components/language-switcher.js +0 -17
  21. package/console/dist/ui/components/layout/app-sidebar.d.ts +0 -27
  22. package/console/dist/ui/components/layout/app-sidebar.js +0 -128
  23. package/console/dist/ui/components/layout/page-loading.d.ts +0 -13
  24. package/console/dist/ui/components/layout/page-loading.js +0 -14
  25. package/console/dist/ui/components/layout/page-shell.d.ts +0 -12
  26. package/console/dist/ui/components/layout/page-shell.js +0 -11
  27. package/console/dist/ui/components/layout/section-title.d.ts +0 -10
  28. package/console/dist/ui/components/layout/section-title.js +0 -9
  29. package/console/dist/ui/components/notifications/NotificationProvider.d.ts +0 -14
  30. package/console/dist/ui/components/notifications/NotificationProvider.js +0 -136
  31. package/console/dist/ui/components/notifications/favicon-badge.d.ts +0 -3
  32. package/console/dist/ui/components/notifications/favicon-badge.js +0 -68
  33. package/console/dist/ui/components/notifications/notification-reducer.d.ts +0 -9
  34. package/console/dist/ui/components/notifications/notification-reducer.js +0 -9
  35. package/console/dist/ui/components/notifications/sound-storage.d.ts +0 -3
  36. package/console/dist/ui/components/notifications/sound-storage.js +0 -37
  37. package/console/dist/ui/components/notifications/useNotifications.d.ts +0 -1
  38. package/console/dist/ui/components/notifications/useNotifications.js +0 -9
  39. package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +0 -8
  40. package/console/dist/ui/components/onboarding/CircuitDiagram.js +0 -18
  41. package/console/dist/ui/components/onboarding/DemoResultView.d.ts +0 -22
  42. package/console/dist/ui/components/onboarding/DemoResultView.js +0 -33
  43. package/console/dist/ui/components/onboarding/SlashCommandsCard.d.ts +0 -16
  44. package/console/dist/ui/components/onboarding/SlashCommandsCard.js +0 -20
  45. package/console/dist/ui/components/onboarding/slashCommands.d.ts +0 -20
  46. package/console/dist/ui/components/onboarding/slashCommands.js +0 -22
  47. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.d.ts +0 -6
  48. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.js +0 -66
  49. package/console/dist/ui/components/theme-provider.d.ts +0 -14
  50. package/console/dist/ui/components/theme-provider.js +0 -40
  51. package/console/dist/ui/components/theme-toggle.d.ts +0 -2
  52. package/console/dist/ui/components/theme-toggle.js +0 -11
  53. package/console/dist/ui/components/ui/alert-dialog.d.ts +0 -20
  54. package/console/dist/ui/components/ui/alert-dialog.js +0 -26
  55. package/console/dist/ui/components/ui/badge.d.ts +0 -9
  56. package/console/dist/ui/components/ui/badge.js +0 -22
  57. package/console/dist/ui/components/ui/button.d.ts +0 -11
  58. package/console/dist/ui/components/ui/button.js +0 -34
  59. package/console/dist/ui/components/ui/card.d.ts +0 -8
  60. package/console/dist/ui/components/ui/card.js +0 -16
  61. package/console/dist/ui/components/ui/charts.d.ts +0 -51
  62. package/console/dist/ui/components/ui/charts.js +0 -72
  63. package/console/dist/ui/components/ui/dialog.d.ts +0 -19
  64. package/console/dist/ui/components/ui/dialog.js +0 -22
  65. package/console/dist/ui/components/ui/input.d.ts +0 -3
  66. package/console/dist/ui/components/ui/input.js +0 -8
  67. package/console/dist/ui/components/ui/markdown.d.ts +0 -24
  68. package/console/dist/ui/components/ui/markdown.js +0 -119
  69. package/console/dist/ui/components/ui/progress-bar.d.ts +0 -20
  70. package/console/dist/ui/components/ui/progress-bar.js +0 -38
  71. package/console/dist/ui/components/ui/select.d.ts +0 -13
  72. package/console/dist/ui/components/ui/select.js +0 -26
  73. package/console/dist/ui/components/ui/separator.d.ts +0 -3
  74. package/console/dist/ui/components/ui/separator.js +0 -6
  75. package/console/dist/ui/components/ui/sheet.d.ts +0 -25
  76. package/console/dist/ui/components/ui/sheet.js +0 -37
  77. package/console/dist/ui/components/ui/shiny-text.d.ts +0 -28
  78. package/console/dist/ui/components/ui/shiny-text.js +0 -46
  79. package/console/dist/ui/components/ui/skeleton.d.ts +0 -3
  80. package/console/dist/ui/components/ui/skeleton.js +0 -6
  81. package/console/dist/ui/components/ui/sonner.d.ts +0 -3
  82. package/console/dist/ui/components/ui/sonner.js +0 -13
  83. package/console/dist/ui/components/ui/tooltip.d.ts +0 -7
  84. package/console/dist/ui/components/ui/tooltip.js +0 -10
  85. package/console/dist/ui/data/daily-thoughts.d.ts +0 -15
  86. package/console/dist/ui/data/daily-thoughts.js +0 -164
  87. package/console/dist/ui/hooks/useNotificationSound.d.ts +0 -12
  88. package/console/dist/ui/hooks/useNotificationSound.js +0 -74
  89. package/console/dist/ui/i18n/en.json +0 -2399
  90. package/console/dist/ui/i18n/index.d.ts +0 -2
  91. package/console/dist/ui/i18n/index.js +0 -32
  92. package/console/dist/ui/i18n/zh-CN.json +0 -2399
  93. package/console/dist/ui/main.d.ts +0 -1
  94. package/console/dist/ui/main.js +0 -9
  95. package/console/dist/ui/pages/ReportProblemValidators.d.ts +0 -144
  96. package/console/dist/ui/pages/ReportProblemValidators.js +0 -418
  97. package/console/dist/ui/pages/activation/ActivationPage.d.ts +0 -1
  98. package/console/dist/ui/pages/activation/ActivationPage.js +0 -512
  99. package/console/dist/ui/pages/activation/ActivationValidators.d.ts +0 -20
  100. package/console/dist/ui/pages/activation/ActivationValidators.js +0 -160
  101. package/console/dist/ui/pages/control-center/AgentCard.d.ts +0 -31
  102. package/console/dist/ui/pages/control-center/AgentCard.js +0 -212
  103. package/console/dist/ui/pages/control-center/AgentGroup.d.ts +0 -26
  104. package/console/dist/ui/pages/control-center/AgentGroup.js +0 -38
  105. package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +0 -1
  106. package/console/dist/ui/pages/control-center/ControlCenterPage.js +0 -509
  107. package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +0 -1
  108. package/console/dist/ui/pages/control-center/DesignGatePanel.js +0 -137
  109. package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +0 -31
  110. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +0 -199
  111. package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +0 -17
  112. package/console/dist/ui/pages/control-center/WorkflowDiagram.js +0 -55
  113. package/console/dist/ui/pages/debt/DebtPage.d.ts +0 -2
  114. package/console/dist/ui/pages/debt/DebtPage.js +0 -222
  115. package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +0 -2
  116. package/console/dist/ui/pages/design-system/DesignSystemPage.js +0 -30
  117. package/console/dist/ui/pages/examiner/ExaminerPage.d.ts +0 -15
  118. package/console/dist/ui/pages/examiner/ExaminerPage.js +0 -158
  119. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.d.ts +0 -1
  120. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.js +0 -421
  121. package/console/dist/ui/pages/focus/ApprovalSubjectReading.d.ts +0 -24
  122. package/console/dist/ui/pages/focus/ApprovalSubjectReading.js +0 -133
  123. package/console/dist/ui/pages/focus/FocusPage.d.ts +0 -123
  124. package/console/dist/ui/pages/focus/FocusPage.js +0 -567
  125. package/console/dist/ui/pages/focus/OwnerDecisionCard.d.ts +0 -9
  126. package/console/dist/ui/pages/focus/OwnerDecisionCard.js +0 -111
  127. package/console/dist/ui/pages/focus/OwnerWorkbench.d.ts +0 -19
  128. package/console/dist/ui/pages/focus/OwnerWorkbench.js +0 -75
  129. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.d.ts +0 -34
  130. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.js +0 -298
  131. package/console/dist/ui/pages/focus/focus-validation.d.ts +0 -40
  132. package/console/dist/ui/pages/focus/focus-validation.js +0 -211
  133. package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +0 -67
  134. package/console/dist/ui/pages/intent/IntentOnboarding.js +0 -289
  135. package/console/dist/ui/pages/intent/IntentPage.d.ts +0 -1
  136. package/console/dist/ui/pages/intent/IntentPage.js +0 -252
  137. package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +0 -59
  138. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +0 -125
  139. package/console/dist/ui/pages/pain/PainPage.d.ts +0 -1
  140. package/console/dist/ui/pages/pain/PainPage.js +0 -420
  141. package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +0 -175
  142. package/console/dist/ui/pages/pain/pain-card-helpers.js +0 -181
  143. package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +0 -10
  144. package/console/dist/ui/pages/principles/CorePrinciplesPage.js +0 -59
  145. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +0 -60
  146. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +0 -602
  147. package/console/dist/ui/pages/principles/PrinciplesPage.d.ts +0 -1
  148. package/console/dist/ui/pages/principles/PrinciplesPage.js +0 -327
  149. package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +0 -8
  150. package/console/dist/ui/pages/principles/PrinciplesViewNav.js +0 -15
  151. package/console/dist/ui/pages/report-problem/ReportProblemPage.d.ts +0 -1
  152. package/console/dist/ui/pages/report-problem/ReportProblemPage.js +0 -467
  153. package/console/dist/ui/pages/settings/SettingsPage.d.ts +0 -4
  154. package/console/dist/ui/pages/settings/SettingsPage.js +0 -457
  155. package/console/dist/ui/pages/settings/UpdatePage.d.ts +0 -1
  156. package/console/dist/ui/pages/settings/UpdatePage.js +0 -215
  157. package/console/dist/ui/pages/welcome/WelcomePage.d.ts +0 -5
  158. package/console/dist/ui/pages/welcome/WelcomePage.js +0 -187
  159. package/console/dist/ui/utils/agent-metadata.d.ts +0 -71
  160. package/console/dist/ui/utils/agent-metadata.js +0 -284
  161. package/console/dist/ui/utils/approval-review.d.ts +0 -30
  162. package/console/dist/ui/utils/approval-review.js +0 -50
  163. package/console/dist/ui/utils/approval-warning-localization.d.ts +0 -34
  164. package/console/dist/ui/utils/approval-warning-localization.js +0 -148
  165. package/console/dist/ui/utils/attention-presentation.d.ts +0 -35
  166. package/console/dist/ui/utils/attention-presentation.js +0 -46
  167. package/console/dist/ui/utils/blocker-localization.d.ts +0 -23
  168. package/console/dist/ui/utils/blocker-localization.js +0 -36
  169. package/console/dist/ui/utils/control-center-helpers.d.ts +0 -79
  170. package/console/dist/ui/utils/control-center-helpers.js +0 -189
  171. package/console/dist/ui/utils/enum-labels.d.ts +0 -50
  172. package/console/dist/ui/utils/enum-labels.js +0 -171
  173. package/console/dist/ui/utils/format-date.d.ts +0 -11
  174. package/console/dist/ui/utils/format-date.js +0 -17
  175. package/console/dist/ui/utils/onboarding-state.d.ts +0 -25
  176. package/console/dist/ui/utils/onboarding-state.js +0 -77
  177. package/console/dist/ui/utils/reading-layout.d.ts +0 -20
  178. package/console/dist/ui/utils/reading-layout.js +0 -46
  179. package/console/dist/ui/utils/rule-binding-validators.d.ts +0 -13
  180. package/console/dist/ui/utils/rule-binding-validators.js +0 -188
  181. package/console/dist/ui/utils/runtime-mode.d.ts +0 -11
  182. package/console/dist/ui/utils/runtime-mode.js +0 -11
  183. package/console/dist/ui/utils/token-storage.d.ts +0 -22
  184. package/console/dist/ui/utils/token-storage.js +0 -47
  185. package/console/dist/ui/utils/validators.d.ts +0 -1178
  186. package/console/dist/ui/utils/validators.js +0 -3297
  187. package/release-manager/dist/bootstrap-entry.d.ts +0 -2
  188. package/release-manager/dist/bootstrap-entry.d.ts.map +0 -1
  189. package/release-manager/dist/bootstrap-entry.js.map +0 -1
  190. package/release-manager/dist/i18n.d.ts +0 -6
  191. package/release-manager/dist/i18n.d.ts.map +0 -1
  192. package/release-manager/dist/i18n.js.map +0 -1
  193. package/release-manager/dist/index.d.ts +0 -7
  194. package/release-manager/dist/index.d.ts.map +0 -1
  195. package/release-manager/dist/index.js +0 -656
  196. package/release-manager/dist/index.js.map +0 -1
  197. package/release-manager/dist/installer.d.ts +0 -629
  198. package/release-manager/dist/installer.d.ts.map +0 -1
  199. package/release-manager/dist/installer.js.map +0 -1
  200. package/release-manager/dist/installers/codex-host-installer.d.ts +0 -39
  201. package/release-manager/dist/installers/codex-host-installer.d.ts.map +0 -1
  202. package/release-manager/dist/installers/codex-host-installer.js.map +0 -1
  203. package/release-manager/dist/installers/index.d.ts +0 -51
  204. package/release-manager/dist/installers/index.d.ts.map +0 -1
  205. package/release-manager/dist/installers/index.js.map +0 -1
  206. package/release-manager/dist/installers/openclaw-host-installer.d.ts +0 -14
  207. package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +0 -1
  208. package/release-manager/dist/installers/openclaw-host-installer.js.map +0 -1
  209. package/release-manager/dist/installers/workbuddy-host-installer.d.ts +0 -335
  210. package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +0 -1
  211. package/release-manager/dist/installers/workbuddy-host-installer.js.map +0 -1
  212. package/release-manager/dist/mvp-config.d.ts +0 -233
  213. package/release-manager/dist/mvp-config.d.ts.map +0 -1
  214. package/release-manager/dist/mvp-config.js.map +0 -1
  215. package/release-manager/dist/prompts.d.ts +0 -43
  216. package/release-manager/dist/prompts.d.ts.map +0 -1
  217. package/release-manager/dist/prompts.js +0 -268
  218. package/release-manager/dist/prompts.js.map +0 -1
  219. package/release-manager/dist/skill-language.d.ts +0 -32
  220. package/release-manager/dist/skill-language.d.ts.map +0 -1
  221. package/release-manager/dist/skill-language.js.map +0 -1
  222. package/release-manager/dist/uninstaller.d.ts +0 -68
  223. package/release-manager/dist/uninstaller.d.ts.map +0 -1
  224. package/release-manager/dist/uninstaller.js +0 -746
  225. package/release-manager/dist/uninstaller.js.map +0 -1
  226. package/release-manager/dist/update/apply-payload.d.ts +0 -143
  227. package/release-manager/dist/update/apply-payload.d.ts.map +0 -1
  228. package/release-manager/dist/update/apply-payload.js.map +0 -1
  229. package/release-manager/dist/update/atomic-file.d.ts +0 -35
  230. package/release-manager/dist/update/atomic-file.d.ts.map +0 -1
  231. package/release-manager/dist/update/atomic-file.js.map +0 -1
  232. package/release-manager/dist/update/bootstrap-executor.d.ts +0 -21
  233. package/release-manager/dist/update/bootstrap-executor.d.ts.map +0 -1
  234. package/release-manager/dist/update/bootstrap-executor.js.map +0 -1
  235. package/release-manager/dist/update/bootstrap-protocol.d.ts +0 -56
  236. package/release-manager/dist/update/bootstrap-protocol.d.ts.map +0 -1
  237. package/release-manager/dist/update/bootstrap-protocol.js.map +0 -1
  238. package/release-manager/dist/update/channel-metadata.d.ts +0 -28
  239. package/release-manager/dist/update/channel-metadata.d.ts.map +0 -1
  240. package/release-manager/dist/update/channel-metadata.js.map +0 -1
  241. package/release-manager/dist/update/channel-promotion.d.ts +0 -39
  242. package/release-manager/dist/update/channel-promotion.d.ts.map +0 -1
  243. package/release-manager/dist/update/channel-promotion.js +0 -55
  244. package/release-manager/dist/update/channel-promotion.js.map +0 -1
  245. package/release-manager/dist/update/console-surface.d.ts +0 -19
  246. package/release-manager/dist/update/console-surface.d.ts.map +0 -1
  247. package/release-manager/dist/update/console-surface.js.map +0 -1
  248. package/release-manager/dist/update/data-compatibility.d.ts +0 -35
  249. package/release-manager/dist/update/data-compatibility.d.ts.map +0 -1
  250. package/release-manager/dist/update/data-compatibility.js +0 -45
  251. package/release-manager/dist/update/data-compatibility.js.map +0 -1
  252. package/release-manager/dist/update/install-layout.d.ts +0 -105
  253. package/release-manager/dist/update/install-layout.d.ts.map +0 -1
  254. package/release-manager/dist/update/install-layout.js.map +0 -1
  255. package/release-manager/dist/update/product-identity.d.ts +0 -70
  256. package/release-manager/dist/update/product-identity.d.ts.map +0 -1
  257. package/release-manager/dist/update/product-identity.js.map +0 -1
  258. package/release-manager/dist/update/release-asset-manifest.d.ts +0 -31
  259. package/release-manager/dist/update/release-asset-manifest.d.ts.map +0 -1
  260. package/release-manager/dist/update/release-asset-manifest.js.map +0 -1
  261. package/release-manager/dist/update/release-identity.d.ts +0 -33
  262. package/release-manager/dist/update/release-identity.d.ts.map +0 -1
  263. package/release-manager/dist/update/release-identity.js.map +0 -1
  264. package/release-manager/dist/update/release-manager-authority.d.ts +0 -39
  265. package/release-manager/dist/update/release-manager-authority.d.ts.map +0 -1
  266. package/release-manager/dist/update/release-manager-authority.js.map +0 -1
  267. package/release-manager/dist/update/release-manager.d.ts +0 -156
  268. package/release-manager/dist/update/release-manager.d.ts.map +0 -1
  269. package/release-manager/dist/update/release-manager.js.map +0 -1
  270. package/release-manager/dist/update/release-metadata-publisher.d.ts +0 -199
  271. package/release-manager/dist/update/release-metadata-publisher.d.ts.map +0 -1
  272. package/release-manager/dist/update/release-metadata-publisher.js +0 -478
  273. package/release-manager/dist/update/release-metadata-publisher.js.map +0 -1
  274. package/release-manager/dist/update/release-metadata-source.d.ts +0 -85
  275. package/release-manager/dist/update/release-metadata-source.d.ts.map +0 -1
  276. package/release-manager/dist/update/release-metadata-source.js.map +0 -1
  277. package/release-manager/dist/update/release-metadata.d.ts +0 -60
  278. package/release-manager/dist/update/release-metadata.d.ts.map +0 -1
  279. package/release-manager/dist/update/release-metadata.js.map +0 -1
  280. package/release-manager/dist/update/release-policy.d.ts +0 -51
  281. package/release-manager/dist/update/release-policy.d.ts.map +0 -1
  282. package/release-manager/dist/update/release-policy.js.map +0 -1
  283. package/release-manager/dist/update/rollback-policy.d.ts +0 -56
  284. package/release-manager/dist/update/rollback-policy.d.ts.map +0 -1
  285. package/release-manager/dist/update/rollback-policy.js +0 -61
  286. package/release-manager/dist/update/rollback-policy.js.map +0 -1
  287. package/release-manager/dist/update/transaction-journal.d.ts +0 -212
  288. package/release-manager/dist/update/transaction-journal.d.ts.map +0 -1
  289. package/release-manager/dist/update/transaction-journal.js.map +0 -1
  290. package/release-manager/dist/update/trust-metadata.d.ts +0 -55
  291. package/release-manager/dist/update/trust-metadata.d.ts.map +0 -1
  292. package/release-manager/dist/update/trust-metadata.js.map +0 -1
  293. package/release-manager/dist/update/trust-root-provisioning.d.ts +0 -99
  294. package/release-manager/dist/update/trust-root-provisioning.d.ts.map +0 -1
  295. package/release-manager/dist/update/trust-root-provisioning.js.map +0 -1
  296. package/release-manager/dist/update/update-history.d.ts +0 -46
  297. package/release-manager/dist/update/update-history.d.ts.map +0 -1
  298. package/release-manager/dist/update/update-history.js +0 -123
  299. package/release-manager/dist/update/update-history.js.map +0 -1
  300. package/release-manager/dist/utils/config-file-io.d.ts +0 -34
  301. package/release-manager/dist/utils/config-file-io.d.ts.map +0 -1
  302. package/release-manager/dist/utils/config-file-io.js.map +0 -1
  303. package/release-manager/dist/utils/env.d.ts +0 -94
  304. package/release-manager/dist/utils/env.d.ts.map +0 -1
  305. package/release-manager/dist/utils/env.js.map +0 -1
  306. package/release-manager/dist/utils/logger.d.ts +0 -15
  307. package/release-manager/dist/utils/logger.d.ts.map +0 -1
  308. package/release-manager/dist/utils/logger.js.map +0 -1
  309. package/release-manager/dist/utils/workspace-divergence.d.ts +0 -36
  310. package/release-manager/dist/utils/workspace-divergence.d.ts.map +0 -1
  311. package/release-manager/dist/utils/workspace-divergence.js.map +0 -1
@@ -1,111 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * OwnerDecisionCard — PRI-629 统一 Owner Inbox 的决策卡(evaluator/rollout)。
4
- *
5
- * 第一层只回答 Owner 关心的问题 (SPEC §26): 发生了什么 / 为什么找我 /
6
- * 机器建议 / 可执行动作与后果。taskId / repairIteration / reasonCode 等
7
- * 实现细节收纳在折叠的高级诊断里。动作经 resolveOwnerDecision 服务端重读
8
- * durable facts — stale → 409,由本组件以可理解文案呈现并触发刷新。
9
- */
10
- import { useState } from "react";
11
- import { Link } from "react-router-dom";
12
- import { useTranslation } from "react-i18next";
13
- import { toast } from "sonner";
14
- import { resolveOwnerDecision } from "../../api.js";
15
- export function OwnerDecisionCard({ item, onResolved, governanceReady = true, actionsLockedReason, }) {
16
- const { t } = useTranslation();
17
- const [actionLoading, setActionLoading] = useState(null);
18
- const [instruction, setInstruction] = useState("");
19
- const [showInstruction, setShowInstruction] = useState(false);
20
- const [showAdvanced, setShowAdvanced] = useState(false);
21
- const [partialEvidenceAcknowledged, setPartialEvidenceAcknowledged] = useState(false);
22
- const isTaskDecision = item.kind === "evaluator_review" || item.kind === "rollout_review";
23
- const canAccept = item.allowedActions.includes("accept_current");
24
- const canRevise = item.allowedActions.includes("revise_once");
25
- const canReject = item.allowedActions.includes("reject_current");
26
- const requiresPartialAcknowledgement = item.review?.capability.acceptRequirement.kind === "acknowledge_partial_evidence";
27
- const evidenceUnavailable = item.evidenceUnavailableReason !== undefined;
28
- // PRI-798 P1-2: when accept is unavailable the copy must name the actual
29
- // reason — the adversarial hard gate, a missing activation candidate, or
30
- // insufficient review evidence are different situations with different next
31
- // actions. Discriminate on the structured reason codes, never on !canAccept.
32
- const acceptBlockedCopy = (() => {
33
- const acceptRequirement = item.review?.capability.acceptRequirement;
34
- if (acceptRequirement?.kind === "forbidden" &&
35
- (acceptRequirement.reasonCode === "adversarial_hard_gate_failed" ||
36
- acceptRequirement.reasonCode === "adversarial_hard_gate_not_passed")) {
37
- return t("pages.focus.ownerDecision.acceptBlockedHardGate");
38
- }
39
- if (item.reasonCode === "rollout_activation_candidate_unresolved") {
40
- return t("pages.focus.ownerDecision.acceptBlockedNoCandidate");
41
- }
42
- return t("pages.focus.ownerDecision.acceptBlockedGeneric");
43
- })();
44
- async function handleAction(action) {
45
- if (action === "revise_once" && showInstruction && instruction.trim().length === 0) {
46
- // 指导为空也可以提交 — instruction 是可选的;这里仅在展开输入后要求非空确认
47
- // (避免误提交空指导),Owner 可收起输入直接提交。
48
- toast.error(t("pages.focus.ownerDecision.instructionRequired"));
49
- return;
50
- }
51
- setActionLoading(action);
52
- try {
53
- const response = await resolveOwnerDecision(item.taskId, {
54
- action,
55
- reviewKey: item.reviewKey,
56
- expectedRevisionEpoch: item.expectedRevisionEpoch,
57
- expectedSourceRunId: item.expectedSourceRunId,
58
- expectedSourceArtifactId: item.expectedSourceArtifactId,
59
- expectedSourceArtifactHash: item.expectedSourceArtifactHash,
60
- expectedEvidenceDigest: item.expectedEvidenceDigest ?? "",
61
- ...(action === "accept_current" && requiresPartialAcknowledgement && partialEvidenceAcknowledged
62
- ? { acknowledgement: { kind: "partial_evidence", acknowledged: true } }
63
- : {}),
64
- ...(action === "revise_once" && instruction.trim().length > 0
65
- ? { ownerInstruction: instruction.trim() }
66
- : { ownerInstruction: null }),
67
- });
68
- if (!response.success) {
69
- if (response.error === "stale_owner_decision") {
70
- toast.error(t("pages.focus.ownerDecision.staleError"));
71
- }
72
- else if (response.error === "already_resolved") {
73
- toast.info(t("pages.focus.ownerDecision.alreadyResolved"));
74
- }
75
- else {
76
- toast.error(response.error ?? t("pages.focus.ownerDecision.actionFailed"));
77
- }
78
- onResolved();
79
- return;
80
- }
81
- toast.success(t("pages.focus.ownerDecision.resolved"));
82
- onResolved();
83
- }
84
- catch {
85
- toast.error(t("pages.focus.ownerDecision.actionFailed"));
86
- }
87
- finally {
88
- setActionLoading(null);
89
- }
90
- }
91
- const kindLabel = item.kind === "rollout_review"
92
- ? t("pages.focus.ownerDecision.kindRollout")
93
- : item.kind === "activation_approval"
94
- ? t("pages.focus.ownerDecision.kindApproval")
95
- : item.kind === "rulecode_decision"
96
- ? t("pages.focus.ownerDecision.kindRulecode")
97
- : t("pages.focus.ownerDecision.kindEvaluator");
98
- return (_jsxs("article", { className: "bg-panel border border-line rounded-[6px] p-4 mb-3", "data-testid": `owner-decision-${item.taskId}`, children: [_jsxs("div", { className: "flex items-start justify-between gap-3 mb-2", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-ink text-[14px] font-medium leading-snug", children: item.title }), _jsx("div", { className: "mt-1 text-ink-4 text-[11px] font-mono uppercase tracking-[0.08em]", children: kindLabel })] }), item.legacy && (_jsx("span", { className: "shrink-0 text-ink-4 border border-line rounded-[2px] px-[7px] py-[3px] text-[10.5px] font-mono", children: t("pages.focus.ownerDecision.legacyBadge") }))] }), _jsx("p", { className: "text-ink-2 text-[13px] leading-relaxed mb-2", children: item.summary }), item.review?.brief.kind === "evaluator" && (_jsxs("div", { className: "mb-3 grid gap-2 text-[12.5px] leading-relaxed", children: [item.review.brief.principle?.statement && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.principleLabel") }), " ", item.review.brief.principle.statement] })), item.review.brief.implementation?.summary && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.implementationLabel") }), " ", item.review.brief.implementation.summary] })), (item.review.brief.concerns?.length ?? 0) > 0 && (_jsxs("p", { className: "text-amber", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.concernLabel") }), " ", item.review.brief.concerns?.[0]] })), (item.review.brief.qualityChecklist?.items?.length ?? 0) > 0 && (_jsxs("div", { className: "mt-1 rounded-[3px] border border-line bg-surface-2 p-2", "data-testid": `owner-quality-checklist-${item.taskId}`, children: [_jsx("div", { className: "font-mono text-[10.5px] uppercase tracking-[0.06em] text-ink-3 mb-1", children: t("pages.focus.ownerDecision.qualityChecklistLabel") }), _jsx("ul", { className: "grid gap-0.5", children: item.review.brief.qualityChecklist?.items.map((qItem) => (_jsxs("li", { className: "flex items-start gap-1.5 text-[12px]", children: [_jsx("span", { className: qItem.pass ? "text-emerald" : "text-amber", "aria-hidden": "true", children: qItem.pass ? "✓" : "!" }), _jsx("span", { className: "sr-only", children: qItem.pass ? t("pages.focus.ownerDecision.qualityCheckStatus.passed") : t("pages.focus.ownerDecision.qualityCheckStatus.failed") }), _jsxs("span", { className: "text-ink-2", children: [_jsx("span", { className: "font-medium", children: t(`pages.focus.ownerDecision.qualityCheck.${qItem.id}`) }), " ", qItem.note] })] }, qItem.id))) })] })), item.review.brief.formationEvidence && (_jsxs("div", { className: "mt-1 rounded-[3px] border border-line bg-surface-2 p-2", "data-testid": `owner-formation-evidence-${item.taskId}`, children: [_jsx("div", { className: "font-mono text-[10.5px] uppercase tracking-[0.06em] text-ink-3 mb-1", children: t("pages.focus.ownerDecision.formationLabel") }), item.review.brief.formationEvidence.sourcePainId ? (_jsxs("p", { className: "text-ink-2", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.formationPainLabel") }), " ", _jsx("span", { className: "font-mono text-[11.5px]", children: item.review.brief.formationEvidence.sourcePainId })] })) : null, item.review.brief.formationEvidence.diagnosis?.summary && (_jsxs("p", { className: "text-ink-2", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.formationDiagnosisLabel") }), " ", item.review.brief.formationEvidence.diagnosis.summary] })), item.review.brief.formationEvidence.diagnosis?.rootCause && (_jsxs("p", { className: "text-ink-2", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.formationRootCauseLabel") }), " ", item.review.brief.formationEvidence.diagnosis.rootCause] })), (item.review.brief.formationEvidence.diagnosis?.evidence.length ?? 0) > 0 && (_jsxs("div", { children: [_jsx("span", { className: "font-medium text-ink-2", children: t("pages.focus.ownerDecision.formationEvidenceLabel") }), _jsx("ul", { className: "mt-0.5 grid gap-0.5 text-[12px] text-ink-3", children: item.review.brief.formationEvidence.diagnosis?.evidence.slice(0, 3).map((row, index) => (_jsxs("li", { children: [_jsx("span", { className: "font-mono text-[11px]", children: row.sourceRef }), " ", row.note] }, `${row.sourceRef}-${index}`))) })] })), !item.review.brief.formationEvidence.diagnosis && (_jsx("p", { className: "text-ink-3", children: t("pages.focus.ownerDecision.formationUnavailableNote") }))] }))] })), item.review && (_jsxs("div", { className: "mb-2 flex flex-wrap items-center gap-2 text-[10.5px] font-mono uppercase tracking-[0.06em]", children: [_jsx("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: t(`pages.focus.ownerDecision.evidence.${item.review.evidence.completeness}`) }), _jsxs("details", { "data-testid": `owner-checks-${item.taskId}`, children: [_jsx("summary", { className: "cursor-pointer text-ink-4 hover:text-ink-3", children: t("pages.focus.ownerDecision.checksDisclosure") }), _jsx("div", { className: "mt-1 flex flex-wrap gap-2", children: item.review.evidence.deterministicChecks.map(check => (_jsxs("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: [check.check, ": ", check.status] }, check.check))) })] })] })), item.machineRecommendation && (_jsxs("p", { className: "text-ink-3 text-[12.5px] mb-1", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.machineRecommendationLabel") }), " ", item.machineRecommendation, item.score !== undefined && _jsx("span", { className: "font-mono ml-1", children: item.score.toFixed(2) })] })), item.kind === "rollout_review" && (_jsx("p", { className: "text-ink-4 text-[12px] mb-1", children: t("pages.focus.ownerDecision.rolloutSafetyNote") })), evidenceUnavailable ? (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: t("pages.focus.ownerDecision.evidenceUnavailable") }), _jsx(Link, { to: `/failed-tasks?taskId=${encodeURIComponent(item.taskId)}`, "data-testid": `owner-evidence-recover-${item.taskId}`, className: "mt-2 inline-flex items-center border border-line text-ink bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.ownerDecision.goRecoverCta") })] })) : isTaskDecision ? (_jsxs(_Fragment, { children: [showInstruction && (_jsxs("div", { className: "mt-2 mb-2", children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("pages.focus.ownerDecision.instructionLabel") }), _jsx("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value.slice(0, 500)), "data-testid": `owner-instruction-${item.taskId}`, placeholder: t("pages.focus.ownerDecision.instructionPlaceholder"), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[64px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov" })] })), requiresPartialAcknowledgement && (_jsxs("label", { className: "mt-2 mb-1 flex items-start gap-2 text-[12px] text-ink-3", children: [_jsx("input", { type: "checkbox", checked: partialEvidenceAcknowledged, onChange: (event) => setPartialEvidenceAcknowledged(event.target.checked), "data-testid": `owner-partial-evidence-ack-${item.taskId}`, className: "mt-0.5" }), _jsx("span", { children: t("pages.focus.ownerDecision.partialEvidenceAcknowledgement") })] })), !governanceReady && actionsLockedReason && (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", "data-testid": `owner-actions-locked-${item.taskId}`, children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: actionsLockedReason }), _jsx(Link, { to: "/settings", "data-testid": `owner-actions-locked-settings-${item.taskId}`, className: "mt-2 inline-flex items-center border border-line text-ink bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.ownerDecision.goSettingsCta") })] })), _jsxs("div", { className: "flex flex-wrap gap-2 mt-3", children: [canAccept && (_jsx("button", { type: "button", onClick: () => handleAction("accept_current"), disabled: !governanceReady || actionLoading !== null || (requiresPartialAcknowledgement && !partialEvidenceAcknowledged), "data-testid": `owner-accept-${item.taskId}`, className: "inline-flex items-center border border-gov text-gov bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: actionLoading === "accept_current" ? t("common.loading") : t("pages.focus.ownerDecision.acceptCurrent") })), canRevise && (_jsx("button", { type: "button", onClick: () => {
99
- if (!showInstruction) {
100
- setShowInstruction(true);
101
- return;
102
- }
103
- void handleAction("revise_once");
104
- }, disabled: !governanceReady || actionLoading !== null, "data-testid": `owner-revise-${item.taskId}`, className: "inline-flex items-center border border-line text-ink bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: actionLoading === "revise_once" ? t("common.loading") : t("pages.focus.ownerDecision.reviseOnce") })), canReject && (_jsx("button", { type: "button", onClick: () => handleAction("reject_current"), disabled: !governanceReady || actionLoading !== null, "data-testid": `owner-reject-${item.taskId}`, className: "inline-flex items-center border border-danger text-danger bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-danger/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: actionLoading === "reject_current" ? t("common.loading") : t("pages.focus.ownerDecision.rejectCurrent") }))] }), _jsx("div", { className: "mt-2 text-ink-4 text-[11.5px] leading-relaxed", children: canAccept
105
- ? t("pages.focus.ownerDecision.actionConsequence")
106
- : acceptBlockedCopy }), _jsxs("button", { type: "button", onClick: () => setShowAdvanced(!showAdvanced), className: "mt-2 text-ink-4 text-[11px] font-mono uppercase tracking-[0.08em] hover:text-ink-3", "data-testid": `owner-advanced-toggle-${item.taskId}`, children: [showAdvanced ? "▾" : "▸", " ", t("pages.focus.ownerDecision.advanced")] }), showAdvanced && (_jsxs("dl", { className: "mt-2 grid gap-1 text-[11.5px] font-mono text-ink-4", children: [_jsxs("div", { children: ["taskId: ", item.taskId] }), _jsxs("div", { children: ["reasonCode: ", item.reasonCode] }), _jsxs("div", { children: ["reviewKey: ", item.reviewKey.slice(0, 24), "\u2026"] }), _jsxs("div", { children: ["epoch: ", item.expectedRevisionEpoch] }), item.review?.brief.requiredChanges.map((change, index) => (_jsxs("div", { children: ["requiredChange: ", change] }, `${change}-${index}`))), item.review?.evidence.items.map((evidence, index) => (_jsxs("div", { children: [evidence.evidenceClass, "/", evidence.label, ": ", evidence.value] }, `${evidence.label}-${index}`))), item.review?.brief.kind === "evaluator" && item.review.brief.formationEvidence && (_jsxs(_Fragment, { children: [_jsxs("div", { children: ["dreamerArtifact: ", item.review.brief.formationEvidence.provenance.sourceDreamerArtifactId] }), item.review.brief.formationEvidence.provenance.sourceDiagnosisArtifactId && (_jsxs("div", { children: ["diagnosisArtifact: ", item.review.brief.formationEvidence.provenance.sourceDiagnosisArtifactId] })), item.review.brief.formationEvidence.notes.map((note, index) => (_jsxs("div", { children: ["formationNote: ", note] }, `${note}-${index}`)))] }))] }))] })) : (_jsxs("div", { className: "mt-2", children: [_jsx("p", { className: "text-ink-4 text-[12px] mb-2", children: item.kind === "activation_approval"
107
- ? t("pages.focus.ownerDecision.approvalHint")
108
- : t("pages.focus.ownerDecision.rulecodeHint") }), item.kind === "activation_approval" ? (_jsx(Link, { to: item.principleId !== undefined
109
- ? `/principles/${encodeURIComponent(item.principleId)}`
110
- : "/principles", "data-testid": `go-approvals-${item.taskId}`, className: "inline-flex items-center border border-gov text-gov bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/5 transition-colors", children: t("pages.focus.ownerDecision.goApprovalsCta") })) : (_jsx(Link, { to: `/activation?activationId=${encodeURIComponent(item.taskId)}`, "data-testid": `go-activation-${item.taskId}`, className: "inline-flex items-center border border-gov text-gov bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/5 transition-colors", children: t("pages.focus.ownerDecision.goActivationCta") }))] }))] }));
111
- }
@@ -1,19 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- export type OwnerWorkItemKind = 'prompt' | 'rule' | 'promotion' | 'revision' | 'validation' | 'binding' | 'archive' | 'approval' | 'unknown';
3
- export interface OwnerWorkItem {
4
- key: string;
5
- title: string;
6
- kind: OwnerWorkItemKind;
7
- summary: string;
8
- reference?: string;
9
- content: ReactNode;
10
- }
11
- /** Presentation only: list grouping never changes an action's identity or authority. */
12
- export declare function OwnerWorkbench({ items, completed, uncertain }: {
13
- items: OwnerWorkItem[];
14
- completed: {
15
- key: string;
16
- message: string;
17
- } | null;
18
- uncertain: boolean;
19
- }): import("react").JSX.Element;
@@ -1,75 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef } from 'react';
3
- import { useSearchParams } from 'react-router-dom';
4
- import { useTranslation } from 'react-i18next';
5
- import { Archive, CircleHelp, ClipboardCheck, Code2, FilePenLine, FlaskConical, Link2, MessageSquareText, ShieldCheck } from 'lucide-react';
6
- // Type describes the decision, not an inferred urgency or permission.
7
- const KIND_PRESENTATION = {
8
- prompt: { icon: MessageSquareText, label: 'promptReview', style: 'border-gov/30 bg-gov/10 text-gov' },
9
- rule: { icon: Code2, label: 'ruleReview', style: 'border-ink-3/30 bg-ink-3/10 text-ink-2' },
10
- promotion: { icon: ShieldCheck, label: 'rulePromotion', style: 'border-amber/30 bg-amber/10 text-ink-2' },
11
- revision: { icon: FilePenLine, label: 'revisionDecision', style: 'border-amber/30 text-ink-2' },
12
- validation: { icon: FlaskConical, label: 'validationReview', style: 'border-gov/30 text-gov' },
13
- binding: { icon: Link2, label: 'bindingReview', style: 'border-gov/30 text-gov' },
14
- archive: { icon: Archive, label: 'archiveReview', style: 'border-line bg-surface text-ink-3' },
15
- approval: { icon: ClipboardCheck, label: 'approvalMaterialReview', style: 'border-line text-ink-2' },
16
- unknown: { icon: CircleHelp, label: 'unknownReview', style: 'border-line text-ink-3' },
17
- };
18
- function WorkItemType({ kind }) {
19
- const { t } = useTranslation();
20
- const { icon: Icon, label, style } = KIND_PRESENTATION[kind];
21
- return _jsxs("span", { "data-testid": "owner-work-type", "data-kind": kind, className: `inline-flex max-w-full items-center gap-1.5 rounded-[4px] border px-2 py-1 text-[11px] font-medium leading-relaxed ${style}`, children: [_jsx(Icon, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0", strokeWidth: 1.75 }), t(`pages.focus.workbench.${label}`)] });
22
- }
23
- /** Presentation only: list grouping never changes an action's identity or authority. */
24
- export function OwnerWorkbench({ items, completed, uncertain }) {
25
- const { t } = useTranslation();
26
- const [params, setParams] = useSearchParams();
27
- const selectedKey = params.get('review') ?? '';
28
- const selected = items.find(item => item.key === selectedKey);
29
- const heading = useRef(null);
30
- const list = useRef(null);
31
- const lastSelected = useRef('');
32
- const listScroll = useRef(0);
33
- // A deep link can arrive before the items do. `focusKey` only becomes the
34
- // selection once the item exists, so the effect re-runs when it appears
35
- // without stealing focus on every data refresh.
36
- const focusKey = selected ? selectedKey : '';
37
- useEffect(() => {
38
- if (focusKey) {
39
- heading.current?.focus({ preventScroll: true });
40
- const reading = heading.current?.closest('[data-testid="owner-work-reading"]');
41
- if (reading && (reading.getBoundingClientRect().top < 0 || reading.getBoundingClientRect().top > window.innerHeight - 100))
42
- reading.scrollIntoView({ block: 'start' });
43
- const current = list.current?.querySelector('[aria-current="true"]');
44
- if (current && list.current && list.current.scrollHeight > list.current.clientHeight) {
45
- list.current.scrollTop = Math.max(0, current.offsetTop - list.current.offsetTop - 24);
46
- }
47
- }
48
- else if (selectedKey) {
49
- heading.current?.focus({ preventScroll: true });
50
- }
51
- else if (lastSelected.current && list.current) {
52
- list.current.scrollTop = listScroll.current;
53
- const previous = Array.from(list.current.querySelectorAll('[data-item-key]')).find(button => button.dataset.itemKey === lastSelected.current);
54
- previous?.focus({ preventScroll: true });
55
- if (previous && (previous.getBoundingClientRect().top < 0 || previous.getBoundingClientRect().bottom > window.innerHeight))
56
- previous.scrollIntoView({ block: 'nearest' });
57
- }
58
- }, [focusKey, selectedKey]);
59
- function choose(key) {
60
- if (!key && selectedKey) {
61
- lastSelected.current = selectedKey;
62
- listScroll.current = list.current?.scrollTop ?? 0;
63
- }
64
- const next = new URLSearchParams(params);
65
- if (key)
66
- next.set('review', key);
67
- else
68
- next.delete('review');
69
- setParams(next, { preventScrollReset: true });
70
- }
71
- const completedHere = completed?.key === selectedKey ? completed : null;
72
- const selectedIndex = items.findIndex(item => item.key === selectedKey);
73
- const nextItem = selectedIndex >= 0 ? items[selectedIndex + 1] : undefined;
74
- return _jsxs("section", { className: "owner-workbench", "data-testid": "owner-workbench", children: [_jsxs("nav", { ref: list, tabIndex: -1, className: `owner-work-list ${selected ? 'owner-work-list-selected' : ''}`, "aria-label": t('pages.focus.workbench.list'), children: [_jsxs("div", { className: "mb-3 flex items-baseline justify-between gap-3", children: [_jsx("h2", { className: "text-[15px] font-medium text-ink", children: t('pages.focus.workbench.list') }), _jsx("span", { className: "text-[12px] text-ink-4", children: t('pages.focus.workbench.count', { count: items.length }) })] }), items.length === 0 && _jsx("p", { className: "text-sm leading-relaxed text-ink-3", children: t(uncertain ? 'pages.focus.workbench.uncertain' : 'pages.focus.workbench.empty') }), _jsx("ol", { className: "space-y-2", children: items.map(item => _jsx("li", { children: _jsxs("button", { type: "button", onClick: () => choose(item.key), "aria-current": selected?.key === item.key ? 'true' : undefined, "data-testid": "owner-work-item", "data-item-key": item.key, className: `w-full rounded-[6px] border px-4 py-4 text-left transition-colors focus-visible:outline-2 focus-visible:outline-gov ${selected?.key === item.key ? 'border-gov bg-gov/5' : 'border-line bg-panel hover:border-gov/50'}`, children: [_jsx("span", { className: "mb-3 block", children: _jsx(WorkItemType, { kind: item.kind }) }), _jsx("span", { className: "block text-[14px] font-medium leading-relaxed text-ink break-words", children: item.title }), _jsx("span", { className: "mt-2 block text-[12.5px] leading-relaxed text-ink-3 line-clamp-2", children: item.summary }), item.reference && items.some(other => other.key !== item.key && other.title === item.title && other.summary === item.summary) && _jsx("span", { className: "mt-2 block break-all font-mono text-[11px] text-ink-4", children: item.reference })] }) }, item.key)) })] }), _jsx("div", { className: "owner-work-reading min-w-0", "data-testid": "owner-work-reading", children: selected ? _jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "mb-5 text-[13px] text-gov underline underline-offset-4", onClick: () => choose(''), children: t('pages.focus.workbench.back') }), _jsx("div", { className: "mb-3", children: _jsx(WorkItemType, { kind: selected.kind }) }), _jsx("h2", { ref: heading, tabIndex: -1, className: "mb-6 text-[22px] font-semibold leading-snug text-ink break-words", children: selected.title }), _jsx("div", { children: selected.content }, selected.key), _jsxs("footer", { className: "mt-7 border-t border-line pt-5", children: [_jsx("p", { className: "mb-3 text-[12.5px] text-ink-3", children: t('pages.focus.workbench.readingEnd') }), nextItem && _jsx("button", { type: "button", className: "text-[13px] text-gov underline underline-offset-4", onClick: () => choose(nextItem.key), children: t('pages.focus.workbench.next') })] })] }) : _jsxs("div", { className: "py-10 text-ink-3", children: [_jsx("h2", { ref: heading, tabIndex: -1, className: "mb-3 text-[22px] font-medium text-ink", children: t(completedHere ? 'pages.focus.workbench.completed' : selectedKey ? 'pages.focus.workbench.notCurrent' : 'pages.focus.workbench.startTitle') }), _jsx("p", { role: completedHere ? 'status' : undefined, className: "max-w-[440px] text-[14px] leading-relaxed", children: completedHere?.message ?? t(selectedKey ? 'pages.focus.workbench.notCurrentBody' : 'pages.focus.workbench.startBody') }), items[0] && _jsx("button", { type: "button", className: "mt-6 rounded-[4px] border border-gov bg-gov px-4 py-2.5 text-sm text-paper", onClick: () => choose(items[0].key), children: t(completedHere ? 'pages.focus.workbench.next' : 'pages.focus.workbench.start') })] }) })] });
75
- }
@@ -1,34 +0,0 @@
1
- import type { RuleBindingQueueItem } from '../../../shared/rule-candidate-binding-contract.js';
2
- export type RuleBindingCardState = 'awaiting_owner' | 'bound_generating' | 'bound_blocked' | 'bound_advanced' | 'bound_not_built' | 'bound_ambiguous' | 'revoked' | 'attention';
3
- /** ERR-106: exhaustive display map over the card state union — no default branch. */
4
- export declare const RULE_BINDING_CARD_STATE_KEY: Record<RuleBindingCardState, string>;
5
- export declare const RULE_BINDING_CARD_STATE_CLASS: Record<RuleBindingCardState, string>;
6
- export declare function deriveRuleBindingCardState(item: RuleBindingQueueItem): RuleBindingCardState;
7
- export interface RuleBindingPainGroup {
8
- key: string;
9
- pain: RuleBindingQueueItem['pain'];
10
- items: RuleBindingQueueItem[];
11
- }
12
- /** Group by canonical pain id; a missing pain id gets its own per-candidate
13
- * group so unattributable candidates never vanish into someone else's group. */
14
- export declare function groupRuleBindingQueue(items: RuleBindingQueueItem[]): RuleBindingPainGroup[];
15
- /** The resume action may only appear when the real backend says ready AND the
16
- * chain is not currently running — a revision during an active run would be
17
- * a fake retry, not the bounded source revision. */
18
- export declare function canOfferRuleBindingResume(item: RuleBindingQueueItem): boolean;
19
- /**
20
- * PRI-1048 R6 #4: the source-correction entry applies when the bounded
21
- * source-correction budget is available on a bound+blocked chain — the shape
22
- * where the binding revision budget is typically already spent (the 52d
23
- * production candidate). Real eligibility is resolved server-side
24
- * (previewRuleSourceCorrection); click-time authority is reviseRuleSourceOnce.
25
- */
26
- export declare function canOfferSourceCorrection(item: Pick<RuleBindingQueueItem, 'binding' | 'generation' | 'sourceCorrection'>): boolean;
27
- /** Model-synthesized fallback sources must stay localized (CodeRabbit PRI-1048:
28
- * `unknown` previously fell through to raw English in the zh-CN group header). */
29
- export declare const PAIN_SOURCE_KEY: Record<string, string>;
30
- /** Inline in Governance Focus; assignment, rule approval and live promotion remain separate. */
31
- export declare function RuleCandidateBindingPanel({ candidateId, onChanged }?: {
32
- candidateId?: string;
33
- onChanged?: () => void;
34
- }): import("react").JSX.Element | null;
@@ -1,298 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from 'react';
3
- import { useTranslation } from 'react-i18next';
4
- import { Link } from 'react-router-dom';
5
- import { fetchRuleBindingQueue, fetchRuleBindingReview, mutateRuleBinding, reviseRuleBindingOnce, correctRuleSource } from '../../api.js';
6
- import { splitReadingTitleBody } from '../../utils/reading-layout.js';
7
- /**
8
- * PRI-1048 治理焦点「规则的正式原则归属」队列。
9
- * 按痛苦信号分组的有界卡片列表;每张卡默认回答三问:
10
- * 这是哪次反馈 / 现在卡在哪 / 我要做什么。技术 ID 与原始 JSON 只进「技术详情」。
11
- * 归属、规则审批、激活三权分立不变(文案见 separate/declaration)。
12
- */
13
- /** Collapsed first screen shows at most this many pain groups. */
14
- const COLLAPSED_GROUP_LIMIT = 3;
15
- /** ERR-106: exhaustive display map over the card state union — no default branch. */
16
- export const RULE_BINDING_CARD_STATE_KEY = {
17
- awaiting_owner: 'pages.focus.ruleBinding.stateAwaitingOwner',
18
- bound_generating: 'pages.focus.ruleBinding.stateBoundGenerating',
19
- bound_blocked: 'pages.focus.ruleBinding.stateBoundBlocked',
20
- bound_advanced: 'pages.focus.ruleBinding.stateBoundAdvanced',
21
- bound_not_built: 'pages.focus.ruleBinding.stateBoundNotBuilt',
22
- bound_ambiguous: 'pages.focus.ruleBinding.stateBoundAmbiguous',
23
- revoked: 'pages.focus.ruleBinding.stateRevoked',
24
- attention: 'pages.focus.ruleBinding.stateAttention',
25
- };
26
- export const RULE_BINDING_CARD_STATE_CLASS = {
27
- awaiting_owner: 'border-gov/40 text-gov',
28
- bound_generating: 'border-green/40 text-green',
29
- bound_blocked: 'border-amber/45 text-amber',
30
- bound_advanced: 'border-green/40 text-green',
31
- bound_not_built: 'border-line text-ink-3',
32
- bound_ambiguous: 'border-amber/45 text-amber',
33
- revoked: 'border-line text-ink-3',
34
- attention: 'border-amber/45 text-amber',
35
- };
36
- export function deriveRuleBindingCardState(item) {
37
- switch (item.binding.status) {
38
- case 'unlinked': return 'awaiting_owner';
39
- case 'binding_revoked': return 'revoked';
40
- case 'attention': return 'attention';
41
- case 'bound':
42
- switch (item.generation?.stage) {
43
- case null:
44
- case undefined:
45
- case 'not_built': return 'bound_not_built';
46
- case 'in_progress': return 'bound_generating';
47
- case 'blocked': return 'bound_blocked';
48
- case 'advanced': return 'bound_advanced';
49
- case 'ambiguous': return 'bound_ambiguous';
50
- }
51
- }
52
- }
53
- /** Group by canonical pain id; a missing pain id gets its own per-candidate
54
- * group so unattributable candidates never vanish into someone else's group. */
55
- export function groupRuleBindingQueue(items) {
56
- const groups = new Map();
57
- for (const item of items) {
58
- const key = item.pain.painId === '' ? `candidate:${item.candidateId}` : item.pain.painId;
59
- const group = groups.get(key) ?? { key, pain: item.pain, items: [] };
60
- group.items.push(item);
61
- groups.set(key, group);
62
- }
63
- return [...groups.values()];
64
- }
65
- /** The resume action may only appear when the real backend says ready AND the
66
- * chain is not currently running — a revision during an active run would be
67
- * a fake retry, not the bounded source revision. */
68
- export function canOfferRuleBindingResume(item) {
69
- return item.binding.status === 'bound'
70
- && item.resume?.status === 'ready'
71
- && item.generation?.stage !== 'in_progress'
72
- && item.generation?.stage !== 'ambiguous';
73
- }
74
- /**
75
- * PRI-1048 R6 #4: the source-correction entry applies when the bounded
76
- * source-correction budget is available on a bound+blocked chain — the shape
77
- * where the binding revision budget is typically already spent (the 52d
78
- * production candidate). Real eligibility is resolved server-side
79
- * (previewRuleSourceCorrection); click-time authority is reviseRuleSourceOnce.
80
- */
81
- export function canOfferSourceCorrection(item) {
82
- return item.binding.status === 'bound'
83
- && item.generation?.stage === 'blocked'
84
- && item.sourceCorrection?.status === 'ready';
85
- }
86
- /** ERR-106: next-step copy and the left bar also use exhaustive maps. */
87
- const RULE_BINDING_NEXT_STEP_KEY = {
88
- awaiting_owner: 'pages.focus.ruleBinding.nextAwaitingOwner',
89
- bound_generating: 'pages.focus.ruleBinding.nextBoundGenerating',
90
- bound_blocked: 'pages.focus.ruleBinding.nextBoundBlocked',
91
- bound_advanced: 'pages.focus.ruleBinding.nextBoundAdvanced',
92
- bound_not_built: 'pages.focus.ruleBinding.nextBoundNotBuilt',
93
- bound_ambiguous: 'pages.focus.ruleBinding.nextBoundAmbiguous',
94
- revoked: 'pages.focus.ruleBinding.nextRevoked',
95
- attention: 'pages.focus.ruleBinding.nextAttention',
96
- };
97
- const RULE_BINDING_CARD_STATE_BAR = {
98
- awaiting_owner: 'bg-gov',
99
- bound_generating: 'bg-green',
100
- bound_blocked: 'bg-amber',
101
- bound_advanced: 'bg-green',
102
- bound_not_built: 'bg-line-2',
103
- bound_ambiguous: 'bg-amber',
104
- revoked: 'bg-line-2',
105
- attention: 'bg-amber',
106
- };
107
- /** Model-synthesized fallback sources must stay localized (CodeRabbit PRI-1048:
108
- * `unknown` previously fell through to raw English in the zh-CN group header). */
109
- export const PAIN_SOURCE_KEY = {
110
- unreadable: 'pages.focus.ruleBinding.sourceUnreadable',
111
- unknown: 'pages.focus.ruleBinding.sourceUnknown',
112
- manual: 'pages.focus.ruleBinding.sourceManual',
113
- tool_failure: 'pages.focus.ruleBinding.sourceToolFailure',
114
- };
115
- const STAGE_KIND_KEY = {
116
- dreamer: 'pages.focus.ruleBinding.stageDreamer',
117
- philosopher: 'pages.focus.ruleBinding.stagePhilosopher',
118
- scribe: 'pages.focus.ruleBinding.stageScribe',
119
- artificer: 'pages.focus.ruleBinding.stageArtificer',
120
- evaluator: 'pages.focus.ruleBinding.stageEvaluator',
121
- rollout_reviewer: 'pages.focus.ruleBinding.stageRolloutReviewer',
122
- };
123
- /** i18n with graceful fallback to the raw server code (visible, not dropped). */
124
- function codeText(t, prefix, code) {
125
- if (!code)
126
- return '';
127
- const key = `${prefix}.${code}`;
128
- const text = t(key);
129
- return text === key ? code : text;
130
- }
131
- function painSourceLabel(t, source) {
132
- const key = PAIN_SOURCE_KEY[source];
133
- return key ? t(key) : source;
134
- }
135
- function stageKindLabel(t, stageKind) {
136
- if (!stageKind)
137
- return null;
138
- const key = STAGE_KIND_KEY[stageKind];
139
- return key ? t(key) : stageKind;
140
- }
141
- /** Inline in Governance Focus; assignment, rule approval and live promotion remain separate. */
142
- export function RuleCandidateBindingPanel({ candidateId, onChanged } = {}) {
143
- const { t } = useTranslation();
144
- const [queue, setQueue] = useState(null);
145
- const [review, setReview] = useState(null);
146
- const [openCandidateId, setOpenCandidateId] = useState('');
147
- const [search, setSearch] = useState('');
148
- const [selectedId, setSelectedId] = useState('');
149
- const [reason, setReason] = useState('');
150
- const [busy, setBusy] = useState(false);
151
- const [message, setMessage] = useState('');
152
- const [error, setError] = useState('');
153
- const [showAllGroups, setShowAllGroups] = useState(false);
154
- useEffect(() => {
155
- let active = true;
156
- void fetchRuleBindingQueue().then(result => {
157
- if (!active)
158
- return;
159
- if (result.success)
160
- setQueue(result.data);
161
- else
162
- setError([result.error, result.nextAction].filter(Boolean).join(' ') || t('pages.focus.ruleBinding.unavailable'));
163
- });
164
- return () => { active = false; };
165
- }, [t]);
166
- async function load(candidateId, query = '') {
167
- setBusy(true);
168
- setError('');
169
- const result = await fetchRuleBindingReview(candidateId, query);
170
- if (result.success) {
171
- setReview(result.data);
172
- setOpenCandidateId(candidateId);
173
- setSelectedId('');
174
- }
175
- else
176
- setError([result.error, result.nextAction].filter(Boolean).join(' ') || t('pages.focus.ruleBinding.unavailable'));
177
- setBusy(false);
178
- }
179
- useEffect(() => { if (candidateId)
180
- void load(candidateId); }, [candidateId]);
181
- function closeReview() { setOpenCandidateId(''); setReview(null); setSearch(''); setReason(''); }
182
- async function refreshQueue() {
183
- const result = await fetchRuleBindingQueue();
184
- if (result.success) {
185
- setQueue(result.data);
186
- onChanged?.();
187
- }
188
- }
189
- async function decide(action) {
190
- if (!review)
191
- return;
192
- const target = review.eligibleTargets.find(p => p.principleId === selectedId);
193
- if (action === 'bind' && !target)
194
- return;
195
- setBusy(true);
196
- setError('');
197
- setMessage('');
198
- const requestId = crypto.randomUUID();
199
- const common = { expectedRevision: review.currentRevision, reason, requestId };
200
- const result = await mutateRuleBinding(review.candidateId, action === 'bind' && target
201
- ? { ...common, action: 'bind', resumeOnce: true, principleId: target.principleId, expectedCandidateDigest: review.candidateDigest, expectedPrincipleDigest: target.digest }
202
- : { ...common, action: 'revoke', resumeOnce: false });
203
- if (result.success) {
204
- setMessage(action === 'revoke' ? t('pages.focus.ruleBinding.revoked')
205
- : result.data.revisionStatus === 'refused' ? t('pages.focus.ruleBinding.resumeFailed') : t('pages.focus.ruleBinding.bound'));
206
- await load(review.candidateId, search);
207
- await refreshQueue();
208
- }
209
- else
210
- setError([result.error, result.nextAction].filter(Boolean).join(' ') || t('pages.focus.ruleBinding.unavailable'));
211
- setBusy(false);
212
- }
213
- /** Only reachable when the real resolver said ready (canOfferRuleBindingResume). */
214
- async function revise() {
215
- if (!review?.resume || review.resume.status !== 'ready' || review.resume.scribeTaskId === null || review.resume.taskRevisionEpoch === null)
216
- return;
217
- setBusy(true);
218
- setError('');
219
- setMessage('');
220
- const result = await reviseRuleBindingOnce(review.candidateId, {
221
- expectedBindingRevision: review.currentRevision,
222
- expectedScribeTaskId: review.resume.scribeTaskId,
223
- expectedTaskRevisionEpoch: review.resume.taskRevisionEpoch,
224
- requestId: crypto.randomUUID(),
225
- });
226
- if (result.success) {
227
- setMessage(result.data.status === 'revision_already_started'
228
- ? t('pages.focus.ruleBinding.reviseAlreadyStarted')
229
- : t('pages.focus.ruleBinding.reviseStarted'));
230
- await load(review.candidateId, search);
231
- await refreshQueue();
232
- }
233
- else
234
- setError([result.error, result.nextAction].filter(Boolean).join(' ') || t('pages.focus.ruleBinding.unavailable'));
235
- setBusy(false);
236
- }
237
- /** PRI-1048 R6 #4: only reachable when the server preview said ready
238
- * (canOfferSourceCorrection); the server re-validates every CAS input. */
239
- async function correctSource() {
240
- const preview = review?.sourceCorrection;
241
- if (!review || !preview || preview.status !== 'ready'
242
- || preview.scribeTaskId === null || preview.artificerTaskId === null
243
- || preview.scribeArtifactDigest === null || preview.expectedBindingRevision === null)
244
- return;
245
- setBusy(true);
246
- setError('');
247
- setMessage('');
248
- const result = await correctRuleSource(review.candidateId, {
249
- expectedBindingRevision: preview.expectedBindingRevision,
250
- expectedScribeTaskId: preview.scribeTaskId,
251
- expectedArtificerTaskId: preview.artificerTaskId,
252
- expectedScribeArtifactDigest: preview.scribeArtifactDigest,
253
- reason,
254
- requestId: crypto.randomUUID(),
255
- });
256
- if (result.success) {
257
- setMessage(result.data.status === 'revision_already_started'
258
- ? t('pages.focus.ruleBinding.sourceCorrectionAlreadyStarted')
259
- : t('pages.focus.ruleBinding.sourceCorrectionStarted'));
260
- await load(review.candidateId, search);
261
- await refreshQueue();
262
- }
263
- else
264
- setError([result.error, result.nextAction].filter(Boolean).join(' ') || t('pages.focus.ruleBinding.unavailable'));
265
- setBusy(false);
266
- }
267
- if ((queue === null || queue.items.length === 0) && !error)
268
- return null;
269
- const groups = groupRuleBindingQueue((queue?.items ?? []).filter(item => candidateId === undefined || item.candidateId === candidateId));
270
- const visibleGroups = showAllGroups ? groups : groups.slice(0, COLLAPSED_GROUP_LIMIT);
271
- const bound = review?.currentBinding?.action === 'bind';
272
- return _jsxs("section", { className: "mb-7 rounded border border-line p-4", "data-testid": "rule-binding-panel", "aria-label": t('pages.focus.ruleBinding.title'), children: [_jsx("h2", { className: "text-sm font-medium", children: t('pages.focus.ruleBinding.title') }), _jsx("p", { className: "mt-2 text-sm text-ink-3", children: t('pages.focus.ruleBinding.separate') }), queue && _jsx("p", { className: "mt-2 text-[13px] text-ink-3", role: "status", "data-testid": "rule-binding-counts", children: t('pages.focus.ruleBinding.countsLine', { candidates: queue.summary.candidates, painGroups: queue.summary.painGroups, bound: queue.summary.bound, unlinked: queue.summary.unlinked, blocked: queue.summary.blocked }) }), queue?.truncated && _jsx("p", { className: "mt-1 text-[12.5px] text-amber", children: t('pages.focus.ruleBinding.truncatedNote', { count: queue.items.length }) }), error && _jsx("p", { role: "alert", className: "my-2 text-amber", children: error }), message && _jsx("p", { role: "status", className: "my-2", children: message }), visibleGroups.map(group => _jsxs("div", { className: "mt-4", "data-testid": "rule-binding-pain-group", children: [_jsxs("div", { className: "border-l-2 border-line pl-3", children: [_jsxs("div", { className: "text-[13px] text-ink-2 leading-relaxed", children: [_jsx("span", { className: "font-medium text-ink", children: t('pages.focus.ruleBinding.groupPrefix') }), ' ', group.pain.text
273
- ? splitReadingTitleBody(group.pain.text).title
274
- : t('pages.focus.ruleBinding.painUnrecorded')] }), _jsxs("div", { className: "mt-0.5 text-[11.5px] text-ink-4", children: [painSourceLabel(t, group.pain.source), group.pain.createdAt ? ` · ${group.pain.createdAt.slice(0, 10)}` : '', ' · ', t('pages.focus.ruleBinding.groupCount', { count: group.items.length })] })] }), group.items.map(item => {
275
- const cardState = deriveRuleBindingCardState(item);
276
- const layout = splitReadingTitleBody(item.text);
277
- const open = openCandidateId === item.candidateId;
278
- return _jsxs("article", { className: "relative mt-3 pl-[22px] py-[14px] pr-[18px] bg-panel border border-line rounded-[6px]", "data-testid": `rule-binding-card-${item.candidateId}`, children: [_jsx("div", { className: `absolute left-0 top-0 bottom-0 w-[3px] rounded-l-[6px] ${RULE_BINDING_CARD_STATE_BAR[cardState]}` }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("span", { className: `inline-flex items-center border rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase ${RULE_BINDING_CARD_STATE_CLASS[cardState]}`, children: t(RULE_BINDING_CARD_STATE_KEY[cardState]) }), (() => {
279
- const stageLabel = stageKindLabel(t, item.generation?.stageKind ?? null);
280
- return stageLabel
281
- ? _jsxs("span", { className: "text-[11.5px] text-ink-4", children: [t('pages.focus.ruleBinding.currentStage'), stageLabel] })
282
- : null;
283
- })()] }), _jsx("div", { className: "mt-[10px] mb-1 font-semibold text-ink leading-snug", "data-testid": `rule-binding-title-${item.candidateId}`, children: layout.title }), layout.body !== null && _jsx("div", { className: "mb-2 text-[14px] leading-relaxed text-ink-2 whitespace-pre-wrap break-words", children: layout.body }), item.binding.status === 'bound' && _jsxs("div", { className: "mt-2 px-3 py-2 bg-surface/60 border-l-2 border-gov text-[13px] leading-relaxed", children: [_jsx("span", { className: "text-ink-3", children: t('pages.focus.ruleBinding.boundTo') }), ' ', _jsx("span", { className: "text-ink", children: splitReadingTitleBody(item.binding.principle.text).title }), ' · ', _jsxs("span", { className: "text-ink-4", children: [t(`principles.status${item.binding.principle.status[0]?.toUpperCase()}${item.binding.principle.status.slice(1)}`, { defaultValue: item.binding.principle.status }), " \u00B7 ", t('pages.focus.ruleBinding.version'), " ", item.binding.principle.version] }), ' · ', _jsx(Link, { to: `/principles/${item.binding.principle.principleId}`, className: "text-gov underline", children: t('pages.focus.ruleBinding.viewPrinciple') })] }), cardState === 'bound_blocked' && item.generation && _jsxs("div", { className: "mt-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `rule-binding-blocked-${item.candidateId}`, children: [t('pages.focus.ruleBinding.blockedLine', {
284
- stage: stageKindLabel(t, item.generation.stageKind) ?? '',
285
- reason: codeText(t, 'pages.focus.ruleBinding.blockReason', item.generation.reasonCode) || t('pages.focus.ruleBinding.blockReasonUnknown'),
286
- }), _jsx("div", { className: "mt-0.5 text-ink-3", children: t('pages.focus.ruleBinding.blockedNoOwnerApproval') }), item.generation.detail && _jsxs("details", { className: "mt-1 text-[11.5px]", children: [_jsx("summary", { className: "cursor-pointer select-none", children: t('pages.focus.ruleBinding.blockedDetail') }), _jsx("pre", { className: "mt-1 max-h-40 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px]", children: item.generation.detail })] })] }), cardState === 'attention' && _jsx("div", { className: "mt-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `rule-binding-attention-${item.candidateId}`, children: t('pages.focus.ruleBinding.attentionLine', { reason: item.binding.status === 'attention' ? item.binding.reason : '' }) }), _jsxs("div", { className: "mt-2 text-[12.5px] text-ink-3 leading-relaxed", "data-testid": `rule-binding-next-${item.candidateId}`, children: [_jsx("span", { className: "font-medium", children: t('pages.focus.ruleBinding.nextLabel') }), ' ', cardState === 'bound_blocked' && item.resume?.status === 'refused'
287
- ? t('pages.focus.ruleBinding.nextBoundBlockedNoResume', { reason: codeText(t, 'pages.focus.ruleBinding.resumeReason', item.resume.reason) })
288
- : t(RULE_BINDING_NEXT_STEP_KEY[cardState])] }), _jsxs("details", { className: "mt-2 text-[11.5px] text-ink-4", children: [_jsx("summary", { className: "cursor-pointer select-none", children: t('pages.focus.ruleBinding.techDetails') }), _jsxs("dl", { className: "mt-1 font-mono text-[11px] break-all", children: [_jsxs("div", { children: ["candidateId: ", item.candidateId] }), _jsxs("div", { children: ["painId: ", item.pain.painId || '—'] }), item.binding.status === 'bound' && _jsxs("div", { children: ["bindingRevision: ", item.binding.principle.revision, " \u00B7 decidedAt: ", item.binding.principle.decidedAt || '—'] }), item.resume && _jsxs("div", { children: ["resume: ", item.resume.status, item.resume.reason ? ` (${item.resume.reason})` : '', item.resume.scribeTaskId ? ` · ${item.resume.scribeTaskId}` : ''] })] })] }), _jsx("button", { type: "button", className: "mt-3 inline-flex items-center border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", disabled: busy, "aria-expanded": open, onClick: () => { if (open)
289
- closeReview();
290
- else {
291
- setSearch('');
292
- setReason('');
293
- void load(item.candidateId);
294
- } }, children: open ? t('pages.focus.ruleBinding.closeReview') : t('pages.focus.ruleBinding.openReview') }), open && review && review.candidateId === item.candidateId && _jsxs("div", { className: "mt-4 border-t border-line pt-3", children: [_jsx("h3", { className: "font-medium text-[13px]", children: t('pages.focus.ruleBinding.candidate') }), _jsx("p", { className: "mt-1 whitespace-pre-wrap text-sm", children: review.candidateText }), _jsxs("p", { className: "mt-2 text-sm", children: [t('pages.focus.ruleBinding.pain'), "\uFF1A", review.sourcePain.text ?? t('pages.focus.ruleBinding.painUnrecorded')] }), _jsxs("details", { className: "mt-2 text-sm", children: [_jsx("summary", { children: t('pages.focus.ruleBinding.evidence') }), _jsx("pre", { className: "whitespace-pre-wrap break-words", children: review.evidence })] }), bound && review.boundPrinciple && _jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-3 px-3 py-2 bg-surface/60 border-l-2 border-gov text-[13px] leading-relaxed", children: [_jsx("div", { className: "whitespace-pre-wrap", children: review.boundPrinciple.text }), _jsxs("div", { className: "mt-1 text-ink-4", children: [t('pages.focus.ruleBinding.boundSince', { revision: review.boundPrinciple.revision, date: review.boundPrinciple.decidedAt.slice(0, 10) || '—' }), " \u00B7 ", _jsx(Link, { to: `/principles/${review.boundPrinciple.principleId}`, className: "text-gov underline", children: t('pages.focus.ruleBinding.viewPrinciple') })] })] }), canOfferRuleBindingResume({ ...item, resume: review.resume }) && _jsx("button", { type: "button", className: "mt-3 rounded border border-gov bg-gov text-paper px-3 py-2 text-sm disabled:opacity-50", disabled: busy, onClick: () => void revise(), children: t('pages.focus.ruleBinding.reviseCta') }), canOfferSourceCorrection({ ...item, sourceCorrection: review.sourceCorrection }) && _jsx("button", { type: "button", className: "mt-3 ml-2 rounded border border-gov bg-gov text-paper px-3 py-2 text-sm disabled:opacity-50", disabled: busy || !reason.trim(), "data-testid": "rule-binding-source-correct-cta", onClick: () => void correctSource(), children: t('pages.focus.ruleBinding.sourceCorrectionCta') }), review.resume?.status === 'refused' && _jsx("p", { className: "mt-3 text-[12.5px] text-ink-3 leading-relaxed", children: t('pages.focus.ruleBinding.resumeUnavailable', { reason: codeText(t, 'pages.focus.ruleBinding.resumeReason', review.resume.reason) }) }), review.generation?.stage === 'blocked' && review.sourceCorrection?.status === 'unavailable' && _jsx("p", { className: "mt-2 text-[12.5px] text-ink-4 leading-relaxed", children: t('pages.focus.ruleBinding.sourceCorrectionUnavailable', { reason: review.sourceCorrection.reason ?? '' }) }), review.generation?.stage === 'in_progress' && _jsx("p", { className: "mt-3 text-[12.5px] text-ink-3", children: t('pages.focus.ruleBinding.nextBoundGenerating') })] }), !bound && _jsxs(_Fragment, { children: [_jsx("p", { className: "mt-3 text-sm text-ink-3", children: t('pages.focus.ruleBinding.chooseTarget') }), _jsxs("form", { className: "mt-3 flex gap-2", onSubmit: event => { event.preventDefault(); void load(review.candidateId, search); }, children: [_jsx("input", { value: search, onChange: event => setSearch(event.target.value), maxLength: 200, "aria-label": t('pages.focus.ruleBinding.search'), className: "border border-line p-2 text-sm" }), _jsx("button", { disabled: busy, type: "submit", children: t('pages.focus.ruleBinding.search') })] }), review.eligibleTargets.length === 0 && _jsxs("p", { className: "mt-2 text-sm", children: [t('pages.focus.ruleBinding.noTarget'), " ", _jsx(Link, { to: "/principles", className: "underline", children: t('pages.focus.ruleBinding.formation') })] }), review.eligibleTargets.map(target => _jsxs("label", { className: "my-3 block border border-line p-3 text-sm", children: [_jsx("input", { type: "radio", name: "binding-target", value: target.principleId, checked: selectedId === target.principleId, onChange: () => setSelectedId(target.principleId) }), _jsxs("span", { className: "ml-2", children: [t(`principles.status${target.status[0]?.toUpperCase()}${target.status.slice(1)}`, { defaultValue: target.status }), " \u00B7 ", t('pages.focus.ruleBinding.version'), " ", target.version] }), _jsx("p", { className: "mt-2 whitespace-pre-wrap", children: target.text })] }, target.principleId)), _jsx("p", { className: "mt-3 text-sm text-ink-3", children: review.resumeNotice }), _jsx("p", { className: "mt-2 text-sm", children: t('pages.focus.ruleBinding.declaration') })] }), _jsxs("label", { className: "mt-3 block text-sm", children: [t('pages.focus.ruleBinding.reason'), _jsx("textarea", { className: "mt-1 block w-full border border-line p-2", maxLength: 2000, value: reason, onChange: event => setReason(event.target.value) })] }), _jsxs("div", { className: "mt-3 flex gap-2 flex-wrap", children: [!bound && _jsx("button", { type: "button", className: "rounded border border-gov px-3 py-2 text-sm disabled:opacity-50", disabled: busy || !reason.trim() || !selectedId, onClick: () => void decide('bind'), children: t('pages.focus.ruleBinding.bind') }), bound && _jsx("button", { type: "button", className: "rounded border border-line px-3 py-2 text-sm disabled:opacity-50", disabled: busy || !reason.trim(), onClick: () => void decide('revoke'), children: t('pages.focus.ruleBinding.revokeSecondary') })] }), _jsxs("p", { className: "mt-3 text-sm text-ink-3", children: [t('pages.focus.ruleBinding.revokeBoundary'), " ", _jsx(Link, { to: "/activation", className: "underline", children: t('pages.focus.ruleBinding.stop') })] })] })] }, item.candidateId);
295
- })] }, group.key)), groups.length > COLLAPSED_GROUP_LIMIT && _jsx("button", { type: "button", className: "mt-3 text-[12.5px] text-gov underline", onClick: () => setShowAllGroups(value => !value), "aria-expanded": showAllGroups, "data-testid": "rule-binding-groups-toggle", children: showAllGroups
296
- ? t('pages.focus.ruleBinding.hideRemaining')
297
- : t('pages.focus.ruleBinding.viewRemaining', { count: groups.length - COLLAPSED_GROUP_LIMIT }) })] });
298
- }