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.
- package/_release/product-identity.json +1 -1
- package/console/dist/web/assets/app.js +26 -26
- package/console/package.json +1 -1
- package/package.json +3 -3
- package/pd-cli/package.json +1 -1
- package/release-manager/package.json +3 -3
- package/console/dist/ui/App.d.ts +0 -1
- package/console/dist/ui/App.js +0 -172
- package/console/dist/ui/api.d.ts +0 -611
- package/console/dist/ui/api.js +0 -1094
- package/console/dist/ui/components/auth/login-form.d.ts +0 -4
- package/console/dist/ui/components/auth/login-form.js +0 -142
- package/console/dist/ui/components/auth/splash-screen.d.ts +0 -9
- package/console/dist/ui/components/auth/splash-screen.js +0 -22
- package/console/dist/ui/components/error-boundary.d.ts +0 -15
- package/console/dist/ui/components/error-boundary.js +0 -30
- package/console/dist/ui/components/focus/daily-thought-card.d.ts +0 -1
- package/console/dist/ui/components/focus/daily-thought-card.js +0 -41
- package/console/dist/ui/components/language-switcher.d.ts +0 -2
- package/console/dist/ui/components/language-switcher.js +0 -17
- package/console/dist/ui/components/layout/app-sidebar.d.ts +0 -27
- package/console/dist/ui/components/layout/app-sidebar.js +0 -128
- package/console/dist/ui/components/layout/page-loading.d.ts +0 -13
- package/console/dist/ui/components/layout/page-loading.js +0 -14
- package/console/dist/ui/components/layout/page-shell.d.ts +0 -12
- package/console/dist/ui/components/layout/page-shell.js +0 -11
- package/console/dist/ui/components/layout/section-title.d.ts +0 -10
- package/console/dist/ui/components/layout/section-title.js +0 -9
- package/console/dist/ui/components/notifications/NotificationProvider.d.ts +0 -14
- package/console/dist/ui/components/notifications/NotificationProvider.js +0 -136
- package/console/dist/ui/components/notifications/favicon-badge.d.ts +0 -3
- package/console/dist/ui/components/notifications/favicon-badge.js +0 -68
- package/console/dist/ui/components/notifications/notification-reducer.d.ts +0 -9
- package/console/dist/ui/components/notifications/notification-reducer.js +0 -9
- package/console/dist/ui/components/notifications/sound-storage.d.ts +0 -3
- package/console/dist/ui/components/notifications/sound-storage.js +0 -37
- package/console/dist/ui/components/notifications/useNotifications.d.ts +0 -1
- package/console/dist/ui/components/notifications/useNotifications.js +0 -9
- package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +0 -8
- package/console/dist/ui/components/onboarding/CircuitDiagram.js +0 -18
- package/console/dist/ui/components/onboarding/DemoResultView.d.ts +0 -22
- package/console/dist/ui/components/onboarding/DemoResultView.js +0 -33
- package/console/dist/ui/components/onboarding/SlashCommandsCard.d.ts +0 -16
- package/console/dist/ui/components/onboarding/SlashCommandsCard.js +0 -20
- package/console/dist/ui/components/onboarding/slashCommands.d.ts +0 -20
- package/console/dist/ui/components/onboarding/slashCommands.js +0 -22
- package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.d.ts +0 -6
- package/console/dist/ui/components/receipts/ReceiptCoverageDisclosure.js +0 -66
- package/console/dist/ui/components/theme-provider.d.ts +0 -14
- package/console/dist/ui/components/theme-provider.js +0 -40
- package/console/dist/ui/components/theme-toggle.d.ts +0 -2
- package/console/dist/ui/components/theme-toggle.js +0 -11
- package/console/dist/ui/components/ui/alert-dialog.d.ts +0 -20
- package/console/dist/ui/components/ui/alert-dialog.js +0 -26
- package/console/dist/ui/components/ui/badge.d.ts +0 -9
- package/console/dist/ui/components/ui/badge.js +0 -22
- package/console/dist/ui/components/ui/button.d.ts +0 -11
- package/console/dist/ui/components/ui/button.js +0 -34
- package/console/dist/ui/components/ui/card.d.ts +0 -8
- package/console/dist/ui/components/ui/card.js +0 -16
- package/console/dist/ui/components/ui/charts.d.ts +0 -51
- package/console/dist/ui/components/ui/charts.js +0 -72
- package/console/dist/ui/components/ui/dialog.d.ts +0 -19
- package/console/dist/ui/components/ui/dialog.js +0 -22
- package/console/dist/ui/components/ui/input.d.ts +0 -3
- package/console/dist/ui/components/ui/input.js +0 -8
- package/console/dist/ui/components/ui/markdown.d.ts +0 -24
- package/console/dist/ui/components/ui/markdown.js +0 -119
- package/console/dist/ui/components/ui/progress-bar.d.ts +0 -20
- package/console/dist/ui/components/ui/progress-bar.js +0 -38
- package/console/dist/ui/components/ui/select.d.ts +0 -13
- package/console/dist/ui/components/ui/select.js +0 -26
- package/console/dist/ui/components/ui/separator.d.ts +0 -3
- package/console/dist/ui/components/ui/separator.js +0 -6
- package/console/dist/ui/components/ui/sheet.d.ts +0 -25
- package/console/dist/ui/components/ui/sheet.js +0 -37
- package/console/dist/ui/components/ui/shiny-text.d.ts +0 -28
- package/console/dist/ui/components/ui/shiny-text.js +0 -46
- package/console/dist/ui/components/ui/skeleton.d.ts +0 -3
- package/console/dist/ui/components/ui/skeleton.js +0 -6
- package/console/dist/ui/components/ui/sonner.d.ts +0 -3
- package/console/dist/ui/components/ui/sonner.js +0 -13
- package/console/dist/ui/components/ui/tooltip.d.ts +0 -7
- package/console/dist/ui/components/ui/tooltip.js +0 -10
- package/console/dist/ui/data/daily-thoughts.d.ts +0 -15
- package/console/dist/ui/data/daily-thoughts.js +0 -164
- package/console/dist/ui/hooks/useNotificationSound.d.ts +0 -12
- package/console/dist/ui/hooks/useNotificationSound.js +0 -74
- package/console/dist/ui/i18n/en.json +0 -2399
- package/console/dist/ui/i18n/index.d.ts +0 -2
- package/console/dist/ui/i18n/index.js +0 -32
- package/console/dist/ui/i18n/zh-CN.json +0 -2399
- package/console/dist/ui/main.d.ts +0 -1
- package/console/dist/ui/main.js +0 -9
- package/console/dist/ui/pages/ReportProblemValidators.d.ts +0 -144
- package/console/dist/ui/pages/ReportProblemValidators.js +0 -418
- package/console/dist/ui/pages/activation/ActivationPage.d.ts +0 -1
- package/console/dist/ui/pages/activation/ActivationPage.js +0 -512
- package/console/dist/ui/pages/activation/ActivationValidators.d.ts +0 -20
- package/console/dist/ui/pages/activation/ActivationValidators.js +0 -160
- package/console/dist/ui/pages/control-center/AgentCard.d.ts +0 -31
- package/console/dist/ui/pages/control-center/AgentCard.js +0 -212
- package/console/dist/ui/pages/control-center/AgentGroup.d.ts +0 -26
- package/console/dist/ui/pages/control-center/AgentGroup.js +0 -38
- package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +0 -1
- package/console/dist/ui/pages/control-center/ControlCenterPage.js +0 -509
- package/console/dist/ui/pages/control-center/DesignGatePanel.d.ts +0 -1
- package/console/dist/ui/pages/control-center/DesignGatePanel.js +0 -137
- package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +0 -31
- package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +0 -199
- package/console/dist/ui/pages/control-center/WorkflowDiagram.d.ts +0 -17
- package/console/dist/ui/pages/control-center/WorkflowDiagram.js +0 -55
- package/console/dist/ui/pages/debt/DebtPage.d.ts +0 -2
- package/console/dist/ui/pages/debt/DebtPage.js +0 -222
- package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +0 -2
- package/console/dist/ui/pages/design-system/DesignSystemPage.js +0 -30
- package/console/dist/ui/pages/examiner/ExaminerPage.d.ts +0 -15
- package/console/dist/ui/pages/examiner/ExaminerPage.js +0 -158
- package/console/dist/ui/pages/failed-tasks/FailedTasksPage.d.ts +0 -1
- package/console/dist/ui/pages/failed-tasks/FailedTasksPage.js +0 -421
- package/console/dist/ui/pages/focus/ApprovalSubjectReading.d.ts +0 -24
- package/console/dist/ui/pages/focus/ApprovalSubjectReading.js +0 -133
- package/console/dist/ui/pages/focus/FocusPage.d.ts +0 -123
- package/console/dist/ui/pages/focus/FocusPage.js +0 -567
- package/console/dist/ui/pages/focus/OwnerDecisionCard.d.ts +0 -9
- package/console/dist/ui/pages/focus/OwnerDecisionCard.js +0 -111
- package/console/dist/ui/pages/focus/OwnerWorkbench.d.ts +0 -19
- package/console/dist/ui/pages/focus/OwnerWorkbench.js +0 -75
- package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.d.ts +0 -34
- package/console/dist/ui/pages/focus/RuleCandidateBindingPanel.js +0 -298
- package/console/dist/ui/pages/focus/focus-validation.d.ts +0 -40
- package/console/dist/ui/pages/focus/focus-validation.js +0 -211
- package/console/dist/ui/pages/intent/IntentOnboarding.d.ts +0 -67
- package/console/dist/ui/pages/intent/IntentOnboarding.js +0 -289
- package/console/dist/ui/pages/intent/IntentPage.d.ts +0 -1
- package/console/dist/ui/pages/intent/IntentPage.js +0 -252
- package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +0 -59
- package/console/dist/ui/pages/pain/PainEvidenceValidators.js +0 -125
- package/console/dist/ui/pages/pain/PainPage.d.ts +0 -1
- package/console/dist/ui/pages/pain/PainPage.js +0 -420
- package/console/dist/ui/pages/pain/pain-card-helpers.d.ts +0 -175
- package/console/dist/ui/pages/pain/pain-card-helpers.js +0 -181
- package/console/dist/ui/pages/principles/CorePrinciplesPage.d.ts +0 -10
- package/console/dist/ui/pages/principles/CorePrinciplesPage.js +0 -59
- package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +0 -60
- package/console/dist/ui/pages/principles/PrincipleDetailPage.js +0 -602
- package/console/dist/ui/pages/principles/PrinciplesPage.d.ts +0 -1
- package/console/dist/ui/pages/principles/PrinciplesPage.js +0 -327
- package/console/dist/ui/pages/principles/PrinciplesViewNav.d.ts +0 -8
- package/console/dist/ui/pages/principles/PrinciplesViewNav.js +0 -15
- package/console/dist/ui/pages/report-problem/ReportProblemPage.d.ts +0 -1
- package/console/dist/ui/pages/report-problem/ReportProblemPage.js +0 -467
- package/console/dist/ui/pages/settings/SettingsPage.d.ts +0 -4
- package/console/dist/ui/pages/settings/SettingsPage.js +0 -457
- package/console/dist/ui/pages/settings/UpdatePage.d.ts +0 -1
- package/console/dist/ui/pages/settings/UpdatePage.js +0 -215
- package/console/dist/ui/pages/welcome/WelcomePage.d.ts +0 -5
- package/console/dist/ui/pages/welcome/WelcomePage.js +0 -187
- package/console/dist/ui/utils/agent-metadata.d.ts +0 -71
- package/console/dist/ui/utils/agent-metadata.js +0 -284
- package/console/dist/ui/utils/approval-review.d.ts +0 -30
- package/console/dist/ui/utils/approval-review.js +0 -50
- package/console/dist/ui/utils/approval-warning-localization.d.ts +0 -34
- package/console/dist/ui/utils/approval-warning-localization.js +0 -148
- package/console/dist/ui/utils/attention-presentation.d.ts +0 -35
- package/console/dist/ui/utils/attention-presentation.js +0 -46
- package/console/dist/ui/utils/blocker-localization.d.ts +0 -23
- package/console/dist/ui/utils/blocker-localization.js +0 -36
- package/console/dist/ui/utils/control-center-helpers.d.ts +0 -79
- package/console/dist/ui/utils/control-center-helpers.js +0 -189
- package/console/dist/ui/utils/enum-labels.d.ts +0 -50
- package/console/dist/ui/utils/enum-labels.js +0 -171
- package/console/dist/ui/utils/format-date.d.ts +0 -11
- package/console/dist/ui/utils/format-date.js +0 -17
- package/console/dist/ui/utils/onboarding-state.d.ts +0 -25
- package/console/dist/ui/utils/onboarding-state.js +0 -77
- package/console/dist/ui/utils/reading-layout.d.ts +0 -20
- package/console/dist/ui/utils/reading-layout.js +0 -46
- package/console/dist/ui/utils/rule-binding-validators.d.ts +0 -13
- package/console/dist/ui/utils/rule-binding-validators.js +0 -188
- package/console/dist/ui/utils/runtime-mode.d.ts +0 -11
- package/console/dist/ui/utils/runtime-mode.js +0 -11
- package/console/dist/ui/utils/token-storage.d.ts +0 -22
- package/console/dist/ui/utils/token-storage.js +0 -47
- package/console/dist/ui/utils/validators.d.ts +0 -1178
- package/console/dist/ui/utils/validators.js +0 -3297
- package/release-manager/dist/bootstrap-entry.d.ts +0 -2
- package/release-manager/dist/bootstrap-entry.d.ts.map +0 -1
- package/release-manager/dist/bootstrap-entry.js.map +0 -1
- package/release-manager/dist/i18n.d.ts +0 -6
- package/release-manager/dist/i18n.d.ts.map +0 -1
- package/release-manager/dist/i18n.js.map +0 -1
- package/release-manager/dist/index.d.ts +0 -7
- package/release-manager/dist/index.d.ts.map +0 -1
- package/release-manager/dist/index.js +0 -656
- package/release-manager/dist/index.js.map +0 -1
- package/release-manager/dist/installer.d.ts +0 -629
- package/release-manager/dist/installer.d.ts.map +0 -1
- package/release-manager/dist/installer.js.map +0 -1
- package/release-manager/dist/installers/codex-host-installer.d.ts +0 -39
- package/release-manager/dist/installers/codex-host-installer.d.ts.map +0 -1
- package/release-manager/dist/installers/codex-host-installer.js.map +0 -1
- package/release-manager/dist/installers/index.d.ts +0 -51
- package/release-manager/dist/installers/index.d.ts.map +0 -1
- package/release-manager/dist/installers/index.js.map +0 -1
- package/release-manager/dist/installers/openclaw-host-installer.d.ts +0 -14
- package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +0 -1
- package/release-manager/dist/installers/openclaw-host-installer.js.map +0 -1
- package/release-manager/dist/installers/workbuddy-host-installer.d.ts +0 -335
- package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +0 -1
- package/release-manager/dist/installers/workbuddy-host-installer.js.map +0 -1
- package/release-manager/dist/mvp-config.d.ts +0 -233
- package/release-manager/dist/mvp-config.d.ts.map +0 -1
- package/release-manager/dist/mvp-config.js.map +0 -1
- package/release-manager/dist/prompts.d.ts +0 -43
- package/release-manager/dist/prompts.d.ts.map +0 -1
- package/release-manager/dist/prompts.js +0 -268
- package/release-manager/dist/prompts.js.map +0 -1
- package/release-manager/dist/skill-language.d.ts +0 -32
- package/release-manager/dist/skill-language.d.ts.map +0 -1
- package/release-manager/dist/skill-language.js.map +0 -1
- package/release-manager/dist/uninstaller.d.ts +0 -68
- package/release-manager/dist/uninstaller.d.ts.map +0 -1
- package/release-manager/dist/uninstaller.js +0 -746
- package/release-manager/dist/uninstaller.js.map +0 -1
- package/release-manager/dist/update/apply-payload.d.ts +0 -143
- package/release-manager/dist/update/apply-payload.d.ts.map +0 -1
- package/release-manager/dist/update/apply-payload.js.map +0 -1
- package/release-manager/dist/update/atomic-file.d.ts +0 -35
- package/release-manager/dist/update/atomic-file.d.ts.map +0 -1
- package/release-manager/dist/update/atomic-file.js.map +0 -1
- package/release-manager/dist/update/bootstrap-executor.d.ts +0 -21
- package/release-manager/dist/update/bootstrap-executor.d.ts.map +0 -1
- package/release-manager/dist/update/bootstrap-executor.js.map +0 -1
- package/release-manager/dist/update/bootstrap-protocol.d.ts +0 -56
- package/release-manager/dist/update/bootstrap-protocol.d.ts.map +0 -1
- package/release-manager/dist/update/bootstrap-protocol.js.map +0 -1
- package/release-manager/dist/update/channel-metadata.d.ts +0 -28
- package/release-manager/dist/update/channel-metadata.d.ts.map +0 -1
- package/release-manager/dist/update/channel-metadata.js.map +0 -1
- package/release-manager/dist/update/channel-promotion.d.ts +0 -39
- package/release-manager/dist/update/channel-promotion.d.ts.map +0 -1
- package/release-manager/dist/update/channel-promotion.js +0 -55
- package/release-manager/dist/update/channel-promotion.js.map +0 -1
- package/release-manager/dist/update/console-surface.d.ts +0 -19
- package/release-manager/dist/update/console-surface.d.ts.map +0 -1
- package/release-manager/dist/update/console-surface.js.map +0 -1
- package/release-manager/dist/update/data-compatibility.d.ts +0 -35
- package/release-manager/dist/update/data-compatibility.d.ts.map +0 -1
- package/release-manager/dist/update/data-compatibility.js +0 -45
- package/release-manager/dist/update/data-compatibility.js.map +0 -1
- package/release-manager/dist/update/install-layout.d.ts +0 -105
- package/release-manager/dist/update/install-layout.d.ts.map +0 -1
- package/release-manager/dist/update/install-layout.js.map +0 -1
- package/release-manager/dist/update/product-identity.d.ts +0 -70
- package/release-manager/dist/update/product-identity.d.ts.map +0 -1
- package/release-manager/dist/update/product-identity.js.map +0 -1
- package/release-manager/dist/update/release-asset-manifest.d.ts +0 -31
- package/release-manager/dist/update/release-asset-manifest.d.ts.map +0 -1
- package/release-manager/dist/update/release-asset-manifest.js.map +0 -1
- package/release-manager/dist/update/release-identity.d.ts +0 -33
- package/release-manager/dist/update/release-identity.d.ts.map +0 -1
- package/release-manager/dist/update/release-identity.js.map +0 -1
- package/release-manager/dist/update/release-manager-authority.d.ts +0 -39
- package/release-manager/dist/update/release-manager-authority.d.ts.map +0 -1
- package/release-manager/dist/update/release-manager-authority.js.map +0 -1
- package/release-manager/dist/update/release-manager.d.ts +0 -156
- package/release-manager/dist/update/release-manager.d.ts.map +0 -1
- package/release-manager/dist/update/release-manager.js.map +0 -1
- package/release-manager/dist/update/release-metadata-publisher.d.ts +0 -199
- package/release-manager/dist/update/release-metadata-publisher.d.ts.map +0 -1
- package/release-manager/dist/update/release-metadata-publisher.js +0 -478
- package/release-manager/dist/update/release-metadata-publisher.js.map +0 -1
- package/release-manager/dist/update/release-metadata-source.d.ts +0 -85
- package/release-manager/dist/update/release-metadata-source.d.ts.map +0 -1
- package/release-manager/dist/update/release-metadata-source.js.map +0 -1
- package/release-manager/dist/update/release-metadata.d.ts +0 -60
- package/release-manager/dist/update/release-metadata.d.ts.map +0 -1
- package/release-manager/dist/update/release-metadata.js.map +0 -1
- package/release-manager/dist/update/release-policy.d.ts +0 -51
- package/release-manager/dist/update/release-policy.d.ts.map +0 -1
- package/release-manager/dist/update/release-policy.js.map +0 -1
- package/release-manager/dist/update/rollback-policy.d.ts +0 -56
- package/release-manager/dist/update/rollback-policy.d.ts.map +0 -1
- package/release-manager/dist/update/rollback-policy.js +0 -61
- package/release-manager/dist/update/rollback-policy.js.map +0 -1
- package/release-manager/dist/update/transaction-journal.d.ts +0 -212
- package/release-manager/dist/update/transaction-journal.d.ts.map +0 -1
- package/release-manager/dist/update/transaction-journal.js.map +0 -1
- package/release-manager/dist/update/trust-metadata.d.ts +0 -55
- package/release-manager/dist/update/trust-metadata.d.ts.map +0 -1
- package/release-manager/dist/update/trust-metadata.js.map +0 -1
- package/release-manager/dist/update/trust-root-provisioning.d.ts +0 -99
- package/release-manager/dist/update/trust-root-provisioning.d.ts.map +0 -1
- package/release-manager/dist/update/trust-root-provisioning.js.map +0 -1
- package/release-manager/dist/update/update-history.d.ts +0 -46
- package/release-manager/dist/update/update-history.d.ts.map +0 -1
- package/release-manager/dist/update/update-history.js +0 -123
- package/release-manager/dist/update/update-history.js.map +0 -1
- package/release-manager/dist/utils/config-file-io.d.ts +0 -34
- package/release-manager/dist/utils/config-file-io.d.ts.map +0 -1
- package/release-manager/dist/utils/config-file-io.js.map +0 -1
- package/release-manager/dist/utils/env.d.ts +0 -94
- package/release-manager/dist/utils/env.d.ts.map +0 -1
- package/release-manager/dist/utils/env.js.map +0 -1
- package/release-manager/dist/utils/logger.d.ts +0 -15
- package/release-manager/dist/utils/logger.d.ts.map +0 -1
- package/release-manager/dist/utils/logger.js.map +0 -1
- package/release-manager/dist/utils/workspace-divergence.d.ts +0 -36
- package/release-manager/dist/utils/workspace-divergence.d.ts.map +0 -1
- 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;
|