create-principles-disciple 1.146.3 → 1.146.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/console/dist/web/assets/app.js +26 -26
  3. package/console/package.json +1 -1
  4. package/package.json +3 -3
  5. package/pd-cli/package.json +1 -1
  6. package/release-manager/package.json +3 -3
  7. package/console/dist/ui/App.d.ts +0 -1
  8. package/console/dist/ui/App.js +0 -172
  9. package/console/dist/ui/api.d.ts +0 -611
  10. package/console/dist/ui/api.js +0 -1094
  11. package/console/dist/ui/components/auth/login-form.d.ts +0 -4
  12. package/console/dist/ui/components/auth/login-form.js +0 -142
  13. package/console/dist/ui/components/auth/splash-screen.d.ts +0 -9
  14. package/console/dist/ui/components/auth/splash-screen.js +0 -22
  15. package/console/dist/ui/components/error-boundary.d.ts +0 -15
  16. package/console/dist/ui/components/error-boundary.js +0 -30
  17. package/console/dist/ui/components/focus/daily-thought-card.d.ts +0 -1
  18. package/console/dist/ui/components/focus/daily-thought-card.js +0 -41
  19. package/console/dist/ui/components/language-switcher.d.ts +0 -2
  20. package/console/dist/ui/components/language-switcher.js +0 -17
  21. package/console/dist/ui/components/layout/app-sidebar.d.ts +0 -27
  22. package/console/dist/ui/components/layout/app-sidebar.js +0 -128
  23. package/console/dist/ui/components/layout/page-loading.d.ts +0 -13
  24. package/console/dist/ui/components/layout/page-loading.js +0 -14
  25. package/console/dist/ui/components/layout/page-shell.d.ts +0 -12
  26. package/console/dist/ui/components/layout/page-shell.js +0 -11
  27. package/console/dist/ui/components/layout/section-title.d.ts +0 -10
  28. package/console/dist/ui/components/layout/section-title.js +0 -9
  29. package/console/dist/ui/components/notifications/NotificationProvider.d.ts +0 -14
  30. package/console/dist/ui/components/notifications/NotificationProvider.js +0 -136
  31. package/console/dist/ui/components/notifications/favicon-badge.d.ts +0 -3
  32. package/console/dist/ui/components/notifications/favicon-badge.js +0 -68
  33. package/console/dist/ui/components/notifications/notification-reducer.d.ts +0 -9
  34. package/console/dist/ui/components/notifications/notification-reducer.js +0 -9
  35. package/console/dist/ui/components/notifications/sound-storage.d.ts +0 -3
  36. package/console/dist/ui/components/notifications/sound-storage.js +0 -37
  37. package/console/dist/ui/components/notifications/useNotifications.d.ts +0 -1
  38. package/console/dist/ui/components/notifications/useNotifications.js +0 -9
  39. package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +0 -8
  40. package/console/dist/ui/components/onboarding/CircuitDiagram.js +0 -18
  41. package/console/dist/ui/components/onboarding/DemoResultView.d.ts +0 -22
  42. package/console/dist/ui/components/onboarding/DemoResultView.js +0 -33
  43. package/console/dist/ui/components/onboarding/SlashCommandsCard.d.ts +0 -16
  44. package/console/dist/ui/components/onboarding/SlashCommandsCard.js +0 -20
  45. package/console/dist/ui/components/onboarding/slashCommands.d.ts +0 -20
  46. package/console/dist/ui/components/onboarding/slashCommands.js +0 -22
  47. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.d.ts +0 -6
  48. package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.js +0 -66
  49. package/console/dist/ui/components/theme-provider.d.ts +0 -14
  50. package/console/dist/ui/components/theme-provider.js +0 -40
  51. package/console/dist/ui/components/theme-toggle.d.ts +0 -2
  52. package/console/dist/ui/components/theme-toggle.js +0 -11
  53. package/console/dist/ui/components/ui/alert-dialog.d.ts +0 -20
  54. package/console/dist/ui/components/ui/alert-dialog.js +0 -26
  55. package/console/dist/ui/components/ui/badge.d.ts +0 -9
  56. package/console/dist/ui/components/ui/badge.js +0 -22
  57. package/console/dist/ui/components/ui/button.d.ts +0 -11
  58. package/console/dist/ui/components/ui/button.js +0 -34
  59. package/console/dist/ui/components/ui/card.d.ts +0 -8
  60. package/console/dist/ui/components/ui/card.js +0 -16
  61. package/console/dist/ui/components/ui/charts.d.ts +0 -51
  62. package/console/dist/ui/components/ui/charts.js +0 -72
  63. package/console/dist/ui/components/ui/dialog.d.ts +0 -19
  64. package/console/dist/ui/components/ui/dialog.js +0 -22
  65. package/console/dist/ui/components/ui/input.d.ts +0 -3
  66. package/console/dist/ui/components/ui/input.js +0 -8
  67. package/console/dist/ui/components/ui/markdown.d.ts +0 -24
  68. package/console/dist/ui/components/ui/markdown.js +0 -119
  69. package/console/dist/ui/components/ui/progress-bar.d.ts +0 -20
  70. package/console/dist/ui/components/ui/progress-bar.js +0 -38
  71. package/console/dist/ui/components/ui/select.d.ts +0 -13
  72. package/console/dist/ui/components/ui/select.js +0 -26
  73. package/console/dist/ui/components/ui/separator.d.ts +0 -3
  74. package/console/dist/ui/components/ui/separator.js +0 -6
  75. package/console/dist/ui/components/ui/sheet.d.ts +0 -25
  76. package/console/dist/ui/components/ui/sheet.js +0 -37
  77. package/console/dist/ui/components/ui/shiny-text.d.ts +0 -28
  78. package/console/dist/ui/components/ui/shiny-text.js +0 -46
  79. package/console/dist/ui/components/ui/skeleton.d.ts +0 -3
  80. package/console/dist/ui/components/ui/skeleton.js +0 -6
  81. package/console/dist/ui/components/ui/sonner.d.ts +0 -3
  82. package/console/dist/ui/components/ui/sonner.js +0 -13
  83. package/console/dist/ui/components/ui/tooltip.d.ts +0 -7
  84. package/console/dist/ui/components/ui/tooltip.js +0 -10
  85. package/console/dist/ui/data/daily-thoughts.d.ts +0 -15
  86. package/console/dist/ui/data/daily-thoughts.js +0 -164
  87. package/console/dist/ui/hooks/useNotificationSound.d.ts +0 -12
  88. package/console/dist/ui/hooks/useNotificationSound.js +0 -74
  89. package/console/dist/ui/i18n/en.json +0 -2399
  90. package/console/dist/ui/i18n/index.d.ts +0 -2
  91. package/console/dist/ui/i18n/index.js +0 -32
  92. package/console/dist/ui/i18n/zh-CN.json +0 -2399
  93. package/console/dist/ui/main.d.ts +0 -1
  94. package/console/dist/ui/main.js +0 -9
  95. package/console/dist/ui/pages/ReportProblemValidators.d.ts +0 -144
  96. package/console/dist/ui/pages/ReportProblemValidators.js +0 -418
  97. package/console/dist/ui/pages/activation/ActivationPage.d.ts +0 -1
  98. package/console/dist/ui/pages/activation/ActivationPage.js +0 -512
  99. package/console/dist/ui/pages/activation/ActivationValidators.d.ts +0 -20
  100. package/console/dist/ui/pages/activation/ActivationValidators.js +0 -160
  101. package/console/dist/ui/pages/control-center/AgentCard.d.ts +0 -31
  102. package/console/dist/ui/pages/control-center/AgentCard.js +0 -212
  103. package/console/dist/ui/pages/control-center/AgentGroup.d.ts +0 -26
  104. package/console/dist/ui/pages/control-center/AgentGroup.js +0 -38
  105. package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +0 -1
  106. package/console/dist/ui/pages/control-center/ControlCenterPage.js +0 -509
  107. package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +0 -1
  108. package/console/dist/ui/pages/control-center/DesignGatePanel.js +0 -137
  109. package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +0 -31
  110. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +0 -199
  111. package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +0 -17
  112. package/console/dist/ui/pages/control-center/WorkflowDiagram.js +0 -55
  113. package/console/dist/ui/pages/debt/DebtPage.d.ts +0 -2
  114. package/console/dist/ui/pages/debt/DebtPage.js +0 -222
  115. package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +0 -2
  116. package/console/dist/ui/pages/design-system/DesignSystemPage.js +0 -30
  117. package/console/dist/ui/pages/examiner/ExaminerPage.d.ts +0 -15
  118. package/console/dist/ui/pages/examiner/ExaminerPage.js +0 -158
  119. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.d.ts +0 -1
  120. package/console/dist/ui/pages/failed-tasks/FailedTasksPage.js +0 -421
  121. package/console/dist/ui/pages/focus/ApprovalSubjectReading.d.ts +0 -24
  122. package/console/dist/ui/pages/focus/ApprovalSubjectReading.js +0 -133
  123. package/console/dist/ui/pages/focus/FocusPage.d.ts +0 -123
  124. package/console/dist/ui/pages/focus/FocusPage.js +0 -567
  125. package/console/dist/ui/pages/focus/OwnerDecisionCard.d.ts +0 -9
  126. package/console/dist/ui/pages/focus/OwnerDecisionCard.js +0 -111
  127. package/console/dist/ui/pages/focus/OwnerWorkbench.d.ts +0 -19
  128. package/console/dist/ui/pages/focus/OwnerWorkbench.js +0 -75
  129. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.d.ts +0 -34
  130. package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.js +0 -298
  131. package/console/dist/ui/pages/focus/focus-validation.d.ts +0 -40
  132. package/console/dist/ui/pages/focus/focus-validation.js +0 -211
  133. package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +0 -67
  134. package/console/dist/ui/pages/intent/IntentOnboarding.js +0 -289
  135. package/console/dist/ui/pages/intent/IntentPage.d.ts +0 -1
  136. package/console/dist/ui/pages/intent/IntentPage.js +0 -252
  137. package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +0 -59
  138. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +0 -125
  139. package/console/dist/ui/pages/pain/PainPage.d.ts +0 -1
  140. package/console/dist/ui/pages/pain/PainPage.js +0 -420
  141. package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +0 -175
  142. package/console/dist/ui/pages/pain/pain-card-helpers.js +0 -181
  143. package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +0 -10
  144. package/console/dist/ui/pages/principles/CorePrinciplesPage.js +0 -59
  145. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +0 -60
  146. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +0 -602
  147. package/console/dist/ui/pages/principles/PrinciplesPage.d.ts +0 -1
  148. package/console/dist/ui/pages/principles/PrinciplesPage.js +0 -327
  149. package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +0 -8
  150. package/console/dist/ui/pages/principles/PrinciplesViewNav.js +0 -15
  151. package/console/dist/ui/pages/report-problem/ReportProblemPage.d.ts +0 -1
  152. package/console/dist/ui/pages/report-problem/ReportProblemPage.js +0 -467
  153. package/console/dist/ui/pages/settings/SettingsPage.d.ts +0 -4
  154. package/console/dist/ui/pages/settings/SettingsPage.js +0 -457
  155. package/console/dist/ui/pages/settings/UpdatePage.d.ts +0 -1
  156. package/console/dist/ui/pages/settings/UpdatePage.js +0 -215
  157. package/console/dist/ui/pages/welcome/WelcomePage.d.ts +0 -5
  158. package/console/dist/ui/pages/welcome/WelcomePage.js +0 -187
  159. package/console/dist/ui/utils/agent-metadata.d.ts +0 -71
  160. package/console/dist/ui/utils/agent-metadata.js +0 -284
  161. package/console/dist/ui/utils/approval-review.d.ts +0 -30
  162. package/console/dist/ui/utils/approval-review.js +0 -50
  163. package/console/dist/ui/utils/approval-warning-localization.d.ts +0 -34
  164. package/console/dist/ui/utils/approval-warning-localization.js +0 -148
  165. package/console/dist/ui/utils/attention-presentation.d.ts +0 -35
  166. package/console/dist/ui/utils/attention-presentation.js +0 -46
  167. package/console/dist/ui/utils/blocker-localization.d.ts +0 -23
  168. package/console/dist/ui/utils/blocker-localization.js +0 -36
  169. package/console/dist/ui/utils/control-center-helpers.d.ts +0 -79
  170. package/console/dist/ui/utils/control-center-helpers.js +0 -189
  171. package/console/dist/ui/utils/enum-labels.d.ts +0 -50
  172. package/console/dist/ui/utils/enum-labels.js +0 -171
  173. package/console/dist/ui/utils/format-date.d.ts +0 -11
  174. package/console/dist/ui/utils/format-date.js +0 -17
  175. package/console/dist/ui/utils/onboarding-state.d.ts +0 -25
  176. package/console/dist/ui/utils/onboarding-state.js +0 -77
  177. package/console/dist/ui/utils/reading-layout.d.ts +0 -20
  178. package/console/dist/ui/utils/reading-layout.js +0 -46
  179. package/console/dist/ui/utils/rule-binding-validators.d.ts +0 -13
  180. package/console/dist/ui/utils/rule-binding-validators.js +0 -188
  181. package/console/dist/ui/utils/runtime-mode.d.ts +0 -11
  182. package/console/dist/ui/utils/runtime-mode.js +0 -11
  183. package/console/dist/ui/utils/token-storage.d.ts +0 -22
  184. package/console/dist/ui/utils/token-storage.js +0 -47
  185. package/console/dist/ui/utils/validators.d.ts +0 -1178
  186. package/console/dist/ui/utils/validators.js +0 -3297
  187. package/release-manager/dist/bootstrap-entry.d.ts +0 -2
  188. package/release-manager/dist/bootstrap-entry.d.ts.map +0 -1
  189. package/release-manager/dist/bootstrap-entry.js.map +0 -1
  190. package/release-manager/dist/i18n.d.ts +0 -6
  191. package/release-manager/dist/i18n.d.ts.map +0 -1
  192. package/release-manager/dist/i18n.js.map +0 -1
  193. package/release-manager/dist/index.d.ts +0 -7
  194. package/release-manager/dist/index.d.ts.map +0 -1
  195. package/release-manager/dist/index.js +0 -656
  196. package/release-manager/dist/index.js.map +0 -1
  197. package/release-manager/dist/installer.d.ts +0 -629
  198. package/release-manager/dist/installer.d.ts.map +0 -1
  199. package/release-manager/dist/installer.js.map +0 -1
  200. package/release-manager/dist/installers/codex-host-installer.d.ts +0 -39
  201. package/release-manager/dist/installers/codex-host-installer.d.ts.map +0 -1
  202. package/release-manager/dist/installers/codex-host-installer.js.map +0 -1
  203. package/release-manager/dist/installers/index.d.ts +0 -51
  204. package/release-manager/dist/installers/index.d.ts.map +0 -1
  205. package/release-manager/dist/installers/index.js.map +0 -1
  206. package/release-manager/dist/installers/openclaw-host-installer.d.ts +0 -14
  207. package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +0 -1
  208. package/release-manager/dist/installers/openclaw-host-installer.js.map +0 -1
  209. package/release-manager/dist/installers/workbuddy-host-installer.d.ts +0 -335
  210. package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +0 -1
  211. package/release-manager/dist/installers/workbuddy-host-installer.js.map +0 -1
  212. package/release-manager/dist/mvp-config.d.ts +0 -233
  213. package/release-manager/dist/mvp-config.d.ts.map +0 -1
  214. package/release-manager/dist/mvp-config.js.map +0 -1
  215. package/release-manager/dist/prompts.d.ts +0 -43
  216. package/release-manager/dist/prompts.d.ts.map +0 -1
  217. package/release-manager/dist/prompts.js +0 -268
  218. package/release-manager/dist/prompts.js.map +0 -1
  219. package/release-manager/dist/skill-language.d.ts +0 -32
  220. package/release-manager/dist/skill-language.d.ts.map +0 -1
  221. package/release-manager/dist/skill-language.js.map +0 -1
  222. package/release-manager/dist/uninstaller.d.ts +0 -68
  223. package/release-manager/dist/uninstaller.d.ts.map +0 -1
  224. package/release-manager/dist/uninstaller.js +0 -746
  225. package/release-manager/dist/uninstaller.js.map +0 -1
  226. package/release-manager/dist/update/apply-payload.d.ts +0 -143
  227. package/release-manager/dist/update/apply-payload.d.ts.map +0 -1
  228. package/release-manager/dist/update/apply-payload.js.map +0 -1
  229. package/release-manager/dist/update/atomic-file.d.ts +0 -35
  230. package/release-manager/dist/update/atomic-file.d.ts.map +0 -1
  231. package/release-manager/dist/update/atomic-file.js.map +0 -1
  232. package/release-manager/dist/update/bootstrap-executor.d.ts +0 -21
  233. package/release-manager/dist/update/bootstrap-executor.d.ts.map +0 -1
  234. package/release-manager/dist/update/bootstrap-executor.js.map +0 -1
  235. package/release-manager/dist/update/bootstrap-protocol.d.ts +0 -56
  236. package/release-manager/dist/update/bootstrap-protocol.d.ts.map +0 -1
  237. package/release-manager/dist/update/bootstrap-protocol.js.map +0 -1
  238. package/release-manager/dist/update/channel-metadata.d.ts +0 -28
  239. package/release-manager/dist/update/channel-metadata.d.ts.map +0 -1
  240. package/release-manager/dist/update/channel-metadata.js.map +0 -1
  241. package/release-manager/dist/update/channel-promotion.d.ts +0 -39
  242. package/release-manager/dist/update/channel-promotion.d.ts.map +0 -1
  243. package/release-manager/dist/update/channel-promotion.js +0 -55
  244. package/release-manager/dist/update/channel-promotion.js.map +0 -1
  245. package/release-manager/dist/update/console-surface.d.ts +0 -19
  246. package/release-manager/dist/update/console-surface.d.ts.map +0 -1
  247. package/release-manager/dist/update/console-surface.js.map +0 -1
  248. package/release-manager/dist/update/data-compatibility.d.ts +0 -35
  249. package/release-manager/dist/update/data-compatibility.d.ts.map +0 -1
  250. package/release-manager/dist/update/data-compatibility.js +0 -45
  251. package/release-manager/dist/update/data-compatibility.js.map +0 -1
  252. package/release-manager/dist/update/install-layout.d.ts +0 -105
  253. package/release-manager/dist/update/install-layout.d.ts.map +0 -1
  254. package/release-manager/dist/update/install-layout.js.map +0 -1
  255. package/release-manager/dist/update/product-identity.d.ts +0 -70
  256. package/release-manager/dist/update/product-identity.d.ts.map +0 -1
  257. package/release-manager/dist/update/product-identity.js.map +0 -1
  258. package/release-manager/dist/update/release-asset-manifest.d.ts +0 -31
  259. package/release-manager/dist/update/release-asset-manifest.d.ts.map +0 -1
  260. package/release-manager/dist/update/release-asset-manifest.js.map +0 -1
  261. package/release-manager/dist/update/release-identity.d.ts +0 -33
  262. package/release-manager/dist/update/release-identity.d.ts.map +0 -1
  263. package/release-manager/dist/update/release-identity.js.map +0 -1
  264. package/release-manager/dist/update/release-manager-authority.d.ts +0 -39
  265. package/release-manager/dist/update/release-manager-authority.d.ts.map +0 -1
  266. package/release-manager/dist/update/release-manager-authority.js.map +0 -1
  267. package/release-manager/dist/update/release-manager.d.ts +0 -156
  268. package/release-manager/dist/update/release-manager.d.ts.map +0 -1
  269. package/release-manager/dist/update/release-manager.js.map +0 -1
  270. package/release-manager/dist/update/release-metadata-publisher.d.ts +0 -199
  271. package/release-manager/dist/update/release-metadata-publisher.d.ts.map +0 -1
  272. package/release-manager/dist/update/release-metadata-publisher.js +0 -478
  273. package/release-manager/dist/update/release-metadata-publisher.js.map +0 -1
  274. package/release-manager/dist/update/release-metadata-source.d.ts +0 -85
  275. package/release-manager/dist/update/release-metadata-source.d.ts.map +0 -1
  276. package/release-manager/dist/update/release-metadata-source.js.map +0 -1
  277. package/release-manager/dist/update/release-metadata.d.ts +0 -60
  278. package/release-manager/dist/update/release-metadata.d.ts.map +0 -1
  279. package/release-manager/dist/update/release-metadata.js.map +0 -1
  280. package/release-manager/dist/update/release-policy.d.ts +0 -51
  281. package/release-manager/dist/update/release-policy.d.ts.map +0 -1
  282. package/release-manager/dist/update/release-policy.js.map +0 -1
  283. package/release-manager/dist/update/rollback-policy.d.ts +0 -56
  284. package/release-manager/dist/update/rollback-policy.d.ts.map +0 -1
  285. package/release-manager/dist/update/rollback-policy.js +0 -61
  286. package/release-manager/dist/update/rollback-policy.js.map +0 -1
  287. package/release-manager/dist/update/transaction-journal.d.ts +0 -212
  288. package/release-manager/dist/update/transaction-journal.d.ts.map +0 -1
  289. package/release-manager/dist/update/transaction-journal.js.map +0 -1
  290. package/release-manager/dist/update/trust-metadata.d.ts +0 -55
  291. package/release-manager/dist/update/trust-metadata.d.ts.map +0 -1
  292. package/release-manager/dist/update/trust-metadata.js.map +0 -1
  293. package/release-manager/dist/update/trust-root-provisioning.d.ts +0 -99
  294. package/release-manager/dist/update/trust-root-provisioning.d.ts.map +0 -1
  295. package/release-manager/dist/update/trust-root-provisioning.js.map +0 -1
  296. package/release-manager/dist/update/update-history.d.ts +0 -46
  297. package/release-manager/dist/update/update-history.d.ts.map +0 -1
  298. package/release-manager/dist/update/update-history.js +0 -123
  299. package/release-manager/dist/update/update-history.js.map +0 -1
  300. package/release-manager/dist/utils/config-file-io.d.ts +0 -34
  301. package/release-manager/dist/utils/config-file-io.d.ts.map +0 -1
  302. package/release-manager/dist/utils/config-file-io.js.map +0 -1
  303. package/release-manager/dist/utils/env.d.ts +0 -94
  304. package/release-manager/dist/utils/env.d.ts.map +0 -1
  305. package/release-manager/dist/utils/env.js.map +0 -1
  306. package/release-manager/dist/utils/logger.d.ts +0 -15
  307. package/release-manager/dist/utils/logger.d.ts.map +0 -1
  308. package/release-manager/dist/utils/logger.js.map +0 -1
  309. package/release-manager/dist/utils/workspace-divergence.d.ts +0 -36
  310. package/release-manager/dist/utils/workspace-divergence.d.ts.map +0 -1
  311. package/release-manager/dist/utils/workspace-divergence.js.map +0 -1
@@ -1,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;