create-principles-disciple 1.144.25 → 1.144.26

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 (45) hide show
  1. package/_release/product-identity.json +2 -2
  2. package/console/dist/ui/App.js +19 -3
  3. package/console/dist/ui/components/layout/app-sidebar.d.ts +11 -0
  4. package/console/dist/ui/components/layout/app-sidebar.js +60 -7
  5. package/console/dist/ui/components/ui/sheet.js +2 -1
  6. package/console/dist/ui/i18n/en.json +66 -5
  7. package/console/dist/ui/i18n/index.js +11 -0
  8. package/console/dist/ui/i18n/zh-CN.json +66 -5
  9. package/console/dist/ui/pages/control-center/ControlCenterPage.js +4 -2
  10. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +3 -3
  11. package/console/dist/ui/pages/focus/FocusPage.d.ts +92 -0
  12. package/console/dist/ui/pages/focus/FocusPage.js +139 -8
  13. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +4 -2
  14. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +54 -16
  15. package/console/dist/ui/pages/settings/UpdatePage.js +1 -1
  16. package/console/dist/web/assets/app.css +109 -20
  17. package/console/dist/web/assets/app.js +59 -58
  18. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +61 -2
  19. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
  20. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +68 -3
  21. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
  22. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  23. package/core/dist/runtime-v2/internalization/artificer-runner.js +5 -0
  24. package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  25. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +18 -0
  26. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
  27. package/core/dist/runtime-v2/internalization/evaluator-output.js +7 -0
  28. package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
  29. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts +36 -2
  30. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts.map +1 -1
  31. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js +31 -1
  32. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js.map +1 -1
  33. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +38 -9
  34. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  35. package/core/dist/runtime-v2/internalization/evaluator-runner.js +170 -46
  36. package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  37. package/core/dist/runtime-v2/internalization/repair-replay-resolver.d.ts +8 -0
  38. package/core/dist/runtime-v2/internalization/repair-replay-resolver.d.ts.map +1 -1
  39. package/core/dist/runtime-v2/internalization/repair-replay-resolver.js +12 -0
  40. package/core/dist/runtime-v2/internalization/repair-replay-resolver.js.map +1 -1
  41. package/core/package.json +1 -1
  42. package/host-runtime/package.json +1 -1
  43. package/package.json +1 -1
  44. package/plugin/dist/bundle.js +447 -438
  45. package/release-manager/package.json +1 -1
@@ -22,6 +22,98 @@ export declare function summarizeDecisionResults(results: readonly DecisionResul
22
22
  failureReason?: string;
23
23
  successWarnings: string[];
24
24
  };
25
+ /**
26
+ * SPEC-PD-UIUX-001 R2: how the owner-inbox display items map onto the Focus
27
+ * page after the reading-order rework. Pure display partitioning — no
28
+ * permission or lifecycle decisions happen here.
29
+ *
30
+ * - decision items whose principleId matches an on-screen action card are NOT
31
+ * duplicated as full cards (one primary action surface per object); the
32
+ * match uses the verified principleId association field, never titles;
33
+ * - unmatched decision items are preserved (with their own entry) — objects
34
+ * are never hidden for visual tidiness;
35
+ * - two different decisions of the same principle are never merged: each
36
+ * action card keeps its own object; this partition only affects the
37
+ * display-only inbox projection;
38
+ * - blocked items follow the inbox.attention semantics: 'individual' items
39
+ * render one card each, everything else gets one aggregate count;
40
+ * - historical unknowns stay an explanatory notice (not part of the todo
41
+ * count).
42
+ */
43
+ export declare function partitionInboxForDisplay<T extends {
44
+ principleId: string;
45
+ inbox: {
46
+ group: string;
47
+ attention: string;
48
+ };
49
+ }>(inbox: {
50
+ groups: {
51
+ decision: T[];
52
+ blocked: T[];
53
+ recovery: T[];
54
+ };
55
+ historicalUnknown: {
56
+ count: number;
57
+ };
58
+ }, actionCardPrincipleIds: ReadonlySet<string>): {
59
+ unmatchedDecisions: T[];
60
+ blockedIndividual: T[];
61
+ blockedAggregate: T[];
62
+ recovery: T[];
63
+ pendingTotal: number;
64
+ };
65
+ /**
66
+ * SPEC-PD-UIUX-001 R2 (Owner review round 2): the conclusion strip's headline
67
+ * and total must agree with the objects actually on screen and with the inbox
68
+ * response contract.
69
+ *
70
+ * Modes (display-only; no permission derivation):
71
+ * - 'unavailable' — inbox projection off (feature_disabled surfaces as
72
+ * ownerInbox===null with NO error) or the request failed: the pending count
73
+ * CANNOT be confirmed; never allClear.
74
+ * - 'degraded' — the inbox answered HTTP-success but carries
75
+ * `degraded: { reason, nextAction }` (e.g. principle ledger unreadable, the
76
+ * server then returns EMPTY groups): counts cannot be trusted; the strip
77
+ * shows the server's reason + nextAction and never allClear.
78
+ * - 'ok' — counts are trusted.
79
+ *
80
+ * Counting (S2): displayTotal = actionableCount + inbox pending items NOT
81
+ * already represented by an on-screen action card. The association is the
82
+ * verified principleId field (partition.unmatchedDecisions are inbox items
83
+ * WITHOUT a card). One inbox item matching N cards of the same principle
84
+ * counts the N cards (each is a distinct decision); disjoint sets sum.
85
+ */
86
+ export declare function deriveConclusionDisplay(input: {
87
+ ownerInbox: {
88
+ groups: {
89
+ decision: unknown[];
90
+ };
91
+ degraded?: {
92
+ reason: string;
93
+ nextAction: string;
94
+ };
95
+ } | null;
96
+ ownerInboxError: string | null;
97
+ partition: {
98
+ pendingTotal: number;
99
+ unmatchedDecisions: unknown[];
100
+ } | null;
101
+ actionableCount: number;
102
+ }): {
103
+ mode: 'ok' | 'degraded' | 'unavailable';
104
+ displayTotal: number;
105
+ actionableCount: number;
106
+ degraded?: {
107
+ reason: string;
108
+ nextAction: string;
109
+ };
110
+ };
111
+ /**
112
+ * SPEC-PD-UIUX-001 R2 (Owner review S3): EVERY conclusion branch must express
113
+ * governance readiness the same way — "actionable now" is only claimable when
114
+ * the actions are not locked. One matrix, one source.
115
+ */
116
+ export declare function resolveConclusionActionableKey(mode: 'ok' | 'degraded' | 'unavailable', locked: boolean): string;
25
117
  export interface OwnerConfigureCommand {
26
118
  /** i18n key for the shell label, e.g. "pages.focus.experience.ownerGuide.cmdPowerShell". */
27
119
  labelKey: string;
@@ -42,6 +42,93 @@ export function summarizeDecisionResults(results) {
42
42
  successWarnings,
43
43
  };
44
44
  }
45
+ /**
46
+ * SPEC-PD-UIUX-001 R2: how the owner-inbox display items map onto the Focus
47
+ * page after the reading-order rework. Pure display partitioning — no
48
+ * permission or lifecycle decisions happen here.
49
+ *
50
+ * - decision items whose principleId matches an on-screen action card are NOT
51
+ * duplicated as full cards (one primary action surface per object); the
52
+ * match uses the verified principleId association field, never titles;
53
+ * - unmatched decision items are preserved (with their own entry) — objects
54
+ * are never hidden for visual tidiness;
55
+ * - two different decisions of the same principle are never merged: each
56
+ * action card keeps its own object; this partition only affects the
57
+ * display-only inbox projection;
58
+ * - blocked items follow the inbox.attention semantics: 'individual' items
59
+ * render one card each, everything else gets one aggregate count;
60
+ * - historical unknowns stay an explanatory notice (not part of the todo
61
+ * count).
62
+ */
63
+ export function partitionInboxForDisplay(inbox, actionCardPrincipleIds) {
64
+ const blockedIndividual = inbox.groups.blocked.filter((item) => item.inbox.attention === "individual");
65
+ const blockedAggregate = inbox.groups.blocked.filter((item) => item.inbox.attention !== "individual");
66
+ const unmatchedDecisions = inbox.groups.decision.filter((item) => !actionCardPrincipleIds.has(item.principleId));
67
+ return {
68
+ unmatchedDecisions,
69
+ blockedIndividual,
70
+ blockedAggregate,
71
+ recovery: inbox.groups.recovery,
72
+ // 待处理口径: decision + blocked-individual + recovery (INV-01 lineage).
73
+ pendingTotal: inbox.groups.decision.length + blockedIndividual.length + inbox.groups.recovery.length,
74
+ };
75
+ }
76
+ /**
77
+ * SPEC-PD-UIUX-001 R2 (Owner review round 2): the conclusion strip's headline
78
+ * and total must agree with the objects actually on screen and with the inbox
79
+ * response contract.
80
+ *
81
+ * Modes (display-only; no permission derivation):
82
+ * - 'unavailable' — inbox projection off (feature_disabled surfaces as
83
+ * ownerInbox===null with NO error) or the request failed: the pending count
84
+ * CANNOT be confirmed; never allClear.
85
+ * - 'degraded' — the inbox answered HTTP-success but carries
86
+ * `degraded: { reason, nextAction }` (e.g. principle ledger unreadable, the
87
+ * server then returns EMPTY groups): counts cannot be trusted; the strip
88
+ * shows the server's reason + nextAction and never allClear.
89
+ * - 'ok' — counts are trusted.
90
+ *
91
+ * Counting (S2): displayTotal = actionableCount + inbox pending items NOT
92
+ * already represented by an on-screen action card. The association is the
93
+ * verified principleId field (partition.unmatchedDecisions are inbox items
94
+ * WITHOUT a card). One inbox item matching N cards of the same principle
95
+ * counts the N cards (each is a distinct decision); disjoint sets sum.
96
+ */
97
+ export function deriveConclusionDisplay(input) {
98
+ if (input.ownerInbox === null || input.ownerInboxError !== null || input.partition === null) {
99
+ return { mode: 'unavailable', displayTotal: input.actionableCount, actionableCount: input.actionableCount };
100
+ }
101
+ const matchedDecisions = input.ownerInbox.groups.decision.length - input.partition.unmatchedDecisions.length;
102
+ const uncoveredInboxPending = Math.max(0, input.partition.pendingTotal - matchedDecisions);
103
+ const base = {
104
+ actionableCount: input.actionableCount,
105
+ };
106
+ if (input.ownerInbox.degraded !== undefined) {
107
+ return {
108
+ mode: 'degraded',
109
+ displayTotal: input.actionableCount + uncoveredInboxPending,
110
+ ...base,
111
+ degraded: input.ownerInbox.degraded,
112
+ };
113
+ }
114
+ return {
115
+ mode: 'ok',
116
+ displayTotal: input.actionableCount + uncoveredInboxPending,
117
+ ...base,
118
+ };
119
+ }
120
+ /**
121
+ * SPEC-PD-UIUX-001 R2 (Owner review S3): EVERY conclusion branch must express
122
+ * governance readiness the same way — "actionable now" is only claimable when
123
+ * the actions are not locked. One matrix, one source.
124
+ */
125
+ export function resolveConclusionActionableKey(mode, locked) {
126
+ if (locked)
127
+ return "pages.focus.conclusion.actionableLocked";
128
+ if (mode === 'unavailable')
129
+ return "pages.focus.conclusion.actionableWithoutTotal";
130
+ return "pages.focus.conclusion.actionableUnlocked";
131
+ }
45
132
  // ── i18n code mapping helpers ─────────────────────────────────────────────
46
133
  /** Map a stateReasonCode to an i18n key, with optional interpolation params. */
47
134
  function getStateReasonText(code, t, pendingReviewCount) {
@@ -600,6 +687,40 @@ export function FocusPage({ featureFlags }) {
600
687
  : t(experienceData.readiness.authenticationMode !== "authenticated"
601
688
  ? "pages.focus.ownerDecision.actionsLockedAuth"
602
689
  : "pages.focus.ownerDecision.actionsLockedIdentity");
690
+ // ── SPEC-PD-UIUX-001 R2: one primary action surface per decision object ──
691
+ // Matching uses the verified principleId association field (never titles).
692
+ // See partitionInboxForDisplay for the semantics.
693
+ const actionCardPrincipleIds = new Set();
694
+ for (const item of decisionItems) {
695
+ if (item.principleId !== undefined)
696
+ actionCardPrincipleIds.add(item.principleId);
697
+ }
698
+ for (const group of pendingGroups)
699
+ actionCardPrincipleIds.add(group.principleId);
700
+ const inboxPartition = ownerInbox !== null && ownerInboxError === null
701
+ ? partitionInboxForDisplay(ownerInbox, actionCardPrincipleIds)
702
+ : null;
703
+ const inboxBlockedIndividual = inboxPartition?.blockedIndividual ?? [];
704
+ const inboxBlockedAggregate = inboxPartition?.blockedAggregate ?? [];
705
+ const inboxRecovery = inboxPartition?.recovery ?? [];
706
+ const unmatchedInboxDecisions = inboxPartition?.unmatchedDecisions ?? [];
707
+ // 待处理口径 (INV-01 lineage): decision + blocked-individual + recovery —
708
+ // same three groups the inbox renders; historical unknowns stay explanatory.
709
+ const inboxPendingTotal = inboxPartition?.pendingTotal ?? 0;
710
+ // 可操作口径: the action cards actually on screen (decision cards + approval
711
+ // cards) — the same number the「需要你决定」section header shows.
712
+ const actionableCount = (ownerDecisionError === null ? decisionItems.length : 0)
713
+ + (showApprovalCards ? pendingGroups.length : 0);
714
+ // Review round 2 (P2): the headline never claims allClear from the inbox
715
+ // alone, degraded payloads surface their reason, and the total is the
716
+ // association-deduped union of on-screen cards and inbox items — see
717
+ // deriveConclusionDisplay.
718
+ const conclusionDisplay = deriveConclusionDisplay({
719
+ ownerInbox,
720
+ ownerInboxError,
721
+ partition: inboxPartition,
722
+ actionableCount,
723
+ });
603
724
  // Map codes to i18n text
604
725
  // Governance Recovery Actions v1: tasks_need_human_review interpolates the
605
726
  // needs_human_review task count, not the approvals count.
@@ -607,9 +728,17 @@ export function FocusPage({ featureFlags }) {
607
728
  const stateReasonCount = stateReasonCode === "tasks_need_human_review" ? humanReviewCount : pendingCount;
608
729
  const stateReason = getStateReasonText(stateReasonCode, t, stateReasonCount);
609
730
  const nextAction = getNextActionText(nextActionCode, t);
610
- 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.focus.eyebrow") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: pendingCount === 0, children: t("pages.focus.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.focus.subtitle") }), _jsxs("section", { "aria-label": t("pages.focus.ownerInbox.sectionTitle"), className: "mb-7", "data-testid": "owner-decision-inbox-section", children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-3", children: [_jsx(SectionTitle, { children: t("pages.focus.ownerInbox.sectionTitle") }), ownerInbox !== null && (_jsx("span", { className: "font-mono text-ink-4 text-[12px]", children: `· ${ownerInbox.groups.decision.length + ownerInbox.groups.blocked.filter((item) => item.inbox.attention === 'individual').length + ownerInbox.groups.recovery.length}` }))] }), ownerInboxError !== null && (_jsx("p", { className: "text-ink-4 text-[12.5px]", children: t("pages.focus.ownerInbox.loadError") })), ownerInbox !== null && ownerInboxError === null && (_jsxs(_Fragment, { children: [ownerInbox.groups.decision.length === 0
611
- && ownerInbox.groups.blocked.filter((item) => item.inbox.attention === 'individual').length === 0
612
- && ownerInbox.groups.recovery.length === 0 && (_jsx("p", { className: "text-ink-4 text-[13px]", children: t("pages.focus.ownerInbox.empty") })), ownerInbox.groups.decision.map((item) => (_jsx(InboxItem, { item: item, t: t }, item.principleId))), ownerInbox.groups.blocked.filter((item) => item.inbox.attention === 'individual').map((item) => (_jsx(InboxItem, { item: item, t: t }, item.principleId))), ownerInbox.groups.recovery.map((item) => (_jsx(InboxItem, { item: item, t: t }, item.principleId))), ownerInbox.historicalUnknown.count > 0 && (_jsxs("p", { className: "text-ink-4 text-[12.5px] leading-relaxed mt-2", "data-testid": "owner-inbox-aggregate-notice", children: [ownerInbox.historicalUnknown.reasonText, " ", _jsx(Link, { to: "/principles", className: "text-gov hover:underline", children: t("pages.focus.ownerInbox.viewLibrary") })] }))] }))] }), _jsxs("section", { "aria-label": t("pages.focus.ownerDecision.sectionTitle"), className: "mb-7", "data-testid": "owner-decisions-section", children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-3", children: [_jsx(SectionTitle, { children: t("pages.focus.ownerDecision.sectionTitle") }), _jsx("span", { className: "font-mono text-ink-4 text-[12px]", children: ownerDecisionError !== null
731
+ 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.focus.eyebrow") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: pendingCount === 0, children: t("pages.focus.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.focus.subtitle") }), _jsxs("section", { "aria-label": t("pages.focus.conclusion.sectionTitle"), "data-testid": "focus-conclusion", className: "mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("span", { className: `inline-flex items-center rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase ${experienceMode && experienceData !== null
732
+ ? EXPERIENCE_ATTENTION[experienceData.summary.primaryAttention].badgeClass
733
+ : governanceState === "owner_review_ready"
734
+ ? "bg-gov/10 text-gov border border-gov/20"
735
+ : governanceState === "degraded"
736
+ ? "bg-amber/10 text-amber border border-amber/20"
737
+ : governanceState === "in_progress"
738
+ ? "bg-green/10 text-green border border-green/20"
739
+ : "text-ink-4 border border-line bg-surface/80"}`, role: "status", "data-testid": "focus-conclusion-badge", children: experienceMode && experienceData !== null
740
+ ? t(EXPERIENCE_ATTENTION[experienceData.summary.primaryAttention].labelKey)
741
+ : t(`pages.focus.stateLabel.${governanceState}`) }), _jsx("div", { className: "text-ink-2 text-[13px] leading-relaxed", "data-testid": "focus-conclusion-counts", children: conclusionDisplay.mode === 'ok' && conclusionDisplay.displayTotal === 0 ? (_jsx("span", { children: t("pages.focus.conclusion.allClear") })) : conclusionDisplay.mode === 'unavailable' || conclusionDisplay.mode === 'degraded' ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium", "data-testid": "focus-conclusion-uncertain", children: t("pages.focus.conclusion.pendingUncertain") }), conclusionDisplay.actionableCount > 0 && (_jsxs("span", { className: "text-ink-4", children: [" · ", t(resolveConclusionActionableKey(conclusionDisplay.mode, ownerActionsLockedReason !== null), { count: conclusionDisplay.actionableCount })] }))] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium", children: t("pages.focus.conclusion.pendingTotal", { count: conclusionDisplay.displayTotal }) }), _jsxs("span", { className: "text-ink-4", children: [" · ", t(resolveConclusionActionableKey(conclusionDisplay.mode, ownerActionsLockedReason !== null), { count: conclusionDisplay.actionableCount })] })] })) })] }), conclusionDisplay.mode === 'degraded' && conclusionDisplay.degraded && (_jsxs("div", { className: "mt-3 border border-amber/30 rounded-[6px] bg-surface px-3 py-2.5", "data-testid": "focus-conclusion-degraded", children: [_jsxs("p", { className: "text-[12px] text-ink-3 leading-relaxed", children: [t("pages.focus.conclusion.degradedLabel"), " ", conclusionDisplay.degraded.reason] }), _jsx("p", { className: "mt-1 text-[12px] text-ink-3 leading-relaxed", children: conclusionDisplay.degraded.nextAction })] })), ownerActionsLockedReason !== null && (_jsxs("div", { id: "focus-global-lock-notice", className: "mt-3 flex items-start justify-between gap-3 border border-amber/30 rounded-[6px] bg-surface px-3 py-2.5", "data-testid": "focus-conclusion-lock", children: [_jsx("p", { className: "text-[12px] text-ink-3 leading-relaxed", children: ownerActionsLockedReason }), _jsx(Link, { to: "/settings", className: "shrink-0 text-[12px] text-gov underline hover:text-gov-2", children: t("pages.focus.ownerDecision.goSettingsCta") })] })), _jsx("p", { className: "mt-2 text-ink-4 text-[11.5px] leading-relaxed", "data-testid": "focus-conclusion-scope-note", children: t("pages.focus.conclusion.countsNote") })] }), _jsxs("section", { "aria-label": t("pages.focus.ownerDecision.sectionTitle"), className: "mb-7", "data-testid": "owner-decisions-section", children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-3", children: [_jsx(SectionTitle, { children: t("pages.focus.ownerDecision.sectionTitle") }), _jsx("span", { className: "font-mono text-ink-4 text-[12px]", children: ownerDecisionError !== null
613
742
  ? t("pages.focus.ownerDecision.unavailable")
614
743
  : `· ${decisionItems.length + (showApprovalCards ? pendingGroups.length : 0)}` })] }), ownerDecisionError !== null && (_jsx("p", { className: "text-ink-4 text-[12.5px]", children: t("pages.focus.ownerDecision.loadError") })), ownerDecisionError === null && decisionItems.length === 0 && !showApprovalCards && (_jsx("p", { className: "text-ink-4 text-[13px]", children: t("pages.focus.ownerDecision.empty") })), decisionItems.map((item) => (_jsx(OwnerDecisionCard, { item: item, governanceReady: experienceData === null || (experienceData.readiness.authenticationMode === "authenticated"
615
744
  && experienceData.readiness.ownerIdentityConfiguration === "configured"), actionsLockedReason: ownerActionsLockedReason ?? undefined, onResolved: () => { void loadData(); } }, item.reviewKey))), (() => {
@@ -627,16 +756,18 @@ export function FocusPage({ featureFlags }) {
627
756
  budget: unconfirmed.budget,
628
757
  full: entry.truncated ? t("pages.focus.promptCapacityPerHostFull") : "",
629
758
  }) }, entry.hostKind))) }), unconfirmed.nextAction !== undefined && (_jsx("p", { className: "mt-1 text-ink-2", children: unconfirmed.nextAction })), _jsxs("div", { className: "mt-2 flex gap-2", children: [["openclaw", "codex"].map((host) => (_jsx("button", { type: "button", onClick: () => setPromptTargetHost(host), "data-testid": `prompt-capacity-pick-${host}`, className: `inline-flex items-center border rounded-[3px] px-[10px] py-[4px] transition-colors ${promptTargetHost === host ? "border-amber bg-amber/10" : "border-line hover:border-line-2"}`, children: t("pages.focus.promptCapacityViewAsHost", { host: host === "openclaw" ? "OpenClaw" : "Codex" }) }, host))), promptTargetHost !== null && (_jsx("button", { type: "button", onClick: () => setPromptTargetHost(null), "data-testid": "prompt-capacity-pick-clear", className: "inline-flex items-center border border-line rounded-[3px] px-[10px] py-[4px] hover:border-line-2", children: t("pages.focus.promptCapacityClearHost", { defaultValue: "清除选择" }) }))] })] }));
630
- })(), groupedAvailable && pendingGroups.map((group) => (_jsx(PendingReviewCard, { group: group, actionsLockedReason: ownerActionsLockedReason ?? undefined, promptInjection: groupedData.promptInjection, promptTargetHost: promptTargetHost ?? undefined, onDecisionApplied: () => { void loadData(); } }, group.principleId)))] }), experienceMode && experienceData !== null ? (_jsx(ExperienceSummaryCard, { snapshot: experienceData })) : !experienceMode ? (_jsxs("div", { className: "mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", children: [_jsx("div", { className: "flex items-center gap-2 mb-1", children: _jsx("span", { className: `inline-flex items-center rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase ${governanceState === "owner_review_ready" ? "bg-gov/10 text-gov border border-gov/20"
759
+ })(), groupedAvailable && pendingGroups.map((group) => (_jsx(PendingReviewCard, { group: group, actionsLockedReason: ownerActionsLockedReason ?? undefined, promptInjection: groupedData.promptInjection, promptTargetHost: promptTargetHost ?? undefined, onDecisionApplied: () => { void loadData(); } }, group.principleId)))] }), _jsxs("section", { "aria-label": t("pages.focus.ownerAttention.sectionTitle"), className: "mb-7", "data-testid": "owner-attention-section", children: [_jsxs("div", { className: "flex items-baseline gap-2 mb-3", children: [_jsx(SectionTitle, { children: t("pages.focus.ownerAttention.sectionTitle") }), ownerInbox !== null && ownerInboxError === null && (_jsx("span", { className: "font-mono text-ink-4 text-[12px]", "data-testid": "owner-attention-counts", children: `· ${t("pages.focus.ownerAttention.blockedCount", { count: ownerInbox.groups.blocked.length })} · ${t("pages.focus.ownerAttention.recoveryCount", { count: inboxRecovery.length })}` }))] }), ownerInboxError !== null && (_jsx("p", { className: "text-ink-4 text-[12.5px]", children: t("pages.focus.ownerInbox.loadError") })), ownerInbox !== null && ownerInboxError === null && (_jsxs(_Fragment, { children: [ownerInbox.groups.blocked.length === 0
760
+ && inboxRecovery.length === 0
761
+ && unmatchedInboxDecisions.length === 0 && (_jsx("p", { className: "text-ink-4 text-[13px]", children: t("pages.focus.ownerAttention.empty") })), unmatchedInboxDecisions.length > 0 && (_jsx("p", { className: "mb-2 text-ink-4 text-[12px] leading-relaxed", "data-testid": "owner-attention-unmatched-note", children: t("pages.focus.ownerAttention.unmatchedTitle") })), unmatchedInboxDecisions.map((item) => (_jsx(InboxItem, { item: item, t: t, note: t("pages.focus.ownerAttention.unmatchedItemNote") }, item.principleId))), inboxBlockedIndividual.map((item) => (_jsx(InboxItem, { item: item, t: t }, item.principleId))), inboxRecovery.map((item) => (_jsx(InboxItem, { item: item, t: t }, item.principleId))), inboxBlockedAggregate.length > 0 && (_jsxs("p", { className: "mt-2 text-ink-4 text-[12.5px] leading-relaxed", "data-testid": "owner-attention-aggregate-notice", children: [t("pages.focus.ownerAttention.blockedAggregate", { count: inboxBlockedAggregate.length }), " ", _jsx(Link, { to: "/principles", className: "text-gov hover:underline", children: t("pages.focus.ownerInbox.viewLibrary") })] })), ownerInbox.historicalUnknown.count > 0 && (_jsxs("p", { className: "text-ink-4 text-[12.5px] leading-relaxed mt-2", "data-testid": "owner-inbox-aggregate-notice", children: [ownerInbox.historicalUnknown.reasonText, " ", _jsx(Link, { to: "/principles", className: "text-gov hover:underline", children: t("pages.focus.ownerInbox.viewLibrary") })] }))] }))] }), experienceMode && experienceData !== null ? (_jsx(ExperienceSummaryCard, { snapshot: experienceData })) : !experienceMode ? (_jsxs("div", { className: "mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", children: [_jsx("div", { className: "flex items-center gap-2 mb-1", children: _jsx("span", { className: `inline-flex items-center rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase ${governanceState === "owner_review_ready" ? "bg-gov/10 text-gov border border-gov/20"
631
762
  : governanceState === "degraded" ? "bg-amber/10 text-amber border border-amber/20"
632
763
  : governanceState === "in_progress" ? "bg-green/10 text-green border border-green/20"
633
- : "text-ink-4 border border-line bg-surface/80"}`, role: "status", children: t(`pages.focus.stateLabel.${governanceState}`) }) }), _jsx("div", { className: "text-ink-2 text-[13px] leading-relaxed mt-1", children: stateReason }), _jsxs("div", { className: "text-ink-4 text-[13px] leading-relaxed mt-1", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.nextActionLabel") }), " ", nextAction] })] })) : null, !experienceMode && (_jsxs(_Fragment, { children: [_jsx(ProseSummary, { pendingCount: pendingCount, deviationCount: deviationCount, stagnationCount: stagnationCount, evidenceCount: evidenceCount }), _jsx(FeedbackStratification, { gateBlocksToday: gateBlocksToday, inProgressCount: evidenceCount, pendingCount: pendingCount }), !experienceMode && governanceState === "none" && pendingCount === 0 && deviationCount === 0 && stagnationCount === 0 && (stateReasonCode === "state_db_missing" ? (_jsx(ZeroStateDbMissing, {})) : (_jsxs(_Fragment, { children: [_jsx(ZeroStateHealthy, {}), _jsx("div", { className: "mt-4", children: _jsx(OnboardingGuide, {}) })] }))), governanceState === "in_progress" && inProgressSummary && (_jsx(InProgressGuide, { summary: inProgressSummary })), degradedSignals && degradedSignals.length > 0 && (_jsx(DegradedSummary, { signals: degradedSignals }))] })), _jsx(DailyThoughtCard, {}), experienceMode && experienceData !== null && experienceData.summary.primaryAttention === "all_clear" && pendingGroups.length === 0 && (_jsx("div", { className: "mt-4", children: _jsx(OnboardingGuide, {}) })), !experienceMode && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-deviation", children: [_jsx(SectionTitle, { id: "section-deviation", children: evidenceCount > 0
764
+ : "text-ink-4 border border-line bg-surface/80"}`, role: "status", children: t(`pages.focus.stateLabel.${governanceState}`) }) }), _jsx("div", { className: "text-ink-2 text-[13px] leading-relaxed mt-1", children: stateReason }), _jsxs("div", { className: "text-ink-4 text-[13px] leading-relaxed mt-1", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.nextActionLabel") }), " ", nextAction] })] })) : null, !experienceMode && (_jsxs(_Fragment, { children: [_jsx(ProseSummary, { pendingCount: pendingCount, deviationCount: deviationCount, stagnationCount: stagnationCount, evidenceCount: evidenceCount }), _jsx(FeedbackStratification, { gateBlocksToday: gateBlocksToday, inProgressCount: evidenceCount, pendingCount: pendingCount }), !experienceMode && governanceState === "none" && pendingCount === 0 && deviationCount === 0 && stagnationCount === 0 && (stateReasonCode === "state_db_missing" ? (_jsx(ZeroStateDbMissing, {})) : (_jsxs(_Fragment, { children: [_jsx(ZeroStateHealthy, {}), _jsx("div", { className: "mt-4", children: _jsx(OnboardingGuide, {}) })] }))), governanceState === "in_progress" && inProgressSummary && (_jsx(InProgressGuide, { summary: inProgressSummary })), degradedSignals && degradedSignals.length > 0 && (_jsx(DegradedSummary, { signals: degradedSignals }))] })), experienceMode && experienceData !== null && experienceData.summary.primaryAttention === "all_clear" && pendingGroups.length === 0 && (_jsx("div", { className: "mt-4", children: _jsx(OnboardingGuide, {}) })), !experienceMode && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-deviation", children: [_jsx(SectionTitle, { id: "section-deviation", children: evidenceCount > 0
634
765
  ? t("pages.focus.sectionEvidenceInProgress")
635
- : t("pages.focus.sectionDeviation") }), deviationCount > 0 ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "text-ink-2 text-sm mb-3", children: [_jsx("span", { className: "font-mono font-semibold text-ink", children: deviationCount }), " ", t("pages.focus.deviationCount", { count: deviationCount })] }), _jsx("div", { className: "text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2 mb-4", children: t("pages.focus.deviationDisclaimer") }), _jsxs("details", { className: "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.focus.viewFullChain") }), _jsx("div", { className: "mt-2 pl-4 border-l-2 border-line text-ink-3 text-[13px]", children: t("pages.focus.deviationDetailPending") })] })] })) : evidenceCount > 0 ? (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.evidenceInProgress", { count: evidenceCount }) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.emptyDeviation") }))] })), !experienceMode && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-signals", children: [_jsx(SectionTitle, { id: "section-signals", children: t("pages.focus.sectionSignals") }), stagnationSignals.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: stagnationSignals.map((signal) => (_jsx(StagnationSignalCard, { signal: signal }, signal.principleId))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.emptySignals") }))] })), _jsx("footer", { className: "mt-12 pt-6 border-t border-line text-ink-3 text-[13px]", children: t("pages.focus.footer") })] }) }));
766
+ : t("pages.focus.sectionDeviation") }), deviationCount > 0 ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "text-ink-2 text-sm mb-3", children: [_jsx("span", { className: "font-mono font-semibold text-ink", children: deviationCount }), " ", t("pages.focus.deviationCount", { count: deviationCount })] }), _jsx("div", { className: "text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2 mb-4", children: t("pages.focus.deviationDisclaimer") }), _jsxs("details", { className: "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.focus.viewFullChain") }), _jsx("div", { className: "mt-2 pl-4 border-l-2 border-line text-ink-3 text-[13px]", children: t("pages.focus.deviationDetailPending") })] })] })) : evidenceCount > 0 ? (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.evidenceInProgress", { count: evidenceCount }) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.emptyDeviation") }))] })), !experienceMode && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-signals", children: [_jsx(SectionTitle, { id: "section-signals", children: t("pages.focus.sectionSignals") }), stagnationSignals.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: stagnationSignals.map((signal) => (_jsx(StagnationSignalCard, { signal: signal }, signal.principleId))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.focus.emptySignals") }))] })), _jsx(DailyThoughtCard, {}), _jsx("footer", { className: "mt-12 pt-6 border-t border-line text-ink-3 text-[13px]", children: t("pages.focus.footer") })] }) }));
636
767
  }
637
768
  /** Owner Decision Experience v1 inbox item — display-only (SPEC §11.1). */
638
- function InboxItem({ item, t }) {
769
+ function InboxItem({ item, t, note }) {
639
770
  return (_jsxs("div", { className: "mb-2 rounded-[var(--radius-md)] border border-line p-3", "data-testid": "owner-inbox-item", children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-2", children: [_jsx(Link, { to: `/principles/${encodeURIComponent(item.principleId)}`, className: "text-ink text-[13.5px] font-medium hover:underline", children: item.learnedPrinciple.status === 'known'
640
771
  ? item.learnedPrinciple.text
641
- : item.learnedPrinciple.reasonText }), _jsx("span", { className: "font-mono text-[11px] text-ink-4 border border-line rounded-[2px] px-1.5 py-0.5", children: t(`pages.focus.ownerInbox.group.${item.inbox.group}`) })] }), _jsx("p", { className: "mt-1 text-ink-3 text-[12.5px] leading-relaxed", children: item.nextAction.ownerText })] }));
772
+ : item.learnedPrinciple.reasonText }), _jsx("span", { className: "font-mono text-[11px] text-ink-4 border border-line rounded-[2px] px-1.5 py-0.5", children: t(`pages.focus.ownerInbox.group.${item.inbox.group}`) })] }), _jsx("p", { className: "mt-1 text-ink-3 text-[12.5px] leading-relaxed", children: note ?? item.nextAction.ownerText })] }));
642
773
  }
@@ -1,5 +1,7 @@
1
- export declare function getReceiptPresentation(effectCount: number): {
2
- headlineKey: 'principles.detail.receipts.headline' | 'principles.detail.receipts.headlinePresence';
1
+ export declare function getReceiptPresentation(effectCount: number, presenceCount: number): {
2
+ headlineKey: 'principles.detail.receipts.headline' | 'principles.detail.receipts.headlinePresence' | 'principles.detail.receipts.headlineNone';
3
+ /** effect>0 且 presence=0 — effects exist without any presence records; note it, never fabricate presence. */
4
+ presenceMissing: boolean;
3
5
  showZeroEffectExplanation: boolean;
4
6
  };
5
7
  export type GovernanceControlBlock = {
@@ -105,10 +105,33 @@ const STAGE_LABEL_KEYS = {
105
105
  behavior: "principles.detail.stageBehavior",
106
106
  };
107
107
  // ── Component ───────────────────────────────────────────────────────────────
108
- export function getReceiptPresentation(effectCount) {
109
- return effectCount > 0
110
- ? { headlineKey: 'principles.detail.receipts.headline', showZeroEffectExplanation: false }
111
- : { headlineKey: 'principles.detail.receipts.headlinePresence', showZeroEffectExplanation: true };
108
+ // SPEC-PD-UIUX-001 R1: the headline must agree with BOTH verified counts.
109
+ // effect>0 → effect headline (records exist; no permanence claim)
110
+ // effect=0,presence>0 → "injections recorded, no effect records yet"
111
+ // effect=0,presence=0 → "nothing observed within the current retention window"
112
+ // Presence is never inferred from approval/activation, and effect is never
113
+ // inferred from presence — the degraded branch (status≠ok) handles
114
+ // "cannot be confirmed" separately.
115
+ export function getReceiptPresentation(effectCount, presenceCount) {
116
+ if (effectCount > 0) {
117
+ return {
118
+ headlineKey: 'principles.detail.receipts.headline',
119
+ presenceMissing: presenceCount === 0,
120
+ showZeroEffectExplanation: false,
121
+ };
122
+ }
123
+ if (presenceCount > 0) {
124
+ return {
125
+ headlineKey: 'principles.detail.receipts.headlinePresence',
126
+ presenceMissing: false,
127
+ showZeroEffectExplanation: true,
128
+ };
129
+ }
130
+ return {
131
+ headlineKey: 'principles.detail.receipts.headlineNone',
132
+ presenceMissing: false,
133
+ showZeroEffectExplanation: true,
134
+ };
112
135
  }
113
136
  export const GOVERNANCE_BLOCK_I18N_KEYS = {
114
137
  recoveryReason: 'principles.detail.governance.reason.recovery_required',
@@ -434,7 +457,7 @@ export function PrincipleDetailPage() {
434
457
  }
435
458
  const hasRules = principle.rules.length > 0;
436
459
  const receiptPresentation = receipts?.status === 'ok'
437
- ? getReceiptPresentation(receipts.effectCount)
460
+ ? getReceiptPresentation(receipts.effectCount, receipts.presenceCount)
438
461
  : null;
439
462
  return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsxs(Button, { variant: "ghost", onClick: () => navigate("/principles"), className: "mb-4 -ml-2", children: ["\u2190 ", t("principles.detail.backToList")] }), _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", children: ownerDecision?.learnedPrinciple.status === 'known'
440
463
  ? ownerDecision.learnedPrinciple.value.text
@@ -476,25 +499,40 @@ export function PrincipleDetailPage() {
476
499
  effectCount: receipts.effectCount,
477
500
  lastEffectAt: receipts.lastEffectAt ? formatDate(receipts.lastEffectAt, i18n.language) : '',
478
501
  })
479
- : t('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('principles.detail.receipts.zeroEffect') })), 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', { defaultValue: '干预证据链(Phase 1)' }) }), 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', {
480
- defaultValue: '投递 {{d}} · 应用 {{a}} · 行为 {{e}} · 效果 {{f}} · 结果 {{o}}',
502
+ : 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
503
+ ? 'principles.detail.receipts.zeroEffectPresence'
504
+ : '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', {
481
505
  d: evidenceAudit.deliveries.length,
482
506
  a: evidenceAudit.applications.length,
483
507
  e: evidenceAudit.episodes.length,
484
508
  f: evidenceAudit.effects.length,
485
509
  o: evidenceAudit.outcomes.length,
486
510
  }) }), evidenceAudit.unresolvedReferences.length > 0 && (_jsx("p", { "data-testid": "evidence-audit-unresolved", className: "mt-2 text-[12px] text-amber", children: t('principles.detail.evidenceAudit.unresolved', {
487
- defaultValue: '{{count}} 条记录的关联对象尚未到达(pending association,非"未发生")',
488
511
  count: evidenceAudit.unresolvedReferences.length,
489
512
  }) })), _jsx("dl", { className: "mt-3 space-y-2 text-[13px]", children: [
490
- ['delivery', '投递(Delivery)', evidenceAudit.deliveries, 'delivery'],
491
- ['application', '应用(Application)', evidenceAudit.applications, 'application'],
492
- ['episode', '行为(Episode)', evidenceAudit.episodes, 'behavior_episode'],
493
- ['effect', '效果(Effect)', evidenceAudit.effects, 'effect'],
494
- ['outcome', '结果(Outcome)', evidenceAudit.outcomes, 'outcome'],
495
- ].map(([key, label, 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: label }), _jsx("dd", { className: "mt-1", children: list.length === 0 ? (_jsx("span", { className: "text-[13px] text-ink-3", children: t('principles.detail.evidenceAudit.emptySection', { defaultValue: '本范围内未观察到(≠ 从未发生)' }) })) : (_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 truncate", title: `${record.observationKey}\n${record.detail}`, children: record.detail }), record.sourceStatus === 'unknown' && _jsx("span", { className: "text-[10px] text-amber", children: "\u6E90\u53EF\u590D\u6838\u6027\u672A\u77E5" }), record.contentRedactedAt && _jsxs("span", { className: "text-[10px] text-ink-4", children: ["\u6B63\u6587\u5DF2\u4E8E ", record.contentRedactedAt.slice(0, 10), " \u6E05\u9664"] }), record.contentReference && _jsxs("span", { className: "text-[10px] text-ink-4", title: record.contentReference.payloadDigest ?? '无载荷摘要', children: ["\u5185\u5BB9\u5F15\u7528\uFF1A", record.contentReference.resolution === 'resolved' ? 'resolved' : 'revision 未解析', " \u00B7 ", record.contentReference.principleId, record.contentReference.artifactId ? ` · ${record.contentReference.artifactId}` : ''] }), record.activationReference && _jsxs("span", { className: "text-[10px] text-ink-4", title: `snapshot ${record.activationReference.sourceSnapshotDigest}`, children: ["\u6FC0\u6D3B\u53D1\u751F\uFF1A", record.activationReference.activationId, record.activationReference.activatedAt ? ` · ${record.activationReference.activatedAt}` : ''] }), record.nativeLineage.length > 0 && _jsxs("span", { className: "text-[10px] text-ink-4", children: ["\u539F\u751F\u7EBF\u7D22\uFF1A", record.nativeLineage.join(' · ')] }), 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', { defaultValue: '待关联' }) }))] }, record.evidenceId))) })) }), evidenceAudit.pages[recordKind].hasMore && (_jsx(Button, { variant: "ghost", size: "sm", disabled: loadingEvidenceKind !== null, onClick: () => void loadOlderEvidence(recordKind), children: loadingEvidenceKind === recordKind ? '读取中…' : '读取更早记录' }))] }, 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', { defaultValue: '宿主能力声明(Supported / Unsupported / Unknown)' }) }), _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}`))) })] })), _jsx("p", { className: "mt-3 text-[11px] leading-relaxed text-ink-4", children: t('principles.detail.evidenceAudit.note', {
496
- defaultValue: '本区只记录事实:投递确认程度、Agent 自述与 Runtime 事实分开列出,缺失=未知而非无效。不提供成功率或有效性评分。',
497
- }) })] })) : (_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', { defaultValue: '干预证据链暂不可用' }) }), _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("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", {
513
+ ['delivery', 'principles.detail.evidenceAudit.sectionDelivery', evidenceAudit.deliveries, 'delivery'],
514
+ ['application', 'principles.detail.evidenceAudit.sectionApplication', evidenceAudit.applications, 'application'],
515
+ ['episode', 'principles.detail.evidenceAudit.sectionEpisode', evidenceAudit.episodes, 'behavior_episode'],
516
+ ['effect', 'principles.detail.evidenceAudit.sectionEffect', evidenceAudit.effects, 'effect'],
517
+ ['outcome', 'principles.detail.evidenceAudit.sectionOutcome', evidenceAudit.outcomes, 'outcome'],
518
+ ].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: [
519
+ ['principles.detail.evidenceAudit.sectionDelivery', evidenceAudit.deliveries],
520
+ ['principles.detail.evidenceAudit.sectionApplication', evidenceAudit.applications],
521
+ ['principles.detail.evidenceAudit.sectionEpisode', evidenceAudit.episodes],
522
+ ['principles.detail.evidenceAudit.sectionEffect', evidenceAudit.effects],
523
+ ['principles.detail.evidenceAudit.sectionOutcome', evidenceAudit.outcomes],
524
+ ].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', {
525
+ resolution: record.contentReference.resolution === 'resolved' ? t('principles.detail.evidenceAudit.referenceResolved') : t('principles.detail.evidenceAudit.referenceUnresolved'),
526
+ principleId: record.contentReference.principleId,
527
+ artifactId: record.contentReference.artifactId ? ` · ${record.contentReference.artifactId}` : '',
528
+ // Review round (P2): keep the payload digest traceable —
529
+ // the technical note promises it.
530
+ payloadDigest: ` · ${t('principles.detail.evidenceAudit.payloadDigestLabel')}: ${record.contentReference.payloadDigest ?? t('principles.detail.evidenceAudit.noPayloadDigest')}`,
531
+ })] })), record.activationReference && (_jsxs(_Fragment, { children: [" \u00B7 ", t('principles.detail.evidenceAudit.activationReference', {
532
+ activationId: record.activationReference.activationId,
533
+ activatedAt: record.activationReference.activatedAt ? ` · ${record.activationReference.activatedAt}` : '',
534
+ snapshotDigest: ` · ${t('principles.detail.evidenceAudit.snapshotDigestLabel')}: ${record.activationReference.sourceSnapshotDigest}`,
535
+ })] })), 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("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", {
498
536
  defaultValue: "已关联 {{count}} 条证据记录",
499
537
  count: principle.derivedFromPainIds.length,
500
538
  }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: async () => {
@@ -205,7 +205,7 @@ export function UpdatePage() {
205
205
  }) }, item.transactionId))), recoveryData.nextAction && (_jsx("p", { className: "mt-2 text-[12px] text-ink-3", children: recoveryData.nextAction }))] })), _jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.update.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.update.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.update.subtitle") }), _jsxs("section", { className: "mb-8", "aria-labelledby": "section-update-status", children: [_jsx(SectionTitle, { id: "section-update-status", children: t("pages.update.currentVersion") }), _jsxs("div", { className: "bg-panel border border-line rounded-[6px] p-5", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.currentVersion") }), _jsx("span", { className: "font-mono text-[13px] text-ink", children: statusData?.currentVersion ?? "—" })] }), statusData?.identityDivergence && (_jsx("div", { className: "border border-amber/35 rounded-[4px] px-3 py-2 text-[12px] leading-relaxed text-ink-2", children: t("pages.update.identityDivergence", {
206
206
  active: statusData.identityDivergence.activeVersion,
207
207
  plugin: statusData.identityDivergence.pluginVersion,
208
- }) })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.latestVersion") }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-[13px] text-ink", children: updateState === 'check_failed' ? "—" : (statusData?.latestVersion || "—") }), updateState === 'check_failed' && (_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.update.checkFailed") })), updateState === 'update_blocked' && (_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.update.blockedBadge") })), updateState === 'up_to_date' && (_jsx("span", { className: "inline-flex items-center border border-green/35 text-green rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.upToDate") })), updateState === 'update_available' && (_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.update.updateAvailable") }))] })] })] }), (updateState === 'update_blocked' || updateState === 'check_failed') && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] leading-relaxed", children: [blockedReason && (_jsxs("p", { className: "text-ink-2", children: [t("pages.update.reasonLabel"), blockedReason] })), statusData?.message && updateState === 'update_blocked' && (_jsx("p", { className: "mt-1 text-ink-3", children: statusData.message })), statusData?.nextAction && (_jsx("p", { className: "mt-1 text-ink-3 font-mono", children: statusData.nextAction }))] })), statusData?.error && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] text-ink-4 font-mono", children: [t("pages.update.checkError"), ": ", statusData.error] })), inProgress && (_jsxs("div", { className: "mt-4 p-4 rounded-[6px] border border-gov/30 bg-surface text-[13px] leading-relaxed", role: "status", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin text-gov" }), _jsx("span", { className: "font-medium text-ink", children: t("pages.update.inProgressPanel") })] }), _jsx("p", { className: "mt-1 font-mono text-[12px] text-ink-3", children: t("pages.update.inProgressPhase", { phase: inProgress.phase ?? "…" }) }), _jsx("p", { className: "mt-1 font-mono text-[12px] text-ink-4", children: inProgress.transactionId })] })), _jsxs("div", { className: "mt-5 pt-4 border-t border-line flex items-center gap-3 flex-wrap", children: [_jsx("button", { type: "button", onClick: handleCheckForUpdates, disabled: checking || fullUpdating || inProgress !== null, className: "border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: checking ? t("pages.update.checking") : t("pages.update.checkForUpdates") }), !isUpToDate && updateState === 'update_available' && (_jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: checking || fullUpdating || inProgress !== null, className: "bg-gov text-white rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: fullUpdating ? (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), t("pages.update.updating")] })) : (t("pages.update.applyUpdate")) }))] }), updateResult && (_jsx("div", { className: `mt-4 p-4 rounded-[6px] border animate-[pdFadeIn_400ms_ease-out] ${updateResult.success ? 'bg-green/5 border-green/20' : updateResult.refusal ? 'bg-amber/5 border-amber/25' : 'bg-red/5 border-red/20'}`, children: _jsxs("div", { className: "flex items-start gap-3", children: [updateResult.success ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-green shrink-0 mt-0.5 animate-[pdFadeIn_600ms_ease-out]", style: { transform: 'scale(1)', animationFillMode: 'both' } })) : updateResult.refusal ? (_jsx(AlertTriangle, { className: "h-6 w-6 text-amber shrink-0 mt-0.5" })) : (_jsx(XCircle, { className: "h-6 w-6 text-red shrink-0 mt-0.5" })), _jsxs("div", { className: "flex-1 min-w-0", children: [updateResult.refusal && (_jsx("p", { className: "text-[12px] font-mono uppercase text-amber mb-1", children: t("pages.update.blockedBadge") })), updateResult.success && updateResult.fromVersion && updateResult.newVersion && (_jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [_jsx("span", { className: "font-mono text-[13px] text-ink-3 line-through", children: updateResult.fromVersion }), _jsx(ArrowRight, { className: "h-3.5 w-3.5 text-green" }), _jsx("span", { className: "font-mono text-[13px] text-green font-medium", children: updateResult.newVersion })] })), _jsx("p", { className: `text-[13px] ${updateResult.success ? 'text-green' : updateResult.refusal ? 'text-ink-2' : 'text-red'}`, children: updateResult.message }), updateResult.success && updateResult.requiresRestart && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed", children: t("pages.update.fullUpdateRestartPrompt") })), updateResult.gatewayNotice && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed font-mono", children: updateResult.gatewayNotice })), !updateResult.success && updateResult.nextAction && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono leading-relaxed", children: updateResult.nextAction })), !updateResult.success && (_jsxs("div", { className: "mt-2 flex items-center gap-2", children: [/network|fetch|timeout|ECONNREFUSED|ENOTFOUND/i.test(updateResult.message) && (_jsx("p", { className: "text-[12px] text-ink-4 font-mono", children: t("pages.update.networkErrorHint") })), _jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: fullUpdating, className: "text-[12px] text-red underline hover:text-red/80 disabled:opacity-50", children: t("pages.update.retry") })] }))] })] }) }))] })] }), _jsxs("section", { "aria-labelledby": "section-update-history", children: [_jsx(SectionTitle, { id: "section-update-history", children: t("pages.update.history") }), historyErrorReason ? (_jsxs("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: [t("pages.update.loadError"), " (", historyErrorReason, ")"] })) : historyData && historyData.updates.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: historyData.updates.map((entry) => (_jsxs("article", { className: "bg-panel border border-line rounded-[6px] px-5 py-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_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: t("pages.update.version") }), _jsxs("span", { className: "font-mono text-[13px] text-ink", children: [entry.fromVersion, " \u2192 ", entry.toVersion === "failed" ? "—" : entry.toVersion] }), entry.kind !== "failure" && (_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: t(`pages.update.historyKind.${entry.kind}`) })), !entry.success && entry.kind !== 'refusal' && (_jsx("span", { className: "inline-flex items-center border border-red/35 text-red rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.failed") }))] }), _jsx("div", { className: "flex items-center gap-3", children: _jsx("span", { className: "text-ink-3 text-[13px]", children: formatDate(entry.timestamp, i18n.language, {
208
+ }) })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.latestVersion") }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-[13px] text-ink", children: updateState === 'check_failed' ? "—" : (statusData?.latestVersion || "—") }), updateState === 'check_failed' && (_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.update.checkFailed") })), updateState === 'update_blocked' && (_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.update.blockedBadge") })), updateState === 'up_to_date' && (_jsx("span", { className: "inline-flex items-center border border-green/35 text-green rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.upToDate") })), updateState === 'update_available' && (_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.update.updateAvailable") }))] })] })] }), (updateState === 'update_blocked' || updateState === 'check_failed') && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] leading-relaxed", children: [blockedReason && (_jsxs("p", { className: "text-ink-2", children: [t("pages.update.reasonLabel"), blockedReason] })), statusData?.message && updateState === 'update_blocked' && (_jsx("p", { className: "mt-1 text-ink-3", children: statusData.message })), statusData?.nextAction && (_jsx("p", { className: "mt-1 text-ink-3 font-mono", children: statusData.nextAction }))] })), statusData?.error && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] text-ink-4 font-mono", children: [t("pages.update.checkError"), ": ", statusData.error] })), inProgress && (_jsxs("div", { className: "mt-4 p-4 rounded-[6px] border border-gov/30 bg-surface text-[13px] leading-relaxed", role: "status", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin text-gov" }), _jsx("span", { className: "font-medium text-ink", children: t("pages.update.inProgressPanel") })] }), _jsx("p", { className: "mt-1 font-mono text-[12px] text-ink-3", children: t("pages.update.inProgressPhase", { phase: inProgress.phase ?? "…" }) }), _jsx("p", { className: "mt-1 font-mono text-[12px] text-ink-4", children: inProgress.transactionId })] })), _jsxs("div", { className: "mt-5 pt-4 border-t border-line flex items-center gap-3 flex-wrap", children: [_jsx("button", { type: "button", onClick: handleCheckForUpdates, disabled: checking || fullUpdating || inProgress !== null, className: "border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: checking ? t("pages.update.checking") : t("pages.update.checkForUpdates") }), !isUpToDate && updateState === 'update_available' && (_jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: checking || fullUpdating || inProgress !== null, className: "bg-gov text-white rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: fullUpdating ? (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), t("pages.update.updating")] })) : (t("pages.update.applyUpdate")) }))] }), updateResult && (_jsx("div", { className: `mt-4 p-4 rounded-[6px] border animate-[pdFadeIn_400ms_ease-out] ${updateResult.success ? 'bg-green/5 border-green/20' : updateResult.refusal ? 'bg-amber/5 border-amber/25' : 'bg-danger/5 border-danger/20'}`, children: _jsxs("div", { className: "flex items-start gap-3", children: [updateResult.success ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-green shrink-0 mt-0.5 animate-[pdFadeIn_600ms_ease-out]", style: { transform: 'scale(1)', animationFillMode: 'both' } })) : updateResult.refusal ? (_jsx(AlertTriangle, { className: "h-6 w-6 text-amber shrink-0 mt-0.5" })) : (_jsx(XCircle, { className: "h-6 w-6 text-danger shrink-0 mt-0.5" })), _jsxs("div", { className: "flex-1 min-w-0", children: [updateResult.refusal && (_jsx("p", { className: "text-[12px] font-mono uppercase text-amber mb-1", children: t("pages.update.blockedBadge") })), updateResult.success && updateResult.fromVersion && updateResult.newVersion && (_jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [_jsx("span", { className: "font-mono text-[13px] text-ink-3 line-through", children: updateResult.fromVersion }), _jsx(ArrowRight, { className: "h-3.5 w-3.5 text-green" }), _jsx("span", { className: "font-mono text-[13px] text-green font-medium", children: updateResult.newVersion })] })), _jsx("p", { className: `text-[13px] ${updateResult.success ? 'text-green' : updateResult.refusal ? 'text-ink-2' : 'text-danger'}`, children: updateResult.message }), updateResult.success && updateResult.requiresRestart && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed", children: t("pages.update.fullUpdateRestartPrompt") })), updateResult.gatewayNotice && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed font-mono", children: updateResult.gatewayNotice })), !updateResult.success && updateResult.nextAction && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono leading-relaxed", children: updateResult.nextAction })), !updateResult.success && (_jsxs("div", { className: "mt-2 flex items-center gap-2", children: [/network|fetch|timeout|ECONNREFUSED|ENOTFOUND/i.test(updateResult.message) && (_jsx("p", { className: "text-[12px] text-ink-4 font-mono", children: t("pages.update.networkErrorHint") })), _jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: fullUpdating, className: "text-[12px] text-danger underline hover:text-danger/80 disabled:opacity-50", children: t("pages.update.retry") })] }))] })] }) }))] })] }), _jsxs("section", { "aria-labelledby": "section-update-history", children: [_jsx(SectionTitle, { id: "section-update-history", children: t("pages.update.history") }), historyErrorReason ? (_jsxs("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: [t("pages.update.loadError"), " (", historyErrorReason, ")"] })) : historyData && historyData.updates.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: historyData.updates.map((entry) => (_jsxs("article", { className: "bg-panel border border-line rounded-[6px] px-5 py-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_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: t("pages.update.version") }), _jsxs("span", { className: "font-mono text-[13px] text-ink", children: [entry.fromVersion, " \u2192 ", entry.toVersion === "failed" ? "—" : entry.toVersion] }), entry.kind !== "failure" && (_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: t(`pages.update.historyKind.${entry.kind}`) })), !entry.success && entry.kind !== 'refusal' && (_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.update.failed") }))] }), _jsx("div", { className: "flex items-center gap-3", children: _jsx("span", { className: "text-ink-3 text-[13px]", children: formatDate(entry.timestamp, i18n.language, {
209
209
  year: "numeric",
210
210
  month: "short",
211
211
  day: "numeric",