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
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-703 / PRI-705 / PRI-700 — Evolution Alignment contract tests
|
|
3
|
+
* (Owner decision 2026-09-07, task §8 test requirements).
|
|
4
|
+
*
|
|
5
|
+
* Covers the four required test classes:
|
|
6
|
+
* 1. Intent Consistency — the intent contract flows scribe → prompt → rule
|
|
7
|
+
* artifact without mutation (same principle ⇒ same contract).
|
|
8
|
+
* 2. Failure Attribution — partitionV2OutOfScopeFailures classifies
|
|
9
|
+
* rule-error / test-error / infra scenarios correctly (v2×v1 out-of-scope
|
|
10
|
+
* is the Episode-001 PRI-700 shape).
|
|
11
|
+
* 3. Repair feedback circuit — priorValidatorErrors reaches the artificer
|
|
12
|
+
* prompt (PRI-700 factor B) and the case-id vocabulary note is present
|
|
13
|
+
* (factor C).
|
|
14
|
+
* 4. Scribe contract validation — intentContract present-but-malformed is
|
|
15
|
+
* a hard rejection; absent stays valid (backward compatibility).
|
|
16
|
+
*/
|
|
17
|
+
import { describe, expect, it } from 'vitest';
|
|
18
|
+
import { extractIntentContract, isValidIntentContractV1, } from '../intent-contract.js';
|
|
19
|
+
import { DefaultScribeValidator } from '../scribe-output.js';
|
|
20
|
+
import { attributionFromLayer, partitionV2OutOfScopeFailures, v2TemplateOracleExpectedDecision, resolveRequiresContextVersionFromArtifact, V2_TEMPLATE_CASE_IDS, } from '../rule-reliability-validation.js';
|
|
21
|
+
import { generateV2ContextAdversarialCases } from '../v2-adversarial-cases.js';
|
|
22
|
+
import { ArtificerPromptBuilder } from '../artificer-prompt-builder.js';
|
|
23
|
+
import { DefaultArtificerValidator, } from '../artificer-output.js';
|
|
24
|
+
import { parseLastValidatorErrors, isFreshForNextAttempt, parsePITaskMetadata } from '../pitask-metadata.js';
|
|
25
|
+
const VALID_CONTRACT = {
|
|
26
|
+
ownerIntent: 'avoid the agent guessing configuration contracts from example files',
|
|
27
|
+
targetBehavior: 'verify a config field has a real consumer before writing it',
|
|
28
|
+
forbiddenBehavior: 'inferring field existence from example files or naming conventions',
|
|
29
|
+
evidenceSource: 'pain manual_1788707211638 (invented config fields, 4th recurrence)',
|
|
30
|
+
validationExpectation: 'absent consumer evidence must surface as an explicit risk',
|
|
31
|
+
};
|
|
32
|
+
function scribeOutputWithContract(overrides = {}) {
|
|
33
|
+
return {
|
|
34
|
+
taskId: 'scribe-1',
|
|
35
|
+
sourcePhilosopherArtifactId: 'pi-art-phil-1',
|
|
36
|
+
principleDraft: {
|
|
37
|
+
title: 'No config field without a verified consumer',
|
|
38
|
+
statement: 'A config field must not be written unless a real consumer is verified.',
|
|
39
|
+
rationale: 'Invented fields from example files caused repeated failures.',
|
|
40
|
+
applicability: ['config', 'env', 'api payloads'],
|
|
41
|
+
antiPatterns: ['copying fields from deploy.example.yml'],
|
|
42
|
+
confidence: 0.86,
|
|
43
|
+
},
|
|
44
|
+
intentContract: { ...VALID_CONTRACT, ...overrides },
|
|
45
|
+
sourceTrace: { philosopherArtifactId: 'pi-art-phil-1' },
|
|
46
|
+
risks: [],
|
|
47
|
+
generatedAt: '2026-09-07T00:00:00.000Z',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
describe('1. Intent Consistency — contract flows scribe → prompt → rule artifact unchanged', () => {
|
|
51
|
+
it('extractIntentContract round-trips the validated contract verbatim (no field drift)', () => {
|
|
52
|
+
const artifact = scribeOutputWithContract();
|
|
53
|
+
const extracted = extractIntentContract(artifact);
|
|
54
|
+
expect(extracted).not.toBeNull();
|
|
55
|
+
expect(extracted).toEqual(artifact.intentContract);
|
|
56
|
+
});
|
|
57
|
+
it('the artificer prompt carries the exact contract the scribe produced (byte-identical intent anchor)', () => {
|
|
58
|
+
const builder = new ArtificerPromptBuilder();
|
|
59
|
+
const { promptInput } = builder.buildPrompt({
|
|
60
|
+
contextMode: 'v1',
|
|
61
|
+
taskId: 'artificer-1',
|
|
62
|
+
contextHash: 'hash-1',
|
|
63
|
+
sourceScribeArtifactId: 'pi-art-scribe-1',
|
|
64
|
+
scribeArtifact: scribeOutputWithContract(),
|
|
65
|
+
intentContract: VALID_CONTRACT,
|
|
66
|
+
});
|
|
67
|
+
expect(promptInput.intentContract).toEqual(VALID_CONTRACT);
|
|
68
|
+
const message = JSON.stringify(promptInput);
|
|
69
|
+
expect(message).toContain('avoid the agent guessing configuration contracts');
|
|
70
|
+
// The intent anchor block must instruct contract precedence over repair
|
|
71
|
+
// instructions — the alignment rule itself is part of the contract.
|
|
72
|
+
expect(promptInput.artificerInstruction).toContain('OWNER INTENT CONTRACT');
|
|
73
|
+
expect(promptInput.artificerInstruction).toContain('intentContract wins');
|
|
74
|
+
});
|
|
75
|
+
it('pre-contract scribe artifacts produce prompts WITHOUT the contract key (backward compatible)', () => {
|
|
76
|
+
const builder = new ArtificerPromptBuilder();
|
|
77
|
+
const legacyArtifact = scribeOutputWithContract();
|
|
78
|
+
delete legacyArtifact.intentContract;
|
|
79
|
+
const { promptInput } = builder.buildPrompt({
|
|
80
|
+
contextMode: 'v1',
|
|
81
|
+
taskId: 'artificer-2',
|
|
82
|
+
contextHash: 'hash-2',
|
|
83
|
+
sourceScribeArtifactId: 'pi-art-scribe-2',
|
|
84
|
+
scribeArtifact: legacyArtifact,
|
|
85
|
+
});
|
|
86
|
+
expect(promptInput).not.toHaveProperty('intentContract');
|
|
87
|
+
});
|
|
88
|
+
it('the scribe validator requires all five contract fields to be non-empty strings', async () => {
|
|
89
|
+
const validator = new DefaultScribeValidator();
|
|
90
|
+
// any single missing/empty field → hard rejection (a corrupted anchor is
|
|
91
|
+
// worse than none)
|
|
92
|
+
for (const field of Object.keys(VALID_CONTRACT)) {
|
|
93
|
+
const bad = scribeOutputWithContract({ [field]: '' });
|
|
94
|
+
const result = await validator.validate(bad, 'scribe-1', 'pi-art-phil-1');
|
|
95
|
+
expect(result.valid).toBe(false);
|
|
96
|
+
expect(result.errors.join(' ')).toContain('intentContract');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
it('absent intentContract stays valid (pre-contract outputs pass unchanged)', async () => {
|
|
100
|
+
const validator = new DefaultScribeValidator();
|
|
101
|
+
const legacy = scribeOutputWithContract();
|
|
102
|
+
delete legacy.intentContract;
|
|
103
|
+
const result = await validator.validate(legacy, 'scribe-1', 'pi-art-phil-1');
|
|
104
|
+
expect(result.valid).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('2. Failure Attribution — where/why/what-next classification', () => {
|
|
108
|
+
// Round-2 R1 (Owner 口径 b): 出界判定按「oracle 期望决策 + 逐 case 验证」,
|
|
109
|
+
// 不按模板名单断言。expectedDecision 的分类真值 = 编译期模板 oracle
|
|
110
|
+
// (generateV2ContextAdversarialCases 定义);沙箱回带值仅作一致性比对
|
|
111
|
+
// (防 caseId 冒名),绝非判定来源。
|
|
112
|
+
it('Case B: pure context-only allow-template failures against a v1 rule ARE out-of-scope (Episode-001 death loop breaker preserved)', () => {
|
|
113
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
114
|
+
requiresContextVersion: undefined, // v1 action-only rule
|
|
115
|
+
failedCases: [
|
|
116
|
+
{ caseId: 'v2-unavailable', expectedDecision: 'allow' },
|
|
117
|
+
{ caseId: 'v2-truncated', expectedDecision: 'allow' },
|
|
118
|
+
{ caseId: 'v2-alias', expectedDecision: 'allow' },
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
expect(partition.isPureOutOfScope).toBe(true);
|
|
122
|
+
expect(partition.outOfScope).toEqual(['v2-unavailable', 'v2-truncated', 'v2-alias']);
|
|
123
|
+
expect(partition.inScope).toEqual([]);
|
|
124
|
+
expect(attributionFromLayer('test')).toBe('FAILED_TEST');
|
|
125
|
+
});
|
|
126
|
+
it('Case A: a rule that violates an explicit block requirement MUST reach repair — block-expecting v2 templates are never out-of-scope', () => {
|
|
127
|
+
// R1 复现回归:原则禁止写危险文件,规则输出 allow,v2-combination
|
|
128
|
+
// (期望 block) 失败——必须进 Rule 修复,禁止被 NHR 豁免。
|
|
129
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
130
|
+
requiresContextVersion: undefined,
|
|
131
|
+
failedCases: [{ caseId: 'v2-combination', expectedDecision: 'block' }],
|
|
132
|
+
});
|
|
133
|
+
expect(partition.isPureOutOfScope).toBe(false);
|
|
134
|
+
expect(partition.outOfScope).toEqual([]);
|
|
135
|
+
expect(partition.inScope).toEqual(['v2-combination']);
|
|
136
|
+
// path-boundary 同理:期望 block 的模板 v1 完全可实现
|
|
137
|
+
const boundaryPartition = partitionV2OutOfScopeFailures({
|
|
138
|
+
requiresContextVersion: undefined,
|
|
139
|
+
failedCases: [
|
|
140
|
+
{ caseId: 'v2-path-boundary', expectedDecision: 'block' },
|
|
141
|
+
{ caseId: 'v2-unavailable', expectedDecision: 'allow' },
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
expect(boundaryPartition.isPureOutOfScope).toBe(false);
|
|
145
|
+
expect(boundaryPartition.inScope).toEqual(['v2-path-boundary']);
|
|
146
|
+
expect(boundaryPartition.outOfScope).toEqual(['v2-unavailable']);
|
|
147
|
+
});
|
|
148
|
+
it('Case C: expectedDecision missing or mismatched → fail-closed IN SCOPE (never exempts the rule)', () => {
|
|
149
|
+
const missing = partitionV2OutOfScopeFailures({
|
|
150
|
+
requiresContextVersion: undefined,
|
|
151
|
+
failedCases: [
|
|
152
|
+
{ caseId: 'v2-unavailable' },
|
|
153
|
+
{ caseId: 'v2-alias', expectedDecision: 'block' }, // 冒名/不一致 → in-scope
|
|
154
|
+
],
|
|
155
|
+
});
|
|
156
|
+
expect(missing.isPureOutOfScope).toBe(false);
|
|
157
|
+
expect(missing.outOfScope).toEqual([]);
|
|
158
|
+
expect(missing.inScope).toEqual(['v2-unavailable', 'v2-alias']);
|
|
159
|
+
});
|
|
160
|
+
it('the same v2 cases against a v2 rule are in scope (the channel CAN express them)', () => {
|
|
161
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
162
|
+
requiresContextVersion: 2,
|
|
163
|
+
failedCases: [
|
|
164
|
+
{ caseId: 'v2-unavailable', expectedDecision: 'allow' },
|
|
165
|
+
{ caseId: 'v2-truncated', expectedDecision: 'allow' },
|
|
166
|
+
{ caseId: 'case-ordinary-1', expectedDecision: 'block' },
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
expect(partition.isPureOutOfScope).toBe(false);
|
|
170
|
+
expect(partition.outOfScope).toEqual([]);
|
|
171
|
+
expect(partition.inScope).toEqual(['v2-unavailable', 'v2-truncated', 'case-ordinary-1']);
|
|
172
|
+
});
|
|
173
|
+
it('mixed failures on a v1 rule: ordinary cases stay in-scope (real rule defect)', () => {
|
|
174
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
175
|
+
requiresContextVersion: undefined,
|
|
176
|
+
failedCases: [
|
|
177
|
+
{ caseId: 'case-ordinary-1', expectedDecision: 'block' },
|
|
178
|
+
{ caseId: 'v2-unavailable', expectedDecision: 'allow' },
|
|
179
|
+
],
|
|
180
|
+
});
|
|
181
|
+
expect(partition.isPureOutOfScope).toBe(false);
|
|
182
|
+
expect(partition.inScope).toEqual(['case-ordinary-1']);
|
|
183
|
+
expect(partition.outOfScope).toEqual(['v2-unavailable']);
|
|
184
|
+
});
|
|
185
|
+
it('a v1 rule failing ONLY on custom v2-* ids stays IN SCOPE (no false test-out-of-scope routing)', () => {
|
|
186
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
187
|
+
requiresContextVersion: undefined,
|
|
188
|
+
failedCases: [
|
|
189
|
+
{ caseId: 'v2-business-boundary', expectedDecision: 'block' },
|
|
190
|
+
{ caseId: 'v2-custom-2', expectedDecision: 'allow' },
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
expect(partition.isPureOutOfScope).toBe(false);
|
|
194
|
+
expect(partition.inScope).toEqual(['v2-business-boundary', 'v2-custom-2']);
|
|
195
|
+
expect(partition.outOfScope).toEqual([]);
|
|
196
|
+
});
|
|
197
|
+
it('v2TemplateOracleExpectedDecision reflects the compile-time template definitions (block templates are never context-only)', () => {
|
|
198
|
+
expect(v2TemplateOracleExpectedDecision('v2-unavailable')).toBe('allow');
|
|
199
|
+
expect(v2TemplateOracleExpectedDecision('v2-truncated')).toBe('allow');
|
|
200
|
+
expect(v2TemplateOracleExpectedDecision('v2-alias')).toBe('allow');
|
|
201
|
+
expect(v2TemplateOracleExpectedDecision('v2-path-boundary')).toBe('block');
|
|
202
|
+
expect(v2TemplateOracleExpectedDecision('v2-combination')).toBe('block');
|
|
203
|
+
expect(v2TemplateOracleExpectedDecision('v2-business-boundary')).toBeNull();
|
|
204
|
+
expect(v2TemplateOracleExpectedDecision('negative-1')).toBeNull();
|
|
205
|
+
});
|
|
206
|
+
it('attributionFromLayer maps the full stage-answer taxonomy onto one vocabulary', () => {
|
|
207
|
+
const expected = [
|
|
208
|
+
['principle', 'FAILED_PRINCIPLE'],
|
|
209
|
+
['rule', 'FAILED_RULE'],
|
|
210
|
+
['evaluation', 'FAILED_EVALUATION'],
|
|
211
|
+
['test', 'FAILED_TEST'],
|
|
212
|
+
['runtime', 'INFRA_BLOCKED'],
|
|
213
|
+
['adapter', 'UNKNOWN'],
|
|
214
|
+
['unknown', 'UNKNOWN'],
|
|
215
|
+
];
|
|
216
|
+
for (const [layer, attribution] of expected) {
|
|
217
|
+
expect(attributionFromLayer(layer)).toBe(attribution);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
it('resolveRequiresContextVersionFromArtifact distinguishes v1 (key-absent) from unresolvable — the out-of-scope wiring regression', () => {
|
|
221
|
+
// 评审 P1 回归:key-absent on a PARSED artifact is deterministically v1
|
|
222
|
+
// (artificer schema only ever writes literal 2)。此前 runner 把它折叠成
|
|
223
|
+
// null,导致 partition 在生产中永远不运行——出界路由的全部目标人群
|
|
224
|
+
// (v1 规则) 被接线断点排除。
|
|
225
|
+
expect(resolveRequiresContextVersionFromArtifact('{"title":"t","statement":"s"}')).toBeUndefined();
|
|
226
|
+
expect(resolveRequiresContextVersionFromArtifact('{"requiresContextVersion":2}')).toBe(2);
|
|
227
|
+
// unresolvable (fail-open) cases must stay null, never v1:
|
|
228
|
+
expect(resolveRequiresContextVersionFromArtifact(null)).toBeNull();
|
|
229
|
+
expect(resolveRequiresContextVersionFromArtifact(undefined)).toBeNull();
|
|
230
|
+
expect(resolveRequiresContextVersionFromArtifact('')).toBeNull();
|
|
231
|
+
expect(resolveRequiresContextVersionFromArtifact('not json')).toBeNull();
|
|
232
|
+
expect(resolveRequiresContextVersionFromArtifact('[1,2]')).toBeNull();
|
|
233
|
+
expect(resolveRequiresContextVersionFromArtifact('{"requiresContextVersion":"2"}')).toBeNull();
|
|
234
|
+
});
|
|
235
|
+
it('WIRING: a resolved v1 artifact whose replay failures are all oracle-verified allow templates routes pure out-of-scope', () => {
|
|
236
|
+
const v1ArtifactContentJson = '{"taskId":"a","ruleCode":"...","statement":"s"}';
|
|
237
|
+
const resolved = resolveRequiresContextVersionFromArtifact(v1ArtifactContentJson);
|
|
238
|
+
expect(resolved).toBeUndefined();
|
|
239
|
+
const partition = partitionV2OutOfScopeFailures({
|
|
240
|
+
requiresContextVersion: resolved === 2 ? 2 : undefined,
|
|
241
|
+
failedCases: [
|
|
242
|
+
{ caseId: 'v2-unavailable', expectedDecision: 'allow' },
|
|
243
|
+
{ caseId: 'v2-alias', expectedDecision: 'allow' },
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
expect(partition.isPureOutOfScope).toBe(true);
|
|
247
|
+
expect(partition.outOfScope).toEqual(['v2-unavailable', 'v2-alias']);
|
|
248
|
+
expect(partition.inScope).toEqual([]);
|
|
249
|
+
});
|
|
250
|
+
it('V2_TEMPLATE_CASE_IDS stays equivalent to the generator output (drift would silently re-open the death loop)', () => {
|
|
251
|
+
const generated = generateV2ContextAdversarialCases({
|
|
252
|
+
toolName: 'write_file',
|
|
253
|
+
targetPath: '/workspace/report.md',
|
|
254
|
+
canonicalKind: 'write',
|
|
255
|
+
});
|
|
256
|
+
const generatedIds = new Set(generated.map((c) => c.caseId));
|
|
257
|
+
expect(generatedIds.size).toBe(5);
|
|
258
|
+
expect([...generatedIds].sort()).toEqual([...V2_TEMPLATE_CASE_IDS].sort());
|
|
259
|
+
// Round-2 R1: the oracle-expected decision per generated template must
|
|
260
|
+
// match the partition's oracle map — generator drift in expectations is
|
|
261
|
+
// caught here, not silently in production routing.
|
|
262
|
+
for (const c of generated) {
|
|
263
|
+
const oracle = v2TemplateOracleExpectedDecision(c.caseId);
|
|
264
|
+
expect(oracle).not.toBeNull();
|
|
265
|
+
expect(oracle).toBe(c.expectedDecision);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
describe('3. Repair feedback circuit — PRI-700 factors B + C', () => {
|
|
270
|
+
it('priorValidatorErrors reaches the serialized artificer prompt (the dead loop is broken)', () => {
|
|
271
|
+
const builder = new ArtificerPromptBuilder();
|
|
272
|
+
const { promptInput, message } = builder.buildPrompt({
|
|
273
|
+
contextMode: 'v1',
|
|
274
|
+
taskId: 'artificer-repair-r1',
|
|
275
|
+
contextHash: 'hash-r1',
|
|
276
|
+
sourceScribeArtifactId: 'pi-art-scribe-1',
|
|
277
|
+
scribeArtifact: scribeOutputWithContract(),
|
|
278
|
+
repairFeedback: 'Previous attempt scored 0.7 (needs_revision).\nEvaluator concerns:\nRequired changes:\n1. handle unavailable context\nFix ALL the above.',
|
|
279
|
+
priorValidatorErrors: {
|
|
280
|
+
recordedAt: '2026-09-07T01:00:00.000Z',
|
|
281
|
+
errorCategory: 'output_invalid',
|
|
282
|
+
errors: [
|
|
283
|
+
'goldenTraceCases[0].ruleContext is required when requiresContextVersion: 2 is declared',
|
|
284
|
+
"expectedDecision 'propose_correction' is forbidden in v2 seed rules",
|
|
285
|
+
],
|
|
286
|
+
// 评审修正: prompt fixture 是"本 attempt 将回喂上一轮"的形态——
|
|
287
|
+
// base runner 泄漏面按 attempt-1 新鲜度判定
|
|
288
|
+
sourceAttemptCount: 1,
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
expect(promptInput.priorValidatorErrors?.errors).toHaveLength(2);
|
|
292
|
+
// The verbatim rejection reasons are IN the prompt the repair LLM sees —
|
|
293
|
+
// attempt N+1 is no longer a zero-information retry.
|
|
294
|
+
expect(message).toContain('expectedDecision \'propose_correction\' is forbidden');
|
|
295
|
+
expect(promptInput.artificerInstruction).toContain('PRIOR OUTPUT-CONTRACT REJECTIONS');
|
|
296
|
+
});
|
|
297
|
+
it('the case-id vocabulary note is part of the prompt contract (factor C)', () => {
|
|
298
|
+
const builder = new ArtificerPromptBuilder();
|
|
299
|
+
const { promptInput } = builder.buildPrompt({
|
|
300
|
+
contextMode: 'v1',
|
|
301
|
+
taskId: 'artificer-repair-r1',
|
|
302
|
+
contextHash: 'hash-r1',
|
|
303
|
+
sourceScribeArtifactId: 'pi-art-scribe-1',
|
|
304
|
+
scribeArtifact: scribeOutputWithContract(),
|
|
305
|
+
repairFeedback: 'Required changes:\n1. allow the evidence-availability boundary cases (v2-unavailable, v2-truncated, v2-alias)',
|
|
306
|
+
});
|
|
307
|
+
expect(promptInput.artificerInstruction).toContain('ADVERSARIAL CASE VOCABULARY NOTE');
|
|
308
|
+
expect(promptInput.artificerInstruction).toContain('v2-*');
|
|
309
|
+
expect(promptInput.artificerInstruction).toContain('NEVER respond to a case id by declaring');
|
|
310
|
+
});
|
|
311
|
+
it('parseLastValidatorErrors guards the trust boundary (malformed data → null, never a crash)', () => {
|
|
312
|
+
expect(parseLastValidatorErrors(null)).toBeNull();
|
|
313
|
+
expect(parseLastValidatorErrors('')).toBeNull();
|
|
314
|
+
expect(parseLastValidatorErrors('not json')).toBeNull();
|
|
315
|
+
expect(parseLastValidatorErrors('{"other":1}')).toBeNull();
|
|
316
|
+
expect(parseLastValidatorErrors('{"lastValidatorErrors":{}}')).toBeNull();
|
|
317
|
+
expect(parseLastValidatorErrors('{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":[]}}')).toBeNull();
|
|
318
|
+
// legacy shape without sourceAttemptCount → null (宁可少回喂一次,不回喂
|
|
319
|
+
// 来源不明的旧错误 — 评审 P1)
|
|
320
|
+
expect(parseLastValidatorErrors('{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":["e1"]}}')).toBeNull();
|
|
321
|
+
expect(parseLastValidatorErrors('{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":["e1"],"sourceAttemptCount":-1}}')).toBeNull();
|
|
322
|
+
const valid = parseLastValidatorErrors('{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":["e1"],"sourceAttemptCount":3}}');
|
|
323
|
+
expect(valid?.errors).toEqual(['e1']);
|
|
324
|
+
expect(valid?.sourceAttemptCount).toBe(3);
|
|
325
|
+
});
|
|
326
|
+
it('parseLastValidatorErrors bounds the re-fed error payload (rc-8: echoed LLM output must not overflow the prompt budget)', () => {
|
|
327
|
+
const longError = 'x'.repeat(1200);
|
|
328
|
+
const parsed = parseLastValidatorErrors(`{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":["${longError}"],"sourceAttemptCount":2}}`);
|
|
329
|
+
expect(parsed).not.toBeNull();
|
|
330
|
+
expect(parsed?.errors[0]?.length).toBeLessThanOrEqual(500 + '…[truncated]'.length);
|
|
331
|
+
expect(parsed?.errors[0]).toContain('…[truncated]');
|
|
332
|
+
// >10 errors: first 10 kept, remainder collapsed into a visible marker
|
|
333
|
+
const many = Array.from({ length: 15 }, (_, i) => `e${i}`);
|
|
334
|
+
const capped = parseLastValidatorErrors(`{"lastValidatorErrors":{"recordedAt":"t","errorCategory":"output_invalid","errors":${JSON.stringify(many)},"sourceAttemptCount":2}}`);
|
|
335
|
+
expect(capped?.errors).toHaveLength(11);
|
|
336
|
+
expect(capped?.errors[9]).toBe('e9');
|
|
337
|
+
expect(capped?.errors[10]).toBe('[+5 more validation error(s) omitted for prompt budget]');
|
|
338
|
+
});
|
|
339
|
+
it('isFreshForNextAttempt: only the immediately-preceding attempt\'s record is re-fed (rc-7, restart-safe)', () => {
|
|
340
|
+
const record = { recordedAt: 't', errorCategory: 'output_invalid', errors: ['e1'], sourceAttemptCount: 2 };
|
|
341
|
+
// fresh: attempt 3 follows the failed attempt 2
|
|
342
|
+
expect(isFreshForNextAttempt(record, 3)).toBe(true);
|
|
343
|
+
// stale: attempt 4 after a runtime-error attempt 3 did not clear the record
|
|
344
|
+
expect(isFreshForNextAttempt(record, 4)).toBe(false);
|
|
345
|
+
// no lease context (non-leased invocation) → suppress, never guess
|
|
346
|
+
expect(isFreshForNextAttempt(record, undefined)).toBe(false);
|
|
347
|
+
// same attempt re-reading its own just-written record (source === current)
|
|
348
|
+
expect(isFreshForNextAttempt(record, 2)).toBe(false);
|
|
349
|
+
});
|
|
350
|
+
it('extractIntentContract returns null on the FOCUSED (flattened) manifest shape — documents why capture-before-narrowing is load-bearing', () => {
|
|
351
|
+
// The focused manifest resolves scribeArtifactInput to resolved.fields —
|
|
352
|
+
// flat summary strings with no root intentContract object. Extraction
|
|
353
|
+
// must yield null there; artificer-runner therefore captures the FULL
|
|
354
|
+
// artifact before resolveContextInjectionAsync (评审 P1 wiring fix).
|
|
355
|
+
const flattenedSummaryShape = {
|
|
356
|
+
summary: '…',
|
|
357
|
+
intentOwner: 'avoid guessing config contracts',
|
|
358
|
+
intentForbidden: 'inferring field existence from examples',
|
|
359
|
+
intentValidation: 'absent consumer evidence surfaces as risk',
|
|
360
|
+
};
|
|
361
|
+
expect(extractIntentContract(flattenedSummaryShape)).toBeNull();
|
|
362
|
+
});
|
|
363
|
+
it('the artificer validator still rejects the forbidden v2 declarations that killed 18/18 attempts', async () => {
|
|
364
|
+
// The gate that CORRECTLY rejected Episode-001 outputs must stay closed —
|
|
365
|
+
// the fix feeds errors back, it does not weaken the contract.
|
|
366
|
+
const validator = new DefaultArtificerValidator();
|
|
367
|
+
const violatingOutput = {
|
|
368
|
+
taskId: 'artificer-repair-r1',
|
|
369
|
+
sourceScribeArtifactId: 'pi-art-scribe-1',
|
|
370
|
+
implementationSummary: 'x',
|
|
371
|
+
sourceTrace: { scribeArtifactId: 'pi-art-scribe-1' },
|
|
372
|
+
risks: [],
|
|
373
|
+
implementationCode: 'function evaluate(input, helpers) { return { decision: "allow", matched: false, reason: "r" }; }',
|
|
374
|
+
goldenTraceCases: [
|
|
375
|
+
{ caseId: 'v2-unavailable', kind: 'negative', toolName: 'write_file', params: { path: '/w/f' }, expectedDecision: 'propose_correction', ruleContext: {} },
|
|
376
|
+
],
|
|
377
|
+
affectedTools: ['write_file'],
|
|
378
|
+
generatedAt: '2026-09-07T00:00:00.000Z',
|
|
379
|
+
requiresContextVersion: 2,
|
|
380
|
+
};
|
|
381
|
+
const result = await validator.validate(violatingOutput, 'artificer-repair-r1', 'pi-art-scribe-1');
|
|
382
|
+
expect(result.valid).toBe(false);
|
|
383
|
+
const joined = result.errors.join(' ');
|
|
384
|
+
expect(joined).toContain('propose_correction');
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
describe('4. Scribe contract — trust boundary on the intent contract', () => {
|
|
388
|
+
it('isValidIntentContractV1 accepts only the five non-empty string fields', () => {
|
|
389
|
+
expect(isValidIntentContractV1(VALID_CONTRACT)).toBe(true);
|
|
390
|
+
expect(isValidIntentContractV1({ ...VALID_CONTRACT, evidenceSource: ' ' })).toBe(false);
|
|
391
|
+
expect(isValidIntentContractV1({ ...VALID_CONTRACT, extra: 'x' })).toBe(true); // additive keys tolerated
|
|
392
|
+
expect(isValidIntentContractV1(null)).toBe(false);
|
|
393
|
+
expect(isValidIntentContractV1('contract')).toBe(false);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
describe('2b. Failure Attribution — RepairPayload carries attribution context', () => {
|
|
397
|
+
it('failureAttribution validates at the metadata trust boundary (malformed → whole metadata invalid)', () => {
|
|
398
|
+
const baseMeta = {
|
|
399
|
+
dependencyTaskIds: ['scribe-1'],
|
|
400
|
+
channel: 'prompt',
|
|
401
|
+
timeoutMs: 300000,
|
|
402
|
+
inputArtifactRefs: [],
|
|
403
|
+
outputArtifactRefs: [],
|
|
404
|
+
repairPayload: {
|
|
405
|
+
requiredChanges: ['fix the ordinary case'],
|
|
406
|
+
concerns: [],
|
|
407
|
+
previousScore: 0.7,
|
|
408
|
+
repairIteration: 1,
|
|
409
|
+
sourceArtificerArtifactId: 'pi-art-art-1',
|
|
410
|
+
sourceEvaluatorTaskId: 'evaluator-1',
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
// Valid payload with attribution hydrates
|
|
414
|
+
const valid = parsePITaskMetadata(JSON.stringify({
|
|
415
|
+
pi_metadata: {
|
|
416
|
+
...baseMeta,
|
|
417
|
+
repairPayload: {
|
|
418
|
+
...baseMeta.repairPayload,
|
|
419
|
+
failureAttribution: {
|
|
420
|
+
attribution: 'FAILED_RULE',
|
|
421
|
+
outOfScopeCaseIds: ['v2-unavailable'],
|
|
422
|
+
reason: 'mixed failures: ordinary in-scope case + channel-limitation v2 case',
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
}));
|
|
427
|
+
expect(valid).not.toBeNull();
|
|
428
|
+
expect(valid?.repairPayload?.failureAttribution?.attribution).toBe('FAILED_RULE');
|
|
429
|
+
// Base payload without attribution still valid (backward compatible)
|
|
430
|
+
const legacy = parsePITaskMetadata(JSON.stringify({ pi_metadata: baseMeta }));
|
|
431
|
+
expect(legacy).not.toBeNull();
|
|
432
|
+
expect(legacy?.repairPayload?.failureAttribution).toBeUndefined();
|
|
433
|
+
// Malformed attribution invalidates the WHOLE metadata (rc-3 fail loud) —
|
|
434
|
+
// a corrupted attribution must never silently steer the repair prompt
|
|
435
|
+
const emptyAttribution = parsePITaskMetadata(JSON.stringify({
|
|
436
|
+
pi_metadata: {
|
|
437
|
+
...baseMeta,
|
|
438
|
+
repairPayload: {
|
|
439
|
+
...baseMeta.repairPayload,
|
|
440
|
+
failureAttribution: { attribution: '', reason: 'x' },
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
}));
|
|
444
|
+
expect(emptyAttribution).toBeNull();
|
|
445
|
+
const badCaseId = parsePITaskMetadata(JSON.stringify({
|
|
446
|
+
pi_metadata: {
|
|
447
|
+
...baseMeta,
|
|
448
|
+
repairPayload: {
|
|
449
|
+
...baseMeta.repairPayload,
|
|
450
|
+
failureAttribution: { attribution: 'FAILED_TEST', reason: 'x', outOfScopeCaseIds: ['ok', 42] },
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
}));
|
|
454
|
+
expect(badCaseId).toBeNull();
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
//# sourceMappingURL=evolution-alignment-contract.test.js.map
|
package/core/dist/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evolution-alignment-contract.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/internalization/__tests__/evolution-alignment-contract.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -84,6 +84,7 @@ function makeStore(options = {}) {
|
|
|
84
84
|
applicability: ['filesystem writes'],
|
|
85
85
|
antiPatterns: ['guessing the target'],
|
|
86
86
|
},
|
|
87
|
+
...options.scribeExtra,
|
|
87
88
|
} }),
|
|
88
89
|
artifact({ artifactId: ARTIFICER_ARTIFACT_ID, sourceTaskId: ARTIFICER_TASK_ID, lineageArtifactIds: [SCRIBE_ARTIFACT_ID], content: {
|
|
89
90
|
...(options.codeBearingArtificer
|
|
@@ -165,6 +166,93 @@ describe('Owner Decision Review Snapshot', () => {
|
|
|
165
166
|
]);
|
|
166
167
|
expect(snapshot.evidence.completeness).toBe('complete');
|
|
167
168
|
});
|
|
169
|
+
it('derives the 5-item quality checklist; boundary passes via antiPatterns on the standard fixture', async () => {
|
|
170
|
+
const snapshot = await buildOwnerDecisionReview(makeStore(), EVALUATOR_ID);
|
|
171
|
+
expect(snapshot?.brief.kind).toBe('evaluator');
|
|
172
|
+
if (snapshot?.brief.kind !== 'evaluator')
|
|
173
|
+
throw new Error('expected evaluator brief');
|
|
174
|
+
const checklist = snapshot.brief.qualityChecklist;
|
|
175
|
+
expect(checklist).toBeDefined();
|
|
176
|
+
expect(checklist?.schemaVersion).toBe(1);
|
|
177
|
+
expect(checklist?.items.map((item) => item.id)).toEqual([
|
|
178
|
+
'understandability', 'evidence', 'actionability', 'generalization', 'boundary',
|
|
179
|
+
]);
|
|
180
|
+
const byId = new Map(checklist?.items.map((item) => [item.id, item]));
|
|
181
|
+
expect(byId.get('understandability')?.pass).toBe(true);
|
|
182
|
+
expect(byId.get('boundary')?.pass).toBe(true);
|
|
183
|
+
expect(byId.get('boundary')?.note).toContain('anti-pattern');
|
|
184
|
+
// 标准单上下文 fixture:generalization 必须 fail(over-fitting 信号)
|
|
185
|
+
expect(byId.get('generalization')?.pass).toBe(false);
|
|
186
|
+
});
|
|
187
|
+
it('boundary: intent-contract forbiddenBehavior is the ONLY accepted fallback — ownerIntent (a goal) must not count (评审 P1)', async () => {
|
|
188
|
+
const draftWithoutAntiPatterns = {
|
|
189
|
+
title: 'Confirm destructive changes',
|
|
190
|
+
statement: 'Before destructive changes, confirm the exact target with the Owner.',
|
|
191
|
+
rationale: 'Prevents irreversible work against an ambiguous target.',
|
|
192
|
+
applicability: ['filesystem writes', 'shell commands'],
|
|
193
|
+
};
|
|
194
|
+
const boundaryItem = async (options) => {
|
|
195
|
+
const snapshot = await buildOwnerDecisionReview(makeStore(options), EVALUATOR_ID);
|
|
196
|
+
expect(snapshot?.brief.kind).toBe('evaluator');
|
|
197
|
+
if (snapshot?.brief.kind !== 'evaluator')
|
|
198
|
+
throw new Error('expected evaluator brief');
|
|
199
|
+
return snapshot.brief.qualityChecklist?.items.find((item) => item.id === 'boundary');
|
|
200
|
+
};
|
|
201
|
+
// forbiddenBehavior present → boundary pass even without antiPatterns
|
|
202
|
+
const forbiddenItem = await boundaryItem({
|
|
203
|
+
scribeExtra: {
|
|
204
|
+
principleDraft: draftWithoutAntiPatterns,
|
|
205
|
+
intentContract: {
|
|
206
|
+
ownerIntent: 'prevent ambiguous destructive targets',
|
|
207
|
+
targetBehavior: 'confirm the exact target before destructive writes',
|
|
208
|
+
forbiddenBehavior: 'guessing or inferring the target without confirmation',
|
|
209
|
+
evidenceSource: 'pain destructive-write misses',
|
|
210
|
+
validationExpectation: 'unconfirmed targets are blocked',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
expect(forbiddenItem?.pass).toBe(true);
|
|
215
|
+
expect(forbiddenItem?.note).toContain('forbiddenBehavior');
|
|
216
|
+
// ownerIntent present but forbiddenBehavior EMPTY → boundary must FAIL
|
|
217
|
+
// (回归:旧实现误把 intentOwner 当 forbidden 证据)
|
|
218
|
+
const ownerOnlyItem = await boundaryItem({
|
|
219
|
+
scribeExtra: {
|
|
220
|
+
principleDraft: draftWithoutAntiPatterns,
|
|
221
|
+
intentContract: {
|
|
222
|
+
ownerIntent: 'prevent ambiguous destructive targets',
|
|
223
|
+
forbiddenBehavior: '',
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
expect(ownerOnlyItem?.pass).toBe(false);
|
|
228
|
+
expect(ownerOnlyItem?.note).toContain('no antiPatterns and no intent-contract forbiddenBehavior present');
|
|
229
|
+
});
|
|
230
|
+
it('R3: evidence item binds to resolvable ancestors beyond scribe; generalization dedups applicability (评审探针正式化)', async () => {
|
|
231
|
+
// 标准链只有 evaluator→artificer→scribe,无 philosopher/dreamer/diag
|
|
232
|
+
// 祖先 —— evidence 项必须 fail(不得宣称 "evidence-derived")。
|
|
233
|
+
const standard = await buildOwnerDecisionReview(makeStore(), EVALUATOR_ID);
|
|
234
|
+
const stdChecklist = standard?.brief.kind === 'evaluator' ? standard.brief.qualityChecklist : undefined;
|
|
235
|
+
const stdEvidence = stdChecklist?.items.find((item) => item.id === 'evidence');
|
|
236
|
+
expect(stdEvidence?.pass).toBe(false);
|
|
237
|
+
expect(stdEvidence?.note).toContain('no ancestor artifact resolvable beyond scribe');
|
|
238
|
+
// 重复同一文件不得计为多上下文:generalization 按去重计数。
|
|
239
|
+
const dupStore = makeStore({
|
|
240
|
+
scribeExtra: {
|
|
241
|
+
principleDraft: {
|
|
242
|
+
title: 'x',
|
|
243
|
+
statement: 'Only patch /tmp/a.ts',
|
|
244
|
+
rationale: 'x',
|
|
245
|
+
applicability: ['/tmp/a.ts', '/tmp/a.ts'],
|
|
246
|
+
antiPatterns: ['x'],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
const dup = await buildOwnerDecisionReview(dupStore, EVALUATOR_ID);
|
|
251
|
+
const dupChecklist = dup?.brief.kind === 'evaluator' ? dup.brief.qualityChecklist : undefined;
|
|
252
|
+
const dupGeneralization = dupChecklist?.items.find((item) => item.id === 'generalization');
|
|
253
|
+
expect(dupGeneralization?.pass).toBe(false);
|
|
254
|
+
expect(dupGeneralization?.note).toContain('distinct applicability entries: 1');
|
|
255
|
+
});
|
|
168
256
|
it('requires acknowledgement for a partial but still identifiable review', async () => {
|
|
169
257
|
const snapshot = await buildOwnerDecisionReview(makeStore({ includeScribe: false }), EVALUATOR_ID);
|
|
170
258
|
expect(snapshot?.evidence.completeness).toBe('partial');
|