create-principles-disciple 1.144.24 → 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 (80) hide show
  1. package/_release/product-identity.json +2 -2
  2. package/codex-adapter/dist/pd-hook.js +84 -9
  3. package/codex-adapter/package.json +1 -1
  4. package/console/dist/ui/App.js +19 -3
  5. package/console/dist/ui/components/layout/app-sidebar.d.ts +11 -0
  6. package/console/dist/ui/components/layout/app-sidebar.js +60 -7
  7. package/console/dist/ui/components/ui/sheet.js +2 -1
  8. package/console/dist/ui/i18n/en.json +66 -5
  9. package/console/dist/ui/i18n/index.js +11 -0
  10. package/console/dist/ui/i18n/zh-CN.json +66 -5
  11. package/console/dist/ui/pages/control-center/ControlCenterPage.js +4 -2
  12. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +3 -3
  13. package/console/dist/ui/pages/focus/FocusPage.d.ts +92 -0
  14. package/console/dist/ui/pages/focus/FocusPage.js +139 -8
  15. package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +4 -2
  16. package/console/dist/ui/pages/principles/PrincipleDetailPage.js +54 -16
  17. package/console/dist/ui/pages/settings/UpdatePage.js +1 -1
  18. package/console/dist/web/assets/app.css +109 -20
  19. package/console/dist/web/assets/app.js +59 -58
  20. package/core/dist/principle-tree-ledger.d.ts +20 -0
  21. package/core/dist/principle-tree-ledger.d.ts.map +1 -1
  22. package/core/dist/principle-tree-ledger.js +13 -9
  23. package/core/dist/principle-tree-ledger.js.map +1 -1
  24. package/core/dist/runtime-v2/activation/activation-dispatcher.d.ts.map +1 -1
  25. package/core/dist/runtime-v2/activation/activation-dispatcher.js +10 -3
  26. package/core/dist/runtime-v2/activation/activation-dispatcher.js.map +1 -1
  27. package/core/dist/runtime-v2/activation/ledger-identity.d.ts +12 -3
  28. package/core/dist/runtime-v2/activation/ledger-identity.d.ts.map +1 -1
  29. package/core/dist/runtime-v2/activation/ledger-identity.js +18 -3
  30. package/core/dist/runtime-v2/activation/ledger-identity.js.map +1 -1
  31. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts +8 -0
  32. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts.map +1 -1
  33. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js +11 -1
  34. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js.map +1 -1
  35. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +61 -2
  36. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
  37. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +68 -3
  38. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
  39. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  40. package/core/dist/runtime-v2/internalization/artificer-runner.js +5 -0
  41. package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  42. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +18 -0
  43. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
  44. package/core/dist/runtime-v2/internalization/evaluator-output.js +7 -0
  45. package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
  46. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts +36 -2
  47. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts.map +1 -1
  48. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js +31 -1
  49. package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js.map +1 -1
  50. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +52 -12
  51. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  52. package/core/dist/runtime-v2/internalization/evaluator-runner.js +180 -48
  53. package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  54. package/core/dist/runtime-v2/internalization/repair-replay-resolver.d.ts +8 -0
  55. package/core/dist/runtime-v2/internalization/repair-replay-resolver.d.ts.map +1 -1
  56. package/core/dist/runtime-v2/internalization/repair-replay-resolver.js +12 -0
  57. package/core/dist/runtime-v2/internalization/repair-replay-resolver.js.map +1 -1
  58. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +4 -0
  59. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
  60. package/core/dist/runtime-v2/internalization/scribe-runner.js +13 -1
  61. package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
  62. package/core/dist/telemetry-event.d.ts.map +1 -1
  63. package/core/dist/telemetry-event.js +3 -2
  64. package/core/dist/telemetry-event.js.map +1 -1
  65. package/core/package.json +1 -1
  66. package/host-runtime/dist/internalization-consumer-cycle.js +6 -0
  67. package/host-runtime/package.json +1 -1
  68. package/package.json +1 -1
  69. package/pd-cli/dist/commands/pain-retry.d.ts.map +1 -1
  70. package/pd-cli/dist/commands/pain-retry.js +9 -3
  71. package/pd-cli/dist/commands/pain-retry.js.map +1 -1
  72. package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
  73. package/pd-cli/dist/commands/runtime-internalization-run-once.js +3 -0
  74. package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
  75. package/pd-cli/dist/services/rulehost-pipeline-runner.d.ts.map +1 -1
  76. package/pd-cli/dist/services/rulehost-pipeline-runner.js +6 -0
  77. package/pd-cli/dist/services/rulehost-pipeline-runner.js.map +1 -1
  78. package/pd-cli/package.json +1 -1
  79. package/plugin/dist/bundle.js +449 -440
  80. package/release-manager/package.json +1 -1
@@ -280,7 +280,9 @@ function readinessTagClasses(readiness) {
280
280
  case "needs_setup":
281
281
  return base.replace("border-line", "border-amber/35").replace("text-ink-3", "text-amber");
282
282
  case "not_ready":
283
- return base.replace("border-line", "border-red/35").replace("text-ink-3", "text-red");
283
+ // SPEC-PD-UIUX-001 R5: bare `red` utilities have no matching theme token
284
+ // (silently unstyled) — use the registered danger token.
285
+ return base.replace("border-line", "border-danger/35").replace("text-ink-3", "text-danger");
284
286
  default:
285
287
  return base;
286
288
  }
@@ -384,7 +386,7 @@ function AdvancedDiagnostics({ config, }) {
384
386
  const grouped = groupAgentsByReadiness(diagnostics);
385
387
  return (_jsxs("details", { className: "group", children: [_jsx("summary", { className: "text-ink-3 text-[13px] cursor-pointer hover:text-ink-2 transition-colors focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("pages.controlCenter.advancedDiagnostics") }), _jsxs("div", { className: "mt-4 space-y-5", children: [_jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.features") }), _jsx("div", { className: "bg-surface/60 border border-line rounded-[6px] px-3 py-2", children: config.features.length === 0 ? (_jsx("span", { className: "text-ink-4 text-[13px]", children: "\u2014" })) : (_jsx("div", { className: "space-y-1", children: config.features.map((f) => (_jsxs("div", { className: "flex items-center gap-2 text-[13px]", children: [_jsx("span", { className: "text-ink-2", children: enumLabel('featureId', f.id, t) }), _jsx("span", { className: "text-ink-4", children: "\u00B7" }), _jsx("span", { className: "text-ink-3", children: enumLabel('featureCategory', f.category, t) }), _jsx("span", { className: "text-ink-4", children: "\u00B7" }), _jsx("span", { className: f.enabled ? "text-ink-2" : "text-ink-4 line-through", children: f.enabled
386
388
  ? t("pages.controlCenter.on")
387
- : t("pages.controlCenter.off") })] }, f.id))) })) })] }), _jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.runtimeProfiles") }), _jsx("div", { className: "bg-surface/60 border border-line rounded-[6px] px-3 py-2", children: config.runtimeProfiles.length === 0 ? (_jsx("span", { className: "text-ink-4 text-[13px]", children: "\u2014" })) : (_jsx("div", { className: "space-y-1", children: config.runtimeProfiles.map((p) => (_jsxs("div", { className: "flex items-center gap-2 text-[13px]", children: [_jsx("span", { className: "text-ink-2", children: p.label }), _jsx("span", { className: "text-ink-4", children: "\u00B7" }), _jsx("span", { className: "text-ink-3", children: p.type }), _jsx("span", { className: readinessTagClasses(p.readiness), children: enumLabel('readiness', p.readiness, t) })] }, p.id))) })) })] }), config.warnings.length > 0 && (_jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.warnings") }), _jsx("div", { className: "bg-surface/60 border border-amber/20 border-l-2 border-l-amber rounded-[6px] px-3 py-2", children: _jsx("ul", { className: "space-y-1", children: config.warnings.map((w, i) => (_jsx("li", { className: "text-ink-2 text-[13px]", children: w }, i))) }) })] })), config.errors && config.errors.length > 0 && (_jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.configErrors") }), _jsx("div", { className: "bg-surface/60 border border-red/20 border-l-2 border-l-red rounded-[6px] px-3 py-2", children: _jsx("ul", { className: "space-y-2", children: config.errors.map((e, i) => (_jsxs("li", { className: "text-[13px]", children: [_jsx("span", { className: "text-ink font-medium", children: e.path }), _jsx("span", { className: "text-ink-4", children: " \u2014 " }), _jsx("span", { className: "text-ink-2", children: e.reason }), _jsxs("div", { className: "text-ink-3 text-[12px] mt-0.5", children: ["\u2192 ", e.nextAction] })] }, i))) }) })] })), _jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.readinessLabel") }), _jsx("div", { className: "bg-surface/60 border border-line rounded-[6px] px-3 py-2 space-y-2", children: Object.keys(grouped).map((status) => {
389
+ : t("pages.controlCenter.off") })] }, f.id))) })) })] }), _jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.runtimeProfiles") }), _jsx("div", { className: "bg-surface/60 border border-line rounded-[6px] px-3 py-2", children: config.runtimeProfiles.length === 0 ? (_jsx("span", { className: "text-ink-4 text-[13px]", children: "\u2014" })) : (_jsx("div", { className: "space-y-1", children: config.runtimeProfiles.map((p) => (_jsxs("div", { className: "flex items-center gap-2 text-[13px]", children: [_jsx("span", { className: "text-ink-2", children: p.label }), _jsx("span", { className: "text-ink-4", children: "\u00B7" }), _jsx("span", { className: "text-ink-3", children: p.type }), _jsx("span", { className: readinessTagClasses(p.readiness), children: enumLabel('readiness', p.readiness, t) })] }, p.id))) })) })] }), config.warnings.length > 0 && (_jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.warnings") }), _jsx("div", { className: "bg-surface/60 border border-amber/20 border-l-2 border-l-amber rounded-[6px] px-3 py-2", children: _jsx("ul", { className: "space-y-1", children: config.warnings.map((w, i) => (_jsx("li", { className: "text-ink-2 text-[13px]", children: w }, i))) }) })] })), config.errors && config.errors.length > 0 && (_jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.configErrors") }), _jsx("div", { className: "bg-surface/60 border border-danger/20 border-l-2 border-l-danger rounded-[6px] px-3 py-2", children: _jsx("ul", { className: "space-y-2", children: config.errors.map((e, i) => (_jsxs("li", { className: "text-[13px]", children: [_jsx("span", { className: "text-ink font-medium", children: e.path }), _jsx("span", { className: "text-ink-4", children: " \u2014 " }), _jsx("span", { className: "text-ink-2", children: e.reason }), _jsxs("div", { className: "text-ink-3 text-[12px] mt-0.5", children: ["\u2192 ", e.nextAction] })] }, i))) }) })] })), _jsxs("div", { children: [_jsx("h3", { className: "font-mono text-[11px] uppercase tracking-[0.1em] text-ink-3 mb-2", children: t("pages.controlCenter.readinessLabel") }), _jsx("div", { className: "bg-surface/60 border border-line rounded-[6px] px-3 py-2 space-y-2", children: Object.keys(grouped).map((status) => {
388
390
  const validatedStatus = validateReadinessStatus(status);
389
391
  if (validatedStatus === null)
390
392
  return null;
@@ -213,7 +213,7 @@ export function RuntimeProfileManager({ profiles, defaultRuntimeId, onMutated, }
213
213
  const v = e.target.value;
214
214
  const typed = v === "pi-ai" ? "pi-ai" : "openclaw";
215
215
  handleFieldChange("type", typed);
216
- }, disabled: mode === "edit" || submitting, className: inputClass, children: [_jsx("option", { value: "openclaw", children: t("pages.controlCenter.profiles.typeOpenclaw") }), _jsx("option", { value: "pi-ai", children: t("pages.controlCenter.profiles.typePiAi") })] }), mode === "edit" && (_jsx("p", { className: hintClass, children: t("pages.controlCenter.profiles.fieldIdHint") }))] }), form.type === "pi-ai" && (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-provider", children: t("pages.controlCenter.profiles.fieldProvider") }), _jsx("input", { id: "rpf-provider", type: "text", value: form.provider, onChange: (e) => handleFieldChange("provider", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldProviderPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-model", children: t("pages.controlCenter.profiles.fieldModel") }), _jsx("input", { id: "rpf-model", type: "text", value: form.model, onChange: (e) => handleFieldChange("model", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldModelPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-apikeyenv", children: t("pages.controlCenter.profiles.fieldApiKeyEnv") }), _jsx("input", { id: "rpf-apikeyenv", type: "text", value: form.apiKeyEnv, onChange: (e) => handleFieldChange("apiKeyEnv", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldApiKeyEnvPlaceholder"), className: cn(inputClass, "font-mono"), autoComplete: "off", spellCheck: false }), _jsx("p", { className: hintClass, children: t("pages.controlCenter.profiles.fieldApiKeyEnvHint") })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-baseurl", children: t("pages.controlCenter.profiles.fieldBaseUrl") }), _jsx("input", { id: "rpf-baseurl", type: "text", value: form.baseUrl, onChange: (e) => handleFieldChange("baseUrl", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldBaseUrlPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] })] })), form.type === "openclaw" && (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-source", children: t("pages.controlCenter.profiles.fieldSource") }), _jsx("input", { id: "rpf-source", type: "text", value: form.source, onChange: (e) => handleFieldChange("source", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldSourcePlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-provider-oc", children: t("pages.controlCenter.profiles.fieldProvider") }), _jsx("input", { id: "rpf-provider-oc", type: "text", value: form.provider, onChange: (e) => handleFieldChange("provider", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldProviderPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-model-oc", children: t("pages.controlCenter.profiles.fieldModel") }), _jsx("input", { id: "rpf-model-oc", type: "text", value: form.model, onChange: (e) => handleFieldChange("model", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldModelPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] })] }))] }), formError !== null && (_jsx("div", { className: "mt-3 px-[12px] py-[8px] border border-red/35 rounded-[4px] bg-red/10 text-[12px] text-red font-mono", children: formError })), _jsxs("div", { className: "mt-3 flex items-center gap-[8px]", children: [_jsx("button", { type: "submit", disabled: submitting, className: "border border-gov bg-gov text-paper rounded-[3px] px-[14px] py-[6px] text-[12.5px] font-medium hover:bg-gov-2 transition-colors disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: submitting
216
+ }, disabled: mode === "edit" || submitting, className: inputClass, children: [_jsx("option", { value: "openclaw", children: t("pages.controlCenter.profiles.typeOpenclaw") }), _jsx("option", { value: "pi-ai", children: t("pages.controlCenter.profiles.typePiAi") })] }), mode === "edit" && (_jsx("p", { className: hintClass, children: t("pages.controlCenter.profiles.fieldIdHint") }))] }), form.type === "pi-ai" && (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-provider", children: t("pages.controlCenter.profiles.fieldProvider") }), _jsx("input", { id: "rpf-provider", type: "text", value: form.provider, onChange: (e) => handleFieldChange("provider", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldProviderPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-model", children: t("pages.controlCenter.profiles.fieldModel") }), _jsx("input", { id: "rpf-model", type: "text", value: form.model, onChange: (e) => handleFieldChange("model", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldModelPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-apikeyenv", children: t("pages.controlCenter.profiles.fieldApiKeyEnv") }), _jsx("input", { id: "rpf-apikeyenv", type: "text", value: form.apiKeyEnv, onChange: (e) => handleFieldChange("apiKeyEnv", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldApiKeyEnvPlaceholder"), className: cn(inputClass, "font-mono"), autoComplete: "off", spellCheck: false }), _jsx("p", { className: hintClass, children: t("pages.controlCenter.profiles.fieldApiKeyEnvHint") })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-baseurl", children: t("pages.controlCenter.profiles.fieldBaseUrl") }), _jsx("input", { id: "rpf-baseurl", type: "text", value: form.baseUrl, onChange: (e) => handleFieldChange("baseUrl", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldBaseUrlPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] })] })), form.type === "openclaw" && (_jsxs(_Fragment, { children: [_jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-source", children: t("pages.controlCenter.profiles.fieldSource") }), _jsx("input", { id: "rpf-source", type: "text", value: form.source, onChange: (e) => handleFieldChange("source", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldSourcePlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-provider-oc", children: t("pages.controlCenter.profiles.fieldProvider") }), _jsx("input", { id: "rpf-provider-oc", type: "text", value: form.provider, onChange: (e) => handleFieldChange("provider", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldProviderPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] }), _jsxs("div", { children: [_jsx("label", { className: labelClass, htmlFor: "rpf-model-oc", children: t("pages.controlCenter.profiles.fieldModel") }), _jsx("input", { id: "rpf-model-oc", type: "text", value: form.model, onChange: (e) => handleFieldChange("model", e.target.value), disabled: submitting, placeholder: t("pages.controlCenter.profiles.fieldModelPlaceholder"), className: inputClass, autoComplete: "off", spellCheck: false })] })] }))] }), formError !== null && (_jsx("div", { className: "mt-3 px-[12px] py-[8px] border border-danger/35 rounded-[4px] bg-danger/10 text-[12px] text-danger font-mono", children: formError })), _jsxs("div", { className: "mt-3 flex items-center gap-[8px]", children: [_jsx("button", { type: "submit", disabled: submitting, className: "border border-gov bg-gov text-paper rounded-[3px] px-[14px] py-[6px] text-[12.5px] font-medium hover:bg-gov-2 transition-colors disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: submitting
217
217
  ? mode === "create"
218
218
  ? t("pages.controlCenter.profiles.creating")
219
219
  : t("pages.controlCenter.profiles.saving")
@@ -225,9 +225,9 @@ export function RuntimeProfileManager({ profiles, defaultRuntimeId, onMutated, }
225
225
  setDeleteError(null);
226
226
  }, disabled: mode !== "closed" ||
227
227
  deleting ||
228
- deleteTarget !== null, className: "text-[11.5px] px-[10px] py-[4px] rounded-[3px] border border-line bg-surface text-ink-3 hover:border-red/40 hover:text-red transition-colors disabled:opacity-40 disabled:cursor-not-allowed", children: t("pages.controlCenter.profiles.deleteButton") })] })] }), isDeleteTarget && (_jsx("div", { className: "px-[16px] pb-[12px]", children: _jsxs("div", { className: "px-[12px] py-[10px] border border-danger rounded-[4px] bg-danger/10 text-[12px] text-ink-2 leading-[1.55]", children: [_jsx("div", { className: "font-medium", children: t("pages.controlCenter.profiles.deleteConfirmMessage", {
228
+ deleteTarget !== null, className: "text-[11.5px] px-[10px] py-[4px] rounded-[3px] border border-line bg-surface text-ink-3 hover:border-danger/40 hover:text-danger transition-colors disabled:opacity-40 disabled:cursor-not-allowed", children: t("pages.controlCenter.profiles.deleteButton") })] })] }), isDeleteTarget && (_jsx("div", { className: "px-[16px] pb-[12px]", children: _jsxs("div", { className: "px-[12px] py-[10px] border border-danger rounded-[4px] bg-danger/10 text-[12px] text-ink-2 leading-[1.55]", children: [_jsx("div", { className: "font-medium", children: t("pages.controlCenter.profiles.deleteConfirmMessage", {
229
229
  id: p.id,
230
- }) }), isDefault && (_jsx("div", { className: "mt-1 text-ink-3", children: t("pages.controlCenter.profiles.sectionDescription") })), deleteError !== null && (_jsx("div", { className: "mt-2 font-mono text-[11.5px] text-red", children: deleteError })), _jsxs("div", { className: "mt-2 flex gap-[8px]", children: [_jsx("button", { type: "button", onClick: handleDeleteConfirm, disabled: deleting, className: "text-[11.5px] px-[12px] py-[4px] rounded-[3px] border border-transparent bg-danger text-paper font-medium hover:opacity-90 transition-opacity disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: deleting
230
+ }) }), isDefault && (_jsx("div", { className: "mt-1 text-ink-3", children: t("pages.controlCenter.profiles.sectionDescription") })), deleteError !== null && (_jsx("div", { className: "mt-2 font-mono text-[11.5px] text-danger", children: deleteError })), _jsxs("div", { className: "mt-2 flex gap-[8px]", children: [_jsx("button", { type: "button", onClick: handleDeleteConfirm, disabled: deleting, className: "text-[11.5px] px-[12px] py-[4px] rounded-[3px] border border-transparent bg-danger text-paper font-medium hover:opacity-90 transition-opacity disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: deleting
231
231
  ? t("pages.controlCenter.profiles.deleting")
232
232
  : t("pages.controlCenter.profiles.deleteConfirmAck") }), _jsx("button", { type: "button", onClick: handleDeleteCancel, disabled: deleting, className: "text-[11.5px] px-[12px] py-[4px] rounded-[3px] border border-line bg-transparent text-ink-3 hover:border-line-2 transition-colors disabled:opacity-50", children: t("pages.controlCenter.profiles.deleteConfirmCancel") })] })] }) }))] }, p.id));
233
233
  })] }))] }));
@@ -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 () => {