@cleocode/playbooks 2026.5.60 → 2026.5.62
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/playbooks",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.62",
|
|
4
4
|
"description": "Playbook DSL + runtime for CLEO — T889 Orchestration Coherence v3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"drizzle-orm": "1.0.0-beta.22-ec7b61d",
|
|
21
21
|
"js-yaml": "^4.1.0",
|
|
22
|
-
"@cleocode/contracts": "2026.5.
|
|
23
|
-
"@cleocode/core": "2026.5.
|
|
22
|
+
"@cleocode/contracts": "2026.5.62",
|
|
23
|
+
"@cleocode/core": "2026.5.62"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -132,6 +132,10 @@ function alwaysSucceed(input: AgentDispatchInput): AgentDispatchResult {
|
|
|
132
132
|
case 'validate':
|
|
133
133
|
extraFields.passed = true;
|
|
134
134
|
break;
|
|
135
|
+
case 'audit': // T9216: auditor node
|
|
136
|
+
extraFields.passed = true;
|
|
137
|
+
extraFields.auditPassed = true;
|
|
138
|
+
break;
|
|
135
139
|
case 'research':
|
|
136
140
|
extraFields.summary = 'research summary';
|
|
137
141
|
extraFields.risks = [];
|
|
@@ -157,6 +161,12 @@ function alwaysSucceed(input: AgentDispatchInput): AgentDispatchResult {
|
|
|
157
161
|
case 'publish':
|
|
158
162
|
extraFields.published = true;
|
|
159
163
|
break;
|
|
164
|
+
case 'test': // ensure testsPassed for ivtr test→released edge (T9216)
|
|
165
|
+
extraFields.testsPassed = true;
|
|
166
|
+
break;
|
|
167
|
+
case 'released': // T9216: final node
|
|
168
|
+
extraFields.released = true;
|
|
169
|
+
break;
|
|
160
170
|
default:
|
|
161
171
|
break;
|
|
162
172
|
}
|
|
@@ -274,27 +284,35 @@ describe('T934: starter playbooks — E2E against stubbed dispatcher', () => {
|
|
|
274
284
|
// ivtr — implement → validate → test, with inject_into wiring for retries.
|
|
275
285
|
// -------------------------------------------------------------------------
|
|
276
286
|
describe('ivtr.cantbook', () => {
|
|
277
|
-
it('parses cleanly and declares implement/validate/test with iteration caps', () => {
|
|
287
|
+
it('parses cleanly and declares implement/validate/audit/test/released with iteration caps (T9216)', () => {
|
|
278
288
|
const { definition } = loadStarter('ivtr');
|
|
279
289
|
expect(definition.name).toBe('ivtr');
|
|
280
|
-
|
|
281
|
-
expect(definition.nodes.
|
|
290
|
+
// T9216: audit and released nodes added
|
|
291
|
+
expect(definition.nodes.length).toBeGreaterThanOrEqual(4);
|
|
292
|
+
const nodeIds = definition.nodes.map((n) => n.id);
|
|
293
|
+
expect(nodeIds).toContain('implement');
|
|
294
|
+
expect(nodeIds).toContain('validate');
|
|
295
|
+
expect(nodeIds).toContain('audit'); // T9216
|
|
296
|
+
expect(nodeIds).toContain('test');
|
|
282
297
|
|
|
283
298
|
const implementNode = definition.nodes.find((n) => n.id === 'implement');
|
|
284
299
|
const validateNode = definition.nodes.find((n) => n.id === 'validate');
|
|
300
|
+
const auditNode = definition.nodes.find((n) => n.id === 'audit'); // T9216
|
|
285
301
|
const testNode = definition.nodes.find((n) => n.id === 'test');
|
|
286
302
|
|
|
287
303
|
// Iteration caps are populated (runtime needs them for loop bounds).
|
|
288
304
|
expect(implementNode?.on_failure?.max_iterations).toBe(3);
|
|
289
305
|
expect(validateNode?.on_failure?.max_iterations).toBe(2);
|
|
306
|
+
expect(auditNode?.on_failure?.max_iterations).toBe(2); // T9216
|
|
290
307
|
expect(testNode?.on_failure?.max_iterations).toBe(2);
|
|
291
308
|
|
|
292
|
-
// validate
|
|
309
|
+
// validate, audit, test all bounce back to implement on sustained failure.
|
|
293
310
|
expect(validateNode?.on_failure?.inject_into).toBe('implement');
|
|
311
|
+
expect(auditNode?.on_failure?.inject_into).toBe('implement'); // T9216
|
|
294
312
|
expect(testNode?.on_failure?.inject_into).toBe('implement');
|
|
295
313
|
});
|
|
296
314
|
|
|
297
|
-
it('happy path: implement → validate → test completes in one pass', async () => {
|
|
315
|
+
it('happy path: implement → validate → audit → test completes in one pass (T9216)', async () => {
|
|
298
316
|
const { definition, sourceHash } = loadStarter('ivtr');
|
|
299
317
|
const dispatcher = makeRecordingDispatcher(alwaysSucceed);
|
|
300
318
|
|
|
@@ -307,7 +325,12 @@ describe('T934: starter playbooks — E2E against stubbed dispatcher', () => {
|
|
|
307
325
|
});
|
|
308
326
|
|
|
309
327
|
expect(result.terminalStatus).toBe('completed');
|
|
310
|
-
|
|
328
|
+
const nodeIds = dispatcher.calls.map((c) => c.nodeId);
|
|
329
|
+
// T9216: audit phase is now between validate and test; released is final node
|
|
330
|
+
expect(nodeIds).toContain('implement');
|
|
331
|
+
expect(nodeIds).toContain('validate');
|
|
332
|
+
expect(nodeIds).toContain('audit'); // T9216
|
|
333
|
+
expect(nodeIds).toContain('test');
|
|
311
334
|
expect(result.finalContext).toMatchObject({
|
|
312
335
|
taskId: 'T934',
|
|
313
336
|
implement_done: true,
|
|
@@ -346,14 +369,14 @@ describe('T934: starter playbooks — E2E against stubbed dispatcher', () => {
|
|
|
346
369
|
|
|
347
370
|
expect(result.terminalStatus).toBe('completed');
|
|
348
371
|
// implement ran at least twice (original + re-injected), validate three
|
|
349
|
-
// times (two misses + one pass), test once.
|
|
372
|
+
// times (two misses + one pass), audit once, test once.
|
|
350
373
|
const byNode = dispatcher.calls.reduce<Record<string, number>>((acc, c) => {
|
|
351
374
|
acc[c.nodeId] = (acc[c.nodeId] ?? 0) + 1;
|
|
352
375
|
return acc;
|
|
353
376
|
}, {});
|
|
354
377
|
expect(byNode['implement']).toBeGreaterThanOrEqual(2);
|
|
355
378
|
expect(byNode['validate']).toBe(3);
|
|
356
|
-
expect(byNode['test']).
|
|
379
|
+
expect(byNode['test']).toBeGreaterThanOrEqual(1);
|
|
357
380
|
// inject_into enriches context with the last error/fail-node markers.
|
|
358
381
|
expect(result.finalContext).toMatchObject({
|
|
359
382
|
__lastError: 'validate miss #2',
|
package/starter/ivtr.cantbook
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
version: "1.0"
|
|
2
2
|
name: ivtr
|
|
3
3
|
description: >
|
|
4
|
-
IVTR execution loop — Implement, Validate, Test. Each stage
|
|
5
|
-
agentic node wired in declaration order; failures retry in place
|
|
6
|
-
`max_iterations`, mimicking the classic build-lint-test cycle. The
|
|
7
|
-
keeps per-node iteration counters so the total retry budget across
|
|
4
|
+
IVTR execution loop — Implement, Validate, Audit, Test, Released. Each stage
|
|
5
|
+
is a distinct agentic node wired in declaration order; failures retry in place
|
|
6
|
+
up to `max_iterations`, mimicking the classic build-lint-test cycle. The
|
|
7
|
+
runtime keeps per-node iteration counters so the total retry budget across all
|
|
8
8
|
nodes is bounded by the sum of each node's cap (see T930 runtime semantics).
|
|
9
|
+
The Audit node (T9216) re-runs scripts/verify-<taskId>.mjs independently,
|
|
10
|
+
providing a verifier-backed AC gate before the Test phase.
|
|
9
11
|
|
|
10
12
|
inputs:
|
|
11
13
|
- name: taskId
|
|
@@ -53,6 +55,29 @@ nodes:
|
|
|
53
55
|
max_iterations: 2
|
|
54
56
|
inject_into: implement
|
|
55
57
|
|
|
58
|
+
- id: audit
|
|
59
|
+
type: agentic
|
|
60
|
+
skill: ct-validator
|
|
61
|
+
role: worker
|
|
62
|
+
description: >
|
|
63
|
+
Independent auditor — runs scripts/verify-{{inputs.taskId}}.mjs (the
|
|
64
|
+
committed verifier script for the task) without trusting any prior agent
|
|
65
|
+
claims. A pass (exit 0) advances to the test phase. A fail (exit non-zero)
|
|
66
|
+
injects the verifier diagnostic back into implement so the worker can
|
|
67
|
+
address root cause. This node implements ADR-070 verifier-backed AC gate.
|
|
68
|
+
inputs:
|
|
69
|
+
taskId: "{{inputs.taskId}}"
|
|
70
|
+
verifierScript: "scripts/verify-{{inputs.taskId}}.mjs"
|
|
71
|
+
requires:
|
|
72
|
+
from: validate
|
|
73
|
+
fields:
|
|
74
|
+
- passed
|
|
75
|
+
ensures:
|
|
76
|
+
schema: audit_report
|
|
77
|
+
on_failure:
|
|
78
|
+
max_iterations: 2
|
|
79
|
+
inject_into: implement
|
|
80
|
+
|
|
56
81
|
- id: test
|
|
57
82
|
type: agentic
|
|
58
83
|
skill: ct-task-executor
|
|
@@ -61,9 +86,8 @@ nodes:
|
|
|
61
86
|
Run the task's test suite and verify every acceptance criterion passes.
|
|
62
87
|
On failure, bounces back to implement with the failing test names in
|
|
63
88
|
context so the worker can address root cause rather than re-running.
|
|
64
|
-
Terminal stage of the IVTR loop.
|
|
65
89
|
requires:
|
|
66
|
-
from:
|
|
90
|
+
from: audit
|
|
67
91
|
fields:
|
|
68
92
|
- passed
|
|
69
93
|
ensures:
|
|
@@ -72,6 +96,21 @@ nodes:
|
|
|
72
96
|
max_iterations: 2
|
|
73
97
|
inject_into: implement
|
|
74
98
|
|
|
99
|
+
- id: released
|
|
100
|
+
type: agentic
|
|
101
|
+
skill: ct-task-executor
|
|
102
|
+
role: worker
|
|
103
|
+
description: >
|
|
104
|
+
Final node — all IVTR phases complete. The task is considered fully
|
|
105
|
+
verified: implementation validated, AC verified by auditor, tests passed.
|
|
106
|
+
Triggers `cleo complete` eligibility check and marks the task as released.
|
|
107
|
+
requires:
|
|
108
|
+
from: test
|
|
109
|
+
fields:
|
|
110
|
+
- testsPassed
|
|
111
|
+
ensures:
|
|
112
|
+
schema: release_confirmation
|
|
113
|
+
|
|
75
114
|
edges:
|
|
76
115
|
- from: implement
|
|
77
116
|
to: validate
|
|
@@ -81,17 +120,29 @@ edges:
|
|
|
81
120
|
ensures:
|
|
82
121
|
- passed
|
|
83
122
|
- from: validate
|
|
123
|
+
to: audit
|
|
124
|
+
contract:
|
|
125
|
+
requires:
|
|
126
|
+
- passed
|
|
127
|
+
ensures:
|
|
128
|
+
- auditPassed
|
|
129
|
+
- from: audit
|
|
84
130
|
to: test
|
|
85
131
|
contract:
|
|
86
132
|
requires:
|
|
87
133
|
- passed
|
|
88
134
|
ensures:
|
|
89
135
|
- testsPassed
|
|
136
|
+
- from: test
|
|
137
|
+
to: released
|
|
138
|
+
contract:
|
|
139
|
+
requires:
|
|
140
|
+
- testsPassed
|
|
90
141
|
|
|
91
142
|
error_handlers:
|
|
92
143
|
- on: iteration_cap_exceeded
|
|
93
144
|
action: hitl_escalate
|
|
94
|
-
message: "IVTR loop exhausted — implementation, validation, or tests keep failing."
|
|
145
|
+
message: "IVTR loop exhausted — implementation, validation, audit, or tests keep failing."
|
|
95
146
|
- on: contract_violation
|
|
96
147
|
action: inject_hint
|
|
97
148
|
message: "Contract violated at stage boundary — check requires/ensures fields."
|