create-principles-disciple 1.146.4 → 1.146.7

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 (350) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/codex-adapter/package.json +1 -1
  3. package/core/dist/runtime-v2/evidence-triage/index.d.ts +1 -3
  4. package/core/dist/runtime-v2/evidence-triage/index.d.ts.map +1 -1
  5. package/core/dist/runtime-v2/evidence-triage/index.js +1 -2
  6. package/core/dist/runtime-v2/evidence-triage/index.js.map +1 -1
  7. package/core/dist/runtime-v2/evidence-triage/observation-resolver.d.ts +0 -19
  8. package/core/dist/runtime-v2/evidence-triage/observation-resolver.d.ts.map +1 -1
  9. package/core/dist/runtime-v2/evidence-triage/observation-resolver.js +0 -25
  10. package/core/dist/runtime-v2/evidence-triage/observation-resolver.js.map +1 -1
  11. package/core/dist/runtime-v2/index.d.ts +2 -2
  12. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  13. package/core/dist/runtime-v2/index.js +1 -1
  14. package/core/dist/runtime-v2/index.js.map +1 -1
  15. package/core/dist/telemetry-event.d.ts +2 -2
  16. package/core/dist/telemetry-event.d.ts.map +1 -1
  17. package/core/dist/telemetry-event.js +4 -5
  18. package/core/dist/telemetry-event.js.map +1 -1
  19. package/core/dist/trajectory-store.d.ts.map +1 -1
  20. package/core/dist/trajectory-store.js +4 -44
  21. package/core/dist/trajectory-store.js.map +1 -1
  22. package/core/package.json +1 -1
  23. package/host-runtime/package.json +1 -1
  24. package/package.json +4 -4
  25. package/plugin/dist/bundle.js +460 -460
  26. package/plugin/dist/core/config.d.ts +0 -2
  27. package/plugin/dist/core/trajectory.d.ts +0 -6
  28. package/plugin/dist/hooks/llm.d.ts +0 -1
  29. package/plugin/dist/hooks/prompt-helpers.d.ts +2 -1
  30. package/plugin/dist/hooks/raw-observation-adapter.d.ts +6 -4
  31. package/plugin/dist/hooks/triage-adapter.d.ts +1 -1
  32. package/plugin/dist/openclaw.plugin.json +1 -1
  33. package/plugin/dist/rulehost-evidence.js +6 -6
  34. package/plugin/dist/templates/pain_settings.json +0 -2
  35. package/plugin/openclaw.plugin.json +1 -1
  36. package/plugin/package.json +1 -1
  37. package/plugin/templates/pain_settings.json +0 -2
  38. package/release-manager/package.json +4 -4
  39. package/workbuddy-adapter/package.json +1 -1
  40. package/console/dist/ui/App.d.ts +0 -1
  41. package/console/dist/ui/App.js +0 -172
  42. package/console/dist/ui/api.d.ts +0 -611
  43. package/console/dist/ui/api.js +0 -1094
  44. package/console/dist/ui/components/auth/login-form.d.ts +0 -4
  45. package/console/dist/ui/components/auth/login-form.js +0 -142
  46. package/console/dist/ui/components/auth/splash-screen.d.ts +0 -9
  47. package/console/dist/ui/components/auth/splash-screen.js +0 -22
  48. package/console/dist/ui/components/error-boundary.d.ts +0 -15
  49. package/console/dist/ui/components/error-boundary.js +0 -30
  50. package/console/dist/ui/components/focus/daily-thought-card.d.ts +0 -1
  51. package/console/dist/ui/components/focus/daily-thought-card.js +0 -41
  52. package/console/dist/ui/components/language-switcher.d.ts +0 -2
  53. package/console/dist/ui/components/language-switcher.js +0 -17
  54. package/console/dist/ui/components/layout/app-sidebar.d.ts +0 -27
  55. package/console/dist/ui/components/layout/app-sidebar.js +0 -128
  56. package/console/dist/ui/components/layout/page-loading.d.ts +0 -13
  57. package/console/dist/ui/components/layout/page-loading.js +0 -14
  58. package/console/dist/ui/components/layout/page-shell.d.ts +0 -12
  59. package/console/dist/ui/components/layout/page-shell.js +0 -11
  60. package/console/dist/ui/components/layout/section-title.d.ts +0 -10
  61. package/console/dist/ui/components/layout/section-title.js +0 -9
  62. package/console/dist/ui/components/notifications/NotificationProvider.d.ts +0 -14
  63. package/console/dist/ui/components/notifications/NotificationProvider.js +0 -136
  64. package/console/dist/ui/components/notifications/favicon-badge.d.ts +0 -3
  65. package/console/dist/ui/components/notifications/favicon-badge.js +0 -68
  66. package/console/dist/ui/components/notifications/notification-reducer.d.ts +0 -9
  67. package/console/dist/ui/components/notifications/notification-reducer.js +0 -9
  68. package/console/dist/ui/components/notifications/sound-storage.d.ts +0 -3
  69. package/console/dist/ui/components/notifications/sound-storage.js +0 -37
  70. package/console/dist/ui/components/notifications/useNotifications.d.ts +0 -1
  71. package/console/dist/ui/components/notifications/useNotifications.js +0 -9
  72. package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +0 -8
  73. package/console/dist/ui/components/onboarding/CircuitDiagram.js +0 -18
  74. package/console/dist/ui/components/onboarding/DemoResultView.d.ts +0 -22
  75. package/console/dist/ui/components/onboarding/DemoResultView.js +0 -33
  76. package/console/dist/ui/components/onboarding/SlashCommandsCard.d.ts +0 -16
  77. package/console/dist/ui/components/onboarding/SlashCommandsCard.js +0 -20
  78. package/console/dist/ui/components/onboarding/slashCommands.d.ts +0 -20
  79. package/console/dist/ui/components/onboarding/slashCommands.js +0 -22
  80. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.d.ts +0 -6
  81. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.js +0 -66
  82. package/console/dist/ui/components/theme-provider.d.ts +0 -14
  83. package/console/dist/ui/components/theme-provider.js +0 -40
  84. package/console/dist/ui/components/theme-toggle.d.ts +0 -2
  85. package/console/dist/ui/components/theme-toggle.js +0 -11
  86. package/console/dist/ui/components/ui/alert-dialog.d.ts +0 -20
  87. package/console/dist/ui/components/ui/alert-dialog.js +0 -26
  88. package/console/dist/ui/components/ui/badge.d.ts +0 -9
  89. package/console/dist/ui/components/ui/badge.js +0 -22
  90. package/console/dist/ui/components/ui/button.d.ts +0 -11
  91. package/console/dist/ui/components/ui/button.js +0 -34
  92. package/console/dist/ui/components/ui/card.d.ts +0 -8
  93. package/console/dist/ui/components/ui/card.js +0 -16
  94. package/console/dist/ui/components/ui/charts.d.ts +0 -51
  95. package/console/dist/ui/components/ui/charts.js +0 -72
  96. package/console/dist/ui/components/ui/dialog.d.ts +0 -19
  97. package/console/dist/ui/components/ui/dialog.js +0 -22
  98. package/console/dist/ui/components/ui/input.d.ts +0 -3
  99. package/console/dist/ui/components/ui/input.js +0 -8
  100. package/console/dist/ui/components/ui/markdown.d.ts +0 -24
  101. package/console/dist/ui/components/ui/markdown.js +0 -119
  102. package/console/dist/ui/components/ui/progress-bar.d.ts +0 -20
  103. package/console/dist/ui/components/ui/progress-bar.js +0 -38
  104. package/console/dist/ui/components/ui/select.d.ts +0 -13
  105. package/console/dist/ui/components/ui/select.js +0 -26
  106. package/console/dist/ui/components/ui/separator.d.ts +0 -3
  107. package/console/dist/ui/components/ui/separator.js +0 -6
  108. package/console/dist/ui/components/ui/sheet.d.ts +0 -25
  109. package/console/dist/ui/components/ui/sheet.js +0 -37
  110. package/console/dist/ui/components/ui/shiny-text.d.ts +0 -28
  111. package/console/dist/ui/components/ui/shiny-text.js +0 -46
  112. package/console/dist/ui/components/ui/skeleton.d.ts +0 -3
  113. package/console/dist/ui/components/ui/skeleton.js +0 -6
  114. package/console/dist/ui/components/ui/sonner.d.ts +0 -3
  115. package/console/dist/ui/components/ui/sonner.js +0 -13
  116. package/console/dist/ui/components/ui/tooltip.d.ts +0 -7
  117. package/console/dist/ui/components/ui/tooltip.js +0 -10
  118. package/console/dist/ui/data/daily-thoughts.d.ts +0 -15
  119. package/console/dist/ui/data/daily-thoughts.js +0 -164
  120. package/console/dist/ui/hooks/useNotificationSound.d.ts +0 -12
  121. package/console/dist/ui/hooks/useNotificationSound.js +0 -74
  122. package/console/dist/ui/i18n/en.json +0 -2399
  123. package/console/dist/ui/i18n/index.d.ts +0 -2
  124. package/console/dist/ui/i18n/index.js +0 -32
  125. package/console/dist/ui/i18n/zh-CN.json +0 -2399
  126. package/console/dist/ui/main.d.ts +0 -1
  127. package/console/dist/ui/main.js +0 -9
  128. package/console/dist/ui/pages/ReportProblemValidators.d.ts +0 -144
  129. package/console/dist/ui/pages/ReportProblemValidators.js +0 -418
  130. package/console/dist/ui/pages/activation/ActivationPage.d.ts +0 -1
  131. package/console/dist/ui/pages/activation/ActivationPage.js +0 -512
  132. package/console/dist/ui/pages/activation/ActivationValidators.d.ts +0 -20
  133. package/console/dist/ui/pages/activation/ActivationValidators.js +0 -160
  134. package/console/dist/ui/pages/control-center/AgentCard.d.ts +0 -31
  135. package/console/dist/ui/pages/control-center/AgentCard.js +0 -212
  136. package/console/dist/ui/pages/control-center/AgentGroup.d.ts +0 -26
  137. package/console/dist/ui/pages/control-center/AgentGroup.js +0 -38
  138. package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +0 -1
  139. package/console/dist/ui/pages/control-center/ControlCenterPage.js +0 -509
  140. package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +0 -1
  141. package/console/dist/ui/pages/control-center/DesignGatePanel.js +0 -137
  142. package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +0 -31
  143. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +0 -199
  144. package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +0 -17
  145. package/console/dist/ui/pages/control-center/WorkflowDiagram.js +0 -55
  146. package/console/dist/ui/pages/debt/DebtPage.d.ts +0 -2
  147. package/console/dist/ui/pages/debt/DebtPage.js +0 -222
  148. package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +0 -2
  149. package/console/dist/ui/pages/design-system/DesignSystemPage.js +0 -30
  150. package/console/dist/ui/pages/examiner/ExaminerPage.d.ts +0 -15
  151. package/console/dist/ui/pages/examiner/ExaminerPage.js +0 -158
  152. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.d.ts +0 -1
  153. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.js +0 -421
  154. package/console/dist/ui/pages/focus/ApprovalSubjectReading.d.ts +0 -24
  155. package/console/dist/ui/pages/focus/ApprovalSubjectReading.js +0 -133
  156. package/console/dist/ui/pages/focus/FocusPage.d.ts +0 -123
  157. package/console/dist/ui/pages/focus/FocusPage.js +0 -567
  158. package/console/dist/ui/pages/focus/OwnerDecisionCard.d.ts +0 -9
  159. package/console/dist/ui/pages/focus/OwnerDecisionCard.js +0 -111
  160. package/console/dist/ui/pages/focus/OwnerWorkbench.d.ts +0 -19
  161. package/console/dist/ui/pages/focus/OwnerWorkbench.js +0 -75
  162. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.d.ts +0 -34
  163. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.js +0 -298
  164. package/console/dist/ui/pages/focus/focus-validation.d.ts +0 -40
  165. package/console/dist/ui/pages/focus/focus-validation.js +0 -211
  166. package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +0 -67
  167. package/console/dist/ui/pages/intent/IntentOnboarding.js +0 -289
  168. package/console/dist/ui/pages/intent/IntentPage.d.ts +0 -1
  169. package/console/dist/ui/pages/intent/IntentPage.js +0 -252
  170. package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +0 -59
  171. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +0 -125
  172. package/console/dist/ui/pages/pain/PainPage.d.ts +0 -1
  173. package/console/dist/ui/pages/pain/PainPage.js +0 -420
  174. package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +0 -175
  175. package/console/dist/ui/pages/pain/pain-card-helpers.js +0 -181
  176. package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +0 -10
  177. package/console/dist/ui/pages/principles/CorePrinciplesPage.js +0 -59
  178. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +0 -60
  179. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +0 -602
  180. package/console/dist/ui/pages/principles/PrinciplesPage.d.ts +0 -1
  181. package/console/dist/ui/pages/principles/PrinciplesPage.js +0 -327
  182. package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +0 -8
  183. package/console/dist/ui/pages/principles/PrinciplesViewNav.js +0 -15
  184. package/console/dist/ui/pages/report-problem/ReportProblemPage.d.ts +0 -1
  185. package/console/dist/ui/pages/report-problem/ReportProblemPage.js +0 -467
  186. package/console/dist/ui/pages/settings/SettingsPage.d.ts +0 -4
  187. package/console/dist/ui/pages/settings/SettingsPage.js +0 -457
  188. package/console/dist/ui/pages/settings/UpdatePage.d.ts +0 -1
  189. package/console/dist/ui/pages/settings/UpdatePage.js +0 -215
  190. package/console/dist/ui/pages/welcome/WelcomePage.d.ts +0 -5
  191. package/console/dist/ui/pages/welcome/WelcomePage.js +0 -187
  192. package/console/dist/ui/utils/agent-metadata.d.ts +0 -71
  193. package/console/dist/ui/utils/agent-metadata.js +0 -284
  194. package/console/dist/ui/utils/approval-review.d.ts +0 -30
  195. package/console/dist/ui/utils/approval-review.js +0 -50
  196. package/console/dist/ui/utils/approval-warning-localization.d.ts +0 -34
  197. package/console/dist/ui/utils/approval-warning-localization.js +0 -148
  198. package/console/dist/ui/utils/attention-presentation.d.ts +0 -35
  199. package/console/dist/ui/utils/attention-presentation.js +0 -46
  200. package/console/dist/ui/utils/blocker-localization.d.ts +0 -23
  201. package/console/dist/ui/utils/blocker-localization.js +0 -36
  202. package/console/dist/ui/utils/control-center-helpers.d.ts +0 -79
  203. package/console/dist/ui/utils/control-center-helpers.js +0 -189
  204. package/console/dist/ui/utils/enum-labels.d.ts +0 -50
  205. package/console/dist/ui/utils/enum-labels.js +0 -171
  206. package/console/dist/ui/utils/format-date.d.ts +0 -11
  207. package/console/dist/ui/utils/format-date.js +0 -17
  208. package/console/dist/ui/utils/onboarding-state.d.ts +0 -25
  209. package/console/dist/ui/utils/onboarding-state.js +0 -77
  210. package/console/dist/ui/utils/reading-layout.d.ts +0 -20
  211. package/console/dist/ui/utils/reading-layout.js +0 -46
  212. package/console/dist/ui/utils/rule-binding-validators.d.ts +0 -13
  213. package/console/dist/ui/utils/rule-binding-validators.js +0 -188
  214. package/console/dist/ui/utils/runtime-mode.d.ts +0 -11
  215. package/console/dist/ui/utils/runtime-mode.js +0 -11
  216. package/console/dist/ui/utils/token-storage.d.ts +0 -22
  217. package/console/dist/ui/utils/token-storage.js +0 -47
  218. package/console/dist/ui/utils/validators.d.ts +0 -1178
  219. package/console/dist/ui/utils/validators.js +0 -3297
  220. package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts +0 -126
  221. package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts.map +0 -1
  222. package/core/dist/runtime-v2/evidence-triage/admission-events.js +0 -159
  223. package/core/dist/runtime-v2/evidence-triage/admission-events.js.map +0 -1
  224. package/plugin/dist/core/detection-funnel.d.ts +0 -47
  225. package/plugin/dist/core/detection-service.d.ts +0 -15
  226. package/release-manager/dist/bootstrap-entry.d.ts +0 -2
  227. package/release-manager/dist/bootstrap-entry.d.ts.map +0 -1
  228. package/release-manager/dist/bootstrap-entry.js.map +0 -1
  229. package/release-manager/dist/i18n.d.ts +0 -6
  230. package/release-manager/dist/i18n.d.ts.map +0 -1
  231. package/release-manager/dist/i18n.js.map +0 -1
  232. package/release-manager/dist/index.d.ts +0 -7
  233. package/release-manager/dist/index.d.ts.map +0 -1
  234. package/release-manager/dist/index.js +0 -656
  235. package/release-manager/dist/index.js.map +0 -1
  236. package/release-manager/dist/installer.d.ts +0 -629
  237. package/release-manager/dist/installer.d.ts.map +0 -1
  238. package/release-manager/dist/installer.js.map +0 -1
  239. package/release-manager/dist/installers/codex-host-installer.d.ts +0 -39
  240. package/release-manager/dist/installers/codex-host-installer.d.ts.map +0 -1
  241. package/release-manager/dist/installers/codex-host-installer.js.map +0 -1
  242. package/release-manager/dist/installers/index.d.ts +0 -51
  243. package/release-manager/dist/installers/index.d.ts.map +0 -1
  244. package/release-manager/dist/installers/index.js.map +0 -1
  245. package/release-manager/dist/installers/openclaw-host-installer.d.ts +0 -14
  246. package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +0 -1
  247. package/release-manager/dist/installers/openclaw-host-installer.js.map +0 -1
  248. package/release-manager/dist/installers/workbuddy-host-installer.d.ts +0 -335
  249. package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +0 -1
  250. package/release-manager/dist/installers/workbuddy-host-installer.js.map +0 -1
  251. package/release-manager/dist/mvp-config.d.ts +0 -233
  252. package/release-manager/dist/mvp-config.d.ts.map +0 -1
  253. package/release-manager/dist/mvp-config.js.map +0 -1
  254. package/release-manager/dist/prompts.d.ts +0 -43
  255. package/release-manager/dist/prompts.d.ts.map +0 -1
  256. package/release-manager/dist/prompts.js +0 -268
  257. package/release-manager/dist/prompts.js.map +0 -1
  258. package/release-manager/dist/skill-language.d.ts +0 -32
  259. package/release-manager/dist/skill-language.d.ts.map +0 -1
  260. package/release-manager/dist/skill-language.js.map +0 -1
  261. package/release-manager/dist/uninstaller.d.ts +0 -68
  262. package/release-manager/dist/uninstaller.d.ts.map +0 -1
  263. package/release-manager/dist/uninstaller.js +0 -746
  264. package/release-manager/dist/uninstaller.js.map +0 -1
  265. package/release-manager/dist/update/apply-payload.d.ts +0 -143
  266. package/release-manager/dist/update/apply-payload.d.ts.map +0 -1
  267. package/release-manager/dist/update/apply-payload.js.map +0 -1
  268. package/release-manager/dist/update/atomic-file.d.ts +0 -35
  269. package/release-manager/dist/update/atomic-file.d.ts.map +0 -1
  270. package/release-manager/dist/update/atomic-file.js.map +0 -1
  271. package/release-manager/dist/update/bootstrap-executor.d.ts +0 -21
  272. package/release-manager/dist/update/bootstrap-executor.d.ts.map +0 -1
  273. package/release-manager/dist/update/bootstrap-executor.js.map +0 -1
  274. package/release-manager/dist/update/bootstrap-protocol.d.ts +0 -56
  275. package/release-manager/dist/update/bootstrap-protocol.d.ts.map +0 -1
  276. package/release-manager/dist/update/bootstrap-protocol.js.map +0 -1
  277. package/release-manager/dist/update/channel-metadata.d.ts +0 -28
  278. package/release-manager/dist/update/channel-metadata.d.ts.map +0 -1
  279. package/release-manager/dist/update/channel-metadata.js.map +0 -1
  280. package/release-manager/dist/update/channel-promotion.d.ts +0 -39
  281. package/release-manager/dist/update/channel-promotion.d.ts.map +0 -1
  282. package/release-manager/dist/update/channel-promotion.js +0 -55
  283. package/release-manager/dist/update/channel-promotion.js.map +0 -1
  284. package/release-manager/dist/update/console-surface.d.ts +0 -19
  285. package/release-manager/dist/update/console-surface.d.ts.map +0 -1
  286. package/release-manager/dist/update/console-surface.js.map +0 -1
  287. package/release-manager/dist/update/data-compatibility.d.ts +0 -35
  288. package/release-manager/dist/update/data-compatibility.d.ts.map +0 -1
  289. package/release-manager/dist/update/data-compatibility.js +0 -45
  290. package/release-manager/dist/update/data-compatibility.js.map +0 -1
  291. package/release-manager/dist/update/install-layout.d.ts +0 -105
  292. package/release-manager/dist/update/install-layout.d.ts.map +0 -1
  293. package/release-manager/dist/update/install-layout.js.map +0 -1
  294. package/release-manager/dist/update/product-identity.d.ts +0 -70
  295. package/release-manager/dist/update/product-identity.d.ts.map +0 -1
  296. package/release-manager/dist/update/product-identity.js.map +0 -1
  297. package/release-manager/dist/update/release-asset-manifest.d.ts +0 -31
  298. package/release-manager/dist/update/release-asset-manifest.d.ts.map +0 -1
  299. package/release-manager/dist/update/release-asset-manifest.js.map +0 -1
  300. package/release-manager/dist/update/release-identity.d.ts +0 -33
  301. package/release-manager/dist/update/release-identity.d.ts.map +0 -1
  302. package/release-manager/dist/update/release-identity.js.map +0 -1
  303. package/release-manager/dist/update/release-manager-authority.d.ts +0 -39
  304. package/release-manager/dist/update/release-manager-authority.d.ts.map +0 -1
  305. package/release-manager/dist/update/release-manager-authority.js.map +0 -1
  306. package/release-manager/dist/update/release-manager.d.ts +0 -156
  307. package/release-manager/dist/update/release-manager.d.ts.map +0 -1
  308. package/release-manager/dist/update/release-manager.js.map +0 -1
  309. package/release-manager/dist/update/release-metadata-publisher.d.ts +0 -199
  310. package/release-manager/dist/update/release-metadata-publisher.d.ts.map +0 -1
  311. package/release-manager/dist/update/release-metadata-publisher.js +0 -478
  312. package/release-manager/dist/update/release-metadata-publisher.js.map +0 -1
  313. package/release-manager/dist/update/release-metadata-source.d.ts +0 -85
  314. package/release-manager/dist/update/release-metadata-source.d.ts.map +0 -1
  315. package/release-manager/dist/update/release-metadata-source.js.map +0 -1
  316. package/release-manager/dist/update/release-metadata.d.ts +0 -60
  317. package/release-manager/dist/update/release-metadata.d.ts.map +0 -1
  318. package/release-manager/dist/update/release-metadata.js.map +0 -1
  319. package/release-manager/dist/update/release-policy.d.ts +0 -51
  320. package/release-manager/dist/update/release-policy.d.ts.map +0 -1
  321. package/release-manager/dist/update/release-policy.js.map +0 -1
  322. package/release-manager/dist/update/rollback-policy.d.ts +0 -56
  323. package/release-manager/dist/update/rollback-policy.d.ts.map +0 -1
  324. package/release-manager/dist/update/rollback-policy.js +0 -61
  325. package/release-manager/dist/update/rollback-policy.js.map +0 -1
  326. package/release-manager/dist/update/transaction-journal.d.ts +0 -212
  327. package/release-manager/dist/update/transaction-journal.d.ts.map +0 -1
  328. package/release-manager/dist/update/transaction-journal.js.map +0 -1
  329. package/release-manager/dist/update/trust-metadata.d.ts +0 -55
  330. package/release-manager/dist/update/trust-metadata.d.ts.map +0 -1
  331. package/release-manager/dist/update/trust-metadata.js.map +0 -1
  332. package/release-manager/dist/update/trust-root-provisioning.d.ts +0 -99
  333. package/release-manager/dist/update/trust-root-provisioning.d.ts.map +0 -1
  334. package/release-manager/dist/update/trust-root-provisioning.js.map +0 -1
  335. package/release-manager/dist/update/update-history.d.ts +0 -46
  336. package/release-manager/dist/update/update-history.d.ts.map +0 -1
  337. package/release-manager/dist/update/update-history.js +0 -123
  338. package/release-manager/dist/update/update-history.js.map +0 -1
  339. package/release-manager/dist/utils/config-file-io.d.ts +0 -34
  340. package/release-manager/dist/utils/config-file-io.d.ts.map +0 -1
  341. package/release-manager/dist/utils/config-file-io.js.map +0 -1
  342. package/release-manager/dist/utils/env.d.ts +0 -94
  343. package/release-manager/dist/utils/env.d.ts.map +0 -1
  344. package/release-manager/dist/utils/env.js.map +0 -1
  345. package/release-manager/dist/utils/logger.d.ts +0 -15
  346. package/release-manager/dist/utils/logger.d.ts.map +0 -1
  347. package/release-manager/dist/utils/logger.js.map +0 -1
  348. package/release-manager/dist/utils/workspace-divergence.d.ts +0 -36
  349. package/release-manager/dist/utils/workspace-divergence.d.ts.map +0 -1
  350. package/release-manager/dist/utils/workspace-divergence.js.map +0 -1
@@ -1,421 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * FailedTasksPage — Pipeline observability page showing failed or
4
- * needs_human_review tasks, grouped by taskKind.
5
- *
6
- * Part of the PD feedback-pipeline observability spec (Task 10).
7
- * Gated by the `failed_tasks_observability` feature flag. When the flag is
8
- * disabled, the backend returns 403 and this page shows a "disabled" state
9
- * with guidance on how to enable the flag.
10
- *
11
- * Each row exposes a "Create Feedback Draft" button that deep-links into the
12
- * Report Problem page with the task/pain context pre-filled.
13
- *
14
- * Governance Recovery Actions v1: when the `failed_task_recovery_console`
15
- * feature flag is enabled, each row also exposes a "Resume Evolution" button.
16
- * Recovery is an Owner governance action (never auto-triggered on load): it
17
- * always goes through an explicit confirmation dialog before POSTing
18
- * /api/v1/failed-tasks/:id/recover. The success state means "Recovery
19
- * Accepted" — the task is pending again; execution is asynchronous.
20
- *
21
- * PRI-747 F22 / PRI-749: each row can be expanded into its detail — the full
22
- * task record plus run history — fetched lazily from the pre-existing
23
- * GET /api/v1/failed-tasks/:id endpoint (server route +
24
- * SqliteTaskStore.getFailedTaskDetail already existed; the UI simply never
25
- * consumed them).
26
- *
27
- * Runtime Contract (rc-*):
28
- * - rc-1: API response is treated as `unknown` and validated before use
29
- * - rc-2: no `as` type assertions — runtime type guards only
30
- * - rc-5: `Object.hasOwn()` for untrusted object keys
31
- * - rc-9: every error/disabled path surfaces a reason + next action
32
- */
33
- import { useState, useEffect, useCallback, useRef, Fragment } from "react";
34
- import { useNavigate, useSearchParams } from "react-router-dom";
35
- import { useTranslation } from "react-i18next";
36
- import { toast } from "sonner";
37
- import { PageShell } from "../../components/layout/page-shell.js";
38
- import { PageLoading } from "../../components/layout/page-loading.js";
39
- import { Badge } from "../../components/ui/badge.js";
40
- import { Card, CardContent, CardHeader, CardTitle } from "../../components/ui/card.js";
41
- import { Button } from "../../components/ui/button.js";
42
- import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, } from "../../components/ui/alert-dialog.js";
43
- import { ShinyText } from "../../components/ui/shiny-text.js";
44
- import { formatDate } from "../../utils/format-date.js";
45
- import i18n from "../../i18n/index.js";
46
- import { recoverFailedTask, fetchConfigSummary, fetchFailedTaskDetail, request } from "../../api.js";
47
- // Same component set the former utils/format.js rendered, now served by the
48
- // defensive single-owner formatter: an invalid date string returns the raw
49
- // input instead of Intl throwing RangeError mid-render (review round of
50
- // PRI-747 F22 — utils/format.js was retired with this migration).
51
- const DATETIME_FORMAT_OPTS = {
52
- year: "numeric",
53
- month: "2-digit",
54
- day: "2-digit",
55
- hour: "2-digit",
56
- minute: "2-digit",
57
- };
58
- function formatDateTime(iso) {
59
- return formatDate(iso, i18n.language, DATETIME_FORMAT_OPTS);
60
- }
61
- // ── Runtime validators (rc-1, rc-2, rc-5) ───────────────────────────────────
62
- //
63
- // The API response is `unknown` until these guards run. No `as` casts.
64
- function isObject(v) {
65
- return typeof v === "object" && v !== null && !Array.isArray(v);
66
- }
67
- function isString(v) {
68
- return typeof v === "string";
69
- }
70
- function isNumber(v) {
71
- return typeof v === "number" && !Number.isNaN(v);
72
- }
73
- function readString(v, key) {
74
- if (!Object.hasOwn(v, key))
75
- return null;
76
- return isString(v[key]) ? v[key] : null;
77
- }
78
- function readNullableString(v, key) {
79
- if (!Object.hasOwn(v, key))
80
- return null;
81
- const val = v[key];
82
- if (val === null)
83
- return null;
84
- return isString(val) ? val : null;
85
- }
86
- function readNumber(v, key) {
87
- if (!Object.hasOwn(v, key))
88
- return null;
89
- return isNumber(v[key]) ? v[key] : null;
90
- }
91
- function validateTask(v) {
92
- if (!isObject(v))
93
- return null;
94
- const taskId = readString(v, "taskId");
95
- const taskKind = readString(v, "taskKind");
96
- const status = readString(v, "status");
97
- const attemptCount = readNumber(v, "attemptCount");
98
- const maxAttempts = readNumber(v, "maxAttempts");
99
- const createdAt = readString(v, "createdAt");
100
- // Required fields — fail loud when missing or wrong type (rc-3)
101
- if (taskId === null ||
102
- taskKind === null ||
103
- status === null ||
104
- attemptCount === null ||
105
- maxAttempts === null ||
106
- createdAt === null) {
107
- return null;
108
- }
109
- const painId = readNullableString(v, "painId");
110
- const lastError = readNullableString(v, "lastError");
111
- const lastAttemptAt = readNullableString(v, "lastAttemptAt");
112
- const ownerDecisionRequired = Object.hasOwn(v, "ownerDecisionRequired")
113
- ? v.ownerDecisionRequired === true
114
- : undefined;
115
- return {
116
- taskId,
117
- taskKind,
118
- painId,
119
- status,
120
- lastError,
121
- attemptCount,
122
- maxAttempts,
123
- createdAt,
124
- lastAttemptAt,
125
- ...(ownerDecisionRequired !== undefined ? { ownerDecisionRequired } : {}),
126
- };
127
- }
128
- function validateFailedTasksData(v) {
129
- if (!isObject(v))
130
- return null;
131
- if (!Object.hasOwn(v, "tasks"))
132
- return null;
133
- const tasksRaw = v.tasks;
134
- if (!Array.isArray(tasksRaw))
135
- return null;
136
- const tasks = [];
137
- for (const item of tasksRaw) {
138
- const task = validateTask(item);
139
- if (task === null)
140
- return null;
141
- tasks.push(task);
142
- }
143
- const total = readNumber(v, "total");
144
- if (total === null)
145
- return null;
146
- const nextAction = readNullableString(v, "nextAction");
147
- // PRI-955 (F11): optional pipeline health block — an invalid block is
148
- // omitted (never fails the whole payload), the page then renders nothing.
149
- let pipeline;
150
- if (Object.hasOwn(v, "pipeline") && isObject(v.pipeline)) {
151
- const p = v.pipeline;
152
- const status = readString(p, "status");
153
- const note = readString(p, "note");
154
- if (status === "healthy" || status === "backlogged" || status === "stalled" || status === "disabled" || status === "unknown") {
155
- if (note !== null) {
156
- pipeline = {
157
- status,
158
- pendingCount: readNumber(p, "pendingCount"),
159
- oldestPendingTaskKind: readNullableString(p, "oldestPendingTaskKind"),
160
- oldestPendingAgeMinutes: readNumber(p, "oldestPendingAgeMinutes"),
161
- lastProgressAt: readNullableString(p, "lastProgressAt"),
162
- note,
163
- nextAction: readNullableString(p, "nextAction") ?? undefined,
164
- };
165
- }
166
- }
167
- }
168
- return { tasks, total, nextAction: nextAction ?? undefined, ...(pipeline ? { pipeline } : {}) };
169
- }
170
- // ── Helpers ──────────────────────────────────────────────────────────────────
171
- function truncateId(id) {
172
- return id.length > 12 ? id.slice(0, 12) + "…" : id;
173
- }
174
- function statusToVariant(status) {
175
- if (status === "failed")
176
- return "destructive";
177
- if (status === "needs_human_review")
178
- return "amber";
179
- return "default";
180
- }
181
- /** A failed task whose retry budget is spent — only a force recovery can requeue it. */
182
- function isAttemptBudgetExhausted(task) {
183
- return task.status === "failed" && task.attemptCount >= task.maxAttempts;
184
- }
185
- function groupTasksByKind(tasks) {
186
- const grouped = new Map();
187
- for (const task of tasks) {
188
- const existing = grouped.get(task.taskKind) ?? [];
189
- existing.push(task);
190
- grouped.set(task.taskKind, existing);
191
- }
192
- return grouped;
193
- }
194
- // ── Component ────────────────────────────────────────────────────────────────
195
- export function FailedTasksPage() {
196
- const { t } = useTranslation();
197
- const navigate = useNavigate();
198
- const [searchParams] = useSearchParams();
199
- // ?taskId= deep link (治理焦点「查看恢复详情」直达): initial value only —
200
- // the row auto-expands once; the Owner can still collapse/switch freely.
201
- const deepLinkTaskId = searchParams.get("taskId") ?? undefined;
202
- const [state, setState] = useState({ status: "loading" });
203
- // Governance Recovery Actions v1 — flag-gated recovery UI (fail-closed:
204
- // absent/false → no recovery entry, Console stays read-only).
205
- const [recoveryEnabled, setRecoveryEnabled] = useState(false);
206
- const [recoverTarget, setRecoverTarget] = useState(null);
207
- const [recoverLoading, setRecoverLoading] = useState(false);
208
- // Exhausted targets recover with force: the dialog warns first and the
209
- // action button becomes 强制恢复 (server refuses force=false for these).
210
- const recoverExhausted = recoverTarget !== null && isAttemptBudgetExhausted(recoverTarget);
211
- let recoverConfirmLabel = t("pages.failedTasks.recoverConfirmButton");
212
- if (recoverLoading) {
213
- recoverConfirmLabel = t("common.loading");
214
- }
215
- else if (recoverExhausted) {
216
- recoverConfirmLabel = t("pages.failedTasks.recoverConfirmForceButton");
217
- }
218
- useEffect(() => {
219
- let cancelled = false;
220
- fetchConfigSummary()
221
- .then((result) => {
222
- if (cancelled)
223
- return;
224
- // Fail-closed: only an explicitly enabled flag shows the action
225
- if (result.success && result.data) {
226
- const flag = result.data.features.find((f) => f.id === "failed_task_recovery_console");
227
- setRecoveryEnabled(flag?.enabled === true);
228
- }
229
- })
230
- .catch(() => {
231
- // rc-9: flag probe failure keeps recovery hidden (fail-closed)
232
- });
233
- return () => {
234
- cancelled = true;
235
- };
236
- }, []);
237
- const loadData = useCallback(async () => {
238
- setState({ status: "loading" });
239
- // Shared request(): same auth header and global 401 session-expiry
240
- // handling as every other page (PRI-643 — a manual fetch here bypassed
241
- // session-expiry routing entirely).
242
- const result = await request("/api/v1/failed-tasks", undefined, validateFailedTasksData);
243
- if (result.success) {
244
- setState({ status: "loaded", data: result.data });
245
- return;
246
- }
247
- // 403 = feature flag disabled — show disabled state (rc-9: surface reason)
248
- if (result.status === 403) {
249
- setState({ status: "disabled" });
250
- return;
251
- }
252
- setState({ status: "error", message: result.error, nextAction: result.nextAction });
253
- }, []);
254
- useEffect(() => {
255
- loadData();
256
- }, [loadData]);
257
- const handleCreateDraft = (task) => {
258
- const params = new URLSearchParams({
259
- source: "failed_tasks_page",
260
- taskId: task.taskId,
261
- });
262
- if (task.painId) {
263
- params.set("painId", task.painId);
264
- }
265
- navigate(`/report-problem?${params.toString()}`);
266
- };
267
- // Owner-confirmed recovery (SPEC §6.3: explicit confirmation only — this
268
- // handler runs exclusively from the dialog's action button, never on load).
269
- const handleRecoverConfirmed = async () => {
270
- if (!recoverTarget || recoverLoading)
271
- return;
272
- setRecoverLoading(true);
273
- try {
274
- const result = await recoverFailedTask(recoverTarget.taskId, undefined, recoverExhausted);
275
- if (result.success) {
276
- toast.success(t("pages.failedTasks.recoverSuccess"));
277
- setRecoverTarget(null);
278
- await loadData();
279
- }
280
- else {
281
- // rc-9: server-provided reason + next action accompany the failure
282
- const detail = result.nextAction
283
- ? `${result.error} — ${result.nextAction}`
284
- : result.error;
285
- toast.error(`${t("pages.failedTasks.recoverFailed")}: ${detail}`);
286
- }
287
- }
288
- catch (err) {
289
- toast.error(`${t("pages.failedTasks.recoverFailed")}: ${err instanceof Error ? err.message : "Network error"}`);
290
- }
291
- finally {
292
- setRecoverLoading(false);
293
- }
294
- };
295
- return (_jsxs(PageShell, { children: [_jsxs("div", { className: "mb-8", children: [_jsx("div", { className: "font-mono text-[11px] uppercase tracking-[0.14em] text-ink-3", children: t("pages.failedTasks.title") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mt-3 mb-2", duration: 4.5, brightness: 0.5, disabled: state.status !== "loaded" || state.data.tasks.length === 0, children: t("pages.failedTasks.title") }), _jsx("p", { className: "text-ink-3 text-sm leading-relaxed max-w-[712px]", children: t("pages.failedTasks.subtitle") })] }), state.status === "loading" && (_jsx(PageLoading, { cardCount: 3, label: t("common.loading") })), state.status === "disabled" && (_jsxs("div", { className: "py-8", children: [_jsx("div", { className: "p-5 bg-panel border border-amber/20 rounded-[var(--radius-md)] text-amber text-[13px] leading-relaxed", children: t("pages.failedTasks.disabled") }), _jsx("div", { className: "mt-4", children: _jsx(Button, { variant: "outline", size: "sm", onClick: loadData, children: t("common.refresh") }) })] })), state.status === "error" && (_jsxs("div", { className: "py-8", children: [_jsxs("div", { className: "text-danger text-sm mb-2", children: [t("pages.failedTasks.error"), ": ", state.message] }), state.nextAction && (_jsx("div", { className: "text-ink-3 text-[13px] mb-3", children: state.nextAction })), _jsx(Button, { variant: "outline", size: "sm", onClick: loadData, children: t("common.refresh") })] })), state.status === "loaded" && (_jsx("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: _jsx(LoadedContent, { data: state.data, onCreateDraft: handleCreateDraft, onRecover: recoveryEnabled ? (task) => setRecoverTarget(task) : undefined, initialExpandedTaskId: deepLinkTaskId, t: t }) })), _jsx(AlertDialog, { open: recoverTarget !== null, onOpenChange: (open) => {
296
- if (!open && !recoverLoading) {
297
- setRecoverTarget(null);
298
- }
299
- }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("pages.failedTasks.recoverConfirmTitle") }), _jsx(AlertDialogDescription, { asChild: true, children: _jsxs("div", { className: "space-y-2 text-[13px] leading-relaxed", children: [_jsxs("div", { children: [_jsxs("span", { className: "font-medium", children: [t("pages.failedTasks.recoverConfirmStatus"), ":"] }), " ", _jsx("span", { className: "font-mono", children: recoverTarget?.status ?? "—" })] }), recoverExhausted && (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsxs("span", { className: "font-medium", children: [t("pages.failedTasks.recoverConfirmAttempts"), ":"] }), " ", _jsxs("span", { className: "font-mono", children: [recoverTarget?.attemptCount, " / ", recoverTarget?.maxAttempts] })] }), _jsx("div", { className: "text-danger", children: t("pages.failedTasks.recoverExhaustedWarning", {
300
- attempt: recoverTarget?.attemptCount ?? 0,
301
- max: recoverTarget?.maxAttempts ?? 0,
302
- }) })] })), _jsxs("div", { children: [_jsxs("span", { className: "font-medium", children: [t("pages.failedTasks.recoverConfirmActionLabel"), ":"] }), " ", t("pages.failedTasks.recoverConfirmActionDesc")] }), _jsxs("div", { children: [_jsxs("span", { className: "font-medium", children: [t("pages.failedTasks.recoverConfirmImpactLabel"), ":"] }), " ", recoverExhausted
303
- ? t("pages.failedTasks.recoverConfirmForceImpactDesc")
304
- : t("pages.failedTasks.recoverConfirmImpactDesc")] })] }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: recoverLoading, children: t("common.cancel") }), _jsx(AlertDialogAction, { disabled: recoverLoading, onClick: (event) => {
305
- // Prevent Radix from auto-closing before the async POST
306
- // resolves; handleRecoverConfirmed closes on success.
307
- event.preventDefault();
308
- void handleRecoverConfirmed();
309
- }, children: recoverConfirmLabel })] })] }) })] }));
310
- }
311
- /** PRI-955 (F11): derived learning-queue health block — never claims health
312
- * from the failed-task count alone. Facts come from the server projection. */
313
- function PipelineHealthCard({ pipeline, t }) {
314
- const statusLabel = pipeline.status === "healthy" ? t("pages.failedTasks.pipeline.statusHealthy")
315
- : pipeline.status === "backlogged" ? t("pages.failedTasks.pipeline.statusBacklogged")
316
- : pipeline.status === "stalled" ? t("pages.failedTasks.pipeline.statusStalled")
317
- : t("pages.failedTasks.pipeline.statusUnknown");
318
- const variant = pipeline.status === "healthy" ? "default"
319
- : pipeline.status === "stalled" ? "destructive"
320
- : pipeline.status === "backlogged" ? "amber"
321
- : "default";
322
- return (_jsxs("div", { className: "p-5 bg-panel border border-line rounded-[var(--radius-md)] mb-4", children: [_jsxs("div", { className: "flex items-center gap-3 mb-2", children: [_jsx("span", { className: "text-[15px] font-semibold text-ink", children: t("pages.failedTasks.pipeline.title") }), _jsx("span", { className: `text-xs px-2 py-0.5 rounded-full border ${variant === "destructive" ? "border-red-300 text-red-700 bg-red-50"
323
- : variant === "amber" ? "border-amber-300 text-amber-700 bg-amber-50"
324
- : "border-line text-ink-3 bg-canvas"}`, children: statusLabel })] }), _jsx("p", { className: "text-ink-3 text-sm leading-relaxed", children: pipeline.note }), pipeline.nextAction && (_jsxs("p", { className: "text-ink-3 text-sm leading-relaxed mt-1", children: [t("pages.failedTasks.pipeline.nextActionPrefix"), pipeline.nextAction] }))] }));
325
- }
326
- function LoadedContent({ data, onCreateDraft, onRecover, initialExpandedTaskId, t }) {
327
- const hasTasks = data.tasks.length > 0;
328
- // Empty state — surface nextAction from the API (rc-9: no silent fallback).
329
- // PRI-955: the empty copy no longer claims the pipeline is healthy; the
330
- // derived queue-health block carries that judgment with facts.
331
- if (!hasTasks) {
332
- return (_jsxs("div", { className: "py-8", children: [_jsxs("div", { className: "p-5 bg-panel border border-line rounded-[var(--radius-md)]", children: [_jsx("h3", { className: "text-[17px] font-semibold text-ink mb-2", children: t("pages.failedTasks.empty") }), data.nextAction && (_jsx("p", { className: "text-ink-3 text-sm leading-relaxed", children: data.nextAction }))] }), data.pipeline && _jsx(PipelineHealthCard, { pipeline: data.pipeline, t: t })] }));
333
- }
334
- const grouped = groupTasksByKind(data.tasks);
335
- const sortedKinds = Array.from(grouped.keys()).sort();
336
- return (_jsxs(_Fragment, { children: [data.pipeline && _jsx(PipelineHealthCard, { pipeline: data.pipeline, t: t }), _jsx("div", { className: "space-y-6", children: sortedKinds.map((kind) => {
337
- const tasks = grouped.get(kind);
338
- if (!tasks || tasks.length === 0)
339
- return null;
340
- return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Badge, { variant: "outline", children: t("pages.failedTasks.kind") }), _jsxs(CardTitle, { className: "text-[15px] font-mono", children: [kind, " (", tasks.length, ")"] })] }) }), _jsx(CardContent, { children: _jsx(TaskTable, { tasks: tasks, onCreateDraft: onCreateDraft, onRecover: onRecover, initialExpandedTaskId: initialExpandedTaskId, t: t }) })] }, kind));
341
- }) }), _jsxs("div", { className: "mt-8 font-mono text-[11px] text-ink-4 space-y-1", children: [_jsxs("div", { children: [t("common.total"), ": ", data.total] }), data.total > data.tasks.length && (_jsx("div", { className: "text-amber/80 leading-relaxed", children: t("pages.failedTasks.partialResults")
342
- .replace("{shown}", String(data.tasks.length))
343
- .replace("{total}", String(data.total)) }))] })] }));
344
- }
345
- function TaskTable({ tasks, onCreateDraft, onRecover, initialExpandedTaskId, t }) {
346
- // PRI-747 F22: one row at a time is expanded into its detail panel.
347
- // ?taskId= deep link seeds the initial expansion (only when this table
348
- // actually contains the task); after mount it behaves like a normal toggle.
349
- const deepLinkTask = initialExpandedTaskId !== undefined
350
- ? tasks.find((task) => task.taskId === initialExpandedTaskId)
351
- : undefined;
352
- const [expandedId, setExpandedId] = useState(deepLinkTask?.taskId ?? null);
353
- const [detail, setDetail] = useState({ status: "idle" });
354
- // Drop responses from a superseded expand/collapse (rc-7: only the newest
355
- // request's result may become current state).
356
- const detailRequestIdRef = useRef(0);
357
- const deepLinkFetchedRef = useRef(false);
358
- // Fetch (or refetch) one task's detail; a stale response from a superseded
359
- // request is dropped (rc-7: only the newest request's result may land).
360
- const requestDetail = useCallback(async (taskId) => {
361
- const requestId = ++detailRequestIdRef.current;
362
- setDetail({ status: "loading", taskId });
363
- // Lazy fetch on expand: the list view stays cheap; the run history is
364
- // only loaded when the Owner actually asks for this task's detail.
365
- const result = await fetchFailedTaskDetail(taskId);
366
- if (requestId !== detailRequestIdRef.current)
367
- return;
368
- if (result.success) {
369
- setDetail({ status: "loaded", taskId, data: result.data });
370
- }
371
- else {
372
- // rc-9: surface the server-provided reason + next action (404 = the
373
- // task recovered/changed state after the list was loaded).
374
- setDetail({ status: "error", taskId, message: result.error, nextAction: result.nextAction });
375
- }
376
- }, []);
377
- // Deep link (?taskId=): fetch the linked task's detail and scroll its row
378
- // into view once. The table mounts only after the task list has loaded, so
379
- // the row is present at first effect run. The URL param is untrusted
380
- // (rc-1): CSS.escape (unquoted attribute selector) keeps a crafted id from
381
- // breaking the selector.
382
- useEffect(() => {
383
- if (deepLinkTask === undefined || deepLinkFetchedRef.current)
384
- return;
385
- deepLinkFetchedRef.current = true;
386
- void requestDetail(deepLinkTask.taskId);
387
- const row = document.querySelector(`[data-testid=${CSS.escape(`detail-toggle-${deepLinkTask.taskId}`)}]`);
388
- row?.scrollIntoView({ block: "center" });
389
- }, [deepLinkTask, requestDetail]);
390
- const toggleDetail = useCallback((taskId) => {
391
- if (expandedId === taskId) {
392
- // Invalidate any in-flight response, then collapse.
393
- detailRequestIdRef.current += 1;
394
- setExpandedId(null);
395
- setDetail({ status: "idle" });
396
- return;
397
- }
398
- setExpandedId(taskId);
399
- void requestDetail(taskId);
400
- }, [expandedId, requestDetail]);
401
- return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_minmax(0,1fr)_auto_minmax(0,1fr)_auto_minmax(0,1fr)_auto_auto] gap-3 pb-2 border-b border-line font-mono text-[10px] uppercase tracking-[0.08em] text-ink-4", children: [_jsx("span", { "aria-hidden": "true" }), _jsx("span", { children: t("pages.failedTasks.taskId") }), _jsx("span", { children: t("pages.failedTasks.painId") }), _jsx("span", { children: t("pages.failedTasks.status") }), _jsx("span", { children: t("pages.failedTasks.lastError") }), _jsx("span", { children: t("pages.failedTasks.attempts") }), _jsx("span", { children: t("pages.failedTasks.lastAttempt") }), _jsx("span", { "aria-hidden": "true" }), _jsx("span", { "aria-hidden": "true" })] }), tasks.map((task) => {
402
- const isExpanded = expandedId === task.taskId;
403
- return (_jsxs(Fragment, { children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_minmax(0,1fr)_auto_minmax(0,1fr)_auto_minmax(0,1fr)_auto_auto] gap-3 py-2 items-center text-[13px] border-b border-line/50 last:border-b-0", children: [_jsx(Button, { variant: "quiet", size: "icon", className: "h-6 w-6 shrink-0 text-[12px]", onClick: () => toggleDetail(task.taskId), "aria-label": t("pages.failedTasks.detailToggle"), "aria-expanded": isExpanded, "data-testid": `detail-toggle-${task.taskId}`, children: isExpanded ? "▾" : "▸" }), _jsx("span", { className: "font-mono text-ink-2 truncate", title: task.taskId, children: truncateId(task.taskId) }), _jsx("span", { className: "font-mono text-ink-3 truncate", title: task.painId ?? "", children: task.painId ? truncateId(task.painId) : t("pages.failedTasks.noPainId") }), _jsx(Badge, { variant: statusToVariant(task.status), children: task.status }), _jsx("span", { className: "text-ink-3 truncate", title: task.lastError ?? "", children: task.lastError ?? "—" }), _jsx("span", { className: "font-mono text-ink-2 text-center", children: task.attemptCount }), _jsx("span", { className: "font-mono text-ink-3 text-[12px]", children: task.lastAttemptAt ? formatDateTime(task.lastAttemptAt) : "—" }), task.ownerDecisionRequired === true ? (_jsxs("span", { className: "whitespace-nowrap text-[12px]", children: [_jsx("span", { className: "text-amber", children: t("pages.failedTasks.awaitingOwnerDecision") }), " ", _jsx("a", { href: "#/focus", className: "text-gov underline underline-offset-2 hover:text-gov/80", "data-testid": `go-focus-${task.taskId}`, children: t("pages.failedTasks.goGovernanceFocus") })] })) : onRecover ? (_jsx(Button, { variant: "default", size: "sm", onClick: () => onRecover(task), className: "whitespace-nowrap", children: t("pages.failedTasks.recover") })) : null, _jsx(Button, { variant: "outline", size: "sm", onClick: () => onCreateDraft(task), className: "whitespace-nowrap", children: t("pages.failedTasks.createDraft") })] }), isExpanded && (_jsx("div", { className: "border border-line/60 rounded-[var(--radius-md)] bg-panel/60 p-4 mb-2", "data-testid": `detail-panel-${task.taskId}`, children: _jsx(TaskDetailPanel, { state: detail.status === "idle" ? { status: "loading", taskId: task.taskId } : detail, taskId: task.taskId, onRetry: requestDetail, t: t }) }))] }, task.taskId));
404
- })] }));
405
- }
406
- function TaskDetailPanel({ state, taskId, onRetry, t }) {
407
- if (state.status === "loading") {
408
- return (_jsx("div", { className: "text-ink-3 text-[13px]", "data-testid": "detail-loading", children: t("common.loading") }));
409
- }
410
- if (state.status === "error") {
411
- // rc-9: reason + next action + an explicit retry affordance
412
- return (_jsxs("div", { className: "text-[13px] space-y-2", "data-testid": "detail-error", children: [_jsxs("div", { className: "text-danger", children: [t("pages.failedTasks.detailError"), ": ", state.message] }), state.nextAction && _jsx("div", { className: "text-ink-3", children: state.nextAction }), _jsx("div", { children: _jsx(Button, { variant: "outline", size: "sm", onClick: () => onRetry(taskId), children: t("common.refresh") }) })] }));
413
- }
414
- // The idle state only occurs if the panel renders for a task whose fetch was
415
- // superseded mid-flight; treat it as loading for the row just expanded.
416
- if (state.status === "idle" || state.taskId !== taskId) {
417
- return (_jsx("div", { className: "text-ink-3 text-[13px]", "data-testid": "detail-loading", children: t("common.loading") }));
418
- }
419
- const { data } = state;
420
- return (_jsxs("div", { className: "space-y-4 text-[13px]", children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-4 gap-y-1 font-mono text-[12px]", children: [_jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.taskId") }), _jsx("span", { className: "text-ink-2 break-all", children: data.taskId }), _jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.kind") }), _jsx("span", { className: "text-ink-2", children: data.taskKind }), _jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.status") }), _jsx("span", { className: "text-ink-2", children: data.status }), _jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.createdAt") }), _jsx("span", { className: "text-ink-3", children: formatDateTime(data.createdAt) }), data.updatedAt && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.updatedAt") }), _jsx("span", { className: "text-ink-3", children: formatDateTime(data.updatedAt) })] })), _jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.attempts") }), _jsxs("span", { className: "text-ink-2", children: [data.attemptCount, " / ", data.maxAttempts] }), _jsx("span", { className: "text-ink-4 uppercase tracking-[0.08em] self-center", children: t("pages.failedTasks.lastError") }), _jsx("span", { className: data.lastError ? "text-danger" : "text-ink-3", children: data.lastError ?? "—" })] }), _jsxs("div", { children: [_jsxs("div", { className: "font-mono text-[10px] uppercase tracking-[0.08em] text-ink-4 mb-2", children: [t("pages.failedTasks.runsTitle"), " (", data.runs.length, ")"] }), data.runs.length === 0 ? (_jsx("div", { className: "text-ink-3", children: t("pages.failedTasks.noRuns") })) : (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "grid grid-cols-[auto_auto_minmax(0,1fr)_minmax(0,1fr)] gap-3 pb-1 border-b border-line/50 font-mono text-[10px] uppercase tracking-[0.08em] text-ink-4", children: [_jsx("span", { children: t("pages.failedTasks.runAttempt") }), _jsx("span", { children: t("pages.failedTasks.status") }), _jsx("span", { children: t("pages.failedTasks.runStarted") }), _jsx("span", { children: t("pages.failedTasks.runReason") })] }), data.runs.map((run) => (_jsxs("div", { className: "grid grid-cols-[auto_auto_minmax(0,1fr)_minmax(0,1fr)] gap-3 py-1 text-[12px] border-b border-line/30 last:border-b-0", title: `${t("pages.failedTasks.runEnded")}: ${run.endedAt ? formatDateTime(run.endedAt) : "—"}${run.errorCategory ? ` · ${t("pages.failedTasks.runErrorCategory")}: ${run.errorCategory}` : ""}`, children: [_jsxs("span", { className: "font-mono text-ink-2", children: ["#", run.attemptNumber] }), _jsx("span", { className: "font-mono text-ink-3", children: run.executionStatus }), _jsx("span", { className: "font-mono text-ink-3", children: formatDateTime(run.startedAt) }), _jsx("span", { className: "text-ink-3 break-words", title: run.reason ?? undefined, children: run.reason ?? (run.errorCategory ?? "—") })] }, run.runId)))] }))] })] }));
421
- }
@@ -1,24 +0,0 @@
1
- import type { ApprovalsGroupedData } from '../../api.js';
2
- export declare function ApprovalSubjectReading({ principleId, approvalId, artifactId, channel, lockedReason, targetHost, onResolved, revisionReview, revisionReviewUnavailable, allowedActions, budgetNotice, promptInjection, sourceUnlinked, showPrincipleLink }: {
3
- principleId: string;
4
- approvalId: string;
5
- artifactId: string;
6
- channel: string;
7
- lockedReason?: string;
8
- targetHost?: 'openclaw' | 'codex' | 'workbuddy';
9
- onResolved?: (message: string) => void;
10
- revisionReview?: {
11
- artifactId?: string;
12
- artifactDigest?: string;
13
- oldStatement: string;
14
- newStatement: string;
15
- intentFields: Record<string, string>;
16
- };
17
- revisionReviewUnavailable?: boolean;
18
- /** Backend-assessed actions for THIS approval; absent means no per-action gate (the guarded submit still applies). */
19
- allowedActions?: readonly ('approve' | 'reject' | 'edit_approval')[];
20
- budgetNotice?: string;
21
- promptInjection?: ApprovalsGroupedData['promptInjection'];
22
- sourceUnlinked?: boolean;
23
- showPrincipleLink?: boolean;
24
- }): import("react").JSX.Element;
@@ -1,133 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { Link, useLocation } from 'react-router-dom';
4
- import { useTranslation } from 'react-i18next';
5
- import { fetchApprovalReview, fetchOwnerDecisionView, approveApproval, rejectApproval, editApproval, fetchAllActivations } from '../../api.js';
6
- import { localizeApprovalWarning } from '../../utils/approval-warning-localization.js';
7
- import { truncateByCodePoints } from '../../utils/reading-layout.js';
8
- export function ApprovalSubjectReading({ principleId, approvalId, artifactId, channel, lockedReason, targetHost, onResolved, revisionReview, revisionReviewUnavailable, allowedActions, budgetNotice, promptInjection, sourceUnlinked, showPrincipleLink = true }) {
9
- const { t } = useTranslation();
10
- const location = useLocation();
11
- const [review, setReview] = useState(null);
12
- const [view, setView] = useState(null);
13
- const [viewSettled, setViewSettled] = useState(false);
14
- const [error, setError] = useState('');
15
- const [resultText, setResultText] = useState('');
16
- const [loading, setLoading] = useState(true);
17
- const [busy, setBusy] = useState(false);
18
- const [mode, setMode] = useState(null);
19
- const [reason, setReason] = useState('');
20
- const [newArtifact, setNewArtifact] = useState('');
21
- const [intentReviewed, setIntentReviewed] = useState(false);
22
- const [approveNote, setApproveNote] = useState('');
23
- const epoch = useRef(0);
24
- const read = useCallback(async () => {
25
- const current = ++epoch.current;
26
- setReview(null);
27
- setLoading(true);
28
- setIntentReviewed(false);
29
- setError('');
30
- const result = await fetchApprovalReview(approvalId);
31
- if (current !== epoch.current)
32
- return null;
33
- setLoading(false);
34
- if (result.success) {
35
- setReview(result.data);
36
- return result.data;
37
- }
38
- setError([result.error, result.nextAction].filter(Boolean).join(' '));
39
- return null;
40
- }, [approvalId]);
41
- useEffect(() => {
42
- setError('');
43
- setResultText('');
44
- setView(null);
45
- setViewSettled(false);
46
- setMode(null);
47
- setReason('');
48
- setNewArtifact('');
49
- setApproveNote('');
50
- let current = true;
51
- void read();
52
- void fetchOwnerDecisionView(principleId).then(result => { if (current) {
53
- setView(result.success ? result.data : null);
54
- setViewSettled(true);
55
- } });
56
- return () => { current = false; epoch.current++; };
57
- }, [principleId, approvalId, artifactId, channel, read]);
58
- const narrative = (field) => field.status === 'known' ? field.value.map(item => item.text).join('\n\n') : field.reason.ownerText;
59
- const subject = view?.decisionSubjects.find(item => item.key === approvalId && item.channel === channel
60
- && item.revisionArtifactId.status === 'known' && item.revisionArtifactId.value === review?.expectedReview.artifactId);
61
- const materialBlocks = subject?.materialGates.find(gate => gate.actionSemantic === 'approve')?.requiredItems.filter(item => item.status !== 'satisfied') ?? [];
62
- const revisionMatches = !revisionReview || (review?.expectedReview.artifactState === 'present' && review.expectedReview.artifactId === artifactId
63
- && revisionReview.artifactId === review.expectedReview.artifactId && revisionReview.artifactDigest === review.expectedReview.artifactDigest);
64
- const approveReady = review?.approval.status === 'pending' && subject !== undefined && review.expectedReview.artifactState === 'present' && review.material.exactBody !== null && review.material.availability === 'available' && revisionMatches && !revisionReviewUnavailable && materialBlocks.length === 0;
65
- const may = (semantic) => allowedActions === undefined || allowedActions.includes(semantic);
66
- async function submit(action) {
67
- if (!review || busy || lockedReason || review.approval.status !== 'pending')
68
- return;
69
- if (!may(action === 'approve' ? 'approve' : action === 'reject' ? 'reject' : 'edit_approval'))
70
- return;
71
- if (action === 'approve' && (!approveReady || (revisionReview && !intentReviewed)))
72
- return;
73
- if (action !== 'approve' && !reason.trim())
74
- return;
75
- if (action === 'edit' && !newArtifact.trim())
76
- return;
77
- const snapshot = review;
78
- const current = epoch.current;
79
- setBusy(true);
80
- setError('');
81
- setResultText('');
82
- const result = action === 'approve' ? await approveApproval(approvalId, approveNote.trim() || undefined, { expectedReview: snapshot.expectedReview, targetHost,
83
- ...(revisionReview ? { intentReviewed, reviewedArtifactId: snapshot.expectedReview.artifactId } : {}) })
84
- : action === 'reject' ? await rejectApproval(approvalId, reason.trim(), snapshot.expectedReview)
85
- : await editApproval(approvalId, newArtifact.trim(), { reason: reason.trim(), expectedReview: snapshot.expectedReview });
86
- if (current !== epoch.current)
87
- return;
88
- const fresh = await read();
89
- setBusy(false);
90
- if (!fresh) {
91
- setError(t('pages.focus.workbench.resultUnknown'));
92
- return;
93
- }
94
- if (fresh.approval.status === 'approved' || fresh.approval.status === 'rejected') {
95
- const state = t(fresh.approval.status === 'approved' ? 'pages.focus.workbench.currentApproved' : 'pages.focus.workbench.currentRejected');
96
- const ownOutcome = result.success && ((action === 'approve' && fresh.approval.status === 'approved') || (action === 'reject' && fresh.approval.status === 'rejected'));
97
- const refused = !result.success && result.status !== undefined && result.status >= 400 && result.status < 500;
98
- let message = ownOutcome ? t(fresh.approval.status === 'approved' ? 'pages.focus.workbench.approved' : 'pages.focus.workbench.rejected')
99
- : refused ? t('pages.focus.workbench.refusedCurrentState', { state }) + ' ' + [result.error, result.nextAction].filter(Boolean).join(' ')
100
- : t('pages.focus.workbench.currentStateConfirmed', { state });
101
- if (fresh.approval.status === 'approved' && !result.success && !refused) {
102
- const activations = await fetchAllActivations(targetHost);
103
- if (epoch.current !== current + 1)
104
- return;
105
- const active = activations.success && activations.data.activations.some(item => item.artifactId === fresh.approval.artifactId && item.status === 'active');
106
- message += ' ' + t(active ? 'pages.focus.workbench.runtimeCheckLink' : result.reason === 'activation_failed' ? 'pages.focus.workbench.activationFailed' : 'pages.focus.workbench.approvedRuntimeUnknown');
107
- }
108
- if (result.success && result.data.warning) {
109
- const warning = localizeApprovalWarning(result.data.warning, t);
110
- message += ` ${warning.title} ${warning.body ?? warning.detail}`;
111
- }
112
- setResultText(message);
113
- onResolved?.(message);
114
- return;
115
- }
116
- if (!result.success)
117
- setError(t(result.status === undefined ? 'pages.focus.workbench.resultUnknown' : 'pages.focus.workbench.notRecorded') + ' ' + [result.error, result.nextAction].filter(Boolean).join(' '));
118
- else if (action === 'edit') {
119
- setResultText(t('pages.focus.workbench.replaced'));
120
- setMode(null);
121
- setReason('');
122
- setNewArtifact('');
123
- setApproveNote('');
124
- }
125
- }
126
- const body = review?.material.exactBody;
127
- const bodyText = body?.text ?? review?.material.statement ?? '';
128
- return _jsxs("div", { className: "space-y-7", children: [_jsxs("section", { children: [_jsx("h3", { className: "mb-3 text-[15px] font-medium text-ink", children: t('pages.focus.workbench.why') }), sourceUnlinked && _jsx("p", { role: "alert", className: "mb-3 text-sm leading-relaxed text-amber", children: t('pages.focus.workbench.sourceUnlinked') }), _jsx("p", { className: "whitespace-pre-wrap text-[14px] leading-relaxed text-ink-2", children: view ? narrative(view.incidentSummary) : t('pages.focus.workbench.materialUnavailable') })] }), _jsxs("section", { children: [_jsx("h3", { className: "mb-3 text-[15px] font-medium text-ink", children: t('pages.focus.workbench.proposal') }), loading ? _jsx("p", { role: "status", className: "text-sm text-ink-3", children: t('pages.focus.workbench.loading') }) : _jsxs(_Fragment, { children: [bodyText ? _jsxs(_Fragment, { children: [_jsx("p", { className: "mb-2 text-[12px] text-ink-4", children: t(body?.kind === 'rule_code' ? 'pages.focus.workbench.codePreview' : 'pages.focus.workbench.textPreview') }), _jsx("p", { className: "whitespace-pre-wrap break-words text-[15px] leading-[1.85] text-ink", children: truncateByCodePoints(bodyText, 240) }), _jsxs("details", { className: "mt-4 rounded-[4px] border border-line px-4 py-3 text-[13px]", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t(body?.kind === 'rule_code' ? 'pages.focus.workbench.fullCode' : 'pages.focus.workbench.fullText') }), _jsx("div", { className: "mt-4 whitespace-pre-wrap break-words text-[15px] leading-[1.85] text-ink-2", children: bodyText })] })] }) : _jsx("p", { className: "text-sm text-amber", children: t('pages.focus.workbench.exactMaterialMissing') }), review?.material.scope.length ? _jsxs("div", { className: "mt-4", children: [_jsx("h4", { className: "text-sm font-medium text-ink", children: t('pages.focus.workbench.scope') }), _jsx("ul", { className: "mt-2 list-disc space-y-1 pl-5 text-[13px] leading-relaxed text-ink-2", children: review.material.scope.map((scope, index) => _jsx("li", { children: scope }, index)) })] }) : null, review?.material.rationale && _jsxs("details", { className: "mt-4 text-[13px] text-ink-3", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.focus.workbench.reasonAndScope') }), _jsx("p", { className: "mt-3 whitespace-pre-wrap leading-relaxed", children: review.material.rationale })] }), revisionReview && _jsxs("details", { className: "mt-4 text-[13px] leading-relaxed text-ink-2", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.focus.workbench.compare') }), _jsx("p", { className: "mt-3 whitespace-pre-wrap", children: revisionReview.oldStatement }), _jsx("p", { className: "mt-3 whitespace-pre-wrap", children: revisionReview.newStatement }), _jsx("dl", { className: "mt-3", children: Object.entries(revisionReview.intentFields).map(([key, value]) => _jsxs("div", { children: [_jsx("dt", { className: "font-medium", children: t(`pages.focus.intentField.${key}`, { defaultValue: key }) }), _jsx("dd", { children: value })] }, key)) })] })] })] }), _jsxs("section", { className: "border-t border-line pt-5", "data-testid": "approval-review-limits", children: [_jsx("h3", { className: "mb-3 text-[15px] font-medium text-ink", children: t('pages.focus.workbench.beforeDecision') }), viewSettled && !subject && _jsx("p", { className: "text-sm leading-relaxed text-amber", children: t('pages.focus.workbench.subjectUnconfirmed') }), review && _jsx("div", { className: "mb-3 text-sm leading-relaxed text-ink-2", "data-testid": "approval-exact-risks", children: review.material.risks?.length ? _jsx("ul", { className: "list-disc space-y-1 pl-5", children: review.material.risks.map((risk, index) => _jsx("li", { children: risk }, index)) }) : _jsx("p", { children: t(review.material.risks === null ? 'pages.focus.workbench.risksUnknown' : 'pages.focus.workbench.risksEmpty') }) }), materialBlocks.map(item => _jsx("p", { className: "mb-2 text-sm leading-relaxed text-amber", children: item.ownerText }, item.key)), !revisionMatches && _jsx("p", { role: "alert", className: "mb-2 text-sm text-amber", children: t('pages.focus.workbench.revisionChanged') }), revisionReviewUnavailable && _jsx("p", { role: "alert", className: "mb-2 text-sm text-amber", children: t('pages.focus.revisionReviewUnavailable') }), budgetNotice && channel === 'prompt' && _jsx("p", { role: "alert", className: "mb-2 text-sm leading-relaxed text-amber", "data-testid": `approve-queue-badge-${principleId}`, children: budgetNotice }), promptInjection && channel === 'prompt' && _jsxs("details", { className: "mb-3 text-[12px] leading-relaxed text-ink-3", "data-testid": `approve-queue-badge-scope-${principleId}`, children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.focus.workbench.budgetBasis') }), _jsxs("p", { className: "mt-2", children: [promptInjection.route === 'shared_render' ? t('pages.focus.promptScopeShared') : t('pages.focus.promptScopeList', { full: promptInjection.fullRenderChars !== undefined ? t('pages.focus.promptScopeFullRender', { count: promptInjection.fullRenderChars }) : '' }), promptInjection.hostKind ? ` · ${promptInjection.hostKind}` : ''] }), _jsx("p", { className: "mt-2", children: promptInjection.budgetCapacityStatus === 'confirmed' && promptInjection.budgetContextWindowTokens !== undefined
129
- ? promptInjection.budgetObservedAt !== undefined ? t('pages.focus.promptBudgetObservedNote', { source: t(promptInjection.budgetCapacitySource === 'pi_catalog_exact' ? 'pages.focus.budgetCapacitySourcePiCatalog' : promptInjection.budgetCapacitySource === 'operator_declared' ? 'pages.focus.budgetCapacitySourceOperatorDeclared' : 'pages.focus.budgetCapacitySourceHostWindow'), window: promptInjection.budgetContextWindowTokens, observedAt: promptInjection.budgetObservedAt })
130
- : t('pages.focus.promptBudgetModelAwareNote', { window: promptInjection.budgetContextWindowTokens, sourceSuffix: promptInjection.budgetCapacitySource === 'operator_declared' ? t('pages.focus.budgetCapacitySourceOperatorDeclaredSuffix') : '' })
131
- : promptInjection.budgetObservedAt !== undefined ? t('pages.focus.promptBudgetFallbackObservedNote', { reason: t(`pages.focus.budgetFallbackReason.${promptInjection.budgetFallbackReason}`, { defaultValue: promptInjection.budgetFallbackReason ?? 'unknown' }), observedAt: promptInjection.budgetObservedAt })
132
- : t('pages.focus.promptBudgetFallbackNote', { reason: promptInjection.budgetFallbackReason ? t('pages.focus.promptBudgetFallbackReasonSuffix', { code: t(`pages.focus.budgetFallbackReason.${promptInjection.budgetFallbackReason}`, { defaultValue: promptInjection.budgetFallbackReason }) }) : '' }) })] }), review?.material.targetBehavior && _jsxs("div", { className: "mb-3 text-[14px] leading-relaxed text-ink-2", "data-testid": "approval-exact-target-behavior", children: [_jsx("h4", { className: "mb-1 font-medium", children: t('pages.focus.workbench.proposedBehavior') }), _jsx("p", { className: "whitespace-pre-wrap break-words", children: review.material.targetBehavior })] }), subject && _jsx("p", { className: "text-sm leading-relaxed text-ink-2", children: narrative(subject.decisionMaterial.consequence) }), _jsx("p", { className: "mt-2 text-[13px] leading-relaxed text-ink-3", children: t('pages.focus.workbench.scopeUnknown') }), view && _jsxs("details", { className: "mt-3 text-[13px] leading-relaxed text-ink-3", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.focus.workbench.principleLimits') }), _jsx("p", { className: "mt-3", children: view.nonApplicabilityOrUnknown.status === 'known' ? view.nonApplicabilityOrUnknown.value.map(item => item.text).join(' ') : view.nonApplicabilityOrUnknown.reason.ownerText }), _jsx("p", { className: "mt-2", children: view.risk.status === 'known' ? view.risk.value?.items.map(item => item.text).join(' ') || t('pages.principles.detail.ownerDecision.riskNotAssessed') : view.risk.reason?.ownerText }), _jsx("p", { className: "mt-2", children: view.uncertainty.status === 'known' ? view.uncertainty.value.map(item => item.text).join(' ') : view.uncertainty.reason.ownerText })] })] }), _jsxs("section", { className: "border-t border-line pt-5", children: [_jsx("h3", { className: "mb-3 text-[15px] font-medium text-ink", children: t('pages.focus.workbench.decision') }), lockedReason && _jsx("p", { role: "alert", className: "mb-3 text-[13px] leading-relaxed text-amber", children: lockedReason }), error && _jsx("p", { role: "alert", className: "mb-3 text-[13px] leading-relaxed text-amber", children: error }), resultText && _jsx("p", { role: "status", className: "mb-3 text-sm leading-relaxed text-ink", children: resultText }), !review && !loading && _jsx("button", { type: "button", className: "text-sm text-gov underline", onClick: () => { void read(); }, children: t('pages.focus.workbench.retry') }), review?.approval.status === 'pending' && _jsxs(_Fragment, { children: [_jsxs("details", { className: "mb-4 text-sm text-ink-3", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.focus.workbench.approvalNote') }), _jsxs("label", { className: "mt-3 block", children: [t('pages.focus.workbench.approvalNote'), _jsx("textarea", { value: approveNote, maxLength: 2000, onChange: event => setApproveNote(event.target.value), className: "mt-2 block w-full rounded border border-line bg-panel px-3 py-2" })] })] }), revisionReview && _jsxs("label", { className: "mb-4 block text-sm text-ink-2", children: [_jsx("input", { type: "checkbox", checked: intentReviewed, onChange: event => setIntentReviewed(event.target.checked), className: "mr-2" }), t('pages.focus.workbench.intentReviewed')] }), _jsx("p", { className: "mb-4 text-[12.5px] leading-relaxed text-ink-3", children: t(channel === 'code_tool_hook' ? 'pages.focus.workbench.ruleConsequence' : channel === 'defer_archive' ? 'pages.focus.workbench.archiveConsequence' : 'pages.focus.workbench.promptConsequence') }), _jsxs("div", { className: "flex flex-wrap gap-3", children: [_jsx("button", { type: "button", disabled: !approveReady || busy || Boolean(lockedReason) || !may('approve') || Boolean(revisionReview && !intentReviewed), "data-testid": `approve-btn-${principleId}`, onClick: () => { void submit('approve'); }, className: "rounded-[4px] border border-gov bg-gov px-4 py-2.5 text-[13px] text-paper disabled:opacity-50", children: t(channel === 'defer_archive' ? 'pages.focus.workbench.approveArchive' : 'pages.focus.workbench.approveOne') }), _jsx("button", { type: "button", disabled: busy || Boolean(lockedReason) || !may('reject'), onClick: () => setMode('reject'), className: "rounded-[4px] border border-line px-4 py-2.5 text-[13px] text-ink disabled:opacity-50", children: t('pages.focus.workbench.rejectOne') }), _jsx("button", { type: "button", "data-testid": `edit-btn-${principleId}`, disabled: busy || Boolean(lockedReason) || !may('edit_approval') || review.expectedReview.artifactState === 'missing', onClick: () => setMode('edit'), className: "text-[13px] text-gov underline disabled:opacity-50", children: t('pages.focus.workbench.replaceOne') })] }), mode && _jsxs("form", { className: "mt-4 space-y-3", onSubmit: event => { event.preventDefault(); void submit(mode); }, children: [mode === 'edit' && _jsxs("label", { className: "block text-sm text-ink-2", children: [t('pages.focus.workbench.replacementId'), _jsx("input", { value: newArtifact, onChange: event => setNewArtifact(event.target.value), className: "mt-2 block w-full rounded border border-line bg-panel px-3 py-2" })] }), _jsxs("label", { className: "block text-sm text-ink-2", children: [t('pages.focus.workbench.reason'), _jsx("textarea", { value: reason, maxLength: 2000, onChange: event => setReason(event.target.value), className: "mt-2 block w-full rounded border border-line bg-panel px-3 py-2" })] }), _jsx("button", { type: "submit", disabled: busy || !reason.trim() || (mode === 'edit' && !newArtifact.trim()), className: "rounded border border-line px-4 py-2 text-sm disabled:opacity-50", children: t('pages.focus.workbench.confirm') }), _jsx("button", { type: "button", onClick: () => setMode(null), className: "ml-3 text-sm text-ink-3", children: t('pages.focus.workbench.cancel') })] })] }), showPrincipleLink && _jsx(Link, { className: "mt-5 inline-block text-[13px] text-gov underline underline-offset-4", state: { returnTo: `/focus${location.search}` }, to: `/principles/${encodeURIComponent(principleId)}`, children: t('pages.focus.workbench.openPrinciple') }), _jsxs("details", { className: "mt-4 text-[12px] text-ink-4", children: [_jsx("summary", { className: "cursor-pointer", children: t('pages.focus.workbench.subjectDetails') }), _jsxs("dl", { className: "mt-2 break-all font-mono", children: [_jsxs("div", { children: ["approval: ", approvalId] }), _jsxs("div", { children: ["artifact: ", review?.expectedReview.artifactId ?? artifactId] }), _jsxs("div", { children: ["channel: ", review?.expectedReview.channel ?? channel] })] })] })] })] });
133
- }