create-principles-disciple 1.145.12 → 1.145.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_release/product-identity.json +2 -2
- package/codex-adapter/package.json +1 -1
- package/console/dist/server/models/ActivationsConsoleModel.d.ts +3 -1
- package/console/dist/server/models/ActivationsConsoleModel.js +38 -4
- package/console/dist/server/models/ApprovalsConsoleModel.js +56 -7
- package/console/dist/server/models/ApprovalsGroupedConsoleModel.d.ts +12 -0
- package/console/dist/server/models/ApprovalsGroupedConsoleModel.js +70 -13
- package/console/dist/server/routes/approvals-grouped.js +5 -2
- package/console/dist/shared/prompt-injection-contract.d.ts +58 -5
- package/console/dist/ui/i18n/en.json +25 -1
- package/console/dist/ui/i18n/zh-CN.json +25 -1
- package/console/dist/ui/pages/activation/ActivationPage.js +39 -1
- package/console/dist/ui/pages/focus/FocusPage.js +70 -28
- package/console/dist/ui/utils/validators.js +70 -11
- package/console/dist/web/assets/app.js +24 -24
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.d.ts +16 -2
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.js +88 -4
- package/core/dist/runtime-v2/internalization/artificer-intent-preflight.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.js +21 -2
- package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/core/package.json +1 -1
- package/dist/installers/codex-host-installer.d.ts +1 -1
- package/dist/installers/codex-host-installer.js +3 -3
- package/dist/installers/codex-host-installer.js.map +1 -1
- package/dist/installers/workbuddy-host-installer.js +1 -1
- package/dist/installers/workbuddy-host-installer.js.map +1 -1
- package/host-runtime/dist/governance-signal-admission.d.ts +16 -2
- package/host-runtime/dist/governance-signal-admission.js +27 -7
- package/host-runtime/dist/index.d.ts +1 -0
- package/host-runtime/dist/index.js +4 -0
- package/host-runtime/dist/prompt-injection-budget-observation.d.ts +176 -0
- package/host-runtime/dist/prompt-injection-budget-observation.js +449 -0
- package/host-runtime/dist/prompt-injection-projection.d.ts +16 -0
- package/host-runtime/dist/prompt-injection-projection.js +18 -3
- package/host-runtime/dist/prompt-injection-status.d.ts +28 -1
- package/host-runtime/dist/prompt-injection-status.js +21 -7
- package/host-runtime/package.json +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/codex-setup.js +1 -1
- package/pd-cli/dist/commands/config-doctor.d.ts.map +1 -1
- package/pd-cli/dist/commands/config-doctor.js +5 -1
- package/pd-cli/dist/commands/config-doctor.js.map +1 -1
- package/pd-cli/dist/commands/health-codex-install.d.ts +6 -6
- package/pd-cli/dist/commands/health-codex-install.d.ts.map +1 -1
- package/pd-cli/dist/commands/health-codex-install.js +7 -7
- package/pd-cli/dist/commands/health-codex-install.js.map +1 -1
- package/pd-cli/dist/commands/health-codex.js +1 -1
- package/pd-cli/dist/commands/health-codex.js.map +1 -1
- package/pd-cli/dist/commands/run.d.ts +2 -0
- package/pd-cli/dist/commands/run.d.ts.map +1 -1
- package/pd-cli/dist/commands/run.js +9 -4
- package/pd-cli/dist/commands/run.js.map +1 -1
- package/pd-cli/dist/commands/runtime-activation.d.ts +3 -1
- package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-activation.js +5 -3
- package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
- package/pd-cli/dist/index.js +6 -4
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/dist/services/config-doctor.d.ts +4 -0
- package/pd-cli/dist/services/config-doctor.d.ts.map +1 -1
- package/pd-cli/dist/services/config-doctor.js +15 -0
- package/pd-cli/dist/services/config-doctor.js.map +1 -1
- package/pd-cli/package.json +1 -1
- package/plugin/dist/bundle.js +391 -391
- package/plugin/dist/core/signal-collector-host.d.ts +17 -1
- package/plugin/dist/core/signal-health.d.ts +15 -0
- package/plugin/dist/openclaw.plugin.json +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-cli-operator/SKILL.md +32 -70
- package/plugin/dist/templates/langs/en/skills/pd-control/SKILL.md +50 -0
- package/plugin/dist/templates/langs/en/skills/pd-pain-signal/SKILL.md +30 -56
- package/plugin/dist/templates/langs/en/skills/pd-review/SKILL.md +32 -0
- package/plugin/dist/templates/langs/zh/skills/pd-cli-operator/SKILL.md +32 -65
- package/plugin/dist/templates/langs/zh/skills/pd-control/SKILL.md +50 -0
- package/plugin/dist/templates/langs/zh/skills/pd-pain-signal/SKILL.md +29 -48
- package/plugin/dist/templates/langs/zh/skills/pd-review/SKILL.md +32 -0
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/plugin/templates/langs/en/skills/pd-cli-operator/SKILL.md +32 -70
- package/plugin/templates/langs/en/skills/pd-control/SKILL.md +50 -0
- package/plugin/templates/langs/en/skills/pd-pain-signal/SKILL.md +30 -56
- package/plugin/templates/langs/en/skills/pd-review/SKILL.md +32 -0
- package/plugin/templates/langs/zh/skills/pd-cli-operator/SKILL.md +32 -65
- package/plugin/templates/langs/zh/skills/pd-control/SKILL.md +50 -0
- package/plugin/templates/langs/zh/skills/pd-pain-signal/SKILL.md +29 -48
- package/plugin/templates/langs/zh/skills/pd-review/SKILL.md +32 -0
- package/release-manager/dist/installers/codex-host-installer.d.ts +1 -1
- package/release-manager/dist/installers/codex-host-installer.js +3 -3
- package/release-manager/dist/installers/codex-host-installer.js.map +1 -1
- package/release-manager/dist/installers/workbuddy-host-installer.js +1 -1
- package/release-manager/dist/installers/workbuddy-host-installer.js.map +1 -1
- package/release-manager/package.json +2 -2
- package/workbuddy-adapter/dist/explicit-owner-statement.js +9 -2
- package/workbuddy-adapter/dist/pd-hook.js +5 -2
- package/workbuddy-adapter/package.json +1 -1
- package/workbuddy-adapter/plugin/skills/pd-cli-operator/SKILL.md +32 -0
- package/workbuddy-adapter/plugin/skills/pd-control/SKILL.md +31 -0
- package/workbuddy-adapter/plugin/skills/pd-pain-signal/SKILL.md +35 -0
- package/workbuddy-adapter/plugin/skills/pd-review/SKILL.md +22 -8
- package/plugin/dist/templates/langs/en/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/dist/templates/langs/en/skills/pd-mentor/SKILL.md +0 -185
- package/plugin/dist/templates/langs/en/skills/pd-runtime-v2/SKILL.md +0 -86
- package/plugin/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +0 -185
- package/plugin/dist/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +0 -81
- package/plugin/templates/langs/en/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/templates/langs/en/skills/pd-mentor/SKILL.md +0 -185
- package/plugin/templates/langs/en/skills/pd-runtime-v2/SKILL.md +0 -86
- package/plugin/templates/langs/zh/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/templates/langs/zh/skills/pd-mentor/SKILL.md +0 -185
- package/plugin/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +0 -81
- package/workbuddy-adapter/plugin/skills/pd-disable/SKILL.md +0 -18
- package/workbuddy-adapter/plugin/skills/pd-record-pain/SKILL.md +0 -21
- package/workbuddy-adapter/plugin/skills/pd-status/SKILL.md +0 -17
|
@@ -399,7 +399,45 @@ export function ActivationPage() {
|
|
|
399
399
|
const ordinaryActive = activeActivations.filter(record => !pendingRuleCode.includes(record) && !safetyAlerts.includes(record));
|
|
400
400
|
const inactiveActivations = activations.filter((a) => a.status === "inactive");
|
|
401
401
|
const neverActivatedCount = activations.filter((a) => a.activatedAt === null).length;
|
|
402
|
-
return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.activation.eyebrow") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: activeActivations.length === 0, children: t("pages.activation.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.activation.subtitle") }), _jsxs("div", { className: "text-sm leading-relaxed text-ink-2 mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", role: "status", "aria-live": "polite", children: [_jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: activeActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryActive") }), " ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: inactiveActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryInactive") }), neverActivatedCount > 0 && (_jsxs(_Fragment, { children: [" ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-amber tabular-nums", children: neverActivatedCount }), " ", _jsx("span", { className: "text-amber", children: t("pages.activation.summaryNeverActivated") })] }))] }), _jsx(CapabilityBoundaryDeclaration, {}), activeActivations.some(record => record.action === 'code_tool_hook_live_activate') && _jsx("div", { className: "mt-4 flex justify-end", children: _jsx(Button, { variant: "destructive", onClick: () => void handleEmergencyPause(), children: t('pages.activation.pauseAll') }) }), degradedNote && (_jsx("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", children: degradedNote })), receiptDegraded && (_jsxs("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", "data-testid": "receipt-counts-degraded", children: [receiptCoverage !== null && (_jsx("span", { className: "block font-medium text-ink-3", children: t(getReceiptSourceStatusLabelKey(receiptCoverage.sourceStatus)) })), t("pages.activation.receiptsUnavailable", { reason: receiptDegraded.reason }), receiptDegraded.nextAction && (_jsx("span", { className: "mt-1 block font-mono text-[12px]", children: receiptDegraded.nextAction }))] })), receiptCounts !== null && receiptCoverage !== null && (_jsx("div", { className: "mt-4 bg-surface/60 border-l-2 border-line px-3 py-2", "data-testid": "receipt-counts-coverage", children: _jsx(ReceiptCoverageDisclosure, { coverage: receiptCoverage }) })), pendingRuleCode.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-pending-rulecode", children: [_jsx(SectionTitle, { id: "section-pending-rulecode", children: t('pages.activation.pendingRules') }), _jsx("p", { className: "mb-3 text-[12px] text-ink-3", children: t('pages.activation.pendingRulesDescription') }), _jsx("div", { className: "space-y-[14px]", children: pendingRuleCode.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), safetyAlerts.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-safety-alerts", children: [_jsx(SectionTitle, { id: "section-safety-alerts", children: t('pages.activation.safetyAlerts') }), _jsx("p", { className: "mb-3 text-[12px] text-danger", children: t('pages.activation.safetyAlertsDescription') }), _jsx("div", { className: "space-y-[14px]", children: safetyAlerts.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), _jsxs("section", { className: "mt-8", "aria-labelledby": "section-active", children: [_jsx(SectionTitle, { id: "section-active", children: t("pages.activation.sectionActive") }),
|
|
402
|
+
return (_jsx(PageShell, { children: _jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.activation.eyebrow") }), _jsx(ShinyText, { as: "h1", className: "text-[29px] font-semibold tracking-tight text-ink mb-2", duration: 4.5, brightness: 0.5, disabled: activeActivations.length === 0, children: t("pages.activation.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.activation.subtitle") }), _jsxs("div", { className: "text-sm leading-relaxed text-ink-2 mb-7 px-[18px] py-[14px] bg-panel border border-line rounded-[6px]", role: "status", "aria-live": "polite", children: [_jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: activeActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryActive") }), " ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-ink tabular-nums", children: inactiveActivations.length }), " ", _jsx("span", { className: "text-ink-3", children: t("pages.activation.summaryInactive") }), neverActivatedCount > 0 && (_jsxs(_Fragment, { children: [" ", "/", " ", _jsx("span", { className: "font-mono font-semibold text-amber tabular-nums", children: neverActivatedCount }), " ", _jsx("span", { className: "text-amber", children: t("pages.activation.summaryNeverActivated") })] }))] }), _jsx(CapabilityBoundaryDeclaration, {}), activeActivations.some(record => record.action === 'code_tool_hook_live_activate') && _jsx("div", { className: "mt-4 flex justify-end", children: _jsx(Button, { variant: "destructive", onClick: () => void handleEmergencyPause(), children: t('pages.activation.pauseAll') }) }), degradedNote && (_jsx("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", children: degradedNote })), receiptDegraded && (_jsxs("div", { className: "mt-4 text-ink-4 text-[13px] bg-surface/60 border-l-2 border-amber px-3 py-2", "data-testid": "receipt-counts-degraded", children: [receiptCoverage !== null && (_jsx("span", { className: "block font-medium text-ink-3", children: t(getReceiptSourceStatusLabelKey(receiptCoverage.sourceStatus)) })), t("pages.activation.receiptsUnavailable", { reason: receiptDegraded.reason }), receiptDegraded.nextAction && (_jsx("span", { className: "mt-1 block font-mono text-[12px]", children: receiptDegraded.nextAction }))] })), receiptCounts !== null && receiptCoverage !== null && (_jsx("div", { className: "mt-4 bg-surface/60 border-l-2 border-line px-3 py-2", "data-testid": "receipt-counts-coverage", children: _jsx(ReceiptCoverageDisclosure, { coverage: receiptCoverage }) })), pendingRuleCode.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-pending-rulecode", children: [_jsx(SectionTitle, { id: "section-pending-rulecode", children: t('pages.activation.pendingRules') }), _jsx("p", { className: "mb-3 text-[12px] text-ink-3", children: t('pages.activation.pendingRulesDescription') }), _jsx("div", { className: "space-y-[14px]", children: pendingRuleCode.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), safetyAlerts.length > 0 && _jsxs("section", { className: "mt-8", "aria-labelledby": "section-safety-alerts", children: [_jsx(SectionTitle, { id: "section-safety-alerts", children: t('pages.activation.safetyAlerts') }), _jsx("p", { className: "mb-3 text-[12px] text-danger", children: t('pages.activation.safetyAlertsDescription') }), _jsx("div", { className: "space-y-[14px]", children: safetyAlerts.map(record => _jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId)) })] }), _jsxs("section", { className: "mt-8", "aria-labelledby": "section-active", children: [_jsx(SectionTitle, { id: "section-active", children: t("pages.activation.sectionActive") }), (() => {
|
|
403
|
+
const route = activationsData?.promptInjectionRoute;
|
|
404
|
+
if (route?.status !== "confirmed")
|
|
405
|
+
return null;
|
|
406
|
+
// The "observed" copy names a source + window. Only a CONFIRMED
|
|
407
|
+
// observation carries those facts; a usable observation can itself
|
|
408
|
+
// be the runtime's fallback (no trusted host capacity), and showing
|
|
409
|
+
// window=0 with a host-window label would be a fabricated claim.
|
|
410
|
+
if (route.budgetCapacityStatus === "confirmed"
|
|
411
|
+
&& route.budgetObservedAt !== undefined
|
|
412
|
+
&& route.budgetContextWindowTokens !== undefined) {
|
|
413
|
+
return (_jsx("p", { className: "mb-3 text-[12px] text-ink-3", "data-testid": "activation-budget-observed-note", children: t("pages.activation.budgetObservedNote", {
|
|
414
|
+
defaultValue: "注入状态中的预算数字取自最近一次运行时观测(来源 {{source}},上下文 {{window}} tokens,观测于 {{observedAt}}),并非实时确认值。",
|
|
415
|
+
source: route.budgetCapacitySource === "pi_catalog_exact"
|
|
416
|
+
? t("pages.focus.budgetCapacitySourcePiCatalog", { defaultValue: "模型目录精确匹配" })
|
|
417
|
+
: t("pages.focus.budgetCapacitySourceHostWindow", { defaultValue: "宿主有效上下文窗口" }),
|
|
418
|
+
window: route.budgetContextWindowTokens,
|
|
419
|
+
observedAt: route.budgetObservedAt,
|
|
420
|
+
}) }));
|
|
421
|
+
}
|
|
422
|
+
if (route.budgetCapacityStatus === "unknown" && route.budgetFallbackReason !== undefined) {
|
|
423
|
+
const observedSuffix = route.budgetObservedAt !== undefined
|
|
424
|
+
// The runtime's own most recent injection ALSO fell back — the
|
|
425
|
+
// reason is that observation's, not a console-only guess.
|
|
426
|
+
? t("pages.focus.promptBudgetFallbackObservedSuffix", {
|
|
427
|
+
defaultValue: ";运行时最近一次观测于 {{observedAt}}",
|
|
428
|
+
observedAt: route.budgetObservedAt,
|
|
429
|
+
})
|
|
430
|
+
: "";
|
|
431
|
+
return (_jsx("p", { className: "mb-3 text-[12px] text-ink-3", "data-testid": "activation-budget-fallback-note", children: t("pages.activation.budgetFallbackNote", {
|
|
432
|
+
defaultValue: "注入状态按固定回退预算估算({{reason}}{{observed}})。",
|
|
433
|
+
reason: t(`pages.focus.budgetFallbackReason.${route.budgetFallbackReason}`, {
|
|
434
|
+
defaultValue: route.budgetFallbackReason,
|
|
435
|
+
}),
|
|
436
|
+
observed: observedSuffix,
|
|
437
|
+
}) }));
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
})(), ordinaryActive.length > 0 ? (_jsx("div", { className: "space-y-[14px]", children: ordinaryActive.map((record) => (_jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: receiptCounts !== null && !receiptCountsUntrustworthy ? (Object.hasOwn(receiptCounts, record.principleId) ? receiptCounts[record.principleId] : null) : undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.activation.emptyActive") }))] }), inactiveActivations.length > 0 && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-inactive", children: [_jsx(SectionTitle, { id: "section-inactive", children: t("pages.activation.sectionInactive") }), _jsx("div", { className: "space-y-[14px]", children: inactiveActivations.map((record) => (_jsx(ActivationFactCard, { record: record, lifecycleData: lifecycleCache[record.principleId], receiptCount: receiptCounts !== null && !receiptCountsUntrustworthy ? (Object.hasOwn(receiptCounts, record.principleId) ? receiptCounts[record.principleId] : null) : undefined, onDisable: handleDisable, disabling: disablingIds.has(record.activationId), onChanged: () => void loadData() }, record.activationId))) })] })), neverActivatedCount > 0 && (_jsxs("section", { className: "mt-8", "aria-labelledby": "section-never-activated", children: [_jsx(SectionTitle, { id: "section-never-activated", children: t("pages.activation.sectionNeverActivated") }), _jsx("div", { className: "space-y-[10px]", children: activations
|
|
403
441
|
.filter((a) => a.activatedAt === null)
|
|
404
442
|
.map((record) => (_jsxs("article", { className: "relative pl-[22px] py-[14px] pr-[18px] bg-panel border border-amber/20 border-l-[3px] border-l-amber rounded-[6px]", children: [_jsxs("div", { className: "text-ink-2 text-sm leading-relaxed", children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.activation.neverActivatedCard") }), " ", "\u2014 ", record.action, " \u00B7 ", getChannelLabel(record.channel, t), _jsx("span", { className: "ml-2 font-mono text-[11px] text-ink-4", children: record.principleId })] }), _jsxs(Link, { to: "/debt", className: "inline-flex items-center mt-2 text-gov text-[13px] hover:underline focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: [t("pages.activation.viewDebt"), " \u2192"] })] }, record.activationId))) })] })), _jsx("footer", { className: "mt-12 pt-6 border-t border-line text-ink-3 text-[13px]", children: t("pages.activation.footer") })] }) }));
|
|
405
443
|
}
|
|
@@ -402,7 +402,7 @@ function PendingReviewCard({ group, actionsLockedReason, onDecisionApplied, prom
|
|
|
402
402
|
? "border-green/40 bg-green/10 text-green"
|
|
403
403
|
: "border-line bg-surface/80 text-ink-3"}`, role: "status", "data-testid": `decided-banner-${group.principleId}`, children: decidedOutcome === "approved"
|
|
404
404
|
? t("pages.focus.decidedApproved", { defaultValue: "已批准 ✓ 正在写入生效记录…" })
|
|
405
|
-
: t("pages.focus.decidedRejected", { defaultValue: "已拒绝" }) })), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", 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: channelLabel }), isReversible && (_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: primaryChannel === "prompt" ? t("pages.focus.tagReversible") : t("pages.focus.tagLowRisk") }))] }), _jsx("div", { className: "mt-[14px] mb-2 font-semibold text-ink leading-snug", "data-testid": `candidate-title-${group.principleId}`, children: readingLayout.title }), readingLayout.body !== null && (_jsx("div", { className: "mb-2 text-[15px] leading-relaxed text-ink whitespace-pre-wrap break-words", "data-testid": `candidate-body-${group.principleId}`, children: readingLayout.body })), group.artifactUnavailable === true && (_jsx("div", { className: "mb-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `artifact-unavailable-${group.principleId}`, children: t("pages.focus.artifactUnavailableNote") })), unlinkedCandidateNote && (_jsx("div", { className: "mb-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `unlinked-candidate-${group.principleId}`, children: t("pages.focus.unlinkedCandidateNote") })), _jsx("div", { className: "mt-2 px-3 py-2 bg-surface/60 border-l-2 border-gov text-ink-3 text-[13px] leading-snug", children: t("pages.focus.evidenceSummary", { count: group.records.length }) }), actionsLocked && (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", "data-testid": `pending-actions-locked-${group.principleId}`, children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: actionsLockedReason }), _jsx(Link, { to: "/settings", "data-testid": `pending-actions-locked-settings-${group.principleId}`, className: "mt-2 inline-flex items-center border border-line text-ink bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.ownerDecision.goSettingsCta") })] })), decidedOutcome === null && primaryChannel === "prompt" && promptInjection?.truncated === true && (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 px-3 py-2 text-[12.5px] text-amber", "data-testid": `approve-queue-badge-${group.principleId}`, children: [promptInjection.productionRotates === true && group.fitsPromptBudget === true && group.promptBudgetTierFit === "model_dependent"
|
|
405
|
+
: t("pages.focus.decidedRejected", { defaultValue: "已拒绝" }) })), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", 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: channelLabel }), isReversible && (_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: primaryChannel === "prompt" ? t("pages.focus.tagReversible") : t("pages.focus.tagLowRisk") }))] }), _jsx("div", { className: "mt-[14px] mb-2 font-semibold text-ink leading-snug", "data-testid": `candidate-title-${group.principleId}`, children: readingLayout.title }), readingLayout.body !== null && (_jsx("div", { className: "mb-2 text-[15px] leading-relaxed text-ink whitespace-pre-wrap break-words", "data-testid": `candidate-body-${group.principleId}`, children: readingLayout.body })), group.artifactUnavailable === true && (_jsx("div", { className: "mb-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `artifact-unavailable-${group.principleId}`, children: t("pages.focus.artifactUnavailableNote") })), unlinkedCandidateNote && (_jsx("div", { className: "mb-2 text-[12.5px] leading-relaxed text-amber", "data-testid": `unlinked-candidate-${group.principleId}`, children: t("pages.focus.unlinkedCandidateNote") })), _jsx("div", { className: "mt-2 px-3 py-2 bg-surface/60 border-l-2 border-gov text-ink-3 text-[13px] leading-snug", children: t("pages.focus.evidenceSummary", { count: group.records.length }) }), actionsLocked && (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", "data-testid": `pending-actions-locked-${group.principleId}`, children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: actionsLockedReason }), _jsx(Link, { to: "/settings", "data-testid": `pending-actions-locked-settings-${group.principleId}`, className: "mt-2 inline-flex items-center border border-line text-ink bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.ownerDecision.goSettingsCta") })] })), decidedOutcome === null && primaryChannel === "prompt" && promptInjection?.truncated === true && promptInjection.capacityStatus !== "unconfirmed" && (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 px-3 py-2 text-[12.5px] text-amber", "data-testid": `approve-queue-badge-${group.principleId}`, children: [promptInjection.productionRotates === true && group.fitsPromptBudget === true && group.promptBudgetTierFit === "model_dependent"
|
|
406
406
|
? t("pages.focus.approveQueueBadgeRotationModelDependent", {
|
|
407
407
|
defaultValue: "批准后可能排队:提示词注入位已满({{used}}/{{budget}} 字符)。这条原则的篇幅在较小上下文模型的注入预算内装不下,轮到它时也未必进入提示词——是否生效取决于当时模型的上限。",
|
|
408
408
|
used: promptInjection.usedChars,
|
|
@@ -430,25 +430,56 @@ function PendingReviewCard({ group, actionsLockedReason, onDecisionApplied, prom
|
|
|
430
430
|
full: promptInjection.fullRenderChars !== undefined
|
|
431
431
|
? t("pages.focus.promptScopeFullRender", { count: promptInjection.fullRenderChars })
|
|
432
432
|
: "",
|
|
433
|
-
}), promptInjection.hostKind !== undefined ? ` · ${promptInjection.hostKind === "openclaw" ? "OpenClaw" : promptInjection.hostKind === "workbuddy" ? "WorkBuddy" : "Codex"}` : "", ` · ${
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
433
|
+
}), promptInjection.hostKind !== undefined ? ` · ${promptInjection.hostKind === "openclaw" ? "OpenClaw" : promptInjection.hostKind === "workbuddy" ? "WorkBuddy" : "Codex"}` : "", ` · ${
|
|
434
|
+
// A "confirmed" claim is only renderable when the window is
|
|
435
|
+
// present: a payload missing it must not print "0 tokens".
|
|
436
|
+
promptInjection.budgetCapacityStatus === "confirmed" && promptInjection.budgetContextWindowTokens !== undefined
|
|
437
|
+
? promptInjection.budgetObservedAt !== undefined
|
|
438
|
+
// PRI-1017: the budget comes from the workspace's most
|
|
439
|
+
// recent RUNTIME OBSERVATION (the last real injection) —
|
|
440
|
+
// say so, with source + window + observation time. Never
|
|
441
|
+
// present a past observation as a live confirmation.
|
|
442
|
+
? t("pages.focus.promptBudgetObservedNote", {
|
|
443
|
+
defaultValue: "预算取自最近一次运行时观测(来源 {{source}},上下文 {{window}} tokens,观测于 {{observedAt}})",
|
|
444
|
+
source: promptInjection.budgetCapacitySource === "pi_catalog_exact"
|
|
445
|
+
? t("pages.focus.budgetCapacitySourcePiCatalog", { defaultValue: "模型目录精确匹配" })
|
|
446
|
+
: t("pages.focus.budgetCapacitySourceHostWindow", { defaultValue: "宿主有效上下文窗口" }),
|
|
447
|
+
window: promptInjection.budgetContextWindowTokens,
|
|
448
|
+
observedAt: promptInjection.budgetObservedAt,
|
|
449
|
+
})
|
|
450
|
+
: t("pages.focus.promptBudgetModelAwareNote", {
|
|
451
|
+
defaultValue: "预算按已确认的模型上下文解析({{window}} tokens)",
|
|
452
|
+
window: promptInjection.budgetContextWindowTokens,
|
|
453
|
+
})
|
|
454
|
+
: promptInjection.budgetObservedAt !== undefined
|
|
455
|
+
// PRI-1017: a fallback that still carries an observation
|
|
456
|
+
// timestamp IS the runtime's own honest fallback (the last
|
|
457
|
+
// injection resolved 2000 with a reason). Saying "console
|
|
458
|
+
// not bound to the runtime model" here would be false — the
|
|
459
|
+
// console DID use the runtime's last observation.
|
|
460
|
+
? t("pages.focus.promptBudgetFallbackObservedNote", {
|
|
461
|
+
defaultValue: "运行时最近一次观测未确认宿主容量,预算按固定回退估算({{reason}},观测于 {{observedAt}})",
|
|
462
|
+
reason: promptInjection.budgetFallbackReason !== undefined
|
|
463
|
+
? t(`pages.focus.budgetFallbackReason.${promptInjection.budgetFallbackReason}`, {
|
|
447
464
|
defaultValue: promptInjection.budgetFallbackReason,
|
|
448
|
-
})
|
|
449
|
-
|
|
450
|
-
:
|
|
451
|
-
|
|
465
|
+
})
|
|
466
|
+
: "unknown",
|
|
467
|
+
observedAt: promptInjection.budgetObservedAt,
|
|
468
|
+
})
|
|
469
|
+
: t("pages.focus.promptBudgetFallbackNote", {
|
|
470
|
+
defaultValue: "按固定回退预算估算(控制台未绑定运行时模型{{reason}})",
|
|
471
|
+
reason: promptInjection.budgetFallbackReason !== undefined
|
|
472
|
+
? t("pages.focus.promptBudgetFallbackReasonSuffix", {
|
|
473
|
+
defaultValue: ",原因: {{code}}",
|
|
474
|
+
// The raw bounded code stays the default: it is the
|
|
475
|
+
// grep-able identifier shared with events/logs. Locales
|
|
476
|
+
// may override via pages.focus.budgetFallbackReason.<code>.
|
|
477
|
+
code: t(`pages.focus.budgetFallbackReason.${promptInjection.budgetFallbackReason}`, {
|
|
478
|
+
defaultValue: promptInjection.budgetFallbackReason,
|
|
479
|
+
}),
|
|
480
|
+
})
|
|
481
|
+
: "",
|
|
482
|
+
})}`] })] })), group.revisionReviewUnavailable === true && _jsx("p", { role: "alert", className: "mt-3 text-danger", children: t("pages.focus.revisionReviewUnavailable") }), group.revisionReview !== undefined && (_jsxs("div", { className: "mt-3 border border-line p-3 text-[12.5px]", "data-testid": `revision-intent-review-${group.principleId}`, children: [_jsx("p", { children: t("pages.focus.revisionIntentReview", { defaultValue: "修订复核:确认新正文保留触发条件、行动要求和必要例外,并与沿用意图一致。" }) }), _jsx("pre", { className: "mt-2 max-h-32 overflow-auto whitespace-pre-wrap", children: group.revisionReview.oldStatement }), _jsx("pre", { className: "mt-2 max-h-32 overflow-auto whitespace-pre-wrap", children: group.revisionReview.newStatement }), _jsx("dl", { className: "mt-2", children: Object.entries(group.revisionReview.intentFields).map(([key, value]) => _jsxs("div", { children: [_jsx("dt", { children: t(`pages.focus.intentField.${key}`, { defaultValue: key }) }), _jsx("dd", { children: value })] }, key)) }), _jsxs("label", { className: "mt-2 flex gap-2", children: [_jsx("input", { type: "checkbox", checked: intentReviewed, onChange: (event) => setIntentReviewed(event.target.checked) }), t("pages.focus.revisionIntentConfirmed", { defaultValue: "我已核对上述意图与新正文一致" })] })] })), _jsxs("div", { className: "flex gap-2 mt-4 flex-wrap items-center", children: [_jsx("button", { type: "button", onClick: handleApprove, disabled: decisionDisabled || (group.revisionReviewUnavailable === true || (group.revisionReview !== undefined && !intentReviewed)), "data-testid": `approve-btn-${group.principleId}`, className: "inline-flex items-center 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 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: actionLoading ? t("common.loading") + "…" : t("pages.focus.approveAction", { defaultValue: "批准" }) }), _jsx("button", { type: "button", onClick: () => { setShowEditInput((v) => !v); setShowRejectInput(false); }, disabled: decisionDisabled, "data-testid": `edit-btn-${group.principleId}`, className: "inline-flex items-center border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("pages.focus.editAction", { defaultValue: "替换待审版本" }) }), _jsx("button", { type: "button", onClick: () => { setShowRejectInput((v) => !v); setShowEditInput(false); }, disabled: decisionDisabled, "data-testid": `reject-btn-${group.principleId}`, className: "inline-flex items-center border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("pages.focus.rejectAction", { defaultValue: "拒绝" }) }), _jsx(Link, { to: "/pain", className: "inline-flex items-center text-gov text-[12.5px] hover:underline focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: t("pages.focus.viewFullChain") })] }), showRejectInput && (_jsxs("div", { className: "mt-3 p-3 border border-danger/20 rounded-[var(--radius-md)]", children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("pages.focus.rejectReasonLabel", { defaultValue: "拒绝原因(必填)" }) }), _jsx("textarea", { value: rejectReason, onChange: (e) => setRejectReason(e.target.value), "data-testid": `reject-reason-${group.principleId}`, placeholder: t("pages.focus.rejectReasonPlaceholder", { defaultValue: "请说明拒绝原因" }), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[80px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov" }), _jsxs("div", { className: "flex gap-2 mt-2", children: [_jsx("button", { type: "button", onClick: handleReject, disabled: !rejectReason.trim() || actionLoading, "data-testid": `confirm-reject-${group.principleId}`, className: "inline-flex items-center border border-danger text-danger bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-danger/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: t("pages.focus.confirmReject", { defaultValue: "确认拒绝" }) }), _jsx("button", { type: "button", onClick: () => { setShowRejectInput(false); setRejectReason(""); }, className: "inline-flex items-center border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.cancelAction", { defaultValue: "取消" }) })] })] })), showEditInput && (_jsxs("div", { className: "mt-3 p-3 border border-gov/20 rounded-[var(--radius-md)]", children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("pages.focus.editReasonLabel", { defaultValue: "替换原因(必填)" }) }), _jsxs("div", { className: "mb-2 text-ink-4 text-[12px] font-mono", children: [t("pages.focus.currentArtifactLabel", { defaultValue: "当前工件" }), ": ", currentArtifactId] }), _jsx("input", { type: "text", value: newArtifactId, onChange: (e) => setNewArtifactId(e.target.value), "data-testid": `edit-new-artifact-${group.principleId}`, placeholder: t("pages.focus.editNewArtifactPlaceholder", { defaultValue: "输入新的已验证工件 ID" }), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] mb-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov", "aria-label": t("pages.focus.editNewArtifactPlaceholder", { defaultValue: "输入新的已验证工件 ID" }) }), _jsx("textarea", { value: editReason, onChange: (e) => setEditReason(e.target.value), "data-testid": `edit-reason-${group.principleId}`, placeholder: t("pages.focus.editReasonPlaceholder", { defaultValue: "请说明为什么需要替换这份待审版本" }), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[80px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov" }), _jsxs("div", { className: "flex gap-2 mt-2", children: [_jsx("button", { type: "button", onClick: handleEdit, disabled: !editReason.trim() || !newArtifactId.trim() || actionLoading, "data-testid": `confirm-edit-${group.principleId}`, className: "inline-flex items-center border border-gov text-gov bg-surface rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: t("pages.focus.confirmEdit", { defaultValue: "确认替换" }) }), _jsx("button", { type: "button", onClick: () => { setShowEditInput(false); setEditReason(""); setNewArtifactId(""); }, className: "inline-flex items-center border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors", children: t("pages.focus.cancelAction", { defaultValue: "取消" }) })] })] }))] }));
|
|
452
483
|
}
|
|
453
484
|
function StagnationSignalCard({ signal }) {
|
|
454
485
|
const { t } = useTranslation();
|
|
@@ -775,15 +806,26 @@ export function FocusPage({ featureFlags }) {
|
|
|
775
806
|
return null;
|
|
776
807
|
return (_jsxs("div", { className: "mb-4 rounded-[3px] border border-amber/40 bg-amber/5 px-3 py-2 text-[12.5px] leading-relaxed text-amber", "data-testid": "prompt-capacity-unconfirmed-banner", children: [_jsx("p", { children: t("pages.focus.promptCapacityUnconfirmed", {
|
|
777
808
|
defaultValue: "当前宿主容量未确认:本工作区适用的宿主会走不同的注入路由,以下数字未绑定具体宿主。",
|
|
778
|
-
}) }), _jsx("ul", { className: "mt-1 list-disc pl-5", children: (unconfirmed.perHost ?? []).map((entry) => (
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
809
|
+
}) }), _jsx("ul", { className: "mt-1 list-disc pl-5", children: (unconfirmed.perHost ?? []).map((entry) => (_jsxs("li", { "data-testid": `prompt-capacity-perhost-${entry.hostKind}`, children: [t("pages.focus.promptCapacityPerHostEntry", {
|
|
810
|
+
host: entry.hostKind === "openclaw" ? "OpenClaw" : entry.hostKind === "workbuddy" ? "WorkBuddy" : "Codex",
|
|
811
|
+
billing: entry.route === "shared_render"
|
|
812
|
+
? t("pages.focus.promptCapacitySharedRoute")
|
|
813
|
+
: t("pages.focus.promptCapacityListRoute"),
|
|
814
|
+
used: entry.usedChars,
|
|
815
|
+
// PRI-1017: each host shows ITS OWN budget basis (runtime
|
|
816
|
+
// observation or its own honest fallback) — never the
|
|
817
|
+
// shared headline number.
|
|
818
|
+
budget: entry.budget ?? unconfirmed.budget,
|
|
819
|
+
full: entry.truncated ? t("pages.focus.promptCapacityPerHostFull") : "",
|
|
820
|
+
observed: entry.budgetObservedAt !== undefined
|
|
821
|
+
? t("pages.focus.promptCapacityPerHostObserved", {
|
|
822
|
+
defaultValue: "(预算来自该宿主最近一次运行时观测,观测于 {{observedAt}})",
|
|
823
|
+
observedAt: entry.budgetObservedAt,
|
|
824
|
+
})
|
|
825
|
+
: "",
|
|
826
|
+
}), entry.budgetFallbackReason !== undefined && (_jsxs("span", { "data-testid": `prompt-capacity-perhost-reason-${entry.hostKind}`, children: [" · ", t(`pages.focus.budgetFallbackReason.${entry.budgetFallbackReason}`, {
|
|
827
|
+
defaultValue: entry.budgetFallbackReason,
|
|
828
|
+
})] }))] }, 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", "workbuddy"].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" : host === "workbuddy" ? "WorkBuddy" : "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: "清除选择" }) }))] })] }));
|
|
787
829
|
})(), 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
|
|
788
830
|
&& inboxRecovery.length === 0
|
|
789
831
|
&& 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"
|
|
@@ -66,6 +66,30 @@ function isGovernanceTimestamp(value) {
|
|
|
66
66
|
function hasOwnFields(value, fields) {
|
|
67
67
|
return fields.every(field => Object.hasOwn(value, field));
|
|
68
68
|
}
|
|
69
|
+
const PROMPT_BUDGET_FALLBACK_REASONS = new Set([
|
|
70
|
+
'host_capacity_absent',
|
|
71
|
+
'host_capacity_source_untrusted',
|
|
72
|
+
'host_capacity_invalid_value',
|
|
73
|
+
'catalog_unavailable',
|
|
74
|
+
'model_identity_absent',
|
|
75
|
+
'catalog_no_exact_match',
|
|
76
|
+
'catalog_no_match_for_model_id',
|
|
77
|
+
'catalog_ambiguous_model_id',
|
|
78
|
+
'catalog_provider_absent',
|
|
79
|
+
'catalog_metadata_invalid',
|
|
80
|
+
// PRI-1017: console-side bounded code — a runtime observation exists but
|
|
81
|
+
// is too old to be presented as the current budget.
|
|
82
|
+
'runtime_budget_observation_stale',
|
|
83
|
+
]);
|
|
84
|
+
function isPromptBudgetFallbackReason(value) {
|
|
85
|
+
return isString(value) && PROMPT_BUDGET_FALLBACK_REASONS.has(value);
|
|
86
|
+
}
|
|
87
|
+
function isPromptBudgetCapacitySource(value) {
|
|
88
|
+
return value === 'host_effective_window' || value === 'pi_catalog_exact' || value === 'legacy_fallback';
|
|
89
|
+
}
|
|
90
|
+
function isPromptBudgetCapacityStatus(value) {
|
|
91
|
+
return value === 'confirmed' || value === 'unknown';
|
|
92
|
+
}
|
|
69
93
|
function isStringEnum(value, allowed) {
|
|
70
94
|
return typeof value === 'string' && allowed.has(value);
|
|
71
95
|
}
|
|
@@ -1163,6 +1187,24 @@ export function validateActivations(v) {
|
|
|
1163
1187
|
summary.nextAction = route.nextAction;
|
|
1164
1188
|
if (Object.hasOwn(route, 'globalReason') && isString(route.globalReason))
|
|
1165
1189
|
summary.globalReason = route.globalReason;
|
|
1190
|
+
// PRI-1017: runtime budget observation timestamp the per-row budget
|
|
1191
|
+
// figures were computed under (additive, drop-on-invalid).
|
|
1192
|
+
if (Object.hasOwn(route, 'budgetObservedAt') && isString(route.budgetObservedAt) && route.budgetObservedAt.length > 0 && Number.isFinite(Date.parse(route.budgetObservedAt))) {
|
|
1193
|
+
summary.budgetObservedAt = route.budgetObservedAt;
|
|
1194
|
+
}
|
|
1195
|
+
if (Object.hasOwn(route, 'budgetCapacitySource') && isPromptBudgetCapacitySource(route.budgetCapacitySource)) {
|
|
1196
|
+
summary.budgetCapacitySource = route.budgetCapacitySource;
|
|
1197
|
+
}
|
|
1198
|
+
if (Object.hasOwn(route, 'budgetCapacityStatus') && isPromptBudgetCapacityStatus(route.budgetCapacityStatus)) {
|
|
1199
|
+
summary.budgetCapacityStatus = route.budgetCapacityStatus;
|
|
1200
|
+
}
|
|
1201
|
+
if (Object.hasOwn(route, 'budgetContextWindowTokens') && typeof route.budgetContextWindowTokens === 'number'
|
|
1202
|
+
&& Number.isInteger(route.budgetContextWindowTokens) && route.budgetContextWindowTokens > 0) {
|
|
1203
|
+
summary.budgetContextWindowTokens = route.budgetContextWindowTokens;
|
|
1204
|
+
}
|
|
1205
|
+
if (Object.hasOwn(route, 'budgetFallbackReason') && isPromptBudgetFallbackReason(route.budgetFallbackReason)) {
|
|
1206
|
+
summary.budgetFallbackReason = route.budgetFallbackReason;
|
|
1207
|
+
}
|
|
1166
1208
|
result.promptInjectionRoute = summary;
|
|
1167
1209
|
}
|
|
1168
1210
|
}
|
|
@@ -1817,25 +1859,23 @@ export function validatePromptInjectionBudgetStatus(v) {
|
|
|
1817
1859
|
// SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §7: budget provenance, additive +
|
|
1818
1860
|
// drop-on-invalid. Absent behaves as the legacy fixed-budget view
|
|
1819
1861
|
// (pre-SPEC server compat).
|
|
1820
|
-
if (Object.hasOwn(v, 'budgetCapacitySource')
|
|
1821
|
-
&& (v.budgetCapacitySource === 'host_effective_window' || v.budgetCapacitySource === 'pi_catalog_exact'
|
|
1822
|
-
|| v.budgetCapacitySource === 'legacy_fallback')) {
|
|
1862
|
+
if (Object.hasOwn(v, 'budgetCapacitySource') && isPromptBudgetCapacitySource(v.budgetCapacitySource)) {
|
|
1823
1863
|
result.budgetCapacitySource = v.budgetCapacitySource;
|
|
1824
1864
|
}
|
|
1825
|
-
if (Object.hasOwn(v, 'budgetFallbackReason')
|
|
1826
|
-
&& (v.budgetFallbackReason === 'host_capacity_absent' || v.budgetFallbackReason === 'host_capacity_source_untrusted'
|
|
1827
|
-
|| v.budgetFallbackReason === 'host_capacity_invalid_value' || v.budgetFallbackReason === 'catalog_unavailable'
|
|
1828
|
-
|| v.budgetFallbackReason === 'model_identity_absent' || v.budgetFallbackReason === 'catalog_no_exact_match'
|
|
1829
|
-
|| v.budgetFallbackReason === 'catalog_no_match_for_model_id' || v.budgetFallbackReason === 'catalog_ambiguous_model_id'
|
|
1830
|
-
|| v.budgetFallbackReason === 'catalog_provider_absent' || v.budgetFallbackReason === 'catalog_metadata_invalid')) {
|
|
1865
|
+
if (Object.hasOwn(v, 'budgetFallbackReason') && isPromptBudgetFallbackReason(v.budgetFallbackReason)) {
|
|
1831
1866
|
result.budgetFallbackReason = v.budgetFallbackReason;
|
|
1832
1867
|
}
|
|
1833
|
-
if (Object.hasOwn(v, 'budgetCapacityStatus') && (v.budgetCapacityStatus
|
|
1868
|
+
if (Object.hasOwn(v, 'budgetCapacityStatus') && isPromptBudgetCapacityStatus(v.budgetCapacityStatus)) {
|
|
1834
1869
|
result.budgetCapacityStatus = v.budgetCapacityStatus;
|
|
1835
1870
|
}
|
|
1836
1871
|
if (Object.hasOwn(v, 'budgetContextWindowTokens') && typeof v.budgetContextWindowTokens === 'number' && Number.isInteger(v.budgetContextWindowTokens) && v.budgetContextWindowTokens > 0) {
|
|
1837
1872
|
result.budgetContextWindowTokens = v.budgetContextWindowTokens;
|
|
1838
1873
|
}
|
|
1874
|
+
// PRI-1017: observation timestamp — a PAST runtime fact, never a live
|
|
1875
|
+
// claim. Present-but-invalid drops (rc-1/rc-2), never propagated.
|
|
1876
|
+
if (Object.hasOwn(v, 'budgetObservedAt') && isString(v.budgetObservedAt) && v.budgetObservedAt.length > 0 && Number.isFinite(Date.parse(v.budgetObservedAt))) {
|
|
1877
|
+
result.budgetObservedAt = v.budgetObservedAt;
|
|
1878
|
+
}
|
|
1839
1879
|
if (Object.hasOwn(v, 'perHost') && Array.isArray(v.perHost)) {
|
|
1840
1880
|
// rc-4: validate every element, not just "is array".
|
|
1841
1881
|
const perHost = [];
|
|
@@ -1849,7 +1889,26 @@ export function validatePromptInjectionBudgetStatus(v) {
|
|
|
1849
1889
|
|| typeof hostTruncated !== 'boolean') {
|
|
1850
1890
|
return null;
|
|
1851
1891
|
}
|
|
1852
|
-
|
|
1892
|
+
const forecast = { hostKind, route, usedChars: hostUsed, truncated: hostTruncated };
|
|
1893
|
+
// PRI-1017: per-host budget basis (additive, drop-on-invalid). Absent
|
|
1894
|
+
// behaves as the pre-PRI-1017 payload where the headline budget was
|
|
1895
|
+
// shared — the UI must not present one host's window as another's.
|
|
1896
|
+
if (Object.hasOwn(entry, 'budget') && typeof entry.budget === 'number' && Number.isInteger(entry.budget) && entry.budget > 0) {
|
|
1897
|
+
forecast.budget = entry.budget;
|
|
1898
|
+
}
|
|
1899
|
+
if (Object.hasOwn(entry, 'budgetCapacitySource') && isPromptBudgetCapacitySource(entry.budgetCapacitySource)) {
|
|
1900
|
+
forecast.budgetCapacitySource = entry.budgetCapacitySource;
|
|
1901
|
+
}
|
|
1902
|
+
if (Object.hasOwn(entry, 'budgetCapacityStatus') && isPromptBudgetCapacityStatus(entry.budgetCapacityStatus)) {
|
|
1903
|
+
forecast.budgetCapacityStatus = entry.budgetCapacityStatus;
|
|
1904
|
+
}
|
|
1905
|
+
if (Object.hasOwn(entry, 'budgetObservedAt') && isString(entry.budgetObservedAt) && entry.budgetObservedAt.length > 0 && Number.isFinite(Date.parse(entry.budgetObservedAt))) {
|
|
1906
|
+
forecast.budgetObservedAt = entry.budgetObservedAt;
|
|
1907
|
+
}
|
|
1908
|
+
if (Object.hasOwn(entry, 'budgetFallbackReason') && isPromptBudgetFallbackReason(entry.budgetFallbackReason)) {
|
|
1909
|
+
forecast.budgetFallbackReason = entry.budgetFallbackReason;
|
|
1910
|
+
}
|
|
1911
|
+
perHost.push(forecast);
|
|
1853
1912
|
}
|
|
1854
1913
|
result.perHost = perHost;
|
|
1855
1914
|
}
|