@osovv/vv-opencode 1.3.4 → 1.3.6-rc.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.
@@ -1,11 +1,19 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.4/schemas/vvoc/v3.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.6-rc.0/schemas/vvoc/v3.json",
4
4
  "title": "vvoc config",
5
5
  "description": "Canonical vvoc configuration document.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
- "required": ["$schema", "version", "roles", "guardian", "secretsRedaction", "presets", "plugins"],
8
+ "required": [
9
+ "$schema",
10
+ "version",
11
+ "roles",
12
+ "guardian",
13
+ "secretsRedaction",
14
+ "presets",
15
+ "plugins"
16
+ ],
9
17
  "properties": {
10
18
  "$schema": {
11
19
  "type": "string",
@@ -31,48 +39,101 @@
31
39
  "orchestration": {
32
40
  "type": "object",
33
41
  "additionalProperties": false,
34
- "required": ["profile"],
42
+ "required": [
43
+ "profile"
44
+ ],
35
45
  "properties": {
36
46
  "profile": {
37
47
  "type": "string",
38
- "enum": ["single-session", "balanced", "orchestrated"]
48
+ "enum": [
49
+ "single-session",
50
+ "balanced",
51
+ "orchestrated"
52
+ ]
39
53
  }
40
54
  }
41
55
  },
42
56
  "guardian": {
43
57
  "type": "object",
44
58
  "additionalProperties": false,
45
- "required": ["timeoutMs", "approvalRiskThreshold", "reviewToastDurationMs"],
59
+ "required": [
60
+ "timeoutMs",
61
+ "approvalRiskThreshold",
62
+ "reviewToastDurationMs"
63
+ ],
46
64
  "properties": {
47
- "model": { "type": "string", "minLength": 1 },
48
- "timeoutMs": { "type": "integer", "minimum": 1 },
49
- "approvalRiskThreshold": { "type": "integer", "minimum": 0, "maximum": 100 },
50
- "reviewToastDurationMs": { "type": "integer", "minimum": 1 }
65
+ "model": {
66
+ "type": "string",
67
+ "minLength": 1
68
+ },
69
+ "timeoutMs": {
70
+ "type": "integer",
71
+ "minimum": 1
72
+ },
73
+ "approvalRiskThreshold": {
74
+ "type": "integer",
75
+ "minimum": 0,
76
+ "maximum": 100
77
+ },
78
+ "reviewToastDurationMs": {
79
+ "type": "integer",
80
+ "minimum": 1
81
+ }
51
82
  }
52
83
  },
53
84
  "secretsRedaction": {
54
85
  "type": "object",
55
86
  "additionalProperties": false,
56
- "required": ["secret", "ttlMs", "maxMappings", "patterns", "debug"],
87
+ "required": [
88
+ "secret",
89
+ "ttlMs",
90
+ "maxMappings",
91
+ "patterns",
92
+ "debug"
93
+ ],
57
94
  "properties": {
58
- "secret": { "type": "string", "minLength": 1 },
59
- "ttlMs": { "type": "integer", "minimum": 0 },
60
- "maxMappings": { "type": "integer", "minimum": 1 },
61
- "debug": { "type": "boolean" },
95
+ "secret": {
96
+ "type": "string",
97
+ "minLength": 1
98
+ },
99
+ "ttlMs": {
100
+ "type": "integer",
101
+ "minimum": 0
102
+ },
103
+ "maxMappings": {
104
+ "type": "integer",
105
+ "minimum": 1
106
+ },
107
+ "debug": {
108
+ "type": "boolean"
109
+ },
62
110
  "patterns": {
63
111
  "type": "object",
64
112
  "additionalProperties": false,
65
- "required": ["keywords", "regex", "builtin", "exclude"],
113
+ "required": [
114
+ "keywords",
115
+ "regex",
116
+ "builtin",
117
+ "exclude"
118
+ ],
66
119
  "properties": {
67
120
  "keywords": {
68
121
  "type": "array",
69
122
  "items": {
70
123
  "type": "object",
71
124
  "additionalProperties": false,
72
- "required": ["value"],
125
+ "required": [
126
+ "value"
127
+ ],
73
128
  "properties": {
74
- "value": { "type": "string", "minLength": 1 },
75
- "category": { "type": "string", "minLength": 1 }
129
+ "value": {
130
+ "type": "string",
131
+ "minLength": 1
132
+ },
133
+ "category": {
134
+ "type": "string",
135
+ "minLength": 1
136
+ }
76
137
  }
77
138
  }
78
139
  },
@@ -81,20 +142,35 @@
81
142
  "items": {
82
143
  "type": "object",
83
144
  "additionalProperties": false,
84
- "required": ["pattern", "category"],
145
+ "required": [
146
+ "pattern",
147
+ "category"
148
+ ],
85
149
  "properties": {
86
- "pattern": { "type": "string", "minLength": 1 },
87
- "category": { "type": "string", "minLength": 1 }
150
+ "pattern": {
151
+ "type": "string",
152
+ "minLength": 1
153
+ },
154
+ "category": {
155
+ "type": "string",
156
+ "minLength": 1
157
+ }
88
158
  }
89
159
  }
90
160
  },
91
161
  "builtin": {
92
162
  "type": "array",
93
- "items": { "type": "string", "minLength": 1 }
163
+ "items": {
164
+ "type": "string",
165
+ "minLength": 1
166
+ }
94
167
  },
95
168
  "exclude": {
96
169
  "type": "array",
97
- "items": { "type": "string", "minLength": 1 }
170
+ "items": {
171
+ "type": "string",
172
+ "minLength": 1
173
+ }
98
174
  }
99
175
  }
100
176
  }
@@ -102,13 +178,20 @@
102
178
  },
103
179
  "presets": {
104
180
  "type": "object",
105
- "propertyNames": { "minLength": 1 },
181
+ "propertyNames": {
182
+ "minLength": 1
183
+ },
106
184
  "additionalProperties": {
107
185
  "type": "object",
108
186
  "additionalProperties": false,
109
- "required": ["agents"],
187
+ "required": [
188
+ "agents"
189
+ ],
110
190
  "properties": {
111
- "description": { "type": "string", "minLength": 1 },
191
+ "description": {
192
+ "type": "string",
193
+ "minLength": 1
194
+ },
112
195
  "agents": {
113
196
  "type": "object",
114
197
  "propertyNames": {
@@ -116,16 +199,25 @@
116
199
  "pattern": "^[a-z][a-z0-9-]*$"
117
200
  },
118
201
  "minProperties": 1,
119
- "additionalProperties": { "type": "string", "minLength": 1 }
202
+ "additionalProperties": {
203
+ "type": "string",
204
+ "minLength": 1
205
+ }
120
206
  },
121
207
  "orchestration": {
122
208
  "type": "object",
123
209
  "additionalProperties": false,
124
- "required": ["profile"],
210
+ "required": [
211
+ "profile"
212
+ ],
125
213
  "properties": {
126
214
  "profile": {
127
215
  "type": "string",
128
- "enum": ["single-session", "balanced", "orchestrated"]
216
+ "enum": [
217
+ "single-session",
218
+ "balanced",
219
+ "orchestrated"
220
+ ]
129
221
  }
130
222
  }
131
223
  }
@@ -134,29 +226,47 @@
134
226
  },
135
227
  "plugins": {
136
228
  "type": "object",
137
- "propertyNames": { "minLength": 1 },
229
+ "propertyNames": {
230
+ "minLength": 1
231
+ },
138
232
  "additionalProperties": {
139
233
  "anyOf": [
140
- { "type": "boolean" },
234
+ {
235
+ "type": "boolean"
236
+ },
141
237
  {
142
238
  "type": "object",
143
239
  "additionalProperties": false,
144
240
  "properties": {
145
- "enabled": { "type": "boolean" },
241
+ "enabled": {
242
+ "type": "boolean"
243
+ },
146
244
  "routing": {
147
245
  "type": "object",
148
246
  "additionalProperties": false,
149
247
  "properties": {
150
248
  "default": {
151
249
  "type": "string",
152
- "enum": ["hashline", "replace", "str_replace_editor", "passthrough"]
250
+ "enum": [
251
+ "hashline",
252
+ "replace",
253
+ "str_replace_editor",
254
+ "passthrough"
255
+ ]
153
256
  },
154
257
  "rules": {
155
258
  "type": "object",
156
- "propertyNames": { "minLength": 1 },
259
+ "propertyNames": {
260
+ "minLength": 1
261
+ },
157
262
  "additionalProperties": {
158
263
  "type": "string",
159
- "enum": ["hashline", "replace", "str_replace_editor", "passthrough"]
264
+ "enum": [
265
+ "hashline",
266
+ "replace",
267
+ "str_replace_editor",
268
+ "passthrough"
269
+ ]
160
270
  }
161
271
  }
162
272
  }
@@ -167,17 +277,124 @@
167
277
  "type": "object",
168
278
  "additionalProperties": false,
169
279
  "properties": {
170
- "enabled": { "type": "boolean" },
171
- "protectLastCalls": { "type": "integer", "minimum": 0 },
172
- "protectRecentMessages": { "type": "integer", "minimum": 0 },
173
- "savePrunedOutput": { "type": "boolean" },
174
- "minSavingsChars": { "type": "integer", "minimum": 0 },
175
- "outputMaxChars": { "type": "integer", "minimum": 0 },
176
- "headChars": { "type": "integer", "minimum": 0 },
177
- "tailChars": { "type": "integer", "minimum": 0 },
178
- "readSlim": { "type": "boolean" },
179
- "retainTools": { "type": "array", "items": { "type": "string", "minLength": 1 } }
280
+ "enabled": {
281
+ "type": "boolean"
282
+ },
283
+ "protectLastCalls": {
284
+ "type": "integer",
285
+ "minimum": 0
286
+ },
287
+ "protectRecentMessages": {
288
+ "type": "integer",
289
+ "minimum": 0
290
+ },
291
+ "savePrunedOutput": {
292
+ "type": "boolean"
293
+ },
294
+ "minSavingsChars": {
295
+ "type": "integer",
296
+ "minimum": 0
297
+ },
298
+ "outputMaxChars": {
299
+ "type": "integer",
300
+ "minimum": 0
301
+ },
302
+ "headChars": {
303
+ "type": "integer",
304
+ "minimum": 0
305
+ },
306
+ "tailChars": {
307
+ "type": "integer",
308
+ "minimum": 0
309
+ },
310
+ "readSlim": {
311
+ "type": "boolean"
312
+ },
313
+ "retainTools": {
314
+ "type": "array",
315
+ "items": {
316
+ "type": "string",
317
+ "minLength": 1
318
+ }
319
+ }
180
320
  }
321
+ },
322
+ {
323
+ "type": "object",
324
+ "description": "peak-hours plugin entry: enabled, mode, graceActiveSessions, and provider peak-window schedules.",
325
+ "properties": {
326
+ "enabled": {
327
+ "type": "boolean"
328
+ },
329
+ "mode": {
330
+ "type": "string",
331
+ "enum": [
332
+ "soft",
333
+ "hard"
334
+ ]
335
+ },
336
+ "graceActiveSessions": {
337
+ "type": "boolean"
338
+ },
339
+ "schedules": {
340
+ "type": "object",
341
+ "propertyNames": {
342
+ "minLength": 1
343
+ },
344
+ "additionalProperties": {
345
+ "type": "object",
346
+ "properties": {
347
+ "mode": {
348
+ "type": "string",
349
+ "enum": [
350
+ "soft",
351
+ "hard"
352
+ ]
353
+ },
354
+ "windows": {
355
+ "type": "array",
356
+ "minItems": 1,
357
+ "items": {
358
+ "type": "object",
359
+ "properties": {
360
+ "start": {
361
+ "type": "string",
362
+ "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
363
+ },
364
+ "end": {
365
+ "type": "string",
366
+ "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
367
+ },
368
+ "tz": {
369
+ "type": "string",
370
+ "minLength": 1
371
+ },
372
+ "days": {
373
+ "type": "array",
374
+ "minItems": 1,
375
+ "items": {
376
+ "type": "integer",
377
+ "minimum": 0,
378
+ "maximum": 6
379
+ }
380
+ }
381
+ },
382
+ "required": [
383
+ "start",
384
+ "end"
385
+ ],
386
+ "additionalProperties": false
387
+ }
388
+ }
389
+ },
390
+ "required": [
391
+ "windows"
392
+ ],
393
+ "additionalProperties": false
394
+ }
395
+ }
396
+ },
397
+ "additionalProperties": false
181
398
  }
182
399
  ]
183
400
  }
@@ -190,17 +407,43 @@
190
407
  "type": "object",
191
408
  "additionalProperties": false,
192
409
  "properties": {
193
- "provider": { "type": "string", "enum": ["exa", "brave", "zai"] },
194
- "region": { "type": "string", "enum": ["international", "china"] },
195
- "apiKey": { "type": "string", "minLength": 1 }
410
+ "provider": {
411
+ "type": "string",
412
+ "enum": [
413
+ "exa",
414
+ "brave",
415
+ "zai"
416
+ ]
417
+ },
418
+ "region": {
419
+ "type": "string",
420
+ "enum": [
421
+ "international",
422
+ "china"
423
+ ]
424
+ },
425
+ "apiKey": {
426
+ "type": "string",
427
+ "minLength": 1
428
+ }
196
429
  },
197
430
  "allOf": [
198
431
  {
199
432
  "if": {
200
- "properties": { "provider": { "const": "zai" } },
201
- "required": ["provider"]
433
+ "properties": {
434
+ "provider": {
435
+ "const": "zai"
436
+ }
437
+ },
438
+ "required": [
439
+ "provider"
440
+ ]
202
441
  },
203
- "then": { "required": ["region"] }
442
+ "then": {
443
+ "required": [
444
+ "region"
445
+ ]
446
+ }
204
447
  }
205
448
  ]
206
449
  },
@@ -208,17 +451,43 @@
208
451
  "type": "object",
209
452
  "additionalProperties": false,
210
453
  "properties": {
211
- "provider": { "type": "string", "enum": ["native", "spider", "zai"] },
212
- "region": { "type": "string", "enum": ["international", "china"] },
213
- "apiKey": { "type": "string", "minLength": 1 }
454
+ "provider": {
455
+ "type": "string",
456
+ "enum": [
457
+ "native",
458
+ "spider",
459
+ "zai"
460
+ ]
461
+ },
462
+ "region": {
463
+ "type": "string",
464
+ "enum": [
465
+ "international",
466
+ "china"
467
+ ]
468
+ },
469
+ "apiKey": {
470
+ "type": "string",
471
+ "minLength": 1
472
+ }
214
473
  },
215
474
  "allOf": [
216
475
  {
217
476
  "if": {
218
- "properties": { "provider": { "const": "zai" } },
219
- "required": ["provider"]
477
+ "properties": {
478
+ "provider": {
479
+ "const": "zai"
480
+ }
481
+ },
482
+ "required": [
483
+ "provider"
484
+ ]
220
485
  },
221
- "then": { "required": ["region"] }
486
+ "then": {
487
+ "required": [
488
+ "region"
489
+ ]
490
+ }
222
491
  }
223
492
  ]
224
493
  }
@@ -45,27 +45,27 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
45
45
  <purpose>List all module names</purpose>
46
46
  </helper>
47
47
  <helper name="list-tasks">
48
- <command>grep '&lt;id&gt;T-' PLAN_PATH</command>
48
+ <command>grep '&lt;TASK-T-' PLAN_PATH</command>
49
49
  <purpose>List all task IDs in document order</purpose>
50
50
  </helper>
51
51
  <helper name="extract-task">
52
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH</command>
53
- <purpose>Extract one full task by ID (replace T-NNN with actual ID like T-001)</purpose>
52
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH</command>
53
+ <purpose>Extract one full task by ID (replace T-NNN in the TASK-T-NNN element name with the actual ID, e.g. TASK-T-001)</purpose>
54
54
  </helper>
55
55
  <helper name="extract-snippet">
56
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | sed -n '/&lt;snippet&gt;/,/&lt;\/snippet&gt;/p'</command>
56
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | sed -n '/&lt;snippet&gt;/,/&lt;\/snippet&gt;/p'</command>
57
57
  <purpose>Extract only the code snippet for a specific task</purpose>
58
58
  </helper>
59
59
  <helper name="extract-acceptance">
60
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | sed -n '/&lt;acceptance&gt;/,/&lt;\/acceptance&gt;/p'</command>
60
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | sed -n '/&lt;acceptance&gt;/,/&lt;\/acceptance&gt;/p'</command>
61
61
  <purpose>Extract all acceptance criteria for a specific task</purpose>
62
62
  </helper>
63
63
  <helper name="task-file">
64
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;file&gt;'</command>
64
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;file&gt;'</command>
65
65
  <purpose>Get the target file for a specific task</purpose>
66
66
  </helper>
67
67
  <helper name="task-status">
68
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;status&gt;'</command>
68
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;status&gt;'</command>
69
69
  <purpose>Get current status of a specific task</purpose>
70
70
  </helper>
71
71
  <helper name="dependency-graph">
@@ -73,11 +73,11 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
73
73
  <purpose>Show all task dependencies</purpose>
74
74
  </helper>
75
75
  <helper name="task-deps">
76
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;task_id&gt;'</command>
76
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;task_id&gt;'</command>
77
77
  <purpose>List dependencies for a specific task</purpose>
78
78
  </helper>
79
79
  <helper name="count-tasks">
80
- <command>grep -c '&lt;id&gt;T-' PLAN_PATH</command>
80
+ <command>grep -c '&lt;TASK-T-' PLAN_PATH</command>
81
81
  <purpose>Count total tasks in the plan</purpose>
82
82
  </helper>
83
83
  <helper name="all-files">
@@ -103,8 +103,8 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
103
103
  <check>Plan contains a non-empty &lt;spec&gt; path pointing to a readable active spec file at .vvoc/specs/&lt;id&gt;/spec.xml. Stop and report if the spec path is under archive/.</check>
104
104
  <check>The linked spec's top-level &lt;status&gt; is approved</check>
105
105
  <check>If the linked spec status is draft, applied, missing, or invalid, stop and report that vv-execute requires an approved active spec.</check>
106
- <check>Plan contains &lt;tasks&gt; section with at least one &lt;task&gt;</check>
107
- <check>Each task has non-empty &lt;id&gt;, &lt;title&gt;, and &lt;file&gt;</check>
106
+ <check>Plan contains &lt;tasks&gt; section with at least one &lt;TASK-T-NNN&gt; element grouped under &lt;WAVE-N&gt; elements</check>
107
+ <check>Each task element name matches the TASK-T-NNN pattern and the task has non-empty &lt;title&gt; and &lt;file&gt;. There is no child id element — identity lives in the element name.</check>
108
108
  <check>Each task has &lt;snippet&gt; (may be empty but must exist)</check>
109
109
  <check>Each task has &lt;acceptance&gt; with at least one &lt;criterion&gt;</check>
110
110
  <action>If any check fails, stop and report the issue with line numbers. Do not proceed with broken plan.</action>
@@ -36,8 +36,9 @@ You are the vv-plan skill. Your job is to take an approved spec and write an imp
36
36
  <rule>When first saving the plan, set the top-level status to &lt;status&gt;draft&lt;/status&gt;. Only change it to approved after the user explicitly reads/reviews and approves the final plan. Never set the top-level status to applied yourself; applied is reserved for vv-execute after successful execution.</rule>
37
37
  <rule>The plan contains two major sections: architecture (modules, contracts, dependencies) and tasks (implementation steps with code snippets).</rule>
38
38
  <rule>Architecture section uses child tags: module, name, purpose, file (path, role), contract, depends_on (module).</rule>
39
- <rule>Tasks use child tags: id (T-NNN pattern), title, file, status, description, depends_on (task_id), snippet (CDATA), acceptance (criterion), verification (command). Task-level &lt;status&gt; values are separate from the top-level plan lifecycle status and may remain pending until execution updates them.</rule>
40
- <rule>Every XML element is named for grep extraction. Use: `grep '&lt;id&gt;T-' plan.xml` to list tasks, `grep '&lt;criterion&gt;' plan.xml` for all criteria, `grep '&lt;task_id&gt;' plan.xml` for dependency graph.</rule>
39
+ <rule>Tasks are grouped into wave elements whose identity is the element name: &lt;WAVE-1&gt;, &lt;WAVE-2&gt;, … Each wave contains a &lt;goal&gt; and its tasks.</rule>
40
+ <rule>A task's identity is its element name in the TASK-T-NNN pattern: &lt;TASK-T-001&gt;…&lt;/TASK-T-001&gt;. The identity repeats on both boundaries so long blocks stay addressable. Tasks use child tags: title, file, status, description, depends_on (task_id), snippet (CDATA), acceptance (criterion), verification (command). Do NOT add a child id element — the element name is the single authoritative identity. Task-level &lt;status&gt; values are separate from the top-level plan lifecycle status and may remain pending until execution updates them.</rule>
41
+ <rule>Every XML element is named for grep extraction. Use: `grep '&lt;TASK-T-' plan.xml` to list tasks, `grep '&lt;criterion&gt;' plan.xml` for all criteria, `grep '&lt;task_id&gt;' plan.xml` for dependency graph.</rule>
41
42
  <rule>Populate the &lt;spec&gt; element with the path to the spec.xml this plan implements.</rule>
42
43
  <rule>If a design-context.xml was found and read as explanatory context, populate the &lt;design-context&gt; element with the path to design-context.xml so execution tools and reviewers can locate it.</rule>
43
44
  <location>Save plan.xml as a sibling of spec.xml in the same spec package directory: .vvoc/specs/&lt;id&gt;/plan.xml</location>
@@ -61,10 +62,9 @@ You are the vv-plan skill. Your job is to take an approved spec and write an imp
61
62
  </acceptance_criteria_format>
62
63
 
63
64
  <example>
64
- <rule>Here is a concrete example of one task in the new format. Every &lt;snippet&gt; uses CDATA, and every &lt;criterion&gt; is testable:</rule>
65
+ <rule>Here is a concrete example of one task. The task identity is the element name, repeated on both boundaries; every &lt;snippet&gt; uses CDATA, and every &lt;criterion&gt; is testable:</rule>
65
66
  <sample-fragment>
66
- &lt;task&gt;
67
- &lt;id&gt;T-001&lt;/id&gt;
67
+ &lt;TASK-T-001&gt;
68
68
  &lt;title&gt;LRU Cache Store&lt;/title&gt;
69
69
  &lt;file&gt;src/lib/cache-store.ts&lt;/file&gt;
70
70
  &lt;status&gt;pending&lt;/status&gt;
@@ -111,9 +111,9 @@ export type CacheStoreOptions = {
111
111
  &lt;verification&gt;
112
112
  &lt;command&gt;bun test src/lib/cache-store.test.ts&lt;/command&gt;
113
113
  &lt;/verification&gt;
114
- &lt;/task&gt;
114
+ &lt;/TASK-T-001&gt;
115
115
  </sample-fragment>
116
- <rule>Notice: the snippet uses CDATA wrapping (mandatory). Every element is a child tag (no attributes). The task has id, title, file, status, description, snippet, acceptance, and verification — all as child elements.</rule>
116
+ <rule>Notice: the task identity TASK-T-001 appears in the opening and closing element names. The snippet uses CDATA wrapping (mandatory). Every field is a child tag (no attributes): title, file, status, description, snippet, acceptance, and verification.</rule>
117
117
  </example>
118
118
 
119
119
  <file_structure>
@@ -142,6 +142,7 @@ export type CacheStoreOptions = {
142
142
  <forbidden>XML attributes in any tag — use child elements only</forbidden>
143
143
  <forbidden>Code outside CDATA — all snippets must be wrapped in CDATA sections</forbidden>
144
144
  <forbidden>Numbered criterion tags — use plain &lt;criterion&gt;, not numbered variants</forbidden>
145
+ <forbidden>Generic &lt;task&gt; or &lt;wave&gt; elements with child id/num elements — identity belongs in the element name: &lt;TASK-T-NNN&gt;, &lt;WAVE-N&gt;</forbidden>
145
146
  </no_placeholders>
146
147
 
147
148
  <self_review>
@@ -150,7 +151,7 @@ export type CacheStoreOptions = {
150
151
  <check>Acceptance criteria quality: Is every criterion testable? Could a reviewer or implementer write a failing test for it?</check>
151
152
  <check>Type consistency: Do types, signatures, and property names match across tasks? A function called `clearLayers()` in Task 3 but `clearFullLayers()` in Task 7 is a bug.</check>
152
153
  <rule>Fix issues inline as you find them. No second review pass needed — just fix and continue.</rule>
153
- <check>Format compliance: Are there zero XML attributes? Is every snippet in CDATA? Are tasks using id child tags instead of task-N numbering?</check>
154
+ <check>Format compliance: Are there zero XML attributes? Is every snippet in CDATA? Is every task a &lt;TASK-T-NNN&gt; element with identity in the element name and no child id element?</check>
154
155
  <check>Architecture presence: Does the plan have an architecture section with modules, contracts, and dependency graph?</check>
155
156
  </self_review>
156
157
 
@@ -28,11 +28,9 @@
28
28
  </architecture>
29
29
 
30
30
  <tasks>
31
- <wave>
32
- <num>1</num>
31
+ <WAVE-1>
33
32
  <goal></goal>
34
- <task>
35
- <id>T-001</id>
33
+ <TASK-T-001>
36
34
  <title></title>
37
35
  <file></file>
38
36
  <status>pending</status>
@@ -49,7 +47,7 @@
49
47
  <verification>
50
48
  <command></command>
51
49
  </verification>
52
- </task>
53
- </wave>
50
+ </TASK-T-001>
51
+ </WAVE-1>
54
52
  </tasks>
55
53
  </plan>