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,602 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useCallback, useRef } from "react";
3
- import { useParams, useNavigate, useLocation, Link } 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 { Button } from "../../components/ui/button.js";
10
- import { fetchPrincipleDetail, fetchApprovalsGrouped, fetchLifecycleMetrics, fetchPrincipleTrajectory, fetchPrincipleGovernance, fetchPrincipleReceipts, fetchEvidenceAudit, fetchOwnerDecisionView, disableActivation, } from "../../api.js";
11
- import { ApprovalSubjectReading } from "../focus/ApprovalSubjectReading.js";
12
- import { ReceiptCoverageDisclosure, getReceiptSourceStatusLabelKey } from "../../components/receipts/ReceiptCoverageDisclosure.js";
13
- import { formatDate } from "../../utils/format-date.js";
14
- import { localizeAggregatedBlocker } from "../../utils/blocker-localization.js";
15
- import { groupByReasonCode, formatGroupedReasonLine } from "../../utils/attention-presentation.js";
16
- import { splitReadingTitleBody, truncateByCodePoints } from "../../utils/reading-layout.js";
17
- import { IS_DEV } from "../../utils/runtime-mode.js";
18
- // ── Runtime validation (H section) ──────────────────────────────────────────
19
- function isString(v) {
20
- return typeof v === "string";
21
- }
22
- function isRecord(v) {
23
- return typeof v === "object" && v !== null && !Array.isArray(v);
24
- }
25
- function safeStringArray(v) {
26
- if (!Array.isArray(v))
27
- return [];
28
- return v.filter(isString);
29
- }
30
- /**
31
- * Validate and normalize a PrincipleDetail from untrusted network data.
32
- * Returns a normalized object with safe defaults for all fields the page
33
- * actually accesses. Never returns null for individual fields — only for
34
- * completely unparseable top-level structures.
35
- */
36
- function validatePrincipleDetail(data) {
37
- if (!isRecord(data))
38
- return null;
39
- if (!Object.hasOwn(data, "principle") || !isRecord(data.principle))
40
- return null;
41
- const raw = data.principle;
42
- // Required fields — fail loud if missing
43
- if (!Object.hasOwn(raw, "id") || !isString(raw.id))
44
- return null;
45
- if (!Object.hasOwn(raw, "text") || !isString(raw.text))
46
- return null;
47
- if (!Object.hasOwn(raw, "status") || !isString(raw.status))
48
- return null;
49
- // Normalize fields the page accesses with safe defaults
50
- const normalized = {
51
- ...raw,
52
- triggerPattern: typeof raw.triggerPattern === "string" ? raw.triggerPattern : "",
53
- action: typeof raw.action === "string" ? raw.action : "",
54
- derivedFromPainIds: safeStringArray(raw.derivedFromPainIds),
55
- rules: Array.isArray(raw.rules) ? raw.rules : [],
56
- };
57
- return { principle: normalized };
58
- }
59
- function validateApprovalsGrouped(data) {
60
- if (!isRecord(data))
61
- return null;
62
- if (!Object.hasOwn(data, "groups") || !Array.isArray(data.groups))
63
- return null;
64
- for (const g of data.groups) {
65
- if (!isRecord(g))
66
- return null;
67
- if (!Object.hasOwn(g, "principleId") || !isString(g.principleId))
68
- return null;
69
- if (!Object.hasOwn(g, "status") || !isString(g.status))
70
- return null;
71
- if (!Object.hasOwn(g, "records") || !Array.isArray(g.records))
72
- return null;
73
- for (const r of g.records) {
74
- if (!isRecord(r))
75
- return null;
76
- if (!Object.hasOwn(r, "id") || !isString(r.id))
77
- return null;
78
- if (!Object.hasOwn(r, "channel") || !isString(r.channel))
79
- return null;
80
- }
81
- }
82
- return data;
83
- }
84
- function validateLifecycleMetrics(data) {
85
- if (!isRecord(data))
86
- return null;
87
- if (!Object.hasOwn(data, "adherence") || !isRecord(data.adherence))
88
- return null;
89
- const a = data.adherence;
90
- if (!Object.hasOwn(a, "insufficientData") || typeof a.insufficientData !== "boolean")
91
- return null;
92
- if (!Object.hasOwn(a, "note") || !isString(a.note))
93
- return null;
94
- // rate can be number or null
95
- if (Object.hasOwn(a, "rate") && a.rate !== null && typeof a.rate !== "number")
96
- return null;
97
- if (!Object.hasOwn(data, "ruleMetrics") || !Array.isArray(data.ruleMetrics))
98
- return null;
99
- return data;
100
- }
101
- // ── Trajectory stage labels (i18n key mapping) ─────────────────────────────
102
- const STAGE_LABEL_KEYS = {
103
- evidence: "principles.detail.stageEvidence",
104
- diagnosis: "principles.detail.stageDiagnosis",
105
- proposal: "principles.detail.stageProposal",
106
- review: "principles.detail.stageReview",
107
- deploy: "principles.detail.stageDeploy",
108
- behavior: "principles.detail.stageBehavior",
109
- };
110
- // ── Component ───────────────────────────────────────────────────────────────
111
- // SPEC-PD-UIUX-001 R1: the headline must agree with BOTH verified counts.
112
- // effect>0 → effect headline (records exist; no permanence claim)
113
- // effect=0,presence>0 → "injections recorded, no effect records yet"
114
- // effect=0,presence=0 → "nothing observed within the current retention window"
115
- // Presence is never inferred from approval/activation, and effect is never
116
- // inferred from presence — the degraded branch (status≠ok) handles
117
- // "cannot be confirmed" separately.
118
- export function getReceiptPresentation(effectCount, presenceCount) {
119
- if (effectCount > 0) {
120
- return {
121
- headlineKey: 'principles.detail.receipts.headline',
122
- presenceMissing: presenceCount === 0,
123
- showZeroEffectExplanation: false,
124
- };
125
- }
126
- if (presenceCount > 0) {
127
- return {
128
- headlineKey: 'principles.detail.receipts.headlinePresence',
129
- presenceMissing: false,
130
- showZeroEffectExplanation: true,
131
- };
132
- }
133
- return {
134
- headlineKey: 'principles.detail.receipts.headlineNone',
135
- presenceMissing: false,
136
- showZeroEffectExplanation: true,
137
- };
138
- }
139
- export const GOVERNANCE_BLOCK_I18N_KEYS = {
140
- recoveryReason: 'principles.detail.governance.reason.recovery_required',
141
- recoveryNextAction: 'principles.detail.governance.next.inspect_recovery',
142
- noDecisionReason: 'principles.detail.governance.actionsNotAuthorized',
143
- nextActionLabel: 'principles.detail.governance.nextActionLabel',
144
- };
145
- /**
146
- * Returns `null` when decision controls may render; otherwise the reason they
147
- * must stay hidden.
148
- */
149
- export function deriveGovernanceControlBlock(input) {
150
- const { governance, governanceUnavailable } = input;
151
- if (governance === null) {
152
- // Flag-off keeps the pre-projection experience: controls stay available and
153
- // no blocked notice is shown (ERR-102: disabled ≠ unavailable).
154
- if (governanceUnavailable === null)
155
- return null;
156
- return governanceUnavailable.nextAction === undefined
157
- ? { source: 'server', reason: governanceUnavailable.reason }
158
- : { source: 'server', reason: governanceUnavailable.reason, nextAction: governanceUnavailable.nextAction };
159
- }
160
- if (governance.attention.primary === 'owner_required')
161
- return null;
162
- if (governance.attention.primary === 'recovery_required') {
163
- return {
164
- source: 'i18n',
165
- reasonKey: GOVERNANCE_BLOCK_I18N_KEYS.recoveryReason,
166
- nextActionKey: GOVERNANCE_BLOCK_I18N_KEYS.recoveryNextAction,
167
- };
168
- }
169
- return { source: 'i18n', reasonKey: GOVERNANCE_BLOCK_I18N_KEYS.noDecisionReason };
170
- }
171
- export function narrativeTexts(field) {
172
- if (field.status === 'known' && Array.isArray(field.value)) {
173
- const texts = [];
174
- for (const item of field.value) {
175
- if (isRecord(item) && isString(item.text))
176
- texts.push(item.text);
177
- }
178
- return { status: 'known', texts };
179
- }
180
- const reason = isRecord(field.reason) && isString(field.reason.ownerText) ? field.reason.ownerText : '';
181
- return { status: 'unknown', reason };
182
- }
183
- /** Resolves the concrete mutation target id for an action (never from URL). */
184
- export function actionTargetId(action, kind) {
185
- const ref = action.targetRefs.find((target) => target.kind === kind);
186
- return ref?.id ?? null;
187
- }
188
- // Codex review P2 fix (localization): the decision panel's CHROME (action
189
- // labels, next action, blocker headline) localizes in the client via stable
190
- // semantic codes; narrative CONTENT (artifact-derived text) stays in its
191
- // source language — the model-generated material cannot be translated by a
192
- // key lookup, so a full locale-carried response remains a follow-up.
193
- const ACTION_LABEL_KEY = {
194
- approve: 'principles.detail.ownerDecision.actionLabel.approve',
195
- reject: 'principles.detail.ownerDecision.actionLabel.reject',
196
- edit_approval: 'principles.detail.ownerDecision.actionLabel.edit_approval',
197
- disable: 'principles.detail.ownerDecision.actionLabel.disable',
198
- };
199
- export function localizeActionLabel(action, t) {
200
- const key = ACTION_LABEL_KEY[action.semantic];
201
- if (key === undefined)
202
- return action.label;
203
- const localized = t(key, { defaultValue: '' });
204
- return localized === '' ? action.label : localized;
205
- }
206
- export function localizeNextAction(code, ownerText, t) {
207
- const localized = t(`principles.detail.ownerDecision.next.${code}`, { defaultValue: '' });
208
- return localized === '' ? ownerText : localized;
209
- }
210
- const DECISION_STATE_LABEL_KEY = {
211
- needs_owner_decision: 'principles.detail.ownerDecision.state.needs_owner_decision',
212
- processing: 'principles.detail.ownerDecision.state.processing',
213
- blocked: 'principles.detail.ownerDecision.state.blocked',
214
- recovery_needed: 'principles.detail.ownerDecision.state.recovery_needed',
215
- decided: 'principles.detail.ownerDecision.state.decided',
216
- no_action: 'principles.detail.ownerDecision.state.no_action',
217
- };
218
- export function PrincipleDetailPage() {
219
- const { t, i18n } = useTranslation("pages");
220
- const { id } = useParams();
221
- const navigate = useNavigate();
222
- const location = useLocation();
223
- const navigationState = location.state;
224
- const requestedReturn = navigationState !== null && typeof navigationState === 'object' && Object.hasOwn(navigationState, 'returnTo') ? Reflect.get(navigationState, 'returnTo') : null;
225
- const returnTo = typeof requestedReturn === 'string' && (requestedReturn === '/principles' || requestedReturn.startsWith('/principles?') || requestedReturn === '/focus' || requestedReturn.startsWith('/focus?')) ? requestedReturn : '/principles';
226
- const [principle, setPrinciple] = useState(null);
227
- const [approvalGroup, setApprovalGroup] = useState(null);
228
- const [approvalGroupUnavailable, setApprovalGroupUnavailable] = useState(false);
229
- const [lifecycle, setLifecycle] = useState(null);
230
- const [trajectory, setTrajectory] = useState(null);
231
- const [governance, setGovernance] = useState(null);
232
- const [governanceUnavailable, setGovernanceUnavailable] = useState(null);
233
- const [ownerDecision, setOwnerDecision] = useState(null);
234
- const [ownerDecisionUnavailable, setOwnerDecisionUnavailable] = useState(null);
235
- const [receipts, setReceipts] = useState(null);
236
- // PD v2 Phase 1: normalized intervention evidence audit (ADR-0027) — the
237
- // four-query read stays a separate surface from the legacy receipt history.
238
- const [evidenceAudit, setEvidenceAudit] = useState(null);
239
- const [loadingEvidenceKind, setLoadingEvidenceKind] = useState(null);
240
- const [loading, setLoading] = useState(true);
241
- const [error, setError] = useState(null);
242
- const detailEpoch = useRef(0);
243
- // Decision action state — driven by backend available_actions only.
244
- const [pendingAction, setPendingAction] = useState(null);
245
- const [rejectReason, setRejectReason] = useState("");
246
- const [newArtifactId, setNewArtifactId] = useState("");
247
- const [approveNote, setApproveNote] = useState("");
248
- const [actionLoading, setActionLoading] = useState(false);
249
- // Evidence ID copy state (Wave 6: stop showing raw UUIDs as primary content)
250
- const [evidenceCopied, setEvidenceCopied] = useState(false);
251
- const [evidenceExpanded, setEvidenceExpanded] = useState(false);
252
- // Fetch data
253
- const loadData = useCallback(async () => {
254
- if (!id)
255
- return;
256
- const epoch = ++detailEpoch.current;
257
- setLoading(true);
258
- setLoadingEvidenceKind(null);
259
- setError(null);
260
- setApprovalGroup(null); // Clear previous approval group to prevent stale actionability (P1)
261
- setApprovalGroupUnavailable(false);
262
- setGovernance(null);
263
- setGovernanceUnavailable(null);
264
- setOwnerDecision(null);
265
- setOwnerDecisionUnavailable(null);
266
- setReceipts(null);
267
- setEvidenceAudit(null);
268
- try {
269
- const [pResult, aResult, lResult, tResult, gResult, dResult, rResult, eResult] = await Promise.all([
270
- fetchPrincipleDetail(id),
271
- fetchApprovalsGrouped(),
272
- fetchLifecycleMetrics(id),
273
- fetchPrincipleTrajectory(id),
274
- fetchPrincipleGovernance(id),
275
- fetchOwnerDecisionView(id),
276
- fetchPrincipleReceipts(id),
277
- fetchEvidenceAudit('principle', id),
278
- ]);
279
- if (epoch !== detailEpoch.current)
280
- return;
281
- if (!pResult.success) {
282
- setError(pResult.error ?? "Failed to load principle");
283
- return;
284
- }
285
- const pData = validatePrincipleDetail(pResult.data);
286
- if (!pData) {
287
- setError("Invalid principle data received");
288
- return;
289
- }
290
- setPrinciple(pData.principle);
291
- const aData = aResult.success ? validateApprovalsGrouped(aResult.data) : null;
292
- if (aData) {
293
- const group = aData.groups.find((g) => g.principleId === id);
294
- setApprovalGroup(group ?? null);
295
- }
296
- else {
297
- setApprovalGroup(null);
298
- // The grouped list is the only source of pending approval records here;
299
- // swallowing the failure would hide the decision surface without a word.
300
- setApprovalGroupUnavailable(true);
301
- }
302
- const lData = lResult.success ? validateLifecycleMetrics(lResult.data) : null;
303
- setLifecycle(lData);
304
- // Trajectory — validated at request layer via validateTrajectoryData
305
- if (tResult.success && tResult.data) {
306
- setTrajectory(tResult.data);
307
- }
308
- else {
309
- setTrajectory(null);
310
- }
311
- if (gResult.success && gResult.data) {
312
- setGovernance(gResult.data);
313
- }
314
- else if (!gResult.success && gResult.reason !== 'feature_disabled') {
315
- setGovernanceUnavailable({ reason: gResult.error, ...(gResult.nextAction === undefined ? {} : { nextAction: gResult.nextAction }) });
316
- }
317
- // Owner Decision Experience v1: the canonical first layer. feature_disabled
318
- // mirrors the governance flag-off path (no owner-decision data, no error).
319
- if (dResult.success && dResult.data) {
320
- setOwnerDecision(dResult.data);
321
- }
322
- else if (!dResult.success && dResult.reason !== 'feature_disabled') {
323
- setOwnerDecisionUnavailable({ reason: dResult.error });
324
- }
325
- // PRI-533: receipt history (degraded carries reason + nextAction)
326
- if (rResult.success && rResult.data) {
327
- setReceipts(rResult.data);
328
- }
329
- else {
330
- setReceipts(null);
331
- }
332
- // PD v2 Phase 1: evidence audit (degraded carries reason + nextAction)
333
- if (eResult.success && eResult.data) {
334
- setEvidenceAudit(eResult.data);
335
- }
336
- else {
337
- setEvidenceAudit(null);
338
- }
339
- }
340
- catch (err) {
341
- if (epoch !== detailEpoch.current)
342
- return;
343
- setError(err instanceof Error ? err.message : "Unknown error");
344
- setApprovalGroup(null);
345
- setApprovalGroupUnavailable(true);
346
- }
347
- finally {
348
- if (epoch === detailEpoch.current)
349
- setLoading(false);
350
- }
351
- }, [id]);
352
- useEffect(() => {
353
- setPendingAction(null);
354
- setRejectReason('');
355
- setNewArtifactId('');
356
- setApproveNote('');
357
- setActionLoading(false);
358
- void loadData();
359
- return () => { detailEpoch.current++; };
360
- }, [loadData]);
361
- const loadOlderEvidence = async (kind) => {
362
- if (!id || !evidenceAudit || loadingEvidenceKind)
363
- return;
364
- const page = evidenceAudit.pages[kind];
365
- if (!page.hasMore || !page.nextCursor)
366
- return;
367
- setLoadingEvidenceKind(kind);
368
- const epoch = detailEpoch.current;
369
- try {
370
- const result = await fetchEvidenceAudit('principle', id, { kind, after: page.nextCursor });
371
- if (epoch !== detailEpoch.current)
372
- return;
373
- if (!result.success || !result.data)
374
- return;
375
- if (result.data.status !== 'ok') {
376
- toast.error(result.data.reason ?? '读取更早的干预证据失败');
377
- return;
378
- }
379
- const section = kind === 'delivery' ? 'deliveries'
380
- : kind === 'application' ? 'applications'
381
- : kind === 'behavior_episode' ? 'episodes'
382
- : kind === 'effect' ? 'effects' : 'outcomes';
383
- setEvidenceAudit((current) => current === null ? current : ({
384
- ...current,
385
- [section]: [...current[section], ...result.data[section]],
386
- pages: { ...current.pages, [kind]: result.data.pages[kind] },
387
- unresolvedReferences: [...new Map([...current.unresolvedReferences, ...result.data.unresolvedReferences]
388
- .map((entry) => [`${entry.evidenceId}:${entry.field}:${entry.missingKey}`, entry])).values()],
389
- }));
390
- }
391
- catch (err) {
392
- if (epoch !== detailEpoch.current)
393
- return;
394
- toast.error(err instanceof Error ? err.message : '读取更早的干预证据失败');
395
- }
396
- finally {
397
- if (epoch === detailEpoch.current)
398
- setLoadingEvidenceKind(null);
399
- }
400
- };
401
- // ── Owner decision actions (SPEC §8.4: mutation service is the authority) ─
402
- // The view's actions are advisory; every submission goes through the real
403
- // mutation service. On failure: show the service reason, invalidate stale
404
- // actions, re-GET the view. Never auto-retry a mutation.
405
- const submitOwnerAction = async (action) => {
406
- if (actionLoading)
407
- return;
408
- if (action.semantic !== 'disable')
409
- return;
410
- setActionLoading(true);
411
- const epoch = detailEpoch.current;
412
- try {
413
- let failed = false;
414
- let failureDetail = '';
415
- const settle = (result) => {
416
- if (!result.success) {
417
- failed = true;
418
- failureDetail = `${result.error ?? ''}${result.nextAction ? ` ${result.nextAction}` : ''}`.trim();
419
- }
420
- };
421
- if (action.semantic === 'disable') {
422
- const activationId = actionTargetId(action, 'activation');
423
- if (activationId === null) {
424
- toast.error(t("principles.detail.ownerDecision.invalidTarget", { defaultValue: "动作目标缺失,无法提交。" }));
425
- return;
426
- }
427
- settle(await disableActivation(activationId));
428
- }
429
- else {
430
- return; // unknown semantics are never rendered; belt-and-suspenders
431
- }
432
- if (epoch !== detailEpoch.current)
433
- return;
434
- if (!failed) {
435
- toast.success(t("principles.detail.ownerDecision.actionDone", { defaultValue: "操作已提交。" }));
436
- }
437
- else {
438
- // SPEC §8.4: surface the service's real refusal reason and let the
439
- // fresh GET decide what is actionable now — never auto-retry.
440
- toast.error(t("principles.detail.ownerDecision.actionFailed", {
441
- defaultValue: "操作被拒绝:{{detail}} 可用操作已刷新,请基于最新状态重新决定。",
442
- detail: failureDetail === '' ? t("principles.detail.unknownFailure", { defaultValue: "请检查服务日志。" }) : failureDetail,
443
- }));
444
- }
445
- }
446
- catch (err) {
447
- if (epoch !== detailEpoch.current)
448
- return;
449
- toast.error(err instanceof Error ? err.message : String(err));
450
- }
451
- finally {
452
- if (epoch === detailEpoch.current) {
453
- setActionLoading(false);
454
- setPendingAction(null);
455
- setRejectReason("");
456
- setNewArtifactId("");
457
- setApproveNote("");
458
- // Invalidate the stale action list and re-derive from a fresh GET.
459
- await loadData();
460
- }
461
- }
462
- };
463
- // ── Render ──────────────────────────────────────────────────────────────
464
- if (loading) {
465
- return (_jsx(PageShell, { children: _jsx(PageLoading, { cardCount: 1, label: t("principles.loading", { defaultValue: "Loading…" }) }) }));
466
- }
467
- if (error || !principle) {
468
- return (_jsxs(PageShell, { children: [_jsxs(Button, { variant: "ghost", onClick: () => navigate(returnTo), className: "mb-4", children: ["\u2190 ", t("principles.detail.backToList")] }), _jsxs("div", { className: "border border-danger/30 rounded-[var(--radius-md)] p-4", children: [_jsx("p", { className: "text-danger text-sm", children: error ?? t("principles.notFound") }), _jsx(Button, { variant: "outline", size: "sm", onClick: loadData, className: "mt-2", children: t("principles.retry", { defaultValue: "Retry" }) })] })] }));
469
- }
470
- const hasRules = principle.rules.length > 0;
471
- const receiptPresentation = receipts?.status === 'ok'
472
- ? getReceiptPresentation(receipts.effectCount, receipts.presenceCount)
473
- : null;
474
- // 切片1(R2/R3/R7):标题/正文分层——h1 只承载短标题预览;known 路径的逐字
475
- // 全文在下方 learned 块渲染(一次),unknown 路径在此处正文块渲染(一次)。
476
- const learnedText = ownerDecision?.learnedPrinciple.status === 'known'
477
- ? ownerDecision.learnedPrinciple.value.text
478
- : undefined;
479
- const learnedKnown = learnedText !== undefined;
480
- const learnedPreview = learnedText === undefined ? undefined : truncateByCodePoints(learnedText, 240);
481
- const learnedTruncated = learnedPreview !== learnedText;
482
- const headlineLayout = splitReadingTitleBody(learnedText ?? principle.text);
483
- return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsxs(Button, { variant: "ghost", onClick: () => navigate(returnTo), className: "-ml-2", children: ["\u2190 ", t("principles.detail.backToList")] }), IS_DEV && (_jsx(Link, { to: `/examiner?principle=${encodeURIComponent(String(id ?? ''))}`, className: "text-[13px] text-ink-3 underline decoration-dotted underline-offset-4 hover:text-ink", "data-testid": "principle-detail-examiner-link", children: t("principles.detail.examinerEntry", { defaultValue: "验证此原则的行为效果 (Examiner)" }) }))] }), _jsxs("section", { className: "mb-8", children: [_jsx(SectionTitle, { children: t("principles.detail.conclusion") }), _jsx("h1", { className: "text-[22px] font-semibold text-ink leading-snug mb-3", "data-testid": "principle-detail-title", children: headlineLayout.title }), headlineLayout.body !== null && !learnedKnown && (_jsx("div", { className: "mb-3 text-[15px] leading-relaxed text-ink whitespace-pre-wrap break-words", "data-testid": "principle-detail-body", children: headlineLayout.body })), ownerDecision !== null && ownerDecision.learnedPrinciple.status !== 'known' && (_jsx("p", { className: "text-amber text-[13px] leading-relaxed mb-3", "data-testid": "owner-decision-technical-note", children: t("principles.detail.ownerDecision.technicalOriginalNote", {
484
- defaultValue: "以上为原始技术建议文本;可读的行为准则暂缺(保留原文以保证可追溯)。",
485
- }) })), _jsx("p", { className: "text-ink-3 text-[14px] leading-relaxed mb-3", children: t("principles.detail.policyNote") }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-ink-4 text-[13px]", children: t("principles.detail.modifyWordingNote") }), _jsx(Button, { variant: "ghost", size: "sm", className: "ml-auto", "data-testid": "principle-feedback", onClick: () => {
486
- const params = new URLSearchParams({ source: "principle_page", principleId: id ?? "" });
487
- navigate(`/report-problem?${params.toString()}`);
488
- }, children: t("reportProblem.entryFeedback") })] })] }), ownerDecision !== null && (_jsxs("section", { className: "mb-8", "aria-labelledby": "owner-decision-title", "data-testid": "owner-decision-view", children: [_jsx(SectionTitle, { children: t("principles.detail.ownerDecision.title", { defaultValue: "这条原则的决策视图" }) }), _jsxs("div", { className: "rounded-[var(--radius-md)] border border-gov/25 bg-gov/5 p-4", children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { children: [_jsx("h2", { id: "owner-decision-title", className: "text-[18px] font-semibold text-ink", children: t(DECISION_STATE_LABEL_KEY[ownerDecision.decisionState]) }), _jsx("p", { className: "mt-1 text-[13px] leading-relaxed text-ink-2", children: localizeNextAction(ownerDecision.nextAction.code, ownerDecision.nextAction.ownerText, t) })] }), _jsx("span", { "data-testid": "owner-decision-state", className: "w-fit rounded-full border border-line px-2 py-1 font-mono text-[11px] text-ink-3", children: ownerDecision.sourceReadStatus === 'complete'
489
- ? t("principles.detail.ownerDecision.readsComplete", { defaultValue: "本次所需数据已读取" })
490
- : t("principles.detail.ownerDecision.readsPartial", { defaultValue: "部分数据源读取失败" }) })] }), _jsxs("div", { className: "mt-4", "data-testid": "owner-decision-learned", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.learned", { defaultValue: "Agent 学到的行为准则" }) }), ownerDecision.learnedPrinciple.status === 'known' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "mt-1 text-ink-2 text-[15px] leading-relaxed whitespace-pre-wrap break-words", children: learnedPreview }), learnedTruncated && _jsxs("details", { className: "mt-3 text-sm text-ink-2", children: [_jsx("summary", { className: "cursor-pointer text-gov", children: t('principles.detail.fullRule') }), _jsx("p", { className: "mt-3 whitespace-pre-wrap break-words leading-relaxed", children: learnedText })] }), _jsx("p", { className: "mt-1 text-ink-4 text-[12px]", children: t("principles.detail.ownerDecision.sourceTierLabel", {
491
- defaultValue: "来源:{{tier}}(未经改写)",
492
- tier: t(`principles.detail.ownerDecision.tier.${ownerDecision.learnedPrinciple.value.sourceTier}`, { defaultValue: ownerDecision.learnedPrinciple.value.sourceTier }),
493
- }) })] })) : (_jsx("p", { className: "mt-1 text-amber text-[13px] leading-relaxed", children: ownerDecision.learnedPrinciple.reason.ownerText }))] }), ownerDecision.decisionSubjects.some((subject) => subject.state !== 'pending') && (_jsxs("div", { className: "mt-3", "data-testid": "owner-decision-history", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.history", { defaultValue: "决定历史" }) }), _jsx("ul", { className: "mt-1 space-y-1 text-[13px] text-ink-2", children: ownerDecision.decisionSubjects.filter((subject) => subject.state !== 'pending').map((subject) => {
494
- const decidedAt = subject.targetRefs.find((target) => target.kind === 'approval')?.recordedAt;
495
- const stateKey = `principles.detail.ownerDecision.historyState.${subject.state}`;
496
- return (_jsxs("li", { children: [t(stateKey, { defaultValue: subject.state }), decidedAt !== undefined ? ` · ${decidedAt.slice(0, 10)}` : '', ' · ', t(`principles.detail.ownerDecision.channel.${subject.channel}`, { defaultValue: subject.channel })] }, `hist-${subject.key}`));
497
- }) })] })), _jsxs("div", { className: "mt-5 border-t border-line pt-4", "data-testid": "owner-decision-actions", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.decision", { defaultValue: "你的决定" }) }), ownerDecision.availableActions.length === 0 && (_jsx("p", { className: "mt-1 text-ink-3 text-[13px]", children: t("principles.detail.ownerDecision.noActions", { defaultValue: "当前没有可以执行的操作。" }) })), approvalGroupUnavailable && ownerDecision.availableActions.length > 0 && (_jsxs("div", { role: "alert", className: "mt-2 text-[13px] leading-relaxed text-amber", "data-testid": "detail-approvals-unavailable", children: [_jsx("p", { children: t('focus.workbench.approvalsUnavailable') }), _jsx("button", { type: "button", onClick: () => { void loadData(); }, className: "mt-1 text-gov underline", children: t('focus.workbench.retry') })] })), approvalGroup?.records.filter(record => record.status === 'pending').map(record => {
498
- const allowedActions = ownerDecision.availableActions
499
- .filter(action => actionTargetId(action, 'approval') === record.id)
500
- .map(action => action.semantic)
501
- .filter((semantic) => semantic === 'approve' || semantic === 'reject' || semantic === 'edit_approval');
502
- // A sibling's broken revision review must not block this record;
503
- // without any per-record defect the group flag still covers the
504
- // "multiple versions pending" ambiguity.
505
- const revisionReviewUnavailable = record.revisionReviewUnavailable
506
- ?? (approvalGroup.records.some(entry => entry.status === 'pending' && entry.revisionReviewUnavailable === true)
507
- ? false : approvalGroup.revisionReviewUnavailable);
508
- return _jsxs("details", { className: "mt-4 rounded border border-line p-4", "data-testid": "detail-approval-review", children: [_jsxs("summary", { className: "cursor-pointer text-sm text-gov", children: [t('focus.workbench.proposal'), " \u00B7 ", t(`principles.detail.ownerDecision.channel.${record.channel}`, { defaultValue: record.channel })] }), _jsx("div", { className: "mt-5", children: _jsx(ApprovalSubjectReading, { principleId: principle.id, approvalId: record.id, artifactId: record.artifactId, channel: record.channel, showPrincipleLink: false, revisionReview: new Set(approvalGroup.records.filter(entry => entry.status === 'pending').map(entry => entry.artifactId)).size === 1 ? approvalGroup.revisionReview : undefined, revisionReviewUnavailable: revisionReviewUnavailable, allowedActions: allowedActions, lockedReason: ownerDecision.availableActions.some(action => actionTargetId(action, 'approval') === record.id) ? undefined : t('focus.workbench.permissionsUnknown'), onResolved: message => { toast.success(message); void loadData(); } }) })] }, record.id);
509
- }), _jsx("div", { className: "mt-2 flex flex-wrap gap-3", children: ownerDecision.availableActions.filter(action => action.semantic === 'disable').map((action) => (_jsx(Button, { variant: action.semantic === 'reject' ? 'destructive' : action.semantic === 'disable' ? 'outline' : 'default', size: "sm", disabled: actionLoading, "data-action-semantic": action.semantic, onClick: () => {
510
- setRejectReason("");
511
- setApproveNote("");
512
- setPendingAction(action);
513
- }, children: localizeActionLabel(action, t) }, action.key))) }), ownerDecision.blockers.length > 0 && (_jsx("ul", { className: "mt-3 space-y-1 text-[12px] text-ink-3", children: ownerDecision.blockers.map((blocker, index) => (_jsx("li", { "data-testid": "owner-decision-blocker", children: localizeAggregatedBlocker(blocker.reason, t) }, `blk-${index}`))) })), pendingAction !== null && (_jsxs("div", { className: "border-t border-line pt-6 mt-6", "data-testid": "owner-decision-confirm", children: [_jsx(SectionTitle, { children: pendingAction.label }), _jsxs("div", { className: "mt-2 p-3 bg-gov/5 border border-gov/20 rounded-[var(--radius-md)]", children: [pendingAction.expectedConsequence.status === 'known' && (_jsx("div", { className: "mb-3", children: pendingAction.expectedConsequence.value.map((item, index) => (_jsx("p", { className: "text-ink-2 text-[13px] leading-relaxed mb-1", children: item.text }, `exp-${index}`))) })), _jsx("p", { className: "text-ink-2 text-[13px] mb-3", children: pendingAction.confirmation.text }), pendingAction.requirements.some((req) => req.name === 'newArtifactId') && (_jsxs(_Fragment, { children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("principles.detail.editNewArtifactLabel", { defaultValue: "新的已验证工件 ID" }) }), _jsx("input", { type: "text", value: newArtifactId, onChange: (e) => setNewArtifactId(e.target.value), placeholder: t("principles.detail.editNewArtifactPlaceholder", { defaultValue: "输入新的已验证工件 ID" }), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] mb-2 font-mono focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov", "aria-label": t("principles.detail.editNewArtifactPlaceholder", { defaultValue: "输入新的已验证工件 ID" }) })] })), pendingAction.requirements.some((req) => req.name === 'reason') && (_jsxs(_Fragment, { children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("principles.detail.rejectReasonLabel", { defaultValue: "拒绝原因" }) }), _jsx("textarea", { value: rejectReason, onChange: (e) => setRejectReason(e.target.value), placeholder: t("principles.detail.rejectReasonPlaceholder"), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[80px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov", "aria-label": t("principles.detail.rejectReasonPlaceholder") })] })), pendingAction.requirements.some((req) => req.name === 'note') && (_jsxs(_Fragment, { children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("principles.detail.approveNoteLabel", { defaultValue: "批准备注(可选)" }) }), _jsx("textarea", { "data-testid": "owner-decision-note", value: approveNote, onChange: (e) => setApproveNote(e.target.value), placeholder: pendingAction.requirements.find((req) => req.name === 'note')?.ownerText
514
- ?? t("principles.detail.approveNotePlaceholder", { defaultValue: "写下批准的理由(可留空)" }), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[80px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov", "aria-label": t("principles.detail.approveNoteLabel", { defaultValue: "批准备注(可选)" }) })] })), _jsxs("div", { className: "flex gap-2 mt-3", children: [_jsx(Button, { variant: pendingAction.semantic === 'reject' ? 'destructive' : 'default', size: "sm", disabled: actionLoading
515
- || (pendingAction.requirements.some((req) => req.name === 'reason') && !rejectReason.trim())
516
- || (pendingAction.requirements.some((req) => req.name === 'newArtifactId') && !newArtifactId.trim()), onClick: () => {
517
- const action = pendingAction;
518
- void submitOwnerAction(action);
519
- }, children: t("principles.detail.confirm", { defaultValue: "确认" }) }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => { setPendingAction(null); setRejectReason(""); setNewArtifactId(""); setApproveNote(""); }, children: t("principles.detail.cancel") })] })] })] }))] }), _jsxs("details", { className: "mt-5 border-t border-line pt-4", "data-testid": "principle-formation-disclosure", children: [_jsx("summary", { className: "cursor-pointer text-sm text-gov", children: t('principles.detail.formationDisclosure') }), _jsxs("div", { className: "mt-4", children: [_jsx(OwnerNarrativeBlock, { testId: "owner-decision-incident", label: t("principles.detail.ownerDecision.incident", { defaultValue: "发生了什么" }), field: ownerDecision.incidentSummary }), _jsx(OwnerNarrativeBlock, { testId: "owner-decision-rationale", label: t("principles.detail.ownerDecision.rationale", { defaultValue: "为什么这么判断" }), field: ownerDecision.rationale })] })] }), _jsx(OwnerNarrativeBlock, { testId: "owner-decision-applicability", label: t("principles.detail.ownerDecision.applicability", { defaultValue: "什么时候适用" }), field: ownerDecision.applicability }), _jsx(OwnerNarrativeBlock, { testId: "owner-decision-expected", label: t("principles.detail.ownerDecision.expected", { defaultValue: "批准后会怎样(拟议行为,未部署)" }), field: ownerDecision.expectedBehavior }), ownerDecision.currentEnforcement.status === 'known' && (_jsxs("div", { className: "mt-4", "data-testid": "owner-decision-enforcement", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.enforcementLabel", { defaultValue: "当前实际执行" }) }), _jsx("p", { className: "mt-1 text-ink-2 text-[14px] leading-relaxed", children: ownerDecision.currentEnforcement.value?.state === 'active'
520
- ? t("principles.detail.ownerDecision.enforcement.active", { defaultValue: "当前有正在执行的生效方式(见下方明细)。" })
521
- : ownerDecision.currentEnforcement.value?.state === 'deactivated'
522
- ? t("principles.detail.ownerDecision.enforcement.deactivated", { defaultValue: "此前的执行方式已停用;当前没有正在执行的生效方式。" })
523
- : ownerDecision.currentEnforcement.value?.state === 'partially_active'
524
- ? t("principles.detail.ownerDecision.enforcement.partial", { defaultValue: "部分执行方式仍在运行(见下方明细)。" })
525
- : t("principles.detail.ownerDecision.enforcement.none", { defaultValue: "这条原则当前没有生效中的执行方式。" }) }), ownerDecision.currentEnforcement.value?.items.map((item) => (_jsxs("p", { className: "mt-1 text-ink-3 text-[12px]", children: [item.mode.status === 'known' ? item.mode.value : item.channel, " · ", item.active
526
- ? t("principles.detail.ownerDecision.enforcement.since", { defaultValue: "生效中(自 {{since}})", since: item.since.status === 'known' ? item.since.value.slice(0, 10) : '?' })
527
- : t("principles.detail.ownerDecision.enforcement.stopped", { defaultValue: "已停用" })] }, item.activationRef.id)))] })), ownerDecision.currentEnforcement.status === 'unknown' && (_jsx("p", { className: "mt-4 text-amber text-[13px]", "data-testid": "owner-decision-enforcement-unknown", children: ownerDecision.currentEnforcement.reason?.ownerText })), ownerDecision.evidenceSummary.status === 'known' && (_jsxs("div", { className: "mt-4", "data-testid": "owner-decision-evidence", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.evidence", { defaultValue: "行为证据" }) }), _jsx("p", { className: "mt-1 text-ink-2 text-[13px] leading-relaxed", children: ownerDecision.evidenceSummary.value?.ownerExplanation })] })), _jsxs("div", { className: "mt-4", "data-testid": "owner-decision-uncertainty", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.uncertainty", { defaultValue: "风险与不确定性" }) }), ownerDecision.risk.status === 'known' && (ownerDecision.risk.value?.items.length ?? 0) > 0 && (_jsx("ul", { className: "mt-1 space-y-1 text-[13px] text-ink-2", children: ownerDecision.risk.value?.items.map((item, index) => (_jsx("li", { children: item.text }, `risk-${index}`))) })), ownerDecision.risk.status === 'known' && (ownerDecision.risk.value?.items.length ?? 0) === 0 && (_jsx("p", { className: "mt-1 text-ink-3 text-[13px]", children: t("principles.detail.ownerDecision.riskNotAssessed", { defaultValue: "尚未做过风险评估;这不代表没有风险。" }) })), ownerDecision.risk.status === 'unknown' && (_jsx("p", { className: "mt-1 text-ink-3 text-[13px]", children: ownerDecision.risk.reason?.ownerText })), ownerDecision.uncertainty.status === 'known' && ownerDecision.uncertainty.value.length > 0 && (_jsx("ul", { className: "mt-2 space-y-1 text-[12px] text-ink-3", children: ownerDecision.uncertainty.value.map((item, index) => (_jsx("li", { children: item.text }, `unc-${index}`))) }))] }), _jsxs("div", { className: "mt-4", "data-testid": "owner-decision-rollback", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t("principles.detail.ownerDecision.rollback", { defaultValue: "如何停止影响" }) }), ownerDecision.rollback.status === 'known' && (_jsxs(_Fragment, { children: [_jsx("p", { className: "mt-1 text-ink-2 text-[13px] leading-relaxed", children: ownerDecision.rollback.value?.ownerText }), ownerDecision.rollback.value?.stopFuture.status === 'known' && (_jsx("ul", { className: "mt-1 space-y-1 text-[12px] text-ink-3", children: ownerDecision.rollback.value.stopFuture.value.map((item, index) => (_jsx("li", { children: item.text }, `rb-${index}`))) })), ownerDecision.rollback.value?.stopFuture.status === 'not_applicable' && (_jsx("p", { className: "mt-1 text-ink-3 text-[12px]", children: ownerDecision.rollback.value.stopFuture.reason.ownerText }))] })), ownerDecision.rollback.status === 'unknown' && (_jsx("p", { className: "mt-1 text-amber text-[13px]", children: ownerDecision.rollback.reason?.ownerText }))] })] })] })), ownerDecision === null && ownerDecisionUnavailable !== null && (_jsxs("section", { className: "mb-8", "data-testid": "owner-decision-unavailable", children: [_jsx(SectionTitle, { children: t("principles.detail.ownerDecision.title", { defaultValue: "这条原则的决策视图" }) }), _jsxs("div", { className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("p", { className: "text-ink-2 text-[13px]", children: t("principles.detail.ownerDecision.unavailable", { defaultValue: "决策视图暂时不可用,无法据此做决定。" }) }), _jsx("p", { className: "mt-1 text-ink-4 text-[12px] font-mono", children: ownerDecisionUnavailable.reason })] })] })), (governance !== null || governanceUnavailable !== null) && (_jsxs("section", { className: "mb-8", "aria-labelledby": "governance-summary-title", children: [_jsx(SectionTitle, { children: t('principles.detail.governance.title') }), governance !== null ? (_jsxs("div", { "data-testid": "governance-summary", className: `rounded-[var(--radius-md)] border p-4 ${governance.dataQuality.degraded ? 'border-amber/30 bg-amber/5' : 'border-gov/25 bg-gov/5'}`, children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { children: [_jsx("h2", { id: "governance-summary-title", className: "text-[18px] font-semibold text-ink", children: t(`principles.detail.${governance.summary.headlineCode}`, { defaultValue: governance.summary.headlineCode }) }), _jsx("p", { className: "mt-1 text-[13px] leading-relaxed text-ink-2", children: t(`principles.detail.${governance.summary.reasonCode}`, { defaultValue: governance.summary.reasonCode }) })] }), _jsx("span", { className: "w-fit rounded-full border border-line px-2 py-1 font-mono text-[11px] text-ink-3", children: t(`principles.detail.governance.confidence.${governance.dataQuality.degraded ? 'degraded' : 'strong'}`) })] }), _jsxs("dl", { className: "mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.principleState') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.state.${governance.principleState.value}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.process') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: governance.process.stage === undefined ? t('principles.detail.governance.none') : t(`principles.detail.governance.stage.${governance.process.stage}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.automation') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.automationState.${governance.automation.state}`) })] })] }), _jsxs("div", { "data-testid": "governance-next-action", className: "mt-4 border-l-2 border-l-gov pl-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.nextAction') }), _jsx("p", { className: "text-[13px] text-ink-2", children: t(`principles.detail.${governance.summary.nextActionCode}`, { defaultValue: governance.summary.nextActionCode }) })] }), governance.attention.items.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.blockers') }), _jsx("ul", { className: "mt-1 space-y-1 text-[13px] text-ink-2", children: groupByReasonCode(governance.attention.items).map(group => _jsx("li", { children: formatGroupedReasonLine(t, 'principles.detail.governance.attention', group) }, group.reasonCode)) })] })), governance.dataQuality.degraded && (_jsxs("div", { "data-testid": "governance-data-quality", className: "mt-4 rounded-[var(--radius-sm)] border border-amber/20 p-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-amber", children: t('principles.detail.governance.uncertainty') }), _jsx("ul", { className: "mt-1 space-y-1 text-[12px] text-ink-3", children: groupByReasonCode(governance.dataQuality.issues).map(group => _jsx("li", { children: formatGroupedReasonLine(t, 'principles.detail.governance.issue', group) }, group.reasonCode)) })] }))] })) : (_jsxs("div", { "data-testid": "governance-data-quality", className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("h2", { id: "governance-summary-title", className: "text-[16px] font-semibold text-ink", children: t('principles.detail.governance.unavailable') }), _jsx("p", { className: "mt-1 text-[13px] text-ink-2", children: t('principles.detail.governance.unavailableReason') }), _jsx("p", { className: "mt-2 text-[12px] text-ink-3", children: t('principles.detail.governance.unavailableNextAction') })] }))] })), receipts !== null && (_jsxs("section", { className: "mb-8", "aria-labelledby": "receipt-history-title", children: [_jsx(SectionTitle, { children: t('principles.detail.receipts.title') }), receipts.status === 'ok' ? (_jsxs("div", { "data-testid": "receipt-history", className: "rounded-[var(--radius-md)] border border-line p-4", children: [_jsxs("div", { className: "flex flex-wrap items-baseline justify-between gap-2", children: [_jsx("h2", { id: "receipt-history-title", className: "text-[15px] font-semibold text-ink", children: receiptPresentation?.headlineKey === 'principles.detail.receipts.headline'
528
- ? t(receiptPresentation.headlineKey, {
529
- defaultValue: '',
530
- effectCount: receipts.effectCount,
531
- lastEffectAt: receipts.lastEffectAt ? formatDate(receipts.lastEffectAt, i18n.language) : '',
532
- })
533
- : t(receiptPresentation?.headlineKey ?? 'principles.detail.receipts.headlinePresence') }), _jsx("span", { "data-testid": "receipt-history-counts", className: "font-mono text-[11px] text-ink-3", children: t('principles.detail.receipts.counts', { effectCount: receipts.effectCount, presenceCount: receipts.presenceCount }) })] }), receiptPresentation?.showZeroEffectExplanation && (_jsx("p", { "data-testid": "receipt-history-zero-effect", className: "mt-2 text-[12px] leading-relaxed text-ink-3", children: t(receipts.presenceCount > 0
534
- ? 'principles.detail.receipts.zeroEffectPresence'
535
- : 'principles.detail.receipts.zeroEffectNone') })), receiptPresentation?.presenceMissing && (_jsx("p", { "data-testid": "receipt-history-presence-missing", className: "mt-2 text-[12px] leading-relaxed text-ink-3", children: t('principles.detail.receipts.presenceMissingNote') })), receipts.events.length > 0 ? (_jsx("ul", { className: "mt-3 space-y-1.5", children: receipts.events.map((event, index) => (_jsxs("li", { className: `flex flex-wrap items-baseline gap-2 text-[13px] ${event.level === 'presence' ? 'text-ink-4' : 'text-ink-2'}`, children: [_jsx("span", { className: "font-mono text-[11px] text-ink-4", children: event.createdAt.slice(0, 16).replace('T', ' ') }), _jsx("span", { className: "font-mono text-[11px]", children: t(`principles.detail.receipts.kind.${event.kind}`, { defaultValue: event.kind }) }), event.digest && _jsx("span", { className: "min-w-0 flex-1 truncate", title: event.digest, children: event.digest })] }, `${event.createdAt}-${index}`))) })) : (_jsx("p", { className: "mt-2 text-[13px] text-ink-3", children: t('principles.detail.receipts.empty') })), _jsx("p", { className: "mt-3 text-[11px] leading-relaxed text-ink-4", children: t('principles.detail.receipts.note') }), _jsx("div", { className: "mt-3 border-t border-line pt-3", children: _jsx(ReceiptCoverageDisclosure, { coverage: receipts.coverage }) })] })) : (_jsxs("div", { "data-testid": "receipt-history-degraded", className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("h3", { className: "text-[13px] font-semibold text-ink", children: i18n.t(getReceiptSourceStatusLabelKey(receipts.coverage.sourceStatus)) }), _jsx("p", { className: "mt-1 text-[13px] text-ink-2", children: receipts.reason ?? t('principles.detail.receipts.unavailableReason') }), receipts.nextAction && _jsx("p", { className: "mt-1 text-[12px] text-ink-3", children: receipts.nextAction })] }))] })), evidenceAudit !== null && (_jsxs("section", { className: "mb-8", "aria-labelledby": "evidence-audit-title", children: [_jsx(SectionTitle, { children: t('principles.detail.evidenceAudit.title') }), evidenceAudit.status === 'ok' ? (_jsxs("div", { "data-testid": "evidence-audit", className: "rounded-[var(--radius-md)] border border-line p-4", children: [_jsx("h2", { id: "evidence-audit-title", className: "text-[15px] font-semibold text-ink", children: t('principles.detail.evidenceAudit.headline', {
536
- d: evidenceAudit.deliveries.length,
537
- a: evidenceAudit.applications.length,
538
- e: evidenceAudit.episodes.length,
539
- f: evidenceAudit.effects.length,
540
- o: evidenceAudit.outcomes.length,
541
- }) }), evidenceAudit.unresolvedReferences.length > 0 && (_jsx("p", { "data-testid": "evidence-audit-unresolved", className: "mt-2 text-[12px] text-amber", children: t('principles.detail.evidenceAudit.unresolved', {
542
- count: evidenceAudit.unresolvedReferences.length,
543
- }) })), _jsx("dl", { className: "mt-3 space-y-2 text-[13px]", children: [
544
- ['delivery', 'principles.detail.evidenceAudit.sectionDelivery', evidenceAudit.deliveries, 'delivery'],
545
- ['application', 'principles.detail.evidenceAudit.sectionApplication', evidenceAudit.applications, 'application'],
546
- ['episode', 'principles.detail.evidenceAudit.sectionEpisode', evidenceAudit.episodes, 'behavior_episode'],
547
- ['effect', 'principles.detail.evidenceAudit.sectionEffect', evidenceAudit.effects, 'effect'],
548
- ['outcome', 'principles.detail.evidenceAudit.sectionOutcome', evidenceAudit.outcomes, 'outcome'],
549
- ].map(([key, labelKey, list, recordKind]) => (_jsxs("div", { className: "border-t border-line pt-2", children: [_jsx("dt", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t(labelKey) }), _jsx("dd", { className: "mt-1", children: list.length === 0 ? (_jsx("span", { className: "text-[13px] text-ink-3", children: t('principles.detail.evidenceAudit.emptySection') })) : (_jsx("ul", { className: "space-y-1", children: list.map((record) => (_jsxs("li", { className: "flex flex-wrap items-baseline gap-2 text-[13px] text-ink-2", children: [_jsx("span", { className: "font-mono text-[11px] text-ink-4", children: record.recordedAt.slice(0, 16).replace('T', ' ') }), _jsx("span", { className: "font-mono text-[11px]", children: record.summary }), _jsx("span", { className: "min-w-0 flex-1 break-words", title: `${record.observationKey}\n${record.detail}`, children: record.detail }), record.associationStatus === 'pending_association' && (_jsx("span", { className: "font-mono text-[10px] rounded bg-amber/15 px-1.5 py-0.5 text-amber", children: t('principles.detail.evidenceAudit.pending') }))] }, record.evidenceId))) })) }), evidenceAudit.pages[recordKind].hasMore && (_jsx(Button, { variant: "ghost", size: "sm", disabled: loadingEvidenceKind !== null, onClick: () => void loadOlderEvidence(recordKind), children: loadingEvidenceKind === recordKind ? t('principles.detail.evidenceAudit.loading') : t('principles.detail.evidenceAudit.loadOlder') }))] }, key))) }), evidenceAudit.capabilityDeclarations.length > 0 && (_jsxs("details", { className: "mt-3 border-t border-line pt-3", children: [_jsx("summary", { className: "cursor-pointer font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.evidenceAudit.capabilities') }), _jsx("ul", { className: "mt-2 space-y-1", children: evidenceAudit.capabilityDeclarations.map((cap) => (_jsxs("li", { className: "text-[12px] text-ink-3", children: [_jsxs("span", { className: "font-mono", children: [cap.hostKind, " \u00B7 ", cap.capability, " \u00B7 ", cap.status] }), cap.note && _jsxs("span", { children: [" \u2014 ", cap.note] })] }, `${cap.hostKind}-${cap.capability}`))) })] })), _jsxs("details", { className: "mt-3 border-t border-line pt-3", "data-testid": "evidence-audit-technical", children: [_jsx("summary", { className: "cursor-pointer font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.evidenceAudit.technicalSummary') }), _jsx("p", { className: "mt-2 text-[11px] leading-relaxed text-ink-4", children: t('principles.detail.evidenceAudit.technicalNote') }), _jsx("ul", { className: "mt-2 space-y-1", children: [
550
- ['principles.detail.evidenceAudit.sectionDelivery', evidenceAudit.deliveries],
551
- ['principles.detail.evidenceAudit.sectionApplication', evidenceAudit.applications],
552
- ['principles.detail.evidenceAudit.sectionEpisode', evidenceAudit.episodes],
553
- ['principles.detail.evidenceAudit.sectionEffect', evidenceAudit.effects],
554
- ['principles.detail.evidenceAudit.sectionOutcome', evidenceAudit.outcomes],
555
- ].flatMap(([labelKey, list]) => list.map((record) => (_jsxs("li", { className: "text-[11px] leading-relaxed text-ink-4", children: [_jsx("span", { className: "font-mono", children: record.evidenceId }), record.sourceStatus === 'unknown' && _jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.sourceUnknown')] }), record.contentRedactedAt && _jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.contentRedacted', { date: record.contentRedactedAt.slice(0, 10) })] }), record.contentReference && (_jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.contentReference', {
556
- resolution: record.contentReference.resolution === 'resolved' ? t('principles.detail.evidenceAudit.referenceResolved') : t('principles.detail.evidenceAudit.referenceUnresolved'),
557
- principleId: record.contentReference.principleId,
558
- artifactId: record.contentReference.artifactId ? ` · ${record.contentReference.artifactId}` : '',
559
- // Review round (P2): keep the payload digest traceable —
560
- // the technical note promises it.
561
- payloadDigest: ` · ${t('principles.detail.evidenceAudit.payloadDigestLabel')}: ${record.contentReference.payloadDigest ?? t('principles.detail.evidenceAudit.noPayloadDigest')}`,
562
- })] })), record.activationReference && (_jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.activationReference', {
563
- activationId: record.activationReference.activationId,
564
- activatedAt: record.activationReference.activatedAt ? ` · ${record.activationReference.activatedAt}` : '',
565
- snapshotDigest: ` · ${t('principles.detail.evidenceAudit.snapshotDigestLabel')}: ${record.activationReference.sourceSnapshotDigest}`,
566
- })] })), record.nativeLineage.length > 0 && _jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.nativeLineage', { lineage: record.nativeLineage.join(' · ') })] })] }, record.evidenceId)))) })] }), _jsx("p", { className: "mt-3 text-[11px] leading-relaxed text-ink-4", children: t('principles.detail.evidenceAudit.note') })] })) : (_jsxs("div", { "data-testid": "evidence-audit-degraded", className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("h3", { className: "text-[13px] font-semibold text-ink", children: t('principles.detail.evidenceAudit.unavailable') }), _jsx("p", { className: "mt-1 text-[13px] text-ink-2", children: evidenceAudit.reason ?? '—' }), evidenceAudit.nextAction && _jsx("p", { className: "mt-1 text-[12px] text-ink-3", children: evidenceAudit.nextAction })] }))] })), _jsxs("details", { className: "mb-8 border-t border-line pt-4", "data-testid": "principle-extra-context", children: [_jsx("summary", { className: "cursor-pointer text-sm text-gov", children: t('principles.detail.extraContext') }), _jsxs("div", { className: "mt-5", children: [_jsxs("section", { className: "mb-8", children: [_jsx(SectionTitle, { children: t("principles.detail.whyExists") }), _jsxs("div", { className: "space-y-3 mb-6", children: [_jsxs("div", { children: [_jsx("span", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3", children: t("principles.detail.applicable", { defaultValue: "适用场景(原始触发配置)" }) }), _jsx("p", { className: "text-ink-2 text-[14px] leading-relaxed font-mono break-all", children: principle.triggerPattern || t("principles.detail.notSpecified", { defaultValue: "未指定" }) })] }), _jsxs("div", { children: [_jsx("span", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3", children: t("principles.detail.expectedBehavior", { defaultValue: "预期行为(原始建议)" }) }), _jsx("p", { className: "text-ink-2 text-[14px] leading-relaxed", children: principle.action || t("principles.detail.notSpecified", { defaultValue: "未指定" }) })] })] }), principle.derivedFromPainIds.length > 0 && (_jsxs("div", { children: [_jsx("span", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3", children: t("principles.detail.evidence") }), _jsxs("div", { className: "mt-2 flex items-center gap-3 flex-wrap", children: [_jsx("p", { className: "text-ink-2 text-[14px] leading-relaxed", children: t("principles.detail.evidenceCount", {
567
- defaultValue: "已关联 {{count}} 条证据记录",
568
- count: principle.derivedFromPainIds.length,
569
- }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: async () => {
570
- try {
571
- const summary = principle.derivedFromPainIds
572
- .map((pid, i) => `pain_${i + 1}_id: ${pid}`)
573
- .join("\n");
574
- await navigator.clipboard.writeText(summary);
575
- setEvidenceCopied(true);
576
- setTimeout(() => setEvidenceCopied(false), 2000);
577
- }
578
- catch (error) {
579
- // clipboard unavailable — expand as fallback
580
- console.warn("Evidence ID copy failed; expanding technical details.", error);
581
- if (!evidenceExpanded)
582
- setEvidenceExpanded(true);
583
- }
584
- }, className: "font-mono text-[11px] h-7", children: evidenceCopied
585
- ? t("principles.detail.evidenceCopied", { defaultValue: "已复制" })
586
- : t("principles.detail.copyEvidenceId", { defaultValue: "复制证据 ID" }) }), _jsx("button", { type: "button", onClick: () => setEvidenceExpanded((v) => !v), className: "font-mono text-[11px] text-ink-4 hover:text-ink-3 transition-colors underline-offset-2 hover:underline", children: t("principles.detail.expandTechDetails", { defaultValue: "展开技术细节" }) }), _jsx(Link, { to: "/pain", className: "font-mono text-[11px] text-gov hover:underline transition-colors", children: t("principles.detail.viewEvidenceChain", { defaultValue: "在证据链页查看 →" }) })] }), evidenceExpanded && (_jsx("div", { className: "mt-3 p-3 bg-paper-2 border border-line rounded-[var(--radius-sm)]", children: _jsx("div", { className: "grid grid-cols-[auto 1fr] gap-x-4 gap-y-2 text-[13px]", children: principle.derivedFromPainIds.map((painId, idx) => (_jsxs("div", { className: "contents", children: [_jsx("span", { className: "font-mono text-ink-4", children: t("principles.detail.evidenceIdLabel", {
587
- defaultValue: "证据 {{n}} ID",
588
- n: idx + 1,
589
- }) }), _jsx("span", { className: "font-mono text-ink-2 break-all", children: painId })] }, `${painId}-${idx}`))) }) }))] }))] }), _jsxs("section", { className: "mb-8 border-t border-line pt-6", children: [_jsx(SectionTitle, { children: t("principles.detail.ownerReflection") }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "border-l-2 border-l-gov pl-3 text-ink-2 text-[13px] leading-relaxed", children: t("principles.detail.reflectionQ1") }), _jsx("div", { className: "border-l-2 border-l-gov pl-3 text-ink-2 text-[13px] leading-relaxed", children: t("principles.detail.reflectionQ2") }), _jsx("div", { className: "border-l-2 border-l-gov pl-3 text-ink-2 text-[13px] leading-relaxed", children: t("principles.detail.reflectionQ3") })] })] })] })] }), _jsxs("details", { className: "mb-8 border border-line rounded-[var(--radius-md)]", children: [_jsx("summary", { className: "px-4 py-3 cursor-pointer font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 hover:text-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov", children: t("principles.detail.trajectory") }), _jsxs("div", { className: "px-4 pb-4 border-t border-line pt-4", children: [governance !== null && (_jsxs("section", { className: "mb-6", "data-testid": "governance-timeline", children: [_jsx(SectionTitle, { children: t('principles.detail.governance.timeline') }), governance.timeline.length === 0 ? _jsx("p", { className: "text-[13px] text-ink-4", children: t('principles.detail.governance.timelineEmpty') }) : (_jsx("ol", { className: "space-y-3 border-l border-line pl-4", children: governance.timeline.map((event, index) => {
590
- const derived = event.code === 'revision_requested' || event.code === 'revision_reopened';
591
- return _jsxs("li", { children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.timelineCode.${event.code}`, { defaultValue: event.code }) }), _jsx("span", { className: "rounded border border-line px-1.5 py-0.5 font-mono text-[10px] text-ink-4", children: t(`principles.detail.governance.${derived ? 'derived' : 'fact'}`) })] }), _jsx("p", { className: "mt-0.5 font-mono text-[11px] text-ink-4", children: event.occurredAt ?? event.recordedAt })] }, `${event.sourceRef.type}-${event.sourceRef.id}-${event.code}-${index}`);
592
- }) }))] })), trajectory?.degraded && (_jsxs("div", { className: "mb-4 p-3 bg-amber/5 border border-amber/20 rounded-[var(--radius-sm)]", children: [_jsx("p", { className: "text-amber text-[12px] font-mono", children: trajectory.degraded.reason }), _jsx("p", { className: "text-ink-4 text-[11px] mt-1", children: trajectory.degraded.nextAction })] })), _jsx("div", { className: "space-y-4", children: (trajectory?.stages ?? []).length > 0 ? (trajectory.stages.map((stage) => (_jsxs("div", { className: "flex gap-4", children: [_jsx("span", { className: "font-mono text-[12px] text-ink-3 min-w-[80px]", children: t(STAGE_LABEL_KEYS[stage.key] ?? `principles.detail.stage${stage.key}`, { defaultValue: stage.key }) }), _jsx("div", { className: "flex-1", children: stage.status === 'available' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-ink-2 text-[13px]", children: stage.summary }), stage.detail && (_jsx("p", { className: "text-ink-3 text-[12px] mt-0.5", children: stage.detail })), stage.timestamp && (_jsx("p", { className: "text-ink-4 text-[11px] mt-0.5 font-mono", children: stage.timestamp }))] })) : (_jsxs("p", { className: "text-ink-4 text-[13px]", children: [stage.unavailableReason ?? '—', stage.nextAction && (_jsx("span", { className: "block text-ink-4 text-[11px] mt-0.5", children: stage.nextAction }))] })) })] }, stage.key)))) : (
593
- // Fallback: show loading state or no-data message
594
- ['evidence', 'diagnosis', 'proposal', 'review', 'deploy', 'behavior'].map((key) => (_jsxs("div", { className: "flex gap-4", children: [_jsx("span", { className: "font-mono text-[12px] text-ink-3 min-w-[80px]", children: t(STAGE_LABEL_KEYS[key] ?? `principles.detail.stage${key}`, { defaultValue: key }) }), _jsx("div", { className: "flex-1", children: _jsx("p", { className: "text-ink-4 text-[13px]", children: trajectory === null
595
- ? t("principles.detail.trajectoryLoadFailed", { defaultValue: "无法加载轨迹数据" })
596
- : "—" }) })] }, key)))) }), hasRules && lifecycle && (_jsxs("div", { className: "mt-6 pt-4 border-t border-line", children: [_jsx("span", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3", children: t("principles.detail.lifecycleMetrics", { defaultValue: "生命周期指标" }) }), _jsx("p", { className: "text-amber text-[12px] font-mono mt-1 mb-3", children: t("principles.detail.lifecycleNote") }), lifecycle.adherence.insufficientData ? (_jsx("p", { className: "text-ink-3 text-[13px] leading-relaxed", children: t("principles.detail.insufficientData") })) : (_jsxs("div", { children: [_jsxs("p", { className: "text-ink-2 text-[14px]", children: [t("principles.detail.adherenceRate", { defaultValue: "遵守率" }), ": ", lifecycle.adherence.rate !== null ? `${(lifecycle.adherence.rate * 100).toFixed(1)}%` : "—"] }), _jsx("p", { className: "text-ink-3 text-[12px] mt-1", children: lifecycle.adherence.note })] })), lifecycle.ruleMetrics.length > 0 && (_jsx("div", { className: "mt-3", children: lifecycle.ruleMetrics.map((rm) => (_jsxs("div", { className: "flex gap-3 text-[12px] font-mono text-ink-3", children: [_jsx("span", { children: rm.ruleId }), _jsxs("span", { children: [t("principles.detail.triggered", { defaultValue: "触发" }), ": ", rm.triggered] })] }, rm.ruleId))) }))] })), hasRules && !lifecycle && (_jsx("div", { className: "mt-6 pt-4 border-t border-line", children: _jsx("p", { className: "text-ink-3 text-[13px]", children: t("principles.detail.lifecycleLoadFailed", { defaultValue: "无法加载生命周期指标。你可以稍后重试。" }) }) }))] })] })] }) }));
597
- }
598
- /** Small presentational block: known narrative items or the honest unknown. */
599
- function OwnerNarrativeBlock({ label, field, testId }) {
600
- const rendered = narrativeTexts(field);
601
- return (_jsxs("div", { className: "mt-4", "data-testid": testId, children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: label }), rendered.status === 'known' ? (rendered.texts.length > 0 ? (rendered.texts.map((text, index) => (_jsx("p", { className: "mt-1 text-ink-2 text-[14px] leading-relaxed", children: text }, `${testId}-${index}`)))) : (_jsx("p", { className: "mt-1 text-ink-4 text-[13px]", children: "\u2014" }))) : (_jsx("p", { className: "mt-1 text-ink-3 text-[13px] leading-relaxed", children: rendered.reason }))] }));
602
- }