zelari-code 1.48.0 → 1.49.0
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/dist/cli/desktopConfig.js +51 -4
- package/dist/cli/desktopConfig.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +80 -0
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/candidateRegistry.js +195 -0
- package/dist/cli/kraken/candidateRegistry.js.map +1 -0
- package/dist/cli/kraken/candidateRegistry.test.js +211 -0
- package/dist/cli/kraken/candidateRegistry.test.js.map +1 -0
- package/dist/cli/kraken/completionGate.js +116 -0
- package/dist/cli/kraken/completionGate.js.map +1 -0
- package/dist/cli/kraken/completionGate.test.js +172 -0
- package/dist/cli/kraken/completionGate.test.js.map +1 -0
- package/dist/cli/kraken/metrics.js +96 -0
- package/dist/cli/kraken/metrics.js.map +1 -0
- package/dist/cli/kraken/metrics.test.js +145 -0
- package/dist/cli/kraken/metrics.test.js.map +1 -0
- package/dist/cli/kraken/selectionPlaybook.js +23 -0
- package/dist/cli/kraken/selectionPlaybook.js.map +1 -0
- package/dist/cli/kraken/selectionPlaybook.test.js +55 -0
- package/dist/cli/kraken/selectionPlaybook.test.js.map +1 -0
- package/dist/cli/kraken/turnRuntime.js +207 -0
- package/dist/cli/kraken/turnRuntime.js.map +1 -0
- package/dist/cli/kraken/turnRuntime.test.js +377 -0
- package/dist/cli/kraken/turnRuntime.test.js.map +1 -0
- package/dist/cli/kraken/verifier.js +233 -0
- package/dist/cli/kraken/verifier.js.map +1 -0
- package/dist/cli/kraken/verifier.test.js +232 -0
- package/dist/cli/kraken/verifier.test.js.map +1 -0
- package/dist/cli/kraken/verifierSettings.test.js +237 -0
- package/dist/cli/kraken/verifierSettings.test.js.map +1 -0
- package/dist/cli/kraken/verifyReport.js +115 -0
- package/dist/cli/kraken/verifyReport.js.map +1 -0
- package/dist/cli/kraken/verifyReport.test.js +111 -0
- package/dist/cli/kraken/verifyReport.test.js.map +1 -0
- package/dist/cli/main.bundled.js +1369 -111
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/provider/openai-compatible.js +40 -6
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/provider/openai-compatible.timeout.test.js +72 -0
- package/dist/cli/provider/openai-compatible.timeout.test.js.map +1 -0
- package/dist/cli/providerConfig.js +46 -0
- package/dist/cli/providerConfig.js.map +1 -1
- package/dist/cli/runHeadless.js +85 -0
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/toolRegistry.js +50 -6
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenSelectTool.js +165 -0
- package/dist/cli/tools/krakenSelectTool.js.map +1 -0
- package/dist/cli/tools/krakenSelectTool.test.js +246 -0
- package/dist/cli/tools/krakenSelectTool.test.js.map +1 -0
- package/dist/cli/tools/taskTool.dynamicChecks.test.js +156 -0
- package/dist/cli/tools/taskTool.dynamicChecks.test.js.map +1 -0
- package/dist/cli/tools/taskTool.js +174 -6
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/dist/cli/tools/taskTool.planSafety.test.js +280 -0
- package/dist/cli/tools/taskTool.planSafety.test.js.map +1 -0
- package/dist/cli/tools/taskTool.verifyReport.test.js +140 -0
- package/dist/cli/tools/taskTool.verifyReport.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* krakenSelectTool.test — Fase 4 (ADR-0020) wiring tests for `kraken_select`:
|
|
3
|
+
* empty-registry no-op, happy path with a mocked provider stream, verifier
|
|
4
|
+
* unavailability degradation, and per-turn verdict storage.
|
|
5
|
+
*/
|
|
6
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
7
|
+
import { createKrakenSelectTool, collectProviderText } from './krakenSelectTool.js';
|
|
8
|
+
import { getKrakenSelection, registerCandidate, resetKrakenCandidates, } from '../kraken/candidateRegistry.js';
|
|
9
|
+
import { collectKrakenTurnMetrics, resetKrakenTurnMetrics } from '../kraken/metrics.js';
|
|
10
|
+
const verdictJson = (o) => `<selection-verdict>\n${JSON.stringify(o, null, 2)}\n</selection-verdict>`;
|
|
11
|
+
function addOkCandidate(hypothesis) {
|
|
12
|
+
registerCandidate({
|
|
13
|
+
status: 'ok',
|
|
14
|
+
description: hypothesis,
|
|
15
|
+
report: {
|
|
16
|
+
hypothesis,
|
|
17
|
+
evidence: [{ claim: `${hypothesis} observed`, basis: 'src/x.ts:10', degraded: false }],
|
|
18
|
+
risks: [],
|
|
19
|
+
hasDegradedEvidence: false,
|
|
20
|
+
},
|
|
21
|
+
raw: '',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function streamReturning(text) {
|
|
25
|
+
return async function* () {
|
|
26
|
+
yield { kind: 'text', delta: text };
|
|
27
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const IDENTITY = { provider: 'grok', model: 'grok-4-fast' };
|
|
31
|
+
function makeTool(overrides = {}) {
|
|
32
|
+
return createKrakenSelectTool({
|
|
33
|
+
loadParentIdentity: async () => IDENTITY,
|
|
34
|
+
loadStream: async () => streamReturning(verdictJson({ status: 'selected', winnerIndex: 1, rationale: 'r' })),
|
|
35
|
+
...overrides,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const ctx = {};
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
resetKrakenCandidates();
|
|
41
|
+
resetKrakenTurnMetrics();
|
|
42
|
+
});
|
|
43
|
+
describe('kraken_select tool', () => {
|
|
44
|
+
it('no candidates → typedOk no-op, no LLM, no stored verdict', async () => {
|
|
45
|
+
let streamCalls = 0;
|
|
46
|
+
const tool = makeTool({
|
|
47
|
+
loadStream: async () => {
|
|
48
|
+
streamCalls++;
|
|
49
|
+
return streamReturning('');
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const res = await tool.execute({}, ctx);
|
|
53
|
+
expect(res.ok).toBe(true);
|
|
54
|
+
if (res.ok)
|
|
55
|
+
expect(res.value.result).toContain('no candidates registered');
|
|
56
|
+
expect(streamCalls).toBe(0);
|
|
57
|
+
expect(getKrakenSelection()).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
it('happy path: two candidates → selected verdict stored + readable result', async () => {
|
|
60
|
+
addOkCandidate('race in refresh');
|
|
61
|
+
addOkCandidate('cookie expiry');
|
|
62
|
+
const tool = makeTool();
|
|
63
|
+
const res = await tool.execute({ task: 'fix intermittent session loss' }, ctx);
|
|
64
|
+
expect(res.ok).toBe(true);
|
|
65
|
+
if (res.ok) {
|
|
66
|
+
expect(res.value.result).toContain('SELECTED candidate #1');
|
|
67
|
+
expect(res.value.result).not.toContain('degraded');
|
|
68
|
+
}
|
|
69
|
+
const v = getKrakenSelection();
|
|
70
|
+
expect(v).toMatchObject({ status: 'selected', winnerIndex: 1, judgedBy: 'llm' });
|
|
71
|
+
expect(v?.verifier).toEqual(IDENTITY);
|
|
72
|
+
});
|
|
73
|
+
it('parent identity unavailable → degraded needs_more_evidence, turn continues', async () => {
|
|
74
|
+
addOkCandidate('a');
|
|
75
|
+
addOkCandidate('b');
|
|
76
|
+
const tool = makeTool({ loadParentIdentity: async () => null });
|
|
77
|
+
const res = await tool.execute({}, ctx);
|
|
78
|
+
expect(res.ok).toBe(true);
|
|
79
|
+
if (res.ok)
|
|
80
|
+
expect(res.value.result).toContain('NEEDS MORE EVIDENCE');
|
|
81
|
+
expect(getKrakenSelection()?.degraded).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
it('verifier provider config missing → degraded, not an error', async () => {
|
|
84
|
+
addOkCandidate('a');
|
|
85
|
+
addOkCandidate('b');
|
|
86
|
+
const tool = makeTool({ loadStream: async () => null });
|
|
87
|
+
const res = await tool.execute({}, ctx);
|
|
88
|
+
expect(res.ok).toBe(true);
|
|
89
|
+
const v = getKrakenSelection();
|
|
90
|
+
expect(v?.degraded).toBe(true);
|
|
91
|
+
expect(v?.fallbackReason).toBe('verifier call failed');
|
|
92
|
+
});
|
|
93
|
+
it('resetKrakenCandidates clears the stored verdict (per-turn lifecycle)', async () => {
|
|
94
|
+
addOkCandidate('a');
|
|
95
|
+
addOkCandidate('b');
|
|
96
|
+
await makeTool().execute({}, ctx);
|
|
97
|
+
expect(getKrakenSelection()).not.toBeNull();
|
|
98
|
+
resetKrakenCandidates();
|
|
99
|
+
expect(getKrakenSelection()).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
it('env model override reaches the verifier identity', async () => {
|
|
102
|
+
addOkCandidate('a');
|
|
103
|
+
addOkCandidate('b');
|
|
104
|
+
let seenModel = '';
|
|
105
|
+
const tool = makeTool({
|
|
106
|
+
env: { ZELARI_KRAKEN_SELECT_MODEL: 'glm-4.6' },
|
|
107
|
+
loadStream: async () => streamReturning(verdictJson({ status: 'selected', winnerIndex: 1 })),
|
|
108
|
+
});
|
|
109
|
+
// Intercept the model through collectProviderText params via a wrapping stream.
|
|
110
|
+
const wrap = async function* (params) {
|
|
111
|
+
seenModel = params.model;
|
|
112
|
+
yield { kind: 'text', delta: verdictJson({ status: 'selected', winnerIndex: 1 }) };
|
|
113
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
114
|
+
};
|
|
115
|
+
const tool2 = createKrakenSelectTool({
|
|
116
|
+
loadParentIdentity: async () => IDENTITY,
|
|
117
|
+
loadStream: async () => wrap,
|
|
118
|
+
env: { ZELARI_KRAKEN_SELECT_MODEL: 'glm-4.6' },
|
|
119
|
+
});
|
|
120
|
+
await tool.execute({}, ctx).catch(() => undefined);
|
|
121
|
+
await tool2.execute({}, ctx);
|
|
122
|
+
expect(seenModel).toBe('glm-4.6');
|
|
123
|
+
expect(getKrakenSelection()?.verifier?.model).toBe('glm-4.6');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('collectProviderText', () => {
|
|
127
|
+
it('concatenates text deltas, stops at finish, ignores thinking; captures usage', async () => {
|
|
128
|
+
const s = async function* () {
|
|
129
|
+
yield { kind: 'thinking', delta: 'hmm' };
|
|
130
|
+
yield { kind: 'text', delta: 'Hello ' };
|
|
131
|
+
yield { kind: 'usage', usage: { promptTokens: 10, completionTokens: 5, totalTokens: 15 } };
|
|
132
|
+
yield { kind: 'text', delta: 'world' };
|
|
133
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
134
|
+
yield { kind: 'text', delta: 'after finish (ignored)' };
|
|
135
|
+
};
|
|
136
|
+
const out = await collectProviderText(s, {
|
|
137
|
+
messages: [],
|
|
138
|
+
model: 'm',
|
|
139
|
+
provider: 'p',
|
|
140
|
+
tools: [],
|
|
141
|
+
});
|
|
142
|
+
expect(out.text).toBe('Hello world');
|
|
143
|
+
expect(out.usage?.totalTokens).toBe(15);
|
|
144
|
+
});
|
|
145
|
+
it('returns no usage when the provider reports none', async () => {
|
|
146
|
+
const s = async function* () {
|
|
147
|
+
yield { kind: 'text', delta: 'x' };
|
|
148
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
149
|
+
};
|
|
150
|
+
const out = await collectProviderText(s, {
|
|
151
|
+
messages: [],
|
|
152
|
+
model: 'm',
|
|
153
|
+
provider: 'p',
|
|
154
|
+
tools: [],
|
|
155
|
+
});
|
|
156
|
+
expect(out.text).toBe('x');
|
|
157
|
+
expect(out.usage).toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
it('throws on error deltas (caller degrades gracefully)', async () => {
|
|
160
|
+
const s = async function* () {
|
|
161
|
+
yield { kind: 'error', message: 'boom' };
|
|
162
|
+
};
|
|
163
|
+
await expect(collectProviderText(s, { messages: [], model: 'm', provider: 'p', tools: [] })).rejects.toThrow('boom');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('kraken_select — Fase 9 verifier override wiring', () => {
|
|
167
|
+
it('persisted override (loadVerifierOverride) → judging identity is the override', async () => {
|
|
168
|
+
addOkCandidate('h1');
|
|
169
|
+
addOkCandidate('h2');
|
|
170
|
+
let seenProvider = '';
|
|
171
|
+
let seenModel = '';
|
|
172
|
+
const captureStream = async function* (params) {
|
|
173
|
+
seenProvider = String(params.provider ?? '');
|
|
174
|
+
seenModel = String(params.model ?? '');
|
|
175
|
+
yield { kind: 'text', delta: verdictJson({ status: 'selected', winnerIndex: 2, rationale: 'r' }) };
|
|
176
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
177
|
+
};
|
|
178
|
+
const tool = makeTool({
|
|
179
|
+
env: {},
|
|
180
|
+
loadVerifierOverride: () => ({ provider: 'anthropic', model: 'claude-sonnet-4-6' }),
|
|
181
|
+
loadStream: async () => captureStream,
|
|
182
|
+
});
|
|
183
|
+
const res = await tool.execute({ task: 't' }, ctx);
|
|
184
|
+
expect(res.ok).toBe(true);
|
|
185
|
+
// the judging call went to the OVERRIDE, not the parent identity
|
|
186
|
+
expect(seenProvider).toBe('anthropic');
|
|
187
|
+
expect(seenModel).toBe('claude-sonnet-4-6');
|
|
188
|
+
expect(getKrakenSelection()?.verifier).toEqual({
|
|
189
|
+
provider: 'anthropic',
|
|
190
|
+
model: 'claude-sonnet-4-6',
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
it('no override → exact parent model (inherit default)', async () => {
|
|
194
|
+
addOkCandidate('h1');
|
|
195
|
+
addOkCandidate('h2');
|
|
196
|
+
let seenProvider = '';
|
|
197
|
+
const captureStream = async function* (params) {
|
|
198
|
+
seenProvider = String(params.provider ?? '');
|
|
199
|
+
yield { kind: 'text', delta: verdictJson({ status: 'selected', winnerIndex: 1, rationale: 'r' }) };
|
|
200
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
201
|
+
};
|
|
202
|
+
const tool = makeTool({
|
|
203
|
+
env: {},
|
|
204
|
+
loadStream: async () => captureStream,
|
|
205
|
+
});
|
|
206
|
+
const res = await tool.execute({ task: 't' }, ctx);
|
|
207
|
+
expect(res.ok).toBe(true);
|
|
208
|
+
expect(seenProvider).toBe(IDENTITY.provider);
|
|
209
|
+
expect(getKrakenSelection()?.verifier).toEqual(IDENTITY);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe('kraken_select — Fase 10 turn metrics', () => {
|
|
213
|
+
it('records selection usage: latency + provider-reported tokens + fallback flag', async () => {
|
|
214
|
+
addOkCandidate('race in refresh');
|
|
215
|
+
addOkCandidate('cookie expiry');
|
|
216
|
+
const tool = createKrakenSelectTool({
|
|
217
|
+
loadParentIdentity: async () => IDENTITY,
|
|
218
|
+
loadStream: async () => (async function* () {
|
|
219
|
+
yield { kind: 'text', delta: verdictJson({ status: 'selected', winnerIndex: 2, rationale: 'r' }) };
|
|
220
|
+
yield { kind: 'usage', usage: { promptTokens: 400, completionTokens: 100, totalTokens: 500 } };
|
|
221
|
+
yield { kind: 'finish', reason: 'stop' };
|
|
222
|
+
}),
|
|
223
|
+
});
|
|
224
|
+
const res = await tool.execute({ task: 'fix it' }, ctx);
|
|
225
|
+
expect(res.ok).toBe(true);
|
|
226
|
+
const m = collectKrakenTurnMetrics();
|
|
227
|
+
expect(m).not.toBeNull();
|
|
228
|
+
expect(m?.selectionUsed).toBe(true);
|
|
229
|
+
expect(m?.candidateCount).toBe(2);
|
|
230
|
+
expect(m?.selectionLatencyMs).toBeGreaterThanOrEqual(0);
|
|
231
|
+
expect(m?.selectionTokens).toBe(500);
|
|
232
|
+
expect(m?.selectionFallback).toBe(false);
|
|
233
|
+
expect(m?.needsMoreEvidence).toBe(false);
|
|
234
|
+
});
|
|
235
|
+
it('records fallback on degraded verdicts (no stream available)', async () => {
|
|
236
|
+
addOkCandidate('a');
|
|
237
|
+
addOkCandidate('b');
|
|
238
|
+
const tool = makeTool({ loadStream: async () => null });
|
|
239
|
+
const res = await tool.execute({ task: 'x' }, ctx);
|
|
240
|
+
expect(res.ok).toBe(true);
|
|
241
|
+
const m = collectKrakenTurnMetrics();
|
|
242
|
+
expect(m?.selectionFallback).toBe(true);
|
|
243
|
+
expect(m?.selectionTokens).toBeUndefined();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
//# sourceMappingURL=krakenSelectTool.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"krakenSelectTool.test.js","sourceRoot":"","sources":["../../../src/cli/tools/krakenSelectTool.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAExF,MAAM,WAAW,GAAG,CAAC,CAA0B,EAAE,EAAE,CACjD,wBAAwB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,wBAAwB,CAAC;AAE7E,SAAS,cAAc,CAAC,UAAkB;IACxC,iBAAiB,CAAC;QAChB,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE;YACN,UAAU;YACV,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,UAAU,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YACtF,KAAK,EAAE,EAAE;YACT,mBAAmB,EAAE,KAAK;SAC3B;QACD,GAAG,EAAE,EAAE;KACR,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,KAAK,SAAS,CAAC;QACpB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACpC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC3C,CAAgC,CAAC;AACnC,CAAC;AAED,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAE5D,SAAS,QAAQ,CAAC,YAAmE,EAAE;IACrF,OAAO,sBAAsB,CAAC;QAC5B,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;QACxC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5G,GAAG,SAAS;KACb,CAAC,CAAC;AACL,CAAC;AAED,MAAM,GAAG,GAAG,EAAW,CAAC;AAExB,SAAS,CAAC,GAAG,EAAE;IACb,qBAAqB,EAAE,CAAC;IACxB,sBAAsB,EAAE,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC;YACpB,UAAU,EAAE,KAAK,IAAI,EAAE;gBACrB,WAAW,EAAE,CAAC;gBACd,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;SACF,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAC3E,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,cAAc,CAAC,iBAAiB,CAAC,CAAC;QAClC,cAAc,CAAC,eAAe,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/E,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;YAC5D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACtE,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC5C,qBAAqB,EAAE,CAAC;QACxB,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,QAAQ,CAAC;YACpB,GAAG,EAAE,EAAE,0BAA0B,EAAE,SAAS,EAAE;YAC9C,UAAU,EAAE,KAAK,IAAI,EAAE,CACrB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;SACvE,CAAC,CAAC;QACH,gFAAgF;QAChF,MAAM,IAAI,GAAqB,KAAK,SAAS,CAAC,EAAE,MAAuC;YACrF,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YACnF,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAgC,CAAC;QACjC,MAAM,KAAK,GAAG,sBAAsB,CAAC;YACnC,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;YACxC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;YAC5B,GAAG,EAAE,EAAE,0BAA0B,EAAE,SAAS,EAAE;SAC/C,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClC,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,CAAC,GAAqB,KAAK,SAAS,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YACxC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC;YAC3F,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;YACvC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;QAC1D,CAAgC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,CAAC,EAAE;YACvC,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,GAAG;YACb,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,CAAC,GAAqB,KAAK,SAAS,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YACnC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAgC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,CAAC,EAAE;YACvC,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,GAAG;YACb,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,CAAC,GAAqB,KAAK,SAAS,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAgC,CAAC;QACjC,MAAM,MAAM,CACV,mBAAmB,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAC/E,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC/D,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,MAAM,aAAa,GAAqB,KAAK,SAAS,CAAC,EACrD,MAAuC;YAEvC,YAAY,GAAG,MAAM,CAAE,MAAgC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YACxE,SAAS,GAAG,MAAM,CAAE,MAA6B,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YAC/D,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YACnG,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAgC,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC;YACpB,GAAG,EAAE,EAAE;YACP,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;YACnF,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,aAAa;SACtC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,iEAAiE;QACjE,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC5C,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC;YAC7C,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,mBAAmB;SAC3B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,MAAM,aAAa,GAAqB,KAAK,SAAS,CAAC,EACrD,MAAuC;YAEvC,YAAY,GAAG,MAAM,CAAE,MAAgC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YACxE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YACnG,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAgC,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC;YACpB,GAAG,EAAE,EAAE;YACP,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,aAAa;SACtC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,cAAc,CAAC,iBAAiB,CAAC,CAAC;QAClC,cAAc,CAAC,eAAe,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,sBAAsB,CAAC;YAClC,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,QAAQ;YACxC,UAAU,EAAE,KAAK,IAAI,EAAE,CACrB,CAAC,KAAK,SAAS,CAAC;gBACd,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;gBACnG,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,CAAC;gBAC/F,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YAC3C,CAAC,CAAgC;SACpC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,wBAAwB,EAAE,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,wBAAwB,EAAE,CAAC;QACrC,MAAM,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,aAAa,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* taskTool.dynamicChecks.test — Fase 6 / ADR-0020 (Kraken Verified Selection).
|
|
3
|
+
*
|
|
4
|
+
* BUILD dynamic checks: le requiredChecks di una selezione `selected`
|
|
5
|
+
* diventano proof obligations AUTOMATICHE di ogni tentacle verify:
|
|
6
|
+
* - append dedupe case-insensitive sull'acceptance del parent
|
|
7
|
+
* - mai iniettate su explore/general
|
|
8
|
+
* - mai con needs_more_evidence (i check restano advisory)
|
|
9
|
+
* - assenza di selezione ⇒ comportamento invariato
|
|
10
|
+
*/
|
|
11
|
+
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
|
|
12
|
+
import { tmpdir } from 'node:os';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import { ToolRegistry } from '@zelari/core/harness/tools/registry';
|
|
16
|
+
import { createTaskTool, resetTaskSpawnCount, } from './taskTool.js';
|
|
17
|
+
import { resetKrakenCandidates, setKrakenSelection, } from '../kraken/candidateRegistry.js';
|
|
18
|
+
function tmpRoot() {
|
|
19
|
+
return fs.mkdtempSync(path.join(tmpdir(), 'zelari-dyn-checks-'));
|
|
20
|
+
}
|
|
21
|
+
function makeCtx(cwd = tmpRoot()) {
|
|
22
|
+
return {
|
|
23
|
+
signal: new AbortController().signal,
|
|
24
|
+
cwd,
|
|
25
|
+
audit: () => undefined,
|
|
26
|
+
sessionId: 'dynamic-checks-test',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Deps fake che cattura il user prompt del tentacle via harnessFactory:
|
|
31
|
+
* config.messages[0] = system, [1] = user (buildTaskUserPrompt output).
|
|
32
|
+
*/
|
|
33
|
+
function capturingDeps() {
|
|
34
|
+
const prompts = [];
|
|
35
|
+
const deps = {
|
|
36
|
+
createSubAgentContext: async ({ agent }) => {
|
|
37
|
+
const ctx = {
|
|
38
|
+
providerStream: (() => {
|
|
39
|
+
throw new Error('not invoked by the scripted harness');
|
|
40
|
+
}),
|
|
41
|
+
model: 'test-model',
|
|
42
|
+
provider: 'test-provider',
|
|
43
|
+
registry: new ToolRegistry(),
|
|
44
|
+
tools: [],
|
|
45
|
+
agent,
|
|
46
|
+
};
|
|
47
|
+
return ctx;
|
|
48
|
+
},
|
|
49
|
+
harnessFactory: (config) => {
|
|
50
|
+
prompts.push(String(config.messages[1]?.content ?? ''));
|
|
51
|
+
return {
|
|
52
|
+
run: async function* () {
|
|
53
|
+
yield { type: 'message_start' };
|
|
54
|
+
yield { type: 'message_delta', delta: 'verified' };
|
|
55
|
+
yield { type: 'message_end' };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
allowWorktree: false,
|
|
60
|
+
};
|
|
61
|
+
return { deps, userPrompts: () => prompts };
|
|
62
|
+
}
|
|
63
|
+
const CHECKS = [
|
|
64
|
+
'unit test for session refresh passes',
|
|
65
|
+
'no Set-Cookie regression on logout',
|
|
66
|
+
];
|
|
67
|
+
function verdict(status, requiredChecks = CHECKS) {
|
|
68
|
+
return {
|
|
69
|
+
status,
|
|
70
|
+
winnerIndex: status === 'selected' ? 1 : null,
|
|
71
|
+
rationale: 'grounded in evidence',
|
|
72
|
+
requiredChecks,
|
|
73
|
+
degraded: false,
|
|
74
|
+
verifier: { provider: 'p', model: 'm' },
|
|
75
|
+
judgedBy: 'llm',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function spawnVerify(deps, acceptance) {
|
|
79
|
+
const tool = createTaskTool(deps);
|
|
80
|
+
const res = await tool.execute({
|
|
81
|
+
description: 'verify the fix',
|
|
82
|
+
prompt: 'Verify the implementation.',
|
|
83
|
+
agent: 'verify',
|
|
84
|
+
...(acceptance ? { acceptance } : {}),
|
|
85
|
+
}, makeCtx());
|
|
86
|
+
if (!res.ok)
|
|
87
|
+
throw new Error(`task failed: ${String(res.error)}`);
|
|
88
|
+
return '';
|
|
89
|
+
}
|
|
90
|
+
describe('verify acceptance injection (ADR-0020 Fase 6)', () => {
|
|
91
|
+
beforeEach(() => {
|
|
92
|
+
resetTaskSpawnCount();
|
|
93
|
+
resetKrakenCandidates();
|
|
94
|
+
});
|
|
95
|
+
afterEach(() => {
|
|
96
|
+
resetKrakenCandidates();
|
|
97
|
+
});
|
|
98
|
+
it('selected verdict → requiredChecks become the verify acceptance', async () => {
|
|
99
|
+
const { deps, userPrompts } = capturingDeps();
|
|
100
|
+
setKrakenSelection(verdict('selected'));
|
|
101
|
+
await spawnVerify(deps);
|
|
102
|
+
const prompt = userPrompts()[0];
|
|
103
|
+
expect(prompt).toContain('## Acceptance criteria');
|
|
104
|
+
expect(prompt).toContain(CHECKS[0]);
|
|
105
|
+
expect(prompt).toContain(CHECKS[1]);
|
|
106
|
+
});
|
|
107
|
+
it('merges with parent acceptance, deduped case-insensitively', async () => {
|
|
108
|
+
const { deps, userPrompts } = capturingDeps();
|
|
109
|
+
setKrakenSelection(verdict('selected'));
|
|
110
|
+
await spawnVerify(deps, [
|
|
111
|
+
'Existing criterion', // parent-provided, must be kept
|
|
112
|
+
'Unit Test For Session Refresh Passes', // same check, different case
|
|
113
|
+
]);
|
|
114
|
+
const prompt = userPrompts()[0];
|
|
115
|
+
expect(prompt).toContain('Existing criterion');
|
|
116
|
+
// dedupe: the case-variant does not produce a second copy
|
|
117
|
+
expect(prompt.match(/session refresh passes/gi)).toHaveLength(1);
|
|
118
|
+
// the non-duplicated required check is appended once
|
|
119
|
+
expect(prompt.match(/Set-Cookie regression/gi)).toHaveLength(1);
|
|
120
|
+
});
|
|
121
|
+
it('needs_more_evidence → checks stay advisory (no injection)', async () => {
|
|
122
|
+
const { deps, userPrompts } = capturingDeps();
|
|
123
|
+
setKrakenSelection(verdict('needs_more_evidence'));
|
|
124
|
+
await spawnVerify(deps);
|
|
125
|
+
expect(userPrompts()[0]).not.toContain('## Acceptance criteria');
|
|
126
|
+
expect(userPrompts()[0]).not.toContain(CHECKS[0]);
|
|
127
|
+
});
|
|
128
|
+
it('explore tentacle is never touched by the injection', async () => {
|
|
129
|
+
const { deps, userPrompts } = capturingDeps();
|
|
130
|
+
setKrakenSelection(verdict('selected'));
|
|
131
|
+
const tool = createTaskTool(deps);
|
|
132
|
+
await tool.execute({ description: 'explore', prompt: 'Look around.', agent: 'explore' }, makeCtx());
|
|
133
|
+
expect(userPrompts()[0]).not.toContain('## Acceptance criteria');
|
|
134
|
+
expect(userPrompts()[0]).not.toContain(CHECKS[0]);
|
|
135
|
+
});
|
|
136
|
+
it('general tentacle keeps its own acceptance only', async () => {
|
|
137
|
+
const { deps, userPrompts } = capturingDeps();
|
|
138
|
+
setKrakenSelection(verdict('selected'));
|
|
139
|
+
const tool = createTaskTool(deps);
|
|
140
|
+
await tool.execute({
|
|
141
|
+
description: 'impl',
|
|
142
|
+
prompt: 'Implement.',
|
|
143
|
+
agent: 'general',
|
|
144
|
+
acceptance: ['Only criterion'],
|
|
145
|
+
}, makeCtx());
|
|
146
|
+
const prompt = userPrompts()[0];
|
|
147
|
+
expect(prompt).toContain('Only criterion');
|
|
148
|
+
expect(prompt).not.toContain(CHECKS[0]);
|
|
149
|
+
});
|
|
150
|
+
it('no selection this turn → verify prompt unchanged (no acceptance)', async () => {
|
|
151
|
+
const { deps, userPrompts } = capturingDeps();
|
|
152
|
+
await spawnVerify(deps);
|
|
153
|
+
expect(userPrompts()[0]).not.toContain('## Acceptance criteria');
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=taskTool.dynamicChecks.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskTool.dynamicChecks.test.js","sourceRoot":"","sources":["../../../src/cli/tools/taskTool.dynamicChecks.test.ts"],"names":[],"mappings":"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"}
|