create-principles-disciple 1.133.11 → 1.133.13
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/ui/i18n/en.json +13 -1
- package/console/dist/ui/i18n/zh-CN.json +13 -1
- package/console/dist/ui/pages/focus/OwnerDecisionCard.js +1 -1
- package/console/dist/ui/utils/validators.d.ts +9 -0
- package/console/dist/ui/utils/validators.js +31 -0
- package/console/dist/web/assets/app.css +3 -0
- package/console/dist/web/assets/app.js +60 -3
- package/console/package.json +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/artifact-summary.property.test.js +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/artifact-summary.property.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js +6 -4
- package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-out-of-scope-governance.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-out-of-scope-governance.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-out-of-scope-governance.test.js +307 -0
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-out-of-scope-governance.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-prompt-builder.test.js +2 -2
- package/core/dist/runtime-v2/internalization/__tests__/evaluator-prompt-builder.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.d.ts +18 -0
- package/core/dist/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.js +457 -0
- package/core/dist/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision-review.test.js +88 -0
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision-review.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artifact-summary.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artifact-summary.js +8 -0
- package/core/dist/runtime-v2/internalization/artifact-summary.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +37 -2
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +31 -1
- package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts +18 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.js +60 -2
- package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/context-manifests.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/context-manifests.js +35 -2
- package/core/dist/runtime-v2/internalization/context-manifests.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts +15 -2
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js +10 -2
- package/core/dist/runtime-v2/internalization/evaluator-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +46 -0
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +352 -21
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/index.d.ts +4 -2
- package/core/dist/runtime-v2/internalization/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/index.js +2 -1
- package/core/dist/runtime-v2/internalization/index.js.map +1 -1
- package/core/dist/runtime-v2/internalization/intent-contract.d.ts +59 -0
- package/core/dist/runtime-v2/internalization/intent-contract.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/intent-contract.js +61 -0
- package/core/dist/runtime-v2/internalization/intent-contract.js.map +1 -0
- package/core/dist/runtime-v2/internalization/owner-decision-review.d.ts +28 -0
- package/core/dist/runtime-v2/internalization/owner-decision-review.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/owner-decision-review.js +76 -0
- package/core/dist/runtime-v2/internalization/owner-decision-review.js.map +1 -1
- package/core/dist/runtime-v2/internalization/owner-review.d.ts +8 -0
- package/core/dist/runtime-v2/internalization/owner-review.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/owner-review.js +10 -0
- package/core/dist/runtime-v2/internalization/owner-review.js.map +1 -1
- package/core/dist/runtime-v2/internalization/pitask-metadata.d.ts +76 -0
- package/core/dist/runtime-v2/internalization/pitask-metadata.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/pitask-metadata.js +116 -3
- package/core/dist/runtime-v2/internalization/pitask-metadata.js.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-reliability-validation.d.ts +141 -1
- package/core/dist/runtime-v2/internalization/rule-reliability-validation.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-reliability-validation.js +140 -0
- package/core/dist/runtime-v2/internalization/rule-reliability-validation.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts +11 -0
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.js +13 -0
- package/core/dist/runtime-v2/internalization/scribe-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts +8 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js +25 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-failure-details.test.js +16 -1
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-failure-details.test.js.map +1 -1
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts +9 -1
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/runner/base-peer-runner.js +32 -3
- package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -1
- package/core/package.json +1 -1
- package/package.json +1 -1
- package/plugin/dist/bundle.js +764 -724
- package/plugin/dist/governance-audit.js +76 -76
- package/plugin/dist/rulehost-evidence.js +116 -116
- package/release-manager/package.json +1 -1
|
@@ -309,7 +309,19 @@
|
|
|
309
309
|
"approvalHint": "The deployment approval for this principle is still waiting in the approval queue.",
|
|
310
310
|
"rulecodeHint": "This rule is in shadow activation and needs a decision in activation management.",
|
|
311
311
|
"goApprovalsCta": "Go to deployment approvals",
|
|
312
|
-
"goActivationCta": "Go to activation management"
|
|
312
|
+
"goActivationCta": "Go to activation management",
|
|
313
|
+
"qualityChecklistLabel": "Quality checklist",
|
|
314
|
+
"qualityCheckStatus": {
|
|
315
|
+
"passed": "passed",
|
|
316
|
+
"failed": "failed"
|
|
317
|
+
},
|
|
318
|
+
"qualityCheck": {
|
|
319
|
+
"understandability": "Understandability",
|
|
320
|
+
"evidence": "Evidence",
|
|
321
|
+
"actionability": "Actionability",
|
|
322
|
+
"generalization": "Generalization",
|
|
323
|
+
"boundary": "Boundary"
|
|
324
|
+
}
|
|
313
325
|
}
|
|
314
326
|
},
|
|
315
327
|
"pain": {
|
|
@@ -309,7 +309,19 @@
|
|
|
309
309
|
"approvalHint": "该原则的部署审批仍在审批队列中等待处理。",
|
|
310
310
|
"rulecodeHint": "该规则处于影子激活期,需要在激活管理中裁决。",
|
|
311
311
|
"goApprovalsCta": "前往部署审批",
|
|
312
|
-
"goActivationCta": "前往激活管理"
|
|
312
|
+
"goActivationCta": "前往激活管理",
|
|
313
|
+
"qualityChecklistLabel": "质量检查表",
|
|
314
|
+
"qualityCheckStatus": {
|
|
315
|
+
"passed": "已通过",
|
|
316
|
+
"failed": "未通过"
|
|
317
|
+
},
|
|
318
|
+
"qualityCheck": {
|
|
319
|
+
"understandability": "可理解性",
|
|
320
|
+
"evidence": "证据来源",
|
|
321
|
+
"actionability": "可执行性",
|
|
322
|
+
"generalization": "泛化度",
|
|
323
|
+
"boundary": "适用边界"
|
|
324
|
+
}
|
|
313
325
|
}
|
|
314
326
|
},
|
|
315
327
|
"pain": {
|
|
@@ -79,7 +79,7 @@ export function OwnerDecisionCard({ item, onResolved, governanceReady = true })
|
|
|
79
79
|
: item.kind === "rulecode_decision"
|
|
80
80
|
? t("pages.focus.ownerDecision.kindRulecode")
|
|
81
81
|
: t("pages.focus.ownerDecision.kindEvaluator");
|
|
82
|
-
return (_jsxs("article", { className: "bg-panel border border-line rounded-[6px] p-4 mb-3", "data-testid": `owner-decision-${item.taskId}`, children: [_jsxs("div", { className: "flex items-start justify-between gap-3 mb-2", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-ink text-[14px] font-medium leading-snug", children: item.title }), _jsx("div", { className: "mt-1 text-ink-4 text-[11px] font-mono uppercase tracking-[0.08em]", children: kindLabel })] }), item.legacy && (_jsx("span", { className: "shrink-0 text-ink-4 border border-line rounded-[2px] px-[7px] py-[3px] text-[10.5px] font-mono", children: t("pages.focus.ownerDecision.legacyBadge") }))] }), _jsx("p", { className: "text-ink-2 text-[13px] leading-relaxed mb-2", children: item.summary }), item.review?.brief.kind === "evaluator" && (_jsxs("div", { className: "mb-3 grid gap-2 text-[12.5px] leading-relaxed", children: [item.review.brief.principle?.statement && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.principleLabel") }), " ", item.review.brief.principle.statement] })), item.review.brief.implementation?.summary && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.implementationLabel") }), " ", item.review.brief.implementation.summary] })), (item.review.brief.concerns?.length ?? 0) > 0 && (_jsxs("p", { className: "text-amber", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.concernLabel") }), " ", item.review.brief.concerns?.[0]] }))] })), item.review?.brief.kind === "rollout" && item.review.brief.summary && (_jsx("p", { className: "mb-3 text-[12.5px] text-ink-2", children: item.review.brief.summary })), item.review && (_jsxs("div", { className: "mb-2 flex flex-wrap gap-2 text-[10.5px] font-mono uppercase tracking-[0.06em]", children: [_jsx("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: t(`pages.focus.ownerDecision.evidence.${item.review.evidence.completeness}`) }), item.review.evidence.deterministicChecks.map(check => (_jsxs("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: [check.check, ": ", check.status] }, check.check)))] })), item.machineRecommendation && (_jsxs("p", { className: "text-ink-3 text-[12.5px] mb-1", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.machineRecommendationLabel") }), " ", item.machineRecommendation, item.score !== undefined && _jsx("span", { className: "font-mono ml-1", children: item.score.toFixed(2) })] })), item.kind === "rollout_review" && (_jsx("p", { className: "text-ink-4 text-[12px] mb-1", children: t("pages.focus.ownerDecision.rolloutSafetyNote") })), evidenceUnavailable ? (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: t("pages.focus.ownerDecision.evidenceUnavailable") }), _jsx(Link, { to: "/failed", "data-testid": `owner-evidence-recover-${item.taskId}`, 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.goRecoverCta") })] })) : isTaskDecision ? (_jsxs(_Fragment, { children: [showInstruction && (_jsxs("div", { className: "mt-2 mb-2", children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("pages.focus.ownerDecision.instructionLabel") }), _jsx("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value.slice(0, 500)), "data-testid": `owner-instruction-${item.taskId}`, placeholder: t("pages.focus.ownerDecision.instructionPlaceholder"), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[64px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov" })] })), requiresPartialAcknowledgement && (_jsxs("label", { className: "mt-2 mb-1 flex items-start gap-2 text-[12px] text-ink-3", children: [_jsx("input", { type: "checkbox", checked: partialEvidenceAcknowledged, onChange: (event) => setPartialEvidenceAcknowledged(event.target.checked), "data-testid": `owner-partial-evidence-ack-${item.taskId}`, className: "mt-0.5" }), _jsx("span", { children: t("pages.focus.ownerDecision.partialEvidenceAcknowledgement") })] })), _jsxs("div", { className: "flex flex-wrap gap-2 mt-3", children: [canAccept && (_jsx("button", { type: "button", onClick: () => handleAction("accept_current"), disabled: !governanceReady || actionLoading !== null || (requiresPartialAcknowledgement && !partialEvidenceAcknowledged), "data-testid": `owner-accept-${item.taskId}`, 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: actionLoading === "accept_current" ? t("common.loading") : t("pages.focus.ownerDecision.acceptCurrent") })), canRevise && (_jsx("button", { type: "button", onClick: () => {
|
|
82
|
+
return (_jsxs("article", { className: "bg-panel border border-line rounded-[6px] p-4 mb-3", "data-testid": `owner-decision-${item.taskId}`, children: [_jsxs("div", { className: "flex items-start justify-between gap-3 mb-2", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-ink text-[14px] font-medium leading-snug", children: item.title }), _jsx("div", { className: "mt-1 text-ink-4 text-[11px] font-mono uppercase tracking-[0.08em]", children: kindLabel })] }), item.legacy && (_jsx("span", { className: "shrink-0 text-ink-4 border border-line rounded-[2px] px-[7px] py-[3px] text-[10.5px] font-mono", children: t("pages.focus.ownerDecision.legacyBadge") }))] }), _jsx("p", { className: "text-ink-2 text-[13px] leading-relaxed mb-2", children: item.summary }), item.review?.brief.kind === "evaluator" && (_jsxs("div", { className: "mb-3 grid gap-2 text-[12.5px] leading-relaxed", children: [item.review.brief.principle?.statement && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.principleLabel") }), " ", item.review.brief.principle.statement] })), item.review.brief.implementation?.summary && (_jsxs("p", { children: [_jsx("span", { className: "font-medium text-ink", children: t("pages.focus.ownerDecision.implementationLabel") }), " ", item.review.brief.implementation.summary] })), (item.review.brief.concerns?.length ?? 0) > 0 && (_jsxs("p", { className: "text-amber", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.concernLabel") }), " ", item.review.brief.concerns?.[0]] })), (item.review.brief.qualityChecklist?.items?.length ?? 0) > 0 && (_jsxs("div", { className: "mt-1 rounded-[3px] border border-line bg-surface-2 p-2", "data-testid": `owner-quality-checklist-${item.taskId}`, children: [_jsx("div", { className: "font-mono text-[10.5px] uppercase tracking-[0.06em] text-ink-3 mb-1", children: t("pages.focus.ownerDecision.qualityChecklistLabel") }), _jsx("ul", { className: "grid gap-0.5", children: item.review.brief.qualityChecklist?.items.map((qItem) => (_jsxs("li", { className: "flex items-start gap-1.5 text-[12px]", children: [_jsx("span", { className: qItem.pass ? "text-emerald" : "text-amber", "aria-hidden": "true", children: qItem.pass ? "✓" : "!" }), _jsx("span", { className: "sr-only", children: qItem.pass ? t("pages.focus.ownerDecision.qualityCheckStatus.passed") : t("pages.focus.ownerDecision.qualityCheckStatus.failed") }), _jsxs("span", { className: "text-ink-2", children: [_jsx("span", { className: "font-medium", children: t(`pages.focus.ownerDecision.qualityCheck.${qItem.id}`) }), " ", qItem.note] })] }, qItem.id))) })] }))] })), item.review?.brief.kind === "rollout" && item.review.brief.summary && (_jsx("p", { className: "mb-3 text-[12.5px] text-ink-2", children: item.review.brief.summary })), item.review && (_jsxs("div", { className: "mb-2 flex flex-wrap gap-2 text-[10.5px] font-mono uppercase tracking-[0.06em]", children: [_jsx("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: t(`pages.focus.ownerDecision.evidence.${item.review.evidence.completeness}`) }), item.review.evidence.deterministicChecks.map(check => (_jsxs("span", { className: "rounded-[2px] border border-line px-2 py-1 text-ink-3", children: [check.check, ": ", check.status] }, check.check)))] })), item.machineRecommendation && (_jsxs("p", { className: "text-ink-3 text-[12.5px] mb-1", children: [_jsx("span", { className: "font-medium", children: t("pages.focus.ownerDecision.machineRecommendationLabel") }), " ", item.machineRecommendation, item.score !== undefined && _jsx("span", { className: "font-mono ml-1", children: item.score.toFixed(2) })] })), item.kind === "rollout_review" && (_jsx("p", { className: "text-ink-4 text-[12px] mb-1", children: t("pages.focus.ownerDecision.rolloutSafetyNote") })), evidenceUnavailable ? (_jsxs("div", { className: "mt-3 rounded-[3px] border border-amber/40 bg-amber/5 p-3", children: [_jsx("p", { className: "text-ink-2 text-[12.5px] leading-relaxed", children: t("pages.focus.ownerDecision.evidenceUnavailable") }), _jsx(Link, { to: "/failed", "data-testid": `owner-evidence-recover-${item.taskId}`, 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.goRecoverCta") })] })) : isTaskDecision ? (_jsxs(_Fragment, { children: [showInstruction && (_jsxs("div", { className: "mt-2 mb-2", children: [_jsx("label", { className: "block font-mono text-[11px] uppercase tracking-[0.08em] text-ink-3 mb-2", children: t("pages.focus.ownerDecision.instructionLabel") }), _jsx("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value.slice(0, 500)), "data-testid": `owner-instruction-${item.taskId}`, placeholder: t("pages.focus.ownerDecision.instructionPlaceholder"), className: "w-full border border-line rounded-[var(--radius-md)] bg-surface text-ink px-3 py-2 text-[13px] min-h-[64px] resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gov" })] })), requiresPartialAcknowledgement && (_jsxs("label", { className: "mt-2 mb-1 flex items-start gap-2 text-[12px] text-ink-3", children: [_jsx("input", { type: "checkbox", checked: partialEvidenceAcknowledged, onChange: (event) => setPartialEvidenceAcknowledged(event.target.checked), "data-testid": `owner-partial-evidence-ack-${item.taskId}`, className: "mt-0.5" }), _jsx("span", { children: t("pages.focus.ownerDecision.partialEvidenceAcknowledgement") })] })), _jsxs("div", { className: "flex flex-wrap gap-2 mt-3", children: [canAccept && (_jsx("button", { type: "button", onClick: () => handleAction("accept_current"), disabled: !governanceReady || actionLoading !== null || (requiresPartialAcknowledgement && !partialEvidenceAcknowledged), "data-testid": `owner-accept-${item.taskId}`, 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: actionLoading === "accept_current" ? t("common.loading") : t("pages.focus.ownerDecision.acceptCurrent") })), canRevise && (_jsx("button", { type: "button", onClick: () => {
|
|
83
83
|
if (!showInstruction) {
|
|
84
84
|
setShowInstruction(true);
|
|
85
85
|
return;
|
|
@@ -866,6 +866,15 @@ export interface OwnerDecisionReviewData {
|
|
|
866
866
|
requiredChanges: string[];
|
|
867
867
|
risks?: string[];
|
|
868
868
|
score?: number;
|
|
869
|
+
/** PRI-704 / PRI-703 Phase 4: 5-item deterministic quality checklist (evaluator briefs only). */
|
|
870
|
+
qualityChecklist?: {
|
|
871
|
+
schemaVersion: number;
|
|
872
|
+
items: {
|
|
873
|
+
id: string;
|
|
874
|
+
pass: boolean;
|
|
875
|
+
note: string;
|
|
876
|
+
}[];
|
|
877
|
+
};
|
|
869
878
|
};
|
|
870
879
|
evidence: {
|
|
871
880
|
completeness: 'complete' | 'partial' | 'insufficient';
|
|
@@ -2415,6 +2415,37 @@ function validateOwnerDecisionReview(value) {
|
|
|
2415
2415
|
return null;
|
|
2416
2416
|
if (isNumber(brief.score))
|
|
2417
2417
|
parsedBrief.score = brief.score;
|
|
2418
|
+
// PRI-704 / PRI-703 Phase 4 (评审修正): optional quality checklist —
|
|
2419
|
+
// strict five-item contract: schemaVersion must be exactly 1 and the five
|
|
2420
|
+
// known item ids must each appear EXACTLY once (the UI builds i18n keys
|
|
2421
|
+
// from the id; an unknown id would render an untranslated label, a
|
|
2422
|
+
// missing id an incomplete checklist). Anything else → omit the whole
|
|
2423
|
+
// checklist (older snapshots legitimately lack it; a partial one must
|
|
2424
|
+
// not masquerade as a review aid).
|
|
2425
|
+
if (brief.qualityChecklist !== undefined) {
|
|
2426
|
+
const KNOWN_IDS = ['understandability', 'evidence', 'actionability', 'generalization', 'boundary'];
|
|
2427
|
+
const qc = brief.qualityChecklist;
|
|
2428
|
+
if (isObject(qc) && qc.schemaVersion === 1 && Array.isArray(qc.items)) {
|
|
2429
|
+
const validItems = [];
|
|
2430
|
+
let shapeValid = true;
|
|
2431
|
+
const seen = new Set();
|
|
2432
|
+
for (const entry of qc.items) {
|
|
2433
|
+
if (!isObject(entry) || !isString(entry.id)
|
|
2434
|
+
|| typeof entry.pass !== 'boolean' || !isString(entry.note)) {
|
|
2435
|
+
shapeValid = false;
|
|
2436
|
+
break;
|
|
2437
|
+
}
|
|
2438
|
+
seen.add(entry.id);
|
|
2439
|
+
validItems.push({ id: entry.id, pass: entry.pass, note: entry.note });
|
|
2440
|
+
}
|
|
2441
|
+
const allKnownOnce = shapeValid
|
|
2442
|
+
&& validItems.length === KNOWN_IDS.length
|
|
2443
|
+
&& KNOWN_IDS.every((id) => seen.has(id));
|
|
2444
|
+
if (allKnownOnce) {
|
|
2445
|
+
parsedBrief.qualityChecklist = { schemaVersion: 1, items: validItems };
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2418
2449
|
}
|
|
2419
2450
|
else {
|
|
2420
2451
|
const risks = readOwnerStringArray(brief.risks);
|