create-principles-disciple 1.121.2 → 1.121.4
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/console/dist/server/models/ActivationsConsoleModel.d.ts +3 -1
- package/console/dist/server/models/ActivationsConsoleModel.js +34 -6
- package/console/dist/server/routes/update.js +7 -7
- package/console/dist/ui/i18n/en.json +5 -3
- package/console/dist/ui/i18n/zh-CN.json +5 -3
- package/console/dist/ui/pages/principles/PrincipleDetailPage.d.ts +4 -0
- package/console/dist/ui/pages/principles/PrincipleDetailPage.js +15 -5
- package/console/dist/web/assets/app.js +18 -9
- package/console/package.json +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +32 -4
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.js +68 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/installer-config-parity.test.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/principle-receipt-block-copy-flag.test.js +7 -7
- package/core/dist/runtime-v2/feature-flags/__tests__/principle-receipt-block-copy-flag.test.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/__tests__/principle-receipt-ledger-flag.test.js +7 -7
- package/core/dist/runtime-v2/feature-flags/__tests__/principle-receipt-ledger-flag.test.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +11 -9
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +3 -3
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +2 -2
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/types/event-payload.d.ts +27 -1
- package/core/dist/runtime-v2/types/event-payload.d.ts.map +1 -1
- package/core/dist/runtime-v2/types/event-payload.js +13 -1
- package/core/dist/runtime-v2/types/event-payload.js.map +1 -1
- package/core/dist/runtime-v2/types/event-types.d.ts +20 -3
- package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/types/event-types.js +17 -0
- package/core/dist/runtime-v2/types/event-types.js.map +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +10 -0
- package/dist/installer.js.map +1 -1
- package/dist/mvp-config.d.ts.map +1 -1
- package/dist/mvp-config.js +3 -4
- package/dist/mvp-config.js.map +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/runtime-activation.d.ts +1 -0
- package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-activation.js +36 -1
- package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
- package/plugin/dist/bundle.js +367 -367
- package/plugin/dist/core/event-log.d.ts +4 -1
- package/plugin/dist/governance-audit.d.ts +5 -0
- package/plugin/dist/types/event-types.d.ts +1 -1
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +5 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ActivationStatusRecord, PromotionReadinessResult, ActivationControlState, ActivationDecisionRecord, GlobalRuleCodePause, OwnerPromotionActor, OwnerPromotionResult } from '@principles/core/runtime-v2';
|
|
2
|
+
import { type GovernanceAuditWriter } from 'principles-disciple/governance-audit';
|
|
2
3
|
/**
|
|
3
4
|
* PRI-491 — owner-observable activation record.
|
|
4
5
|
*
|
|
@@ -107,7 +108,8 @@ export interface OwnerMutationInput {
|
|
|
107
108
|
}
|
|
108
109
|
export declare class ActivationsConsoleModel {
|
|
109
110
|
private readonly workspaceDir;
|
|
110
|
-
|
|
111
|
+
private readonly governanceAuditWriter;
|
|
112
|
+
constructor(workspaceDir: string, governanceAuditWriter?: GovernanceAuditWriter);
|
|
111
113
|
getActivations(): Promise<ActivationsResponse>;
|
|
112
114
|
getOwnerReview(activationId: string, ownerIdentityConfigured?: boolean): Promise<RuleCodeOwnerReview>;
|
|
113
115
|
continueObserving(activationId: string, input: OwnerMutationInput): Promise<{
|
|
@@ -4,6 +4,7 @@ import { loadPdConfig, computeFlagsFromLoadResult } from '../config/pd-config-st
|
|
|
4
4
|
import * as fs from 'node:fs';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import { createHash, randomUUID } from 'node:crypto';
|
|
7
|
+
import { authorizeGovernanceAction, writeGovernanceAction, } from 'principles-disciple/governance-audit';
|
|
7
8
|
/**
|
|
8
9
|
* Type guard for parsed JSON objects (rc-2-no-as-bypass).
|
|
9
10
|
* Replaces `as Record<string, unknown>` casts on untrusted contentJson.
|
|
@@ -112,8 +113,10 @@ function readRuleCodeTelemetry(workspaceDir, activationId, decisions) {
|
|
|
112
113
|
}
|
|
113
114
|
export class ActivationsConsoleModel {
|
|
114
115
|
workspaceDir;
|
|
115
|
-
|
|
116
|
+
governanceAuditWriter;
|
|
117
|
+
constructor(workspaceDir, governanceAuditWriter = writeGovernanceAction) {
|
|
116
118
|
this.workspaceDir = workspaceDir;
|
|
119
|
+
this.governanceAuditWriter = governanceAuditWriter;
|
|
117
120
|
}
|
|
118
121
|
async getActivations() {
|
|
119
122
|
const stateDbPath = path.join(this.workspaceDir, '.pd', 'state.db');
|
|
@@ -415,7 +418,13 @@ export class ActivationsConsoleModel {
|
|
|
415
418
|
async deactivateRuleCode(activationId, decision, input) {
|
|
416
419
|
if (decision === 'reject_after_shadow')
|
|
417
420
|
this.requireOwnerDecisionFeature();
|
|
418
|
-
return this.withMutableRuleCode(activationId, async (store, activation, artifactDigest) =>
|
|
421
|
+
return this.withMutableRuleCode(activationId, async (store, activation, artifactDigest) => authorizeGovernanceAction(path.join(this.workspaceDir, '.pd'), {
|
|
422
|
+
action: 'deactivate',
|
|
423
|
+
activationId,
|
|
424
|
+
actor: 'owner',
|
|
425
|
+
reasonCode: input.reasonCode,
|
|
426
|
+
outcome: 'authorized',
|
|
427
|
+
}, () => store.deactivateWithDecision(makeActivationDecision({ activation, artifactDigest, decision, input }), input.idempotencyKey), this.governanceAuditWriter));
|
|
419
428
|
}
|
|
420
429
|
async recoverRuleCodeToShadow(activationId, expectedControlVersion, input) {
|
|
421
430
|
this.requireOwnerDecisionFeature();
|
|
@@ -433,7 +442,13 @@ export class ActivationsConsoleModel {
|
|
|
433
442
|
...(input.actor.operator ? { operator: input.actor.operator } : {}), reasonCode: input.reasonCode,
|
|
434
443
|
note: input.note ?? null, evidenceSnapshotId: null, decidedAt: new Date().toISOString(),
|
|
435
444
|
};
|
|
436
|
-
return await
|
|
445
|
+
return await authorizeGovernanceAction(path.join(this.workspaceDir, '.pd'), {
|
|
446
|
+
action: 'global_pause',
|
|
447
|
+
subject: 'all_live_rulecode',
|
|
448
|
+
actor: 'owner',
|
|
449
|
+
reasonCode: input.reasonCode,
|
|
450
|
+
outcome: 'authorized',
|
|
451
|
+
}, () => new SqliteActivationSafetyStore(conn).pauseAllLive(decision, `pause-${randomUUID()}`, input.idempotencyKey), this.governanceAuditWriter);
|
|
437
452
|
}
|
|
438
453
|
finally {
|
|
439
454
|
try {
|
|
@@ -470,15 +485,22 @@ export class ActivationsConsoleModel {
|
|
|
470
485
|
ownerLiveDecisionEnabled: () => isFeatureEnabled(flags, 'rulecode_owner_live_decision'),
|
|
471
486
|
safetyControlsEnabled: () => isFeatureEnabled(flags, 'rulecode_safety_controls'),
|
|
472
487
|
evaluateReadiness: async () => review.readiness,
|
|
473
|
-
commitPromotion: value =>
|
|
488
|
+
commitPromotion: value => authorizeGovernanceAction(path.join(this.workspaceDir, '.pd'), {
|
|
489
|
+
action: 'promote',
|
|
490
|
+
activationId,
|
|
491
|
+
actor: 'owner',
|
|
492
|
+
reasonCode: input.reasonCode,
|
|
493
|
+
outcome: 'authorized',
|
|
494
|
+
}, () => store.commitPromotion(value), this.governanceAuditWriter),
|
|
474
495
|
newDecisionId: () => `decision-${randomUUID()}`,
|
|
475
496
|
now: () => new Date().toISOString(),
|
|
476
497
|
});
|
|
477
|
-
|
|
498
|
+
const result = await service.promote({
|
|
478
499
|
activationId, expectedArtifactId: expected.artifactId, expectedArtifactDigest: expected.artifactDigest,
|
|
479
500
|
expectedControlVersion: expected.controlVersion, idempotencyKey: input.idempotencyKey,
|
|
480
501
|
reasonCode: input.reasonCode, note: input.note, confirmed: expected.confirmed,
|
|
481
502
|
}, input.actor);
|
|
503
|
+
return result;
|
|
482
504
|
}
|
|
483
505
|
finally {
|
|
484
506
|
try {
|
|
@@ -525,7 +547,13 @@ export class ActivationsConsoleModel {
|
|
|
525
547
|
try {
|
|
526
548
|
const activationStore = new SqliteActivationStateStore(conn);
|
|
527
549
|
try {
|
|
528
|
-
const deactivated = await
|
|
550
|
+
const deactivated = await authorizeGovernanceAction(path.join(this.workspaceDir, '.pd'), {
|
|
551
|
+
action: 'deactivate',
|
|
552
|
+
activationId,
|
|
553
|
+
actor: 'session',
|
|
554
|
+
reasonCode: 'console_disable_confirmed',
|
|
555
|
+
outcome: 'authorized',
|
|
556
|
+
}, () => activationStore.deactivateActivation(activationId, new Date().toISOString()), this.governanceAuditWriter);
|
|
529
557
|
if (!deactivated) {
|
|
530
558
|
return { ok: false, reason: `Activation '${activationId}' not found or already inactive`, nextAction: 'Refresh the activation list and verify the activation ID is correct.' };
|
|
531
559
|
}
|
|
@@ -678,21 +678,21 @@ function depsMeaningfullyChanged(oldDeps, newDeps) {
|
|
|
678
678
|
*/
|
|
679
679
|
function ensureHostRuntimeResolutionLinks(extDir) {
|
|
680
680
|
const hostRuntimeDir = path.join(extDir, 'host-runtime');
|
|
681
|
-
const
|
|
682
|
-
path.join(extDir, 'console', 'node_modules', '@principles', 'host-runtime'),
|
|
683
|
-
path.join(extDir, 'pd-cli', 'node_modules', '@principles', 'host-runtime'),
|
|
681
|
+
const links = [
|
|
682
|
+
{ linkPath: path.join(extDir, 'console', 'node_modules', '@principles', 'host-runtime'), target: hostRuntimeDir, unixTarget: '../../../host-runtime' },
|
|
683
|
+
{ linkPath: path.join(extDir, 'pd-cli', 'node_modules', '@principles', 'host-runtime'), target: hostRuntimeDir, unixTarget: '../../../host-runtime' },
|
|
684
|
+
{ linkPath: path.join(extDir, 'console', 'node_modules', 'principles-disciple'), target: extDir, unixTarget: '../../' },
|
|
684
685
|
];
|
|
685
|
-
for (const linkPath of
|
|
686
|
+
for (const { linkPath, target, unixTarget } of links) {
|
|
686
687
|
if (fs.existsSync(linkPath))
|
|
687
688
|
continue;
|
|
688
689
|
try {
|
|
689
690
|
fs.mkdirSync(path.dirname(linkPath), { recursive: true });
|
|
690
691
|
if (process.platform === 'win32') {
|
|
691
|
-
fs.symlinkSync(
|
|
692
|
+
fs.symlinkSync(target, linkPath, 'junction');
|
|
692
693
|
}
|
|
693
694
|
else {
|
|
694
|
-
|
|
695
|
-
fs.symlinkSync('../../../host-runtime', linkPath, 'dir');
|
|
695
|
+
fs.symlinkSync(unixTarget, linkPath, 'dir');
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
698
|
catch (error) {
|
|
@@ -446,9 +446,11 @@
|
|
|
446
446
|
"receipts": {
|
|
447
447
|
"title": "Receipt History",
|
|
448
448
|
"headline": "Your principle is influencing agent behavior",
|
|
449
|
-
"
|
|
449
|
+
"headlinePresence": "Your principle is part of the agent's decision context — no recorded behavior effect yet",
|
|
450
|
+
"counts": "{{effectCount}} behavior effect(s) · {{presenceCount}} context injection(s)",
|
|
451
|
+
"zeroEffect": "Why 0 effects? Effects need evidence: a block, an auto-correction, or an agent self-report. So far this principle has only entered task context (Presence). Being present in a decision does not mean behavior changed — the first effect record will appear here as runtime evidence accumulates.",
|
|
450
452
|
"empty": "No recent records — this principle has not been triggered at runtime yet.",
|
|
451
|
-
"note": "
|
|
453
|
+
"note": "Two levels: Effect = the principle actually changed behavior (block / auto-correction / agent self-report); Presence = the principle entered task context (gray rows). Presence in a decision ≠ changed behavior. Self-reports are probabilistic agent claims, listed separately from deterministic events.",
|
|
452
454
|
"unavailableReason": "Receipt history is unavailable right now.",
|
|
453
455
|
"kind": {
|
|
454
456
|
"rule_blocked": "Block",
|
|
@@ -626,7 +628,7 @@
|
|
|
626
628
|
"viewDebt": "View in Principle Debt",
|
|
627
629
|
"loadError": "Unable to load activation data. You can try refreshing the page.",
|
|
628
630
|
"receiptsLabel": "Receipts",
|
|
629
|
-
"receiptsValue": "{{effect}} effect(s) · {{presence}} injection(s)",
|
|
631
|
+
"receiptsValue": "{{effect}} behavior effect(s) · {{presence}} context injection(s)",
|
|
630
632
|
"receiptsUnavailable": "Receipt history unavailable: {{reason}}",
|
|
631
633
|
"ownerDecisionTitle": "Owner Live Decision",
|
|
632
634
|
"ownerDecisionRecorded": "RuleCode decision recorded",
|
|
@@ -446,9 +446,11 @@
|
|
|
446
446
|
"receipts": {
|
|
447
447
|
"title": "生效履历",
|
|
448
448
|
"headline": "你的原则正在影响智能体行为",
|
|
449
|
-
"
|
|
449
|
+
"headlinePresence": "原则已进入智能体决策上下文——尚无行为生效记录",
|
|
450
|
+
"counts": "行为生效 {{effectCount}} 次 · 参与上下文 {{presenceCount}} 次",
|
|
451
|
+
"zeroEffect": "为什么「行为生效」是 0?生效需要证据:一次拦截、一次自动纠正,或智能体自述遵循。目前这条原则只进入过任务上下文(Presence)——参与决策 ≠ 已改变行为。随着运行积累出第一条证据,「行为生效」会从这里开始计数。",
|
|
450
452
|
"empty": "最近没有记录——这条原则尚未在运行中被触发。",
|
|
451
|
-
"note": "
|
|
453
|
+
"note": "两级语义:Effect(行为生效)= 拦截 / 自动纠正 / 智能体自述遵循;Presence(参与上下文)= 原则进入任务上下文(灰色行)。参与决策 ≠ 已改变行为。智能体自述为概率性自报,与确定性事件分列。",
|
|
452
454
|
"unavailableReason": "暂无法读取生效履历。",
|
|
453
455
|
"kind": {
|
|
454
456
|
"rule_blocked": "拦截",
|
|
@@ -626,7 +628,7 @@
|
|
|
626
628
|
"viewDebt": "在原则债务中查看",
|
|
627
629
|
"loadError": "无法加载生效数据。你可以尝试刷新页面。",
|
|
628
630
|
"receiptsLabel": "生效履历",
|
|
629
|
-
"receiptsValue": "
|
|
631
|
+
"receiptsValue": "行为生效 {{effect}} 次 · 参与上下文 {{presence}} 次",
|
|
630
632
|
"receiptsUnavailable": "生效履历暂不可用:{{reason}}",
|
|
631
633
|
"ownerDecisionTitle": "拥有者上线决策",
|
|
632
634
|
"ownerDecisionRecorded": "RuleCode 决策已记录",
|
|
@@ -1 +1,5 @@
|
|
|
1
|
+
export declare function getReceiptPresentation(effectCount: number): {
|
|
2
|
+
headlineKey: 'principles.detail.receipts.headline' | 'principles.detail.receipts.headlinePresence';
|
|
3
|
+
showZeroEffectExplanation: boolean;
|
|
4
|
+
};
|
|
1
5
|
export declare function PrincipleDetailPage(): import("react").JSX.Element;
|
|
@@ -108,6 +108,11 @@ const STAGE_LABEL_KEYS = {
|
|
|
108
108
|
behavior: "principles.detail.stageBehavior",
|
|
109
109
|
};
|
|
110
110
|
// ── Component ───────────────────────────────────────────────────────────────
|
|
111
|
+
export function getReceiptPresentation(effectCount) {
|
|
112
|
+
return effectCount > 0
|
|
113
|
+
? { headlineKey: 'principles.detail.receipts.headline', showZeroEffectExplanation: false }
|
|
114
|
+
: { headlineKey: 'principles.detail.receipts.headlinePresence', showZeroEffectExplanation: true };
|
|
115
|
+
}
|
|
111
116
|
export function PrincipleDetailPage() {
|
|
112
117
|
const { t, i18n } = useTranslation("pages");
|
|
113
118
|
const { id } = useParams();
|
|
@@ -409,14 +414,19 @@ export function PrincipleDetailPage() {
|
|
|
409
414
|
}
|
|
410
415
|
const isPending = approvalGroup?.status === "pending" || principle.status === "candidate" || principle.status === "probation";
|
|
411
416
|
const hasRules = principle.rules.length > 0;
|
|
417
|
+
const receiptPresentation = receipts?.status === 'ok'
|
|
418
|
+
? getReceiptPresentation(receipts.effectCount)
|
|
419
|
+
: null;
|
|
412
420
|
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: principle.text }), _jsx("p", { className: "text-ink-3 text-[14px] leading-relaxed mb-3", children: t("principles.detail.policyNote") }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Button, { variant: "outline", size: "sm", disabled: true, children: t("principles.detail.modifyWording") }), _jsx("span", { className: "text-ink-4 text-[13px]", children: t("principles.detail.modifyWordingNote") }), _jsx(Button, { variant: "ghost", size: "sm", className: "ml-auto", "data-testid": "principle-feedback", onClick: () => {
|
|
413
421
|
const params = new URLSearchParams({ source: "principle_page", principleId: id ?? "" });
|
|
414
422
|
navigate(`/report-problem?${params.toString()}`);
|
|
415
|
-
}, children: t("reportProblem.entryFeedback") })] })] }), (governance !== null || governanceUnavailable !== null) && (_jsxs("section", { className: "mb-8", "aria-labelledby": "governance-summary-title", children: [_jsx(SectionTitle, { children: t('principles.detail.governance.title') }), governance !== null ? (_jsxs("div", { "data-testid": "governance-summary", className: `rounded-[var(--radius-md)] border p-4 ${governance.dataQuality.degraded ? 'border-amber/30 bg-amber/5' : 'border-gov/25 bg-gov/5'}`, children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { children: [_jsx("h2", { id: "governance-summary-title", className: "text-[18px] font-semibold text-ink", children: t(`principles.detail.${governance.summary.headlineCode}`, { defaultValue: governance.summary.headlineCode }) }), _jsx("p", { className: "mt-1 text-[13px] leading-relaxed text-ink-2", children: t(`principles.detail.${governance.summary.reasonCode}`, { defaultValue: governance.summary.reasonCode }) })] }), _jsx("span", { className: "w-fit rounded-full border border-line px-2 py-1 font-mono text-[11px] text-ink-3", children: t(`principles.detail.governance.confidence.${governance.dataQuality.degraded ? 'degraded' : 'strong'}`) })] }), _jsxs("dl", { className: "mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.principleState') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.state.${governance.principleState.value}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.process') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: governance.process.stage === undefined ? t('principles.detail.governance.none') : t(`principles.detail.governance.stage.${governance.process.stage}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.automation') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.automationState.${governance.automation.state}`) })] })] }), _jsxs("div", { "data-testid": "governance-next-action", className: "mt-4 border-l-2 border-l-gov pl-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.nextAction') }), _jsx("p", { className: "text-[13px] text-ink-2", children: t(`principles.detail.${governance.summary.nextActionCode}`, { defaultValue: governance.summary.nextActionCode }) })] }), governance.attention.items.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.blockers') }), _jsx("ul", { className: "mt-1 space-y-1 text-[13px] text-ink-2", children: governance.attention.items.map(item => _jsx("li", { children: t(`principles.detail.governance.attention.${item.reasonCode}`, { defaultValue: item.reasonCode }) }, `${item.kind}-${item.sourceRef.type}-${item.sourceRef.id}`)) })] })), governance.dataQuality.degraded && (_jsxs("div", { "data-testid": "governance-data-quality", className: "mt-4 rounded-[var(--radius-sm)] border border-amber/20 p-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-amber", children: t('principles.detail.governance.uncertainty') }), _jsx("ul", { className: "mt-1 space-y-1 text-[12px] text-ink-3", children: governance.dataQuality.issues.map((item, index) => _jsx("li", { children: t(`principles.detail.governance.issue.${item.reasonCode}`, { defaultValue: item.reasonCode }) }, `${item.source}-${item.reasonCode}-${index}`)) })] }))] })) : (_jsxs("div", { "data-testid": "governance-data-quality", className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("h2", { id: "governance-summary-title", className: "text-[16px] font-semibold text-ink", children: t('principles.detail.governance.unavailable') }), _jsx("p", { className: "mt-1 text-[13px] text-ink-2", children: t('principles.detail.governance.unavailableReason') }), _jsx("p", { className: "mt-2 text-[12px] text-ink-3", children: t('principles.detail.governance.unavailableNextAction') })] }))] })), receipts !== null && (_jsxs("section", { className: "mb-8", "aria-labelledby": "receipt-history-title", children: [_jsx(SectionTitle, { children: t('principles.detail.receipts.title') }), receipts.status === 'ok' ? (_jsxs("div", { "data-testid": "receipt-history", className: "rounded-[var(--radius-md)] border border-line p-4", children: [_jsxs("div", { className: "flex flex-wrap items-baseline justify-between gap-2", children: [_jsx("h2", { id: "receipt-history-title", className: "text-[15px] font-semibold text-ink", children:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
423
|
+
}, children: t("reportProblem.entryFeedback") })] })] }), (governance !== null || governanceUnavailable !== null) && (_jsxs("section", { className: "mb-8", "aria-labelledby": "governance-summary-title", children: [_jsx(SectionTitle, { children: t('principles.detail.governance.title') }), governance !== null ? (_jsxs("div", { "data-testid": "governance-summary", className: `rounded-[var(--radius-md)] border p-4 ${governance.dataQuality.degraded ? 'border-amber/30 bg-amber/5' : 'border-gov/25 bg-gov/5'}`, children: [_jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { children: [_jsx("h2", { id: "governance-summary-title", className: "text-[18px] font-semibold text-ink", children: t(`principles.detail.${governance.summary.headlineCode}`, { defaultValue: governance.summary.headlineCode }) }), _jsx("p", { className: "mt-1 text-[13px] leading-relaxed text-ink-2", children: t(`principles.detail.${governance.summary.reasonCode}`, { defaultValue: governance.summary.reasonCode }) })] }), _jsx("span", { className: "w-fit rounded-full border border-line px-2 py-1 font-mono text-[11px] text-ink-3", children: t(`principles.detail.governance.confidence.${governance.dataQuality.degraded ? 'degraded' : 'strong'}`) })] }), _jsxs("dl", { className: "mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.principleState') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.state.${governance.principleState.value}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.process') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: governance.process.stage === undefined ? t('principles.detail.governance.none') : t(`principles.detail.governance.stage.${governance.process.stage}`) })] }), _jsxs("div", { children: [_jsx("dt", { className: "font-mono text-[11px] text-ink-4", children: t('principles.detail.governance.automation') }), _jsx("dd", { className: "text-[13px] text-ink-2", children: t(`principles.detail.governance.automationState.${governance.automation.state}`) })] })] }), _jsxs("div", { "data-testid": "governance-next-action", className: "mt-4 border-l-2 border-l-gov pl-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.nextAction') }), _jsx("p", { className: "text-[13px] text-ink-2", children: t(`principles.detail.${governance.summary.nextActionCode}`, { defaultValue: governance.summary.nextActionCode }) })] }), governance.attention.items.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-ink-4", children: t('principles.detail.governance.blockers') }), _jsx("ul", { className: "mt-1 space-y-1 text-[13px] text-ink-2", children: governance.attention.items.map(item => _jsx("li", { children: t(`principles.detail.governance.attention.${item.reasonCode}`, { defaultValue: item.reasonCode }) }, `${item.kind}-${item.sourceRef.type}-${item.sourceRef.id}`)) })] })), governance.dataQuality.degraded && (_jsxs("div", { "data-testid": "governance-data-quality", className: "mt-4 rounded-[var(--radius-sm)] border border-amber/20 p-3", children: [_jsx("p", { className: "font-mono text-[11px] uppercase tracking-[0.08em] text-amber", children: t('principles.detail.governance.uncertainty') }), _jsx("ul", { className: "mt-1 space-y-1 text-[12px] text-ink-3", children: governance.dataQuality.issues.map((item, index) => _jsx("li", { children: t(`principles.detail.governance.issue.${item.reasonCode}`, { defaultValue: item.reasonCode }) }, `${item.source}-${item.reasonCode}-${index}`)) })] }))] })) : (_jsxs("div", { "data-testid": "governance-data-quality", className: "rounded-[var(--radius-md)] border border-amber/30 bg-amber/5 p-4", role: "status", children: [_jsx("h2", { id: "governance-summary-title", className: "text-[16px] font-semibold text-ink", children: t('principles.detail.governance.unavailable') }), _jsx("p", { className: "mt-1 text-[13px] text-ink-2", children: t('principles.detail.governance.unavailableReason') }), _jsx("p", { className: "mt-2 text-[12px] text-ink-3", children: t('principles.detail.governance.unavailableNextAction') })] }))] })), receipts !== null && (_jsxs("section", { className: "mb-8", "aria-labelledby": "receipt-history-title", children: [_jsx(SectionTitle, { children: t('principles.detail.receipts.title') }), receipts.status === 'ok' ? (_jsxs("div", { "data-testid": "receipt-history", className: "rounded-[var(--radius-md)] border border-line p-4", children: [_jsxs("div", { className: "flex flex-wrap items-baseline justify-between gap-2", children: [_jsx("h2", { id: "receipt-history-title", className: "text-[15px] font-semibold text-ink", children: receiptPresentation?.headlineKey === 'principles.detail.receipts.headline'
|
|
424
|
+
? t(receiptPresentation.headlineKey, {
|
|
425
|
+
defaultValue: '',
|
|
426
|
+
effectCount: receipts.effectCount,
|
|
427
|
+
lastEffectAt: receipts.lastEffectAt ? formatDate(receipts.lastEffectAt, i18n.language) : '',
|
|
428
|
+
})
|
|
429
|
+
: 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') })] })) : (_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("p", { className: "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 })] }))] })), _jsxs("section", { className: "mb-8", children: [_jsx(SectionTitle, { children: t("principles.detail.channel") }), _jsx("p", { className: "text-ink-2 text-[14px] leading-relaxed", children: t("principles.detail.channelPromptReversible") })] }), _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", 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", {
|
|
420
430
|
defaultValue: "已关联 {{count}} 条证据记录",
|
|
421
431
|
count: principle.derivedFromPainIds.length,
|
|
422
432
|
}) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: async () => {
|