create-principles-disciple 1.146.4 → 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 (308) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/package.json +3 -3
  3. package/release-manager/package.json +3 -3
  4. package/console/dist/ui/App.d.ts +0 -1
  5. package/console/dist/ui/App.js +0 -172
  6. package/console/dist/ui/api.d.ts +0 -611
  7. package/console/dist/ui/api.js +0 -1094
  8. package/console/dist/ui/components/auth/login-form.d.ts +0 -4
  9. package/console/dist/ui/components/auth/login-form.js +0 -142
  10. package/console/dist/ui/components/auth/splash-screen.d.ts +0 -9
  11. package/console/dist/ui/components/auth/splash-screen.js +0 -22
  12. package/console/dist/ui/components/error-boundary.d.ts +0 -15
  13. package/console/dist/ui/components/error-boundary.js +0 -30
  14. package/console/dist/ui/components/focus/daily-thought-card.d.ts +0 -1
  15. package/console/dist/ui/components/focus/daily-thought-card.js +0 -41
  16. package/console/dist/ui/components/language-switcher.d.ts +0 -2
  17. package/console/dist/ui/components/language-switcher.js +0 -17
  18. package/console/dist/ui/components/layout/app-sidebar.d.ts +0 -27
  19. package/console/dist/ui/components/layout/app-sidebar.js +0 -128
  20. package/console/dist/ui/components/layout/page-loading.d.ts +0 -13
  21. package/console/dist/ui/components/layout/page-loading.js +0 -14
  22. package/console/dist/ui/components/layout/page-shell.d.ts +0 -12
  23. package/console/dist/ui/components/layout/page-shell.js +0 -11
  24. package/console/dist/ui/components/layout/section-title.d.ts +0 -10
  25. package/console/dist/ui/components/layout/section-title.js +0 -9
  26. package/console/dist/ui/components/notifications/NotificationProvider.d.ts +0 -14
  27. package/console/dist/ui/components/notifications/NotificationProvider.js +0 -136
  28. package/console/dist/ui/components/notifications/favicon-badge.d.ts +0 -3
  29. package/console/dist/ui/components/notifications/favicon-badge.js +0 -68
  30. package/console/dist/ui/components/notifications/notification-reducer.d.ts +0 -9
  31. package/console/dist/ui/components/notifications/notification-reducer.js +0 -9
  32. package/console/dist/ui/components/notifications/sound-storage.d.ts +0 -3
  33. package/console/dist/ui/components/notifications/sound-storage.js +0 -37
  34. package/console/dist/ui/components/notifications/useNotifications.d.ts +0 -1
  35. package/console/dist/ui/components/notifications/useNotifications.js +0 -9
  36. package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +0 -8
  37. package/console/dist/ui/components/onboarding/CircuitDiagram.js +0 -18
  38. package/console/dist/ui/components/onboarding/DemoResultView.d.ts +0 -22
  39. package/console/dist/ui/components/onboarding/DemoResultView.js +0 -33
  40. package/console/dist/ui/components/onboarding/SlashCommandsCard.d.ts +0 -16
  41. package/console/dist/ui/components/onboarding/SlashCommandsCard.js +0 -20
  42. package/console/dist/ui/components/onboarding/slashCommands.d.ts +0 -20
  43. package/console/dist/ui/components/onboarding/slashCommands.js +0 -22
  44. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.d.ts +0 -6
  45. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.js +0 -66
  46. package/console/dist/ui/components/theme-provider.d.ts +0 -14
  47. package/console/dist/ui/components/theme-provider.js +0 -40
  48. package/console/dist/ui/components/theme-toggle.d.ts +0 -2
  49. package/console/dist/ui/components/theme-toggle.js +0 -11
  50. package/console/dist/ui/components/ui/alert-dialog.d.ts +0 -20
  51. package/console/dist/ui/components/ui/alert-dialog.js +0 -26
  52. package/console/dist/ui/components/ui/badge.d.ts +0 -9
  53. package/console/dist/ui/components/ui/badge.js +0 -22
  54. package/console/dist/ui/components/ui/button.d.ts +0 -11
  55. package/console/dist/ui/components/ui/button.js +0 -34
  56. package/console/dist/ui/components/ui/card.d.ts +0 -8
  57. package/console/dist/ui/components/ui/card.js +0 -16
  58. package/console/dist/ui/components/ui/charts.d.ts +0 -51
  59. package/console/dist/ui/components/ui/charts.js +0 -72
  60. package/console/dist/ui/components/ui/dialog.d.ts +0 -19
  61. package/console/dist/ui/components/ui/dialog.js +0 -22
  62. package/console/dist/ui/components/ui/input.d.ts +0 -3
  63. package/console/dist/ui/components/ui/input.js +0 -8
  64. package/console/dist/ui/components/ui/markdown.d.ts +0 -24
  65. package/console/dist/ui/components/ui/markdown.js +0 -119
  66. package/console/dist/ui/components/ui/progress-bar.d.ts +0 -20
  67. package/console/dist/ui/components/ui/progress-bar.js +0 -38
  68. package/console/dist/ui/components/ui/select.d.ts +0 -13
  69. package/console/dist/ui/components/ui/select.js +0 -26
  70. package/console/dist/ui/components/ui/separator.d.ts +0 -3
  71. package/console/dist/ui/components/ui/separator.js +0 -6
  72. package/console/dist/ui/components/ui/sheet.d.ts +0 -25
  73. package/console/dist/ui/components/ui/sheet.js +0 -37
  74. package/console/dist/ui/components/ui/shiny-text.d.ts +0 -28
  75. package/console/dist/ui/components/ui/shiny-text.js +0 -46
  76. package/console/dist/ui/components/ui/skeleton.d.ts +0 -3
  77. package/console/dist/ui/components/ui/skeleton.js +0 -6
  78. package/console/dist/ui/components/ui/sonner.d.ts +0 -3
  79. package/console/dist/ui/components/ui/sonner.js +0 -13
  80. package/console/dist/ui/components/ui/tooltip.d.ts +0 -7
  81. package/console/dist/ui/components/ui/tooltip.js +0 -10
  82. package/console/dist/ui/data/daily-thoughts.d.ts +0 -15
  83. package/console/dist/ui/data/daily-thoughts.js +0 -164
  84. package/console/dist/ui/hooks/useNotificationSound.d.ts +0 -12
  85. package/console/dist/ui/hooks/useNotificationSound.js +0 -74
  86. package/console/dist/ui/i18n/en.json +0 -2399
  87. package/console/dist/ui/i18n/index.d.ts +0 -2
  88. package/console/dist/ui/i18n/index.js +0 -32
  89. package/console/dist/ui/i18n/zh-CN.json +0 -2399
  90. package/console/dist/ui/main.d.ts +0 -1
  91. package/console/dist/ui/main.js +0 -9
  92. package/console/dist/ui/pages/ReportProblemValidators.d.ts +0 -144
  93. package/console/dist/ui/pages/ReportProblemValidators.js +0 -418
  94. package/console/dist/ui/pages/activation/ActivationPage.d.ts +0 -1
  95. package/console/dist/ui/pages/activation/ActivationPage.js +0 -512
  96. package/console/dist/ui/pages/activation/ActivationValidators.d.ts +0 -20
  97. package/console/dist/ui/pages/activation/ActivationValidators.js +0 -160
  98. package/console/dist/ui/pages/control-center/AgentCard.d.ts +0 -31
  99. package/console/dist/ui/pages/control-center/AgentCard.js +0 -212
  100. package/console/dist/ui/pages/control-center/AgentGroup.d.ts +0 -26
  101. package/console/dist/ui/pages/control-center/AgentGroup.js +0 -38
  102. package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +0 -1
  103. package/console/dist/ui/pages/control-center/ControlCenterPage.js +0 -509
  104. package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +0 -1
  105. package/console/dist/ui/pages/control-center/DesignGatePanel.js +0 -137
  106. package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +0 -31
  107. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +0 -199
  108. package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +0 -17
  109. package/console/dist/ui/pages/control-center/WorkflowDiagram.js +0 -55
  110. package/console/dist/ui/pages/debt/DebtPage.d.ts +0 -2
  111. package/console/dist/ui/pages/debt/DebtPage.js +0 -222
  112. package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +0 -2
  113. package/console/dist/ui/pages/design-system/DesignSystemPage.js +0 -30
  114. package/console/dist/ui/pages/examiner/ExaminerPage.d.ts +0 -15
  115. package/console/dist/ui/pages/examiner/ExaminerPage.js +0 -158
  116. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.d.ts +0 -1
  117. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.js +0 -421
  118. package/console/dist/ui/pages/focus/ApprovalSubjectReading.d.ts +0 -24
  119. package/console/dist/ui/pages/focus/ApprovalSubjectReading.js +0 -133
  120. package/console/dist/ui/pages/focus/FocusPage.d.ts +0 -123
  121. package/console/dist/ui/pages/focus/FocusPage.js +0 -567
  122. package/console/dist/ui/pages/focus/OwnerDecisionCard.d.ts +0 -9
  123. package/console/dist/ui/pages/focus/OwnerDecisionCard.js +0 -111
  124. package/console/dist/ui/pages/focus/OwnerWorkbench.d.ts +0 -19
  125. package/console/dist/ui/pages/focus/OwnerWorkbench.js +0 -75
  126. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.d.ts +0 -34
  127. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.js +0 -298
  128. package/console/dist/ui/pages/focus/focus-validation.d.ts +0 -40
  129. package/console/dist/ui/pages/focus/focus-validation.js +0 -211
  130. package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +0 -67
  131. package/console/dist/ui/pages/intent/IntentOnboarding.js +0 -289
  132. package/console/dist/ui/pages/intent/IntentPage.d.ts +0 -1
  133. package/console/dist/ui/pages/intent/IntentPage.js +0 -252
  134. package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +0 -59
  135. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +0 -125
  136. package/console/dist/ui/pages/pain/PainPage.d.ts +0 -1
  137. package/console/dist/ui/pages/pain/PainPage.js +0 -420
  138. package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +0 -175
  139. package/console/dist/ui/pages/pain/pain-card-helpers.js +0 -181
  140. package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +0 -10
  141. package/console/dist/ui/pages/principles/CorePrinciplesPage.js +0 -59
  142. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +0 -60
  143. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +0 -602
  144. package/console/dist/ui/pages/principles/PrinciplesPage.d.ts +0 -1
  145. package/console/dist/ui/pages/principles/PrinciplesPage.js +0 -327
  146. package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +0 -8
  147. package/console/dist/ui/pages/principles/PrinciplesViewNav.js +0 -15
  148. package/console/dist/ui/pages/report-problem/ReportProblemPage.d.ts +0 -1
  149. package/console/dist/ui/pages/report-problem/ReportProblemPage.js +0 -467
  150. package/console/dist/ui/pages/settings/SettingsPage.d.ts +0 -4
  151. package/console/dist/ui/pages/settings/SettingsPage.js +0 -457
  152. package/console/dist/ui/pages/settings/UpdatePage.d.ts +0 -1
  153. package/console/dist/ui/pages/settings/UpdatePage.js +0 -215
  154. package/console/dist/ui/pages/welcome/WelcomePage.d.ts +0 -5
  155. package/console/dist/ui/pages/welcome/WelcomePage.js +0 -187
  156. package/console/dist/ui/utils/agent-metadata.d.ts +0 -71
  157. package/console/dist/ui/utils/agent-metadata.js +0 -284
  158. package/console/dist/ui/utils/approval-review.d.ts +0 -30
  159. package/console/dist/ui/utils/approval-review.js +0 -50
  160. package/console/dist/ui/utils/approval-warning-localization.d.ts +0 -34
  161. package/console/dist/ui/utils/approval-warning-localization.js +0 -148
  162. package/console/dist/ui/utils/attention-presentation.d.ts +0 -35
  163. package/console/dist/ui/utils/attention-presentation.js +0 -46
  164. package/console/dist/ui/utils/blocker-localization.d.ts +0 -23
  165. package/console/dist/ui/utils/blocker-localization.js +0 -36
  166. package/console/dist/ui/utils/control-center-helpers.d.ts +0 -79
  167. package/console/dist/ui/utils/control-center-helpers.js +0 -189
  168. package/console/dist/ui/utils/enum-labels.d.ts +0 -50
  169. package/console/dist/ui/utils/enum-labels.js +0 -171
  170. package/console/dist/ui/utils/format-date.d.ts +0 -11
  171. package/console/dist/ui/utils/format-date.js +0 -17
  172. package/console/dist/ui/utils/onboarding-state.d.ts +0 -25
  173. package/console/dist/ui/utils/onboarding-state.js +0 -77
  174. package/console/dist/ui/utils/reading-layout.d.ts +0 -20
  175. package/console/dist/ui/utils/reading-layout.js +0 -46
  176. package/console/dist/ui/utils/rule-binding-validators.d.ts +0 -13
  177. package/console/dist/ui/utils/rule-binding-validators.js +0 -188
  178. package/console/dist/ui/utils/runtime-mode.d.ts +0 -11
  179. package/console/dist/ui/utils/runtime-mode.js +0 -11
  180. package/console/dist/ui/utils/token-storage.d.ts +0 -22
  181. package/console/dist/ui/utils/token-storage.js +0 -47
  182. package/console/dist/ui/utils/validators.d.ts +0 -1178
  183. package/console/dist/ui/utils/validators.js +0 -3297
  184. package/release-manager/dist/bootstrap-entry.d.ts +0 -2
  185. package/release-manager/dist/bootstrap-entry.d.ts.map +0 -1
  186. package/release-manager/dist/bootstrap-entry.js.map +0 -1
  187. package/release-manager/dist/i18n.d.ts +0 -6
  188. package/release-manager/dist/i18n.d.ts.map +0 -1
  189. package/release-manager/dist/i18n.js.map +0 -1
  190. package/release-manager/dist/index.d.ts +0 -7
  191. package/release-manager/dist/index.d.ts.map +0 -1
  192. package/release-manager/dist/index.js +0 -656
  193. package/release-manager/dist/index.js.map +0 -1
  194. package/release-manager/dist/installer.d.ts +0 -629
  195. package/release-manager/dist/installer.d.ts.map +0 -1
  196. package/release-manager/dist/installer.js.map +0 -1
  197. package/release-manager/dist/installers/codex-host-installer.d.ts +0 -39
  198. package/release-manager/dist/installers/codex-host-installer.d.ts.map +0 -1
  199. package/release-manager/dist/installers/codex-host-installer.js.map +0 -1
  200. package/release-manager/dist/installers/index.d.ts +0 -51
  201. package/release-manager/dist/installers/index.d.ts.map +0 -1
  202. package/release-manager/dist/installers/index.js.map +0 -1
  203. package/release-manager/dist/installers/openclaw-host-installer.d.ts +0 -14
  204. package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +0 -1
  205. package/release-manager/dist/installers/openclaw-host-installer.js.map +0 -1
  206. package/release-manager/dist/installers/workbuddy-host-installer.d.ts +0 -335
  207. package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +0 -1
  208. package/release-manager/dist/installers/workbuddy-host-installer.js.map +0 -1
  209. package/release-manager/dist/mvp-config.d.ts +0 -233
  210. package/release-manager/dist/mvp-config.d.ts.map +0 -1
  211. package/release-manager/dist/mvp-config.js.map +0 -1
  212. package/release-manager/dist/prompts.d.ts +0 -43
  213. package/release-manager/dist/prompts.d.ts.map +0 -1
  214. package/release-manager/dist/prompts.js +0 -268
  215. package/release-manager/dist/prompts.js.map +0 -1
  216. package/release-manager/dist/skill-language.d.ts +0 -32
  217. package/release-manager/dist/skill-language.d.ts.map +0 -1
  218. package/release-manager/dist/skill-language.js.map +0 -1
  219. package/release-manager/dist/uninstaller.d.ts +0 -68
  220. package/release-manager/dist/uninstaller.d.ts.map +0 -1
  221. package/release-manager/dist/uninstaller.js +0 -746
  222. package/release-manager/dist/uninstaller.js.map +0 -1
  223. package/release-manager/dist/update/apply-payload.d.ts +0 -143
  224. package/release-manager/dist/update/apply-payload.d.ts.map +0 -1
  225. package/release-manager/dist/update/apply-payload.js.map +0 -1
  226. package/release-manager/dist/update/atomic-file.d.ts +0 -35
  227. package/release-manager/dist/update/atomic-file.d.ts.map +0 -1
  228. package/release-manager/dist/update/atomic-file.js.map +0 -1
  229. package/release-manager/dist/update/bootstrap-executor.d.ts +0 -21
  230. package/release-manager/dist/update/bootstrap-executor.d.ts.map +0 -1
  231. package/release-manager/dist/update/bootstrap-executor.js.map +0 -1
  232. package/release-manager/dist/update/bootstrap-protocol.d.ts +0 -56
  233. package/release-manager/dist/update/bootstrap-protocol.d.ts.map +0 -1
  234. package/release-manager/dist/update/bootstrap-protocol.js.map +0 -1
  235. package/release-manager/dist/update/channel-metadata.d.ts +0 -28
  236. package/release-manager/dist/update/channel-metadata.d.ts.map +0 -1
  237. package/release-manager/dist/update/channel-metadata.js.map +0 -1
  238. package/release-manager/dist/update/channel-promotion.d.ts +0 -39
  239. package/release-manager/dist/update/channel-promotion.d.ts.map +0 -1
  240. package/release-manager/dist/update/channel-promotion.js +0 -55
  241. package/release-manager/dist/update/channel-promotion.js.map +0 -1
  242. package/release-manager/dist/update/console-surface.d.ts +0 -19
  243. package/release-manager/dist/update/console-surface.d.ts.map +0 -1
  244. package/release-manager/dist/update/console-surface.js.map +0 -1
  245. package/release-manager/dist/update/data-compatibility.d.ts +0 -35
  246. package/release-manager/dist/update/data-compatibility.d.ts.map +0 -1
  247. package/release-manager/dist/update/data-compatibility.js +0 -45
  248. package/release-manager/dist/update/data-compatibility.js.map +0 -1
  249. package/release-manager/dist/update/install-layout.d.ts +0 -105
  250. package/release-manager/dist/update/install-layout.d.ts.map +0 -1
  251. package/release-manager/dist/update/install-layout.js.map +0 -1
  252. package/release-manager/dist/update/product-identity.d.ts +0 -70
  253. package/release-manager/dist/update/product-identity.d.ts.map +0 -1
  254. package/release-manager/dist/update/product-identity.js.map +0 -1
  255. package/release-manager/dist/update/release-asset-manifest.d.ts +0 -31
  256. package/release-manager/dist/update/release-asset-manifest.d.ts.map +0 -1
  257. package/release-manager/dist/update/release-asset-manifest.js.map +0 -1
  258. package/release-manager/dist/update/release-identity.d.ts +0 -33
  259. package/release-manager/dist/update/release-identity.d.ts.map +0 -1
  260. package/release-manager/dist/update/release-identity.js.map +0 -1
  261. package/release-manager/dist/update/release-manager-authority.d.ts +0 -39
  262. package/release-manager/dist/update/release-manager-authority.d.ts.map +0 -1
  263. package/release-manager/dist/update/release-manager-authority.js.map +0 -1
  264. package/release-manager/dist/update/release-manager.d.ts +0 -156
  265. package/release-manager/dist/update/release-manager.d.ts.map +0 -1
  266. package/release-manager/dist/update/release-manager.js.map +0 -1
  267. package/release-manager/dist/update/release-metadata-publisher.d.ts +0 -199
  268. package/release-manager/dist/update/release-metadata-publisher.d.ts.map +0 -1
  269. package/release-manager/dist/update/release-metadata-publisher.js +0 -478
  270. package/release-manager/dist/update/release-metadata-publisher.js.map +0 -1
  271. package/release-manager/dist/update/release-metadata-source.d.ts +0 -85
  272. package/release-manager/dist/update/release-metadata-source.d.ts.map +0 -1
  273. package/release-manager/dist/update/release-metadata-source.js.map +0 -1
  274. package/release-manager/dist/update/release-metadata.d.ts +0 -60
  275. package/release-manager/dist/update/release-metadata.d.ts.map +0 -1
  276. package/release-manager/dist/update/release-metadata.js.map +0 -1
  277. package/release-manager/dist/update/release-policy.d.ts +0 -51
  278. package/release-manager/dist/update/release-policy.d.ts.map +0 -1
  279. package/release-manager/dist/update/release-policy.js.map +0 -1
  280. package/release-manager/dist/update/rollback-policy.d.ts +0 -56
  281. package/release-manager/dist/update/rollback-policy.d.ts.map +0 -1
  282. package/release-manager/dist/update/rollback-policy.js +0 -61
  283. package/release-manager/dist/update/rollback-policy.js.map +0 -1
  284. package/release-manager/dist/update/transaction-journal.d.ts +0 -212
  285. package/release-manager/dist/update/transaction-journal.d.ts.map +0 -1
  286. package/release-manager/dist/update/transaction-journal.js.map +0 -1
  287. package/release-manager/dist/update/trust-metadata.d.ts +0 -55
  288. package/release-manager/dist/update/trust-metadata.d.ts.map +0 -1
  289. package/release-manager/dist/update/trust-metadata.js.map +0 -1
  290. package/release-manager/dist/update/trust-root-provisioning.d.ts +0 -99
  291. package/release-manager/dist/update/trust-root-provisioning.d.ts.map +0 -1
  292. package/release-manager/dist/update/trust-root-provisioning.js.map +0 -1
  293. package/release-manager/dist/update/update-history.d.ts +0 -46
  294. package/release-manager/dist/update/update-history.d.ts.map +0 -1
  295. package/release-manager/dist/update/update-history.js +0 -123
  296. package/release-manager/dist/update/update-history.js.map +0 -1
  297. package/release-manager/dist/utils/config-file-io.d.ts +0 -34
  298. package/release-manager/dist/utils/config-file-io.d.ts.map +0 -1
  299. package/release-manager/dist/utils/config-file-io.js.map +0 -1
  300. package/release-manager/dist/utils/env.d.ts +0 -94
  301. package/release-manager/dist/utils/env.d.ts.map +0 -1
  302. package/release-manager/dist/utils/env.js.map +0 -1
  303. package/release-manager/dist/utils/logger.d.ts +0 -15
  304. package/release-manager/dist/utils/logger.d.ts.map +0 -1
  305. package/release-manager/dist/utils/logger.js.map +0 -1
  306. package/release-manager/dist/utils/workspace-divergence.d.ts +0 -36
  307. package/release-manager/dist/utils/workspace-divergence.d.ts.map +0 -1
  308. package/release-manager/dist/utils/workspace-divergence.js.map +0 -1
@@ -1,512 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useCallback } from "react";
3
- import { Link, useNavigate, useSearchParams } from "react-router-dom";
4
- import { useTranslation } from "react-i18next";
5
- import { toast } from "sonner";
6
- import { PageShell } from "../../components/layout/page-shell.js";
7
- import { PageLoading } from "../../components/layout/page-loading.js";
8
- import { SectionTitle } from "../../components/layout/section-title.js";
9
- import { ShinyText } from "../../components/ui/shiny-text.js";
10
- import { Button } from "../../components/ui/button.js";
11
- import { fetchAllActivations, disableActivation, fetchLifecycleMetrics, fetchReceiptCounts, fetchRuleCodeOwnerReview, fetchApprovedRuleRevisionPreview, reviseApprovedRuleOnce, proposePromptRevision, ruleCodeDecision, pauseAllRuleCode, releaseRuleCodePause, } from "../../api.js";
12
- import { ReceiptCoverageDisclosure, getReceiptSourceStatusLabelKey } from "../../components/receipts/ReceiptCoverageDisclosure.js";
13
- import { validateActivationsData, validateLifecycleMetricsData, isReversibleChannel, } from "./ActivationValidators.js";
14
- import { enumLabel } from "../../utils/enum-labels.js";
15
- import { formatDate } from "../../utils/format-date.js";
16
- function tierFitLabel(t, tierFit) {
17
- if (tierFit === undefined)
18
- return t("pages.activation.fitUnknown", { defaultValue: "未知" });
19
- if (tierFit === "fits_all_tiers")
20
- return t("pages.activation.fitYes", { defaultValue: "可装入" });
21
- if (tierFit === "model_dependent")
22
- return t("pages.activation.fitModelDependent", { defaultValue: "视模型而定" });
23
- return t("pages.activation.fitNo", { defaultValue: "超长" });
24
- }
25
- // Date+time rendering options — mirrors the old default toLocaleString() shape
26
- // (numeric date, hours/minutes/seconds) while following the UI language.
27
- const DATETIME_OPTS = {
28
- year: "numeric",
29
- month: "numeric",
30
- day: "numeric",
31
- hour: "numeric",
32
- minute: "2-digit",
33
- second: "2-digit",
34
- };
35
- // ── Channel label helper ─────────────────────────────────────────────────────
36
- function getChannelLabel(channel, t) {
37
- return enumLabel('channel', channel, t);
38
- }
39
- // ── Sub-components ───────────────────────────────────────────────────────────
40
- function CapabilityBoundaryDeclaration() {
41
- const { t } = useTranslation();
42
- return (_jsx("div", { className: "px-[18px] py-[14px] bg-panel border border-line rounded-[6px] text-ink-3 text-[13px] leading-relaxed", role: "note", "aria-label": t("pages.activation.boundaryLabel"), children: t("pages.activation.boundaryText") }));
43
- }
44
- function ApprovedRuleRevisionPanel({ activationId, onChanged }) {
45
- const { t } = useTranslation();
46
- const [preview, setPreview] = useState(null);
47
- const [feedback, setFeedback] = useState('');
48
- const [error, setError] = useState(null);
49
- const [busy, setBusy] = useState(false);
50
- const [submitted, setSubmitted] = useState(false);
51
- // A concurrent/earlier revision already holds this artifact's budget. That is
52
- // not this request succeeding, and the feedback just typed was NOT recorded.
53
- const [alreadyStarted, setAlreadyStarted] = useState(false);
54
- // Preserve the exact request across a transport retry; a new ID is not a new
55
- // budget (the server's budget is anchored on the artifact digest + receipt,
56
- // so editing the feedback and resending cannot spend a second round).
57
- const [pendingRequestId, setPendingRequestId] = useState(null);
58
- const load = useCallback(async () => {
59
- const result = await fetchApprovedRuleRevisionPreview(activationId);
60
- if (result.success) {
61
- setPreview(result.data);
62
- setError(null);
63
- }
64
- else
65
- setError(result.error);
66
- }, [activationId]);
67
- useEffect(() => { void load(); }, [load]);
68
- const revise = async () => {
69
- if (preview?.status !== 'ready')
70
- return;
71
- const input = {
72
- expectedArtifactId: preview.expectedArtifactId, expectedArtifactDigest: preview.expectedArtifactDigest,
73
- expectedBindingRevision: preview.expectedBindingRevision, expectedControlVersion: preview.expectedControlVersion,
74
- expectedTaskRevisionEpoch: preview.expectedTaskRevisionEpoch,
75
- requestId: pendingRequestId ?? crypto.randomUUID(), feedback: feedback.trim(),
76
- };
77
- setPendingRequestId(input.requestId);
78
- setBusy(true);
79
- setError(null);
80
- const result = await reviseApprovedRuleOnce(activationId, input);
81
- setBusy(false);
82
- if (!result.success) {
83
- setError(result.error);
84
- return;
85
- }
86
- if (result.data.status === 'refused') {
87
- setPendingRequestId(null);
88
- // Take the server verdict as the current view: if the refresh below also
89
- // fails, the stale `ready` form must not stay submittable.
90
- setPreview(result.data);
91
- setError(result.data.nextAction);
92
- await load();
93
- return;
94
- }
95
- if (result.data.status === 'already_started') {
96
- toast.info(t('pages.activation.ruleRevisionAlreadyExists'));
97
- setAlreadyStarted(true);
98
- return;
99
- }
100
- // Announce before onChanged(): the parent reload unmounts this panel, and a
101
- // panel-local confirmation would disappear with it.
102
- toast.success(t('pages.activation.ruleRevisionStarted'));
103
- setSubmitted(true);
104
- onChanged();
105
- };
106
- return _jsxs("div", { className: "mt-3 rounded border border-line p-3 text-[12px] text-ink-3", "data-testid": `approved-rule-revision-${activationId}`, children: [_jsx("div", { className: "font-medium text-ink", children: t('pages.activation.ruleRevisionTitle') }), _jsx("p", { className: "mt-1", children: t('pages.activation.ruleRevisionBoundary') }), error && _jsx("p", { role: "alert", className: "mt-2 text-danger", children: error }), alreadyStarted ? _jsxs("div", { className: "mt-2", children: [_jsx("p", { role: "status", children: t('pages.activation.ruleRevisionAlreadyExists') }), _jsx(Link, { to: "/focus", className: "mt-1 inline-block text-gov underline", children: t('pages.activation.ruleRevisionReviewQueue') })] })
107
- : submitted ? _jsxs("div", { className: "mt-2", children: [_jsx("p", { role: "status", className: "text-green", children: t('pages.activation.ruleRevisionStarted') }), _jsx(Link, { to: "/focus", className: "mt-1 inline-block text-gov underline", children: t('pages.activation.ruleRevisionReviewQueue') })] })
108
- : preview?.status === 'ready' ? _jsxs(_Fragment, { children: [_jsxs("label", { className: "mt-2 block", children: [t('pages.activation.ruleRevisionFeedback'), _jsx("textarea", { value: feedback, maxLength: 4000, disabled: busy, onChange: event => { setFeedback(event.target.value); setPendingRequestId(null); }, className: "mt-1 min-h-20 w-full rounded border border-line bg-panel px-3 py-2 text-ink" })] }), _jsx(Button, { disabled: busy || feedback.trim().length === 0, onClick: () => void revise(), children: t('pages.activation.ruleRevisionOnce') })] }) : preview?.status === 'refused' ? _jsx("p", { className: "mt-2", children: preview.nextAction })
109
- : _jsx("p", { className: "mt-2", children: t('pages.activation.ownerDecisionLoading') })] });
110
- }
111
- function RuleCodeOwnerPanel({ record, onChanged }) {
112
- const { t } = useTranslation();
113
- const [review, setReview] = useState(null);
114
- const [error, setError] = useState(null);
115
- const [busy, setBusy] = useState(false);
116
- const [note, setNote] = useState('');
117
- const [overrideReason, setOverrideReason] = useState('rare_behavior');
118
- const load = useCallback(async () => { const result = await fetchRuleCodeOwnerReview(record.activationId); if (result.success) {
119
- setReview(result.data);
120
- setError(null);
121
- }
122
- else
123
- setError(result.error); }, [record.activationId]);
124
- useEffect(() => { void load(); }, [load]);
125
- const decide = async (action) => {
126
- if (!review)
127
- return;
128
- setBusy(true);
129
- const reasonCode = action === 'promote' && review.readiness.status === 'evidence_insufficient'
130
- ? overrideReason
131
- : action;
132
- const body = { idempotencyKey: `${action}-${crypto.randomUUID()}`, reasonCode, note };
133
- if (action === 'promote')
134
- Object.assign(body, { confirmed: true, artifactId: review.artifact.artifactId, artifactDigest: review.artifact.digest, controlVersion: review.controlState?.version });
135
- if (action === 'recover-to-shadow')
136
- Object.assign(body, { controlVersion: review.controlState?.version });
137
- const result = await ruleCodeDecision(record.activationId, action, body);
138
- setBusy(false);
139
- if (result.success) {
140
- toast.success(t('pages.activation.ownerDecisionRecorded'));
141
- onChanged();
142
- await load();
143
- }
144
- else {
145
- setError(result.error);
146
- if (result.nextAction)
147
- toast.info(result.nextAction);
148
- }
149
- };
150
- const releasePause = async () => { if (!review?.globalPause)
151
- return; setBusy(true); const result = await releaseRuleCodePause(review.globalPause.pauseId, { idempotencyKey: `release-${crypto.randomUUID()}`, reasonCode: 'owner_releases_global_latch', expectedVersion: review.globalPause.version, note }); setBusy(false); if (result.success) {
152
- toast.success(t('pages.activation.globalPauseReleased'));
153
- onChanged();
154
- await load();
155
- }
156
- else
157
- setError(result.error); };
158
- if (error)
159
- return _jsx("div", { className: "mt-3 border-l-2 border-danger px-3 text-[12px] text-danger", children: error });
160
- if (!review)
161
- return _jsx("div", { className: "mt-3 text-[12px] text-ink-4", children: t('pages.activation.ownerDecisionLoading') });
162
- const summary = review.readiness.evidenceSnapshot.shadowSummary;
163
- const value = (number) => number === null ? t('pages.activation.notCollected') : String(number);
164
- const affectedTools = Array.isArray(review.artifact.content?.affectedTools) ? review.artifact.content.affectedTools.filter((item) => typeof item === 'string') : [];
165
- const renderWindow = (title, window) => _jsxs("div", { className: "rounded border border-line p-2", children: [_jsx("div", { className: "font-medium text-ink", children: title }), _jsxs("div", { className: "mt-1 grid grid-cols-2 gap-1 md:grid-cols-5", children: [_jsxs("span", { children: [t('pages.activation.eligibleEvaluations'), ": ", value(window.eligible)] }), _jsxs("span", { children: [t('pages.activation.matched'), ": ", value(window.matched)] }), _jsxs("span", { children: [t('pages.activation.blocked'), ": ", value(window.blocked)] }), _jsxs("span", { children: [t('pages.activation.unhealthy'), ": ", value(window.unhealthy)] }), _jsxs("span", { children: [t('pages.activation.circuitTrips'), ": ", window.circuitTrips] })] }), _jsxs("div", { className: "mt-1 text-ink-4", children: [t('pages.activation.toolDistribution'), ": ", window.toolDistribution === null ? t('pages.activation.notCollected') : Object.entries(window.toolDistribution).map(([tool, count]) => `${tool} ${count}`).join(', ') || '—'] })] });
166
- return _jsxs("div", { className: "mt-4 rounded-[5px] border border-gov/25 bg-surface/70 p-4", "data-testid": `owner-review-${record.activationId}`, children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("strong", { className: "text-[13px] text-ink", children: t('pages.activation.ownerDecisionTitle') }), _jsx("span", { className: "font-mono text-[11px] text-gov", children: review.readiness.status }), review.controlState?.enforcement === 'safety_isolated' && _jsx("span", { className: "text-danger text-[11px]", children: t('pages.activation.safetyIsolation') })] }), _jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2 text-[12px] text-ink-3 md:grid-cols-4", children: [_jsxs("span", { children: [t('pages.activation.eligibleEvaluations'), ": ", value(summary.observed)] }), _jsxs("span", { children: [t('pages.activation.matched'), ": ", value(summary.matched)] }), _jsxs("span", { children: [t('pages.activation.wouldBlock'), ": ", value(summary.wouldBlock)] }), _jsxs("span", { children: [t('pages.activation.wouldAllow'), ": ", value(summary.wouldAllow)] }), _jsxs("span", { children: [t('pages.activation.requireApproval'), ": ", value(summary.requireApproval)] }), _jsxs("span", { children: [t('pages.activation.autoCorrect'), ": ", value(summary.autoCorrect)] }), _jsxs("span", { children: [t('pages.activation.neutralControl'), ": ", value(summary.neutralControl)] }), _jsxs("span", { children: [t('pages.activation.evaluationErrors'), ": ", value(summary.errors)] })] }), _jsx("div", { className: "mt-2 text-[11px] text-ink-4", children: t('pages.activation.shadowWindow', { first: summary.firstObservedAt ?? t('pages.activation.notCollected'), last: summary.lastObservedAt ?? t('pages.activation.notCollected') }) }), _jsx("div", { className: "mt-2 text-[12px] text-ink-3", children: t('pages.activation.runtimeCapability', { version: review.runtimeCapability.hostRuntimeVersion, supported: t(review.runtimeCapability.shadowEvidence ? 'pages.activation.supported' : 'pages.activation.unsupported') }) }), _jsx("div", { className: "mt-2 text-[12px] text-amber", children: t('pages.activation.worstImpact', { tools: affectedTools.join(', ') || t('pages.activation.notCollected') }) }), _jsxs("div", { className: "mt-3 text-[12px] text-ink-3", children: [_jsx("div", { className: "mb-1 font-medium text-ink", children: t('pages.activation.hardSafetyChecks') }), review.readiness.evidenceSnapshot.safetyGateResults.map(check => _jsxs("div", { className: check.status === 'passed' ? 'text-green' : 'text-danger', children: [t(`pages.activation.checks.${check.checkId}`, { defaultValue: check.checkId }), ": ", t(`pages.activation.checkStatus.${check.status}`, { defaultValue: check.status }), check.reasonCode ? ` · ${t(`pages.activation.reasonCodes.${check.reasonCode}`, { defaultValue: check.reasonCode })}` : ''] }, check.checkId))] }), review.readiness.failedChecks.length > 0 && _jsx("ul", { className: "mt-2 text-[12px] text-danger", children: review.readiness.failedChecks.map(check => _jsxs("li", { children: [t(`pages.activation.checks.${check.checkId}`, { defaultValue: check.checkId }), ": ", t(`pages.activation.reasonCodes.${check.reasonCode}`, { defaultValue: check.reasonCode })] }, check.checkId)) }), _jsxs("details", { className: "mt-2 text-[12px]", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.activation.scopeArtifactCode') }), _jsx("pre", { className: "mt-2 max-h-64 overflow-auto whitespace-pre-wrap text-ink-3", children: JSON.stringify(review.artifact.content, null, 2) })] }), _jsxs("div", { className: "mt-3 grid gap-2 text-[11px] text-ink-3 md:grid-cols-2", children: [renderWindow(t('pages.activation.live24Hours'), review.liveMetrics.last24Hours), renderWindow(t('pages.activation.live7Days'), review.liveMetrics.last7Days)] }), _jsx("div", { className: "mt-2 text-[11px] text-ink-3", children: t('pages.activation.behaviorDrift', { approved: value(review.behaviorDrift.approvedBlockRate), live: value(review.behaviorDrift.liveBlockRate), delta: value(review.behaviorDrift.delta) }) }), review.liveMetrics.representativeSamples.length > 0 && _jsxs("details", { className: "mt-2 text-[12px]", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.activation.representativeSamples') }), review.liveMetrics.representativeSamples.map((sample, index) => _jsxs("div", { className: "font-mono text-ink-3", children: [sample.toolName, " \u00B7 ", sample.decision, " \u00B7 ", sample.pathCategory] }, `${sample.toolName}-${index}`))] }), review.decisions.length > 0 && _jsxs("details", { className: "mt-2 text-[12px]", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('pages.activation.ownerDecisionHistory') }), review.decisions.map(decision => _jsxs("div", { className: "mt-1 border-l border-line pl-2 text-ink-3", children: [_jsx("span", { className: "font-mono", children: decision.decidedAt }), " \u00B7 ", decision.decision, " \u00B7 ", decision.principalKind, ":", decision.actorId, " \u00B7 ", decision.authenticationMethod, " \u00B7 ", decision.reasonCode, decision.note ? ` · ${decision.note}` : ''] }, decision.decisionId))] }), _jsx("div", { className: "mt-2 text-[11px] text-ink-4", children: t('pages.activation.circuitConditions') }), record.action === 'code_tool_hook_shadow_activate' && _jsx(ApprovedRuleRevisionPanel, { activationId: record.activationId, onChanged: onChanged }), review.readiness.status === 'evidence_insufficient' && _jsxs("label", { className: "mt-3 block text-[12px] text-ink-3", children: [t('pages.activation.overrideReason'), _jsxs("select", { value: overrideReason, onChange: event => setOverrideReason(event.target.value), className: "mt-1 w-full rounded border border-line bg-panel px-3 py-2 text-ink", children: [_jsx("option", { value: "rare_behavior", children: t('pages.activation.overrideRareBehavior') }), _jsx("option", { value: "controlled_rollout", children: t('pages.activation.overrideControlledRollout') }), _jsx("option", { value: "owner_accepts_limited_evidence", children: t('pages.activation.overrideOwnerAccepts') })] })] }), _jsx("input", { value: note, onChange: event => setNote(event.target.value), placeholder: t('pages.activation.ownerReviewNote'), className: "mt-3 w-full rounded border border-line bg-panel px-3 py-2 text-[12px] text-ink" }), _jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [review.globalPause?.status === 'paused' && _jsx(Button, { disabled: busy || !review.ownerDecisionEnabled, variant: "outline", onClick: () => void releasePause(), children: t('pages.activation.releaseGlobalPause') }), record.action === 'code_tool_hook_shadow_activate' && _jsxs(_Fragment, { children: [_jsx(Button, { disabled: busy || !review.ownerDecisionEnabled, onClick: () => void decide('continue-observing'), children: t('pages.activation.continueObserving') }), _jsx(Button, { disabled: busy || !review.ownerDecisionEnabled, variant: "outline", onClick: () => void decide('reject-after-shadow'), children: t('pages.activation.rejectAfterShadow') }), _jsx(Button, { disabled: busy || !review.ownerDecisionEnabled || (review.readiness.status !== 'ready' && review.readiness.status !== 'evidence_insufficient') || (review.readiness.status === 'evidence_insufficient' && note.trim().length === 0), onClick: () => void decide('promote'), children: t('pages.activation.confirmLive') })] }), (record.action === 'code_tool_hook_live_activate' || review.controlState?.enforcement === 'safety_isolated') && _jsx(Button, { disabled: busy, variant: "destructive", onClick: () => void decide('emergency-deactivate'), children: t('pages.activation.emergencyDeactivate') }), review.controlState?.enforcement === 'safety_isolated' && _jsx(Button, { disabled: busy || !review.ownerDecisionEnabled, variant: "outline", onClick: () => void decide('recover-to-shadow'), children: t('pages.activation.recoverToShadow') })] }), !review.ownerDecisionEnabled && _jsx("div", { className: "mt-2 text-[11px] text-amber", children: t('pages.activation.rolloutDisabled') })] });
167
- }
168
- function ActivationFactCard({ record, lifecycleData, receiptCount, onDisable, disabling, onChanged, }) {
169
- const { t, i18n } = useTranslation();
170
- const navigate = useNavigate();
171
- const [showConfirm, setShowConfirm] = useState(false);
172
- const neverActivated = record.activatedAt === null;
173
- const channelLabel = getChannelLabel(record.channel, t);
174
- const reversible = isReversibleChannel(record.channel);
175
- // PD_PROMPT_CAPACITY_V1 R-B3: “修改为可注入版本”入口——只对 live prompt 激活开放。
176
- const canProposeRevision = record.channel === "prompt" && record.status === "active";
177
- const [showRevisionInput, setShowRevisionInput] = useState(false);
178
- const [revisionText, setRevisionText] = useState("");
179
- const [revisionSubmitting, setRevisionSubmitting] = useState(false);
180
- const [revisionResult, setRevisionResult] = useState(null);
181
- const handleProposeRevision = async () => {
182
- if (!revisionText.trim() || revisionSubmitting)
183
- return;
184
- setRevisionSubmitting(true);
185
- try {
186
- const res = await proposePromptRevision(record.activationId, revisionText.trim());
187
- if (res.success) {
188
- if (res.data?.ok === true) {
189
- setRevisionResult(res.data);
190
- setShowRevisionInput(false);
191
- toast.success(res.data.alreadyPending
192
- ? t("pages.activation.revisionAlreadyPending", { defaultValue: "该原则已有一个待审批的修改版本" })
193
- : t("pages.activation.revisionQueued", { defaultValue: "新版本已创建并进入待审批,批准后将自动替换当前版本" }));
194
- onChanged();
195
- }
196
- else {
197
- toast.error(t("pages.activation.revisionFailed", {
198
- defaultValue: "创建修改版本失败:{{reason}}",
199
- reason: res.data?.reason ?? res.data?.error ?? "unknown",
200
- }));
201
- }
202
- }
203
- else {
204
- toast.error(t("pages.activation.revisionFailed", {
205
- defaultValue: "创建修改版本失败:{{reason}}",
206
- reason: res.reason ?? res.error ?? "unknown",
207
- }));
208
- }
209
- }
210
- catch {
211
- toast.error(t("pages.activation.revisionFailedNetwork", { defaultValue: "创建修改版本失败,请稍后重试。" }));
212
- }
213
- finally {
214
- setRevisionSubmitting(false);
215
- }
216
- };
217
- return (_jsxs("article", { className: `relative pl-[22px] py-[18px] pr-[18px] bg-panel border rounded-[6px] transition-colors hover:border-line-2 ${neverActivated ? "border-amber/30 border-l-[3px] border-l-amber" : "border-line"}`, "data-testid": `activation-card-${record.activationId}`, children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap pr-24", children: [_jsx("span", { className: `inline-flex items-center border rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase ${record.status === "active"
218
- ? "border-green/35 text-green bg-green/5"
219
- : "border-line text-ink-4 bg-surface/80"}`, role: "status", children: record.status === "active" ? t("pages.activation.statusActive") : t("pages.activation.statusInactive") }), _jsx("span", { className: "inline-flex items-center border border-line rounded-[2px] px-[7px] py-1 font-mono text-[11px] text-ink-3 bg-surface/80 uppercase", children: channelLabel }), reversible && (_jsx("span", { className: "inline-flex items-center border border-amber/35 text-amber rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.activation.tagReversible") })), !reversible && record.channel === "code_tool_hook" && (_jsx("span", { className: "inline-flex items-center border border-danger/35 text-danger rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.activation.tagHighRisk") })), neverActivated && (_jsx("span", { className: "inline-flex items-center border border-amber/35 text-amber rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.activation.tagNeverActivated") }))] }), _jsx(Button, { variant: "ghost", size: "sm", className: "absolute top-[14px] right-[14px]", "data-testid": `activation-feedback-${record.activationId}`, onClick: () => {
220
- const params = new URLSearchParams({
221
- source: "activation_page",
222
- activationId: record.activationId,
223
- });
224
- if (record.principleId) {
225
- params.set("principleId", record.principleId);
226
- }
227
- navigate(`/report-problem?${params.toString()}`);
228
- }, children: t("pages.reportProblem.entryFeedback") }), _jsxs("div", { className: "mt-[14px] mb-2", children: [_jsx("span", { className: "text-ink-2 text-[13px]", children: t("pages.activation.principleLabel") }), " ", _jsx(Link, { to: `/principles/${record.principleId}`, className: "text-gov text-[13px] hover:underline focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", "data-testid": `principle-link-${record.principleId}`, title: record.principleId, children: record.action }), _jsx("span", { className: "ml-2 font-mono text-[11px] text-ink-4", children: record.principleId })] }), record.legacyDecisionUnknown && _jsx("div", { className: "mt-3 border-l-2 border-amber px-3 text-[12px] text-amber", children: t('pages.activation.legacyUnknown', { due: record.ownerReviewDueAt ? formatDate(record.ownerReviewDueAt, i18n.language, DATETIME_OPTS) : t('pages.activation.sevenDays') }) }), _jsxs("div", { className: "text-ink-3 text-[13px] leading-relaxed space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "text-ink-4 font-mono text-[11px] uppercase", children: t("pages.activation.actionLabel") }), " ", _jsx("span", { className: "text-ink-2", children: record.action })] }), _jsxs("div", { children: [_jsx("span", { className: "text-ink-4 font-mono text-[11px] uppercase", children: t("pages.activation.targetLabel") }), " ", _jsx("span", { className: "text-ink-2 font-mono text-[12px]", children: record.targetRef })] }), _jsxs("div", { children: [_jsx("span", { className: "text-ink-4 font-mono text-[11px] uppercase", children: t("pages.activation.activatedAtLabel") }), " ", neverActivated ? (_jsx("span", { className: "text-amber", children: t("pages.activation.neverActivated") })) : (_jsx("span", { className: "text-ink-2 font-mono text-[12px] tabular-nums", children: formatDate(record.activatedAt, i18n.language, DATETIME_OPTS) }))] }), record.promptInjection !== undefined && (_jsxs("div", { className: "flex items-start gap-2", "data-testid": `activation-injection-${record.activationId}`, children: [_jsx("span", { className: "text-ink-4 font-mono text-[11px] uppercase", children: t("pages.activation.injectionLabel", { defaultValue: "注入状态" }) }), _jsxs("span", { className: `text-[12.5px] leading-relaxed ${record.promptInjection.status === "injectable"
229
- ? "text-ink-2"
230
- : record.promptInjection.status === "window_excluded" || record.promptInjection.status === "model_dependent"
231
- ? "text-amber"
232
- : "text-danger"}`, children: [record.promptInjection.status === "injectable" &&
233
- t("pages.activation.injectionInjectable", {
234
- defaultValue: "可注入(当前窗口内,{{cost}}/{{budget}} 字符)",
235
- cost: record.promptInjection.costChars ?? 0,
236
- budget: record.promptInjection.budget ?? 0,
237
- }), record.promptInjection.status === "window_excluded" &&
238
- (record.promptInjection.route === "legacy_trim"
239
- ? t("pages.activation.injectionWindowRotates", {
240
- defaultValue: "本轮未入窗口:单条可装入({{cost}}/{{budget}} 字符),后续轮次会轮到(预测)",
241
- cost: record.promptInjection.costChars ?? 0,
242
- budget: record.promptInjection.budget ?? 0,
243
- })
244
- : t("pages.activation.injectionWindowFifo", {
245
- defaultValue: "本轮未入窗口:单条可装入({{cost}}/{{budget}} 字符),当前路由不轮转,需腾出容量才会注入",
246
- cost: record.promptInjection.costChars ?? 0,
247
- budget: record.promptInjection.budget ?? 0,
248
- })), record.promptInjection.status === "oversized" &&
249
- t("pages.activation.injectionOversized", {
250
- defaultValue: "超长不可注入:单条已 {{cost}} 字符 > 上限 {{budget}} 字符,轮转也救不了——需精简正文",
251
- cost: record.promptInjection.costChars ?? 0,
252
- budget: record.promptInjection.budget ?? 0,
253
- }), record.promptInjection.status === "model_dependent" &&
254
- t("pages.activation.injectionModelDependent", {
255
- defaultValue: "取决于模型上下文:单条 {{cost}} 字符在最小预算内装不下、但在支持上限内——较小上下文模型会排除它,较大模型可注入",
256
- cost: record.promptInjection.costChars ?? 0,
257
- }), record.promptInjection.status === "resolution_failed" &&
258
- t("pages.activation.injectionResolutionFailed", {
259
- defaultValue: "无法判定:{{reason}}",
260
- reason: record.promptInjection.reason ?? "unknown",
261
- }), record.promptInjection.status === "route_unconfirmed" && (_jsxs(_Fragment, { children: [t("pages.activation.injectionRouteUnconfirmed", {
262
- defaultValue: "当前宿主容量未确认:OpenClaw {{oc}} / Codex {{cx}} / WorkBuddy {{wb}}",
263
- oc: tierFitLabel(t, record.promptInjection.perHostFits?.find((f) => f.hostKind === "openclaw")?.tierFit),
264
- cx: tierFitLabel(t, record.promptInjection.perHostFits?.find((f) => f.hostKind === "codex")?.tierFit),
265
- wb: tierFitLabel(t, record.promptInjection.perHostFits?.find((f) => f.hostKind === "workbuddy")?.tierFit),
266
- }), record.promptInjection.reason !== undefined && (_jsx("span", { className: "block text-ink-4 text-[11.5px]", children: record.promptInjection.reason }))] }))] })] })), canProposeRevision && (_jsxs("div", { className: "mt-2", "data-testid": `activation-revision-${record.activationId}`, children: [!showRevisionInput && revisionResult === null && (_jsx("button", { type: "button", onClick: () => { setShowRevisionInput(true); setRevisionText(""); }, "data-testid": `activation-revision-open-${record.activationId}`, className: "inline-flex items-center border border-line rounded-[3px] px-[10px] py-[4px] text-[12px] hover:border-line-2", children: t("pages.activation.revisionOpen", { defaultValue: "修改为可注入版本" }) })), showRevisionInput && (_jsxs("div", { className: "rounded-[3px] border border-line bg-surface/60 p-2", children: [_jsx("textarea", { value: revisionText, onChange: (e) => setRevisionText(e.target.value), rows: 3, className: "w-full rounded-[2px] border border-line bg-panel px-2 py-1 text-[12.5px]", placeholder: t("pages.activation.revisionPlaceholder", { defaultValue: "输入新的原则正文(保留触发条件、必须动作和必要例外,尽量精简)" }), "data-testid": `activation-revision-input-${record.activationId}` }), _jsxs("div", { className: "mt-1 flex gap-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: handleProposeRevision, disabled: revisionSubmitting || revisionText.trim().length === 0, "data-testid": `activation-revision-submit-${record.activationId}`, children: revisionSubmitting ? t("common.loading") + "…" : t("pages.activation.revisionSubmit", { defaultValue: "创建待审批的新版本" }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setShowRevisionInput(false), children: t("common.cancel", { defaultValue: "取消" }) })] })] })), revisionResult !== null && (_jsxs("div", { className: "rounded-[3px] border border-gov/40 bg-gov/5 p-2 text-[12px] leading-relaxed", "data-testid": `activation-revision-result-${record.activationId}`, children: [_jsx("p", { children: t("pages.activation.revisionResultNote", {
267
- defaultValue: "新版本已进入待审批(审批号 {{approvalId}})。批准后旧版本自动停用并由新版本替换;拒绝则旧版本继续生效。",
268
- approvalId: revisionResult.approvalId ?? "",
269
- }) }), typeof revisionResult.oldStatement === "string" && revisionResult.oldStatement.length > 0 && (_jsxs("details", { className: "mt-1", children: [_jsx("summary", { className: "cursor-pointer text-ink-3", children: t("pages.activation.revisionDiff", { defaultValue: "查看正文差异" }) }), _jsxs("div", { className: "mt-1 grid gap-1", children: [_jsx("div", { className: "rounded-[2px] bg-amber/5 p-1 text-ink-2 line-through", children: revisionResult.oldStatement }), _jsx("div", { className: "rounded-[2px] bg-green/5 p-1 text-ink", children: revisionResult.newStatement })] })] })), _jsx(Link, { to: "/", className: "mt-1 inline-block text-gov hover:underline", "data-testid": `activation-revision-goto-approve-${record.activationId}`, children: t("pages.activation.revisionGoApprove", { defaultValue: "前往治理焦点审批新版本" }) })] }))] })), receiptCount !== undefined && (_jsxs("div", { "data-testid": `activation-receipts-${record.activationId}`, children: [_jsx("span", { className: "text-ink-4 font-mono text-[11px] uppercase", children: t("pages.activation.receiptsLabel") }), " ", _jsx("span", { className: "text-ink-2 font-mono text-[12px] tabular-nums", children: t("pages.activation.receiptsValue", {
270
- effect: receiptCount?.effectCount ?? 0,
271
- presence: receiptCount?.presenceCount ?? 0,
272
- }) })] }))] }), lifecycleData !== undefined && (_jsxs("details", { className: "mt-4 group", children: [_jsx("summary", { className: "text-gov text-[13px] cursor-pointer hover:underline focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("pages.activation.lifecycleToggle") }), _jsx("div", { className: "mt-2 pl-4 border-l-2 border-line", children: lifecycleData === null ? (_jsx("div", { className: "text-ink-4 text-[13px] py-2", children: t("pages.activation.lifecycleUnavailable") })) : lifecycleData.adherence.insufficientData ? (_jsx("div", { className: "text-ink-4 text-[13px] py-2", children: t("pages.activation.insufficientData") })) : (_jsxs("div", { className: "py-2 space-y-2", children: [_jsxs("div", { className: "text-ink-2 text-[13px]", children: [_jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: lifecycleData.adherence.rate !== null
273
- ? `${(lifecycleData.adherence.rate * 100).toFixed(0)}%`
274
- : "—" }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.adherenceLabel") }), _jsx("div", { className: "text-ink-4 text-[11px] mt-1 font-mono", children: t("pages.activation.lifecycleNote") })] }), lifecycleData.ruleMetrics.length > 0 && (_jsx("div", { className: "space-y-1", children: lifecycleData.ruleMetrics.map((rm) => (_jsxs("div", { className: "text-ink-3 text-[12px] font-mono", children: [_jsx("span", { className: "text-ink-2", children: rm.ruleId }), ":", " ", rm.triggered, " ", t("pages.activation.triggered"), " ", rm.lastTriggeredAt && (_jsxs("span", { className: "text-ink-4", children: ["(", formatDate(rm.lastTriggeredAt, i18n.language, DATETIME_OPTS), ")"] }))] }, rm.ruleId))) }))] })) })] })), record.status === "active" && reversible && (_jsx("div", { className: "mt-4", children: !showConfirm ? (_jsx("button", { onClick: () => setShowConfirm(true), disabled: disabling, className: "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 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", "data-testid": `disable-btn-${record.activationId}`, children: t("pages.activation.disableAction") })) : (_jsxs("div", { className: "flex items-center gap-3 px-[14px] py-[10px] bg-surface border border-amber/25 rounded-[4px]", role: "alert", "data-testid": `confirm-bar-${record.activationId}`, children: [_jsx("span", { className: "text-ink-2 text-[13px] flex-1", children: t("pages.activation.confirmDisable") }), _jsx("button", { onClick: () => {
275
- onDisable(record);
276
- setShowConfirm(false);
277
- }, disabled: disabling, className: "inline-flex items-center border border-danger/40 text-danger bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-danger/5 transition-colors focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", "data-testid": `confirm-disable-${record.activationId}`, children: disabling ? t("pages.activation.disabling") : t("common.confirm") }), _jsx("button", { onClick: () => setShowConfirm(false), className: "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 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("common.cancel") })] })) })), record.channel === 'code_tool_hook' && record.status === 'active' && _jsx(RuleCodeOwnerPanel, { record: record, onChanged: onChanged })] }));
278
- }
279
- export function ActivationPage() {
280
- const { t } = useTranslation();
281
- const [searchParams] = useSearchParams();
282
- // ?activationId= deep link (治理焦点 RuleCode 决策卡直达): once the list has
283
- // loaded, scroll the linked card into view and pulse a theme-token ring
284
- // around it. Unknown id → plain landing (the list itself stays the truth).
285
- const deepLinkActivationId = searchParams.get("activationId");
286
- const [activationsData, setActivationsData] = useState(null);
287
- const [lifecycleCache, setLifecycleCache] = useState({});
288
- const [receiptCounts, setReceiptCounts] = useState(null);
289
- const [receiptDegraded, setReceiptDegraded] = useState(null);
290
- // PRI-590: page-level coverage disclosure for the receipt counts.
291
- const [receiptCoverage, setReceiptCoverage] = useState(null);
292
- // PRI-594: unknown is never presented as a trustworthy zero — when the ledger
293
- // is malformed the per-card count rows are omitted and the page-level
294
- // coverage block carries the "requires recovery" verdict instead.
295
- const receiptCountsUntrustworthy = receiptCoverage !== null && receiptCoverage.validationStatus === "malformed";
296
- const [loadingState, setLoadingState] = useState("loading");
297
- const [errorMessage, setErrorMessage] = useState(null);
298
- const [disablingIds, setDisablingIds] = useState(new Set());
299
- const [degradedNote, setDegradedNote] = useState(null);
300
- const loadData = useCallback(async () => {
301
- setLoadingState("loading");
302
- setErrorMessage(null);
303
- setDegradedNote(null);
304
- setReceiptCounts(null);
305
- setReceiptDegraded(null);
306
- setReceiptCoverage(null);
307
- const result = await fetchAllActivations();
308
- if (!result.success) {
309
- setLoadingState("error");
310
- setErrorMessage(result.error);
311
- return;
312
- }
313
- const validated = validateActivationsData(result.data);
314
- if (validated === null) {
315
- setLoadingState("error");
316
- setErrorMessage("Activation data has unexpected shape");
317
- return;
318
- }
319
- setActivationsData(validated);
320
- if (validated.reason) {
321
- setDegradedNote(validated.reason);
322
- }
323
- // PRI-533: per-principle receipt counts for the activation cards.
324
- // Counts are supplementary evidence — a degraded/failed counts API never
325
- // blocks the page; the cards omit the row and the page surfaces the
326
- // degraded reason once (ERR-002: no silent fallback).
327
- try {
328
- const rResult = await fetchReceiptCounts();
329
- if (!rResult.success) {
330
- setReceiptDegraded({
331
- reason: rResult.error,
332
- ...(rResult.nextAction === undefined ? {} : { nextAction: rResult.nextAction }),
333
- });
334
- }
335
- else if (rResult.data.status === "ok") {
336
- const byId = {};
337
- for (const entry of rResult.data.counts) {
338
- byId[entry.principleId] = entry;
339
- }
340
- setReceiptCounts(byId);
341
- setReceiptCoverage(rResult.data.coverage);
342
- }
343
- else {
344
- setReceiptDegraded({
345
- reason: rResult.data.reason ?? "unknown",
346
- ...(rResult.data.nextAction === undefined ? {} : { nextAction: rResult.data.nextAction }),
347
- });
348
- // Degraded responses still carry coverage — it names the state
349
- // (disabled vs unavailable) for the localized headline.
350
- setReceiptCoverage(rResult.data.coverage);
351
- }
352
- }
353
- catch (err) {
354
- // EP-03: counts are optional — degrade with reason, never block the page.
355
- setReceiptDegraded({ reason: err instanceof Error ? err.message : String(err) });
356
- }
357
- // Pre-fetch lifecycle metrics for active principles with rules
358
- // (only for principles that are active, to populate the expandable section)
359
- const activePrinciples = new Set(validated.activations
360
- .filter((a) => a.status === "active")
361
- .map((a) => a.principleId));
362
- const newCache = {};
363
- await Promise.all(Array.from(activePrinciples).map(async (principleId) => {
364
- try {
365
- const lifecycleResult = await fetchLifecycleMetrics(principleId);
366
- if (lifecycleResult.success) {
367
- const validatedMetrics = validateLifecycleMetricsData(lifecycleResult.data);
368
- newCache[principleId] = validatedMetrics;
369
- }
370
- else {
371
- newCache[principleId] = null;
372
- }
373
- }
374
- catch {
375
- // EP-03: graceful degradation — lifecycle metrics are optional
376
- // Individual principle failure must not block the entire page
377
- newCache[principleId] = null;
378
- }
379
- }));
380
- setLifecycleCache(newCache);
381
- setLoadingState("loaded");
382
- }, []);
383
- useEffect(() => {
384
- loadData();
385
- }, [loadData]);
386
- // Deep link (?activationId=): scroll the linked activation card into view
387
- // and pulse a theme-token ring for a few seconds. Runs once the list has
388
- // actually rendered; a card that is not on the page degrades to a plain
389
- // landing (rc-9 — no fabricated focus). The URL param is untrusted (rc-1):
390
- // CSS.escape (unquoted attribute selector) keeps a crafted id from breaking
391
- // the selector.
392
- useEffect(() => {
393
- if (deepLinkActivationId === null || loadingState !== "loaded")
394
- return;
395
- const card = document.querySelector(`[data-testid=${CSS.escape(`activation-card-${deepLinkActivationId}`)}]`);
396
- if (card === null)
397
- return;
398
- card.scrollIntoView({ block: "center" });
399
- const HIGHLIGHT_CLASSES = ["ring-2", "ring-gov", "ring-offset-2", "ring-offset-paper"];
400
- card.classList.add(...HIGHLIGHT_CLASSES);
401
- const timer = window.setTimeout(() => card.classList.remove(...HIGHLIGHT_CLASSES), 3000);
402
- return () => {
403
- window.clearTimeout(timer);
404
- card.classList.remove(...HIGHLIGHT_CLASSES);
405
- };
406
- }, [deepLinkActivationId, loadingState]);
407
- const handleDisable = useCallback(async (record) => {
408
- setDisablingIds((prev) => new Set(prev).add(record.activationId));
409
- const result = await disableActivation(record.activationId);
410
- if (result.success) {
411
- toast.success(t("pages.activation.disableSuccess"), {
412
- description: t("pages.activation.disableSuccessDescription", { id: record.principleId }),
413
- duration: 5000,
414
- });
415
- // Update local state only on real backend success
416
- setActivationsData((prev) => {
417
- if (!prev)
418
- return prev;
419
- return {
420
- ...prev,
421
- activations: prev.activations.map((a) => a.activationId === record.activationId ? { ...a, status: "inactive" } : a),
422
- };
423
- });
424
- }
425
- else {
426
- // EP-03: failure surfaces reason + nextAction
427
- toast.error(t("pages.activation.disableFailed"), {
428
- description: result.error,
429
- duration: 8000,
430
- });
431
- if (result.nextAction) {
432
- toast.info(result.nextAction, { duration: 8000 });
433
- }
434
- }
435
- setDisablingIds((prev) => {
436
- const next = new Set(prev);
437
- next.delete(record.activationId);
438
- return next;
439
- });
440
- }, [t]);
441
- const handleEmergencyPause = useCallback(async () => {
442
- const result = await pauseAllRuleCode({ idempotencyKey: `pause-${crypto.randomUUID()}`, reasonCode: 'owner_emergency_pause' });
443
- if (result.success) {
444
- toast.success(t('pages.activation.pauseAllSucceeded'));
445
- await loadData();
446
- }
447
- else {
448
- toast.error(result.error);
449
- if (result.nextAction)
450
- toast.info(result.nextAction);
451
- }
452
- }, [loadData, t]);
453
- // ── Loading state ────────────────────────────────────────────────────────
454
- if (loadingState === "loading") {
455
- return (_jsx(PageShell, { children: _jsx(PageLoading, { cardCount: 4, label: t("common.loading") }) }));
456
- }
457
- // ── Error state (ERR-002: degradation with reason) ───────────────────────
458
- if (loadingState === "error") {
459
- return (_jsxs(PageShell, { children: [_jsx("div", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.activation.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.activation.title") }), _jsxs("div", { className: "mt-6 p-4 bg-panel border border-line rounded-[6px] text-ink-2 text-sm", children: [_jsx("p", { children: t("pages.activation.loadError") }), errorMessage && (_jsx("p", { className: "mt-2 text-ink-4 text-[13px] font-mono", children: errorMessage }))] })] }));
460
- }
461
- // ── Loaded state ─────────────────────────────────────────────────────────
462
- const activations = activationsData?.activations ?? [];
463
- const activeActivations = activations.filter((a) => a.status === "active");
464
- const pendingRuleCode = activeActivations.filter(record => record.action === 'code_tool_hook_shadow_activate' && record.enforcement !== 'safety_isolated');
465
- const safetyAlerts = activeActivations.filter(record => record.channel === 'code_tool_hook' && record.enforcement === 'safety_isolated');
466
- const ordinaryActive = activeActivations.filter(record => !pendingRuleCode.includes(record) && !safetyAlerts.includes(record));
467
- const inactiveActivations = activations.filter((a) => a.status === "inactive");
468
- const neverActivatedCount = activations.filter((a) => a.activatedAt === null).length;
469
- return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.activation.eyebrow") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: activeActivations.length === 0, children: t("pages.activation.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.activation.subtitle") }), _jsxs("div", { className: "text-sm leading-relaxed text-ink-2 mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", role: "status", "aria-live": "polite", children: [_jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: activeActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryActive") }), " ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: inactiveActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryInactive") }), neverActivatedCount > 0 && (_jsxs(_Fragment, { children: [" ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-amber tabular-nums", children: neverActivatedCount }), " ", _jsx("span", { className: "text-amber", children: t("pages.activation.summaryNeverActivated") })] }))] }), _jsx(CapabilityBoundaryDeclaration, {}), activeActivations.some(record => record.action === 'code_tool_hook_live_activate') && _jsx("div", { className: "mt-4 flex justify-end", children: _jsx(Button, { variant: "destructive", onClick: () => void handleEmergencyPause(), children: t('pages.activation.pauseAll') }) }), degradedNote && (_jsx("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", children: degradedNote })), receiptDegraded && (_jsxs("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", "data-testid": "receipt-counts-degraded", children: [receiptCoverage !== null && (_jsx("span", { className: "block font-medium text-ink-3", children: t(getReceiptSourceStatusLabelKey(receiptCoverage.sourceStatus)) })), t("pages.activation.receiptsUnavailable", { reason: receiptDegraded.reason }), receiptDegraded.nextAction && (_jsx("span", { className: "mt-1 block font-mono text-[12px]", children: receiptDegraded.nextAction }))] })), receiptCounts !== null && receiptCoverage !== null && (_jsx("div", { className: "mt-4 bg-surface/60 border-l-2 border-line px-3 py-2", "data-testid": "receipt-counts-coverage", children: _jsx(ReceiptCoverageDisclosure, { coverage: receiptCoverage }) })), pendingRuleCode.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-pending-rulecode", children: [_jsx(SectionTitle, { id: "section-pending-rulecode", children: t('pages.activation.pendingRules') }), _jsx("p", { className: "mb-3 text-[12px] text-ink-3", children: t('pages.activation.pendingRulesDescription') }), _jsx("div", { className: "space-y-[14px]", children: pendingRuleCode.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), safetyAlerts.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-safety-alerts", children: [_jsx(SectionTitle, { id: "section-safety-alerts", children: t('pages.activation.safetyAlerts') }), _jsx("p", { className: "mb-3 text-[12px] text-danger", children: t('pages.activation.safetyAlertsDescription') }), _jsx("div", { className: "space-y-[14px]", children: safetyAlerts.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), _jsxs("section", { className: "mt-8", "aria-labelledby": "section-active", children: [_jsx(SectionTitle, { id: "section-active", children: t("pages.activation.sectionActive") }), (() => {
470
- const route = activationsData?.promptInjectionRoute;
471
- if (route?.status !== "confirmed")
472
- return null;
473
- // The "observed" copy names a source + window. Only a CONFIRMED
474
- // observation carries those facts; a usable observation can itself
475
- // be the runtime's fallback (no trusted host capacity), and showing
476
- // window=0 with a host-window label would be a fabricated claim.
477
- if (route.budgetCapacityStatus === "confirmed"
478
- && route.budgetObservedAt !== undefined
479
- && route.budgetContextWindowTokens !== undefined) {
480
- return (_jsx("p", { className: "mb-3 text-[12px] text-ink-3", "data-testid": "activation-budget-observed-note", children: t("pages.activation.budgetObservedNote", {
481
- defaultValue: "注入状态中的预算数字取自最近一次运行时观测(来源 {{source}},上下文 {{window}} tokens,观测于 {{observedAt}}),并非实时确认值。",
482
- source: route.budgetCapacitySource === "pi_catalog_exact"
483
- ? t("pages.focus.budgetCapacitySourcePiCatalog", { defaultValue: "模型目录精确匹配" })
484
- : route.budgetCapacitySource === "operator_declared"
485
- ? t("pages.focus.budgetCapacitySourceOperatorDeclared", { defaultValue: "工作区配置声明" })
486
- : t("pages.focus.budgetCapacitySourceHostWindow", { defaultValue: "宿主有效上下文窗口" }),
487
- window: route.budgetContextWindowTokens,
488
- observedAt: route.budgetObservedAt,
489
- }) }));
490
- }
491
- if (route.budgetCapacityStatus === "unknown" && route.budgetFallbackReason !== undefined) {
492
- const observedSuffix = route.budgetObservedAt !== undefined
493
- // The runtime's own most recent injection ALSO fell back — the
494
- // reason is that observation's, not a console-only guess.
495
- ? t("pages.focus.promptBudgetFallbackObservedSuffix", {
496
- defaultValue: ";运行时最近一次观测于 {{observedAt}}",
497
- observedAt: route.budgetObservedAt,
498
- })
499
- : "";
500
- return (_jsx("p", { className: "mb-3 text-[12px] text-ink-3", "data-testid": "activation-budget-fallback-note", children: t("pages.activation.budgetFallbackNote", {
501
- defaultValue: "注入状态按固定回退预算估算({{reason}}{{observed}})。",
502
- reason: t(`pages.focus.budgetFallbackReason.${route.budgetFallbackReason}`, {
503
- defaultValue: route.budgetFallbackReason,
504
- }),
505
- observed: observedSuffix,
506
- }) }));
507
- }
508
- return null;
509
- })(), ordinaryActive.length > 0 ? (_jsx("div", { className: "space-y-[14px]", children: ordinaryActive.map((record) => (_jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: receiptCounts !== null && !receiptCountsUntrustworthy ? (Object.hasOwn(receiptCounts, record.principleId) ? receiptCounts[record.principleId] : null) : undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.activation.emptyActive") }))] }), inactiveActivations.length > 0 && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-inactive", children: [_jsx(SectionTitle, { id: "section-inactive", children: t("pages.activation.sectionInactive") }), _jsx("div", { className: "space-y-[14px]", children: inactiveActivations.map((record) => (_jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: receiptCounts !== null && !receiptCountsUntrustworthy ? (Object.hasOwn(receiptCounts, record.principleId) ? receiptCounts[record.principleId] : null) : undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId))) })] })), neverActivatedCount > 0 && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-never-activated", children: [_jsx(SectionTitle, { id: "section-never-activated", children: t("pages.activation.sectionNeverActivated") }), _jsx("div", { className: "space-y-[10px]", children: activations
510
- .filter((a) => a.activatedAt === null)
511
- .map((record) => (_jsxs("article", { className: "relative pl-[22px] py-[14px] pr-[18px] bg-panel border border-amber/20 border-l-[3px] border-l-amber rounded-[6px]", children: [_jsxs("div", { className: "text-ink-2 text-sm leading-relaxed", children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.activation.neverActivatedCard") }), " ", "\u2014 ", record.action, " \u00B7 ", getChannelLabel(record.channel, t), _jsx("span", { className: "ml-2 font-mono text-[11px] text-ink-4", children: record.principleId })] }), _jsxs(Link, { to: "/debt", className: "inline-flex items-center mt-2 text-gov text-[13px] hover:underline focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: [t("pages.activation.viewDebt"), " \u2192"] })] }, record.activationId))) })] })), _jsx("footer", { className: "mt-12 pt-6 border-t border-line text-ink-3 text-[13px]", children: t("pages.activation.footer") })] }) }));
512
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * Activation page validators — PRI-CR6
3
- *
4
- * Runtime validators for activation and lifecycle API responses.
5
- * All API responses are treated as `unknown` and validated with runtime type guards.
6
- * No `as` casts to bypass validation (ERR-001/005).
7
- * Required fields fail loud when missing or malformed (ERR-009/010).
8
- * Array elements validated individually (ERR-005/007).
9
- * `Object.hasOwn()` used for untrusted keys (ERR-013).
10
- * Degraded states include a reason (ERR-002).
11
- */
12
- import type { ActivationRecord, ActivationsData, LifecycleAdherence, LifecycleRuleMetric, LifecycleMetricsData } from "../../api.js";
13
- /** Type guard: is this a non-null object with own properties (not inherited)? */
14
- export declare function isRecord(value: unknown): value is Record<string, unknown>;
15
- export declare function validateActivationRecord(raw: unknown): ActivationRecord | null;
16
- export declare function validateActivationsData(raw: unknown): ActivationsData | null;
17
- export declare function validateLifecycleRuleMetric(raw: unknown): LifecycleRuleMetric | null;
18
- export declare function validateLifecycleAdherence(raw: unknown): LifecycleAdherence | null;
19
- export declare function validateLifecycleMetricsData(raw: unknown): LifecycleMetricsData | null;
20
- export declare function isReversibleChannel(channel: string): boolean;