@fernado03/zoo-flow 0.8.8 → 0.9.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/bin/zoo-flow.js CHANGED
@@ -5,74 +5,75 @@ import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
7
  const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
- const packageRoot = path.resolve(__dirname, "..");
10
- const templateRoot = path.join(packageRoot, "templates", "full");
11
-
12
- const COMMAND_POLICY = {
13
- routed: {
14
- "tweak": "code-tweaker",
15
- "tdd": "code-tweaker",
16
- "update-docs": "code-tweaker",
17
- "commit-and-document": "code-tweaker",
18
- "prototype": "code-tweaker",
19
- "scaffold-context": "code-tweaker",
20
- "verify": "code-tweaker",
21
- "fix": "system-architect",
22
- "feature": "system-architect",
23
- "refactor": "system-architect",
24
- "explore": "system-architect",
25
- "triage": "system-architect",
26
- "review": "system-architect"
27
- },
28
- helpers: {
29
- "diagnose": "system-architect",
30
- "grill-with-docs": "system-architect",
31
- "improve-codebase-architecture": "system-architect",
32
- "to-prd": "system-architect",
33
- "to-issues": "system-architect",
34
- "zoom-out": "system-architect",
35
- "handoff": "system-architect",
36
- "grill-me": "system-architect",
37
- "write-a-skill": "code-tweaker",
38
- "setup-matt-pocock-skills": "code-tweaker"
39
- },
40
- modelessUtilities: ["caveman"]
41
- };
42
-
43
- const ALLOWED_COMMAND_MODES = new Set(["system-architect", "code-tweaker", "custom-orchestrator"]);
44
- const BUILT_IN_MODE_NAMES = new Set([
45
- "Ask",
46
- "Code",
47
- "Debug",
48
- "Architect",
49
- "Orchestrator",
50
- "ask",
51
- "code",
52
- "debug",
53
- "architect",
54
- "orchestrator"
55
- ]);
8
+ const __dirname = path.dirname(__filename);
9
+ const packageRoot = path.resolve(__dirname, "..");
10
+ const templateRoot = path.join(packageRoot, "templates", "full");
11
+
12
+ const COMMAND_POLICY = {
13
+ routed: {
14
+ "tweak": "code-tweaker",
15
+ "tdd": "code-tweaker",
16
+ "update-docs": "code-tweaker",
17
+ "commit-and-document": "code-tweaker",
18
+ "prototype": "code-tweaker",
19
+ "scaffold-context": "code-tweaker",
20
+ "verify": "code-tweaker",
21
+ "fix": "system-architect",
22
+ "feature": "system-architect",
23
+ "refactor": "system-architect",
24
+ "explore": "system-architect",
25
+ "triage": "system-architect",
26
+ "review": "system-architect"
27
+ },
28
+ helpers: {
29
+ "diagnose": "system-architect",
30
+ "grill-with-docs": "system-architect",
31
+ "improve-codebase-architecture": "system-architect",
32
+ "to-prd": "system-architect",
33
+ "to-issues": "system-architect",
34
+ "zoom-out": "system-architect",
35
+ "handoff": "system-architect",
36
+ "grill-me": "system-architect",
37
+ "write-a-skill": "code-tweaker",
38
+ "setup-matt-pocock-skills": "code-tweaker",
39
+ "teach": "code-tweaker"
40
+ },
41
+ modelessUtilities: ["caveman"]
42
+ };
43
+
44
+ const ALLOWED_COMMAND_MODES = new Set(["system-architect", "code-tweaker", "custom-orchestrator"]);
45
+ const BUILT_IN_MODE_NAMES = new Set([
46
+ "Ask",
47
+ "Code",
48
+ "Debug",
49
+ "Architect",
50
+ "Orchestrator",
51
+ "ask",
52
+ "code",
53
+ "debug",
54
+ "architect",
55
+ "orchestrator"
56
+ ]);
56
57
 
57
58
  const command = process.argv[2];
58
59
 
59
60
  const HELP = `
60
61
  Zoo Flow
61
62
 
62
- Usage:
63
+ Usage:
63
64
  npx @fernado03/zoo-flow@latest init
64
65
  npx @fernado03/zoo-flow@latest init --force
65
66
  npx @fernado03/zoo-flow@latest update
66
67
  npx @fernado03/zoo-flow@latest update --dry-run
67
- npx @fernado03/zoo-flow@latest update --force
68
- npx @fernado03/zoo-flow@latest doctor
69
- npx @fernado03/zoo-flow@latest doctor --template-only
68
+ npx @fernado03/zoo-flow@latest update --force
69
+ npx @fernado03/zoo-flow@latest doctor
70
+ npx @fernado03/zoo-flow@latest doctor --template-only
70
71
 
71
72
  Commands:
72
73
  init Install Zoo Flow into the current project
73
74
  update Back up current config and copy the latest template
74
- doctor Validate Zoo Flow in the current project
75
- doctor --template-only Validate this package's bundled template
75
+ doctor Validate Zoo Flow in the current project
76
+ doctor --template-only Validate this package's bundled template
76
77
 
77
78
  Options:
78
79
  --force Overwrite existing .roomodes and .roo after backup
@@ -191,7 +192,7 @@ function readJson(filePath) {
191
192
  }
192
193
  }
193
194
 
194
- function walkFiles(rootDir) {
195
+ function walkFiles(rootDir) {
195
196
  const files = [];
196
197
 
197
198
  function walk(current) {
@@ -211,110 +212,110 @@ function walkFiles(rootDir) {
211
212
  }
212
213
 
213
214
  walk(rootDir);
214
- return files;
215
- }
216
-
217
- function stripFrontmatter(text) {
218
- if (!text.startsWith("---")) return text;
219
-
220
- const lines = text.split(/\r?\n/);
221
- for (let index = 1; index < lines.length; index += 1) {
222
- if (lines[index].trim() === "---") {
223
- return lines.slice(index + 1).join("\n");
224
- }
225
- }
226
-
227
- return text;
228
- }
229
-
230
- function getFrontmatter(text) {
231
- if (!text.startsWith("---")) return "";
232
-
233
- const lines = text.split(/\r?\n/);
234
- for (let index = 1; index < lines.length; index += 1) {
235
- if (lines[index].trim() === "---") {
236
- return lines.slice(1, index).join("\n");
237
- }
238
- }
239
-
240
- return "";
241
- }
242
-
243
- function getFrontmatterMode(text) {
244
- const frontmatter = getFrontmatter(text);
245
- const match = frontmatter.match(/^mode:\s*([^\r\n#]+)\s*$/m);
246
- return match ? match[1].trim().replace(/^['"]|['"]$/g, "") : null;
247
- }
248
-
249
- function getCommandPolicyMode(commandName) {
250
- return COMMAND_POLICY.routed[commandName] || COMMAND_POLICY.helpers[commandName] || null;
251
- }
252
-
253
- function getPolicyCommandEntries() {
254
- return Object.entries({ ...COMMAND_POLICY.routed, ...COMMAND_POLICY.helpers });
255
- }
256
-
257
- function isThinNonCanonicalSkillWrapper(text) {
258
- const body = stripFrontmatter(text);
259
- const lines = body
260
- .split(/\r?\n/)
261
- .map((line) => line.trim())
262
- .filter(Boolean);
263
-
264
- const runSkillLines = lines.filter((line) =>
265
- /^run skill:\s*`?\.roo\/skills\/[^\s`]+SKILL\.md`?\s*$/i.test(line)
266
- );
267
-
268
- if (runSkillLines.length !== 1) return false;
269
-
270
- const otherLines = lines.filter((line) =>
271
- !/^run skill:/i.test(line) && line !== "$ARGUMENTS"
272
- );
273
-
274
- return otherLines.every(
275
- (line) => line.length <= 120 && !/^(#{1,6}\s|[-*]\s|\d+[.)]\s|[A-Z][A-Z\s]+:)/.test(line)
276
- );
277
- }
278
-
279
- function getRoutedCommandRows(routingText) {
280
- const routedSection = routingText.match(/## Routed commands\s*\n([\s\S]*?)(?=\n## |$)/);
281
- if (!routedSection) return [];
282
-
283
- return routedSection[1]
284
- .split(/\r?\n/)
285
- .map((line) => line.trim())
286
- .filter((line) => line.startsWith("|") && !/^\|\s*-+/.test(line))
287
- .map((line) => line.split("|").slice(1, -1).map((cell) => cell.trim()))
288
- .filter((cells) => cells.length >= 3 && cells[1].includes("`/"));
289
- }
290
-
291
- function findPositiveBuiltInDelegation(text) {
292
- const findings = [];
293
- const target = "(ask|code|debug|architect|orchestrator)";
294
- const end = "(?=$|[\\s.,;:)\\]`])";
295
- const optionalBacktick = "[`]?";
296
- const patterns = [
297
- new RegExp("\\bnew_task\\b[^\\n]*(?:to|target|slug:)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
298
- new RegExp("\\bdelegate(?:s|d)?\\b[^\\n]*(?:to|into|with)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
299
- new RegExp("\\bswitch_mode\\b[^\\n]*(?:to|->|slug:)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
300
- new RegExp("\\bswitch\\s+to\\s*" + optionalBacktick + target + "(?:\\s+mode)?" + optionalBacktick + end, "i")
301
- ];
302
-
303
- const negativePattern = /\b(never|do not|don't|must not|no valid|not fall back|outside zoo flow)\b/i;
304
-
305
- for (const line of text.split(/\r?\n/)) {
306
- const trimmed = line.trim();
307
- if (!trimmed || negativePattern.test(trimmed)) continue;
308
-
309
- if (patterns.some((pattern) => pattern.test(trimmed))) {
310
- findings.push(trimmed);
311
- }
312
- }
313
-
314
- return findings;
315
- }
316
-
317
- function validateTemplate(rootDir) {
215
+ return files;
216
+ }
217
+
218
+ function stripFrontmatter(text) {
219
+ if (!text.startsWith("---")) return text;
220
+
221
+ const lines = text.split(/\r?\n/);
222
+ for (let index = 1; index < lines.length; index += 1) {
223
+ if (lines[index].trim() === "---") {
224
+ return lines.slice(index + 1).join("\n");
225
+ }
226
+ }
227
+
228
+ return text;
229
+ }
230
+
231
+ function getFrontmatter(text) {
232
+ if (!text.startsWith("---")) return "";
233
+
234
+ const lines = text.split(/\r?\n/);
235
+ for (let index = 1; index < lines.length; index += 1) {
236
+ if (lines[index].trim() === "---") {
237
+ return lines.slice(1, index).join("\n");
238
+ }
239
+ }
240
+
241
+ return "";
242
+ }
243
+
244
+ function getFrontmatterMode(text) {
245
+ const frontmatter = getFrontmatter(text);
246
+ const match = frontmatter.match(/^mode:\s*([^\r\n#]+)\s*$/m);
247
+ return match ? match[1].trim().replace(/^['"]|['"]$/g, "") : null;
248
+ }
249
+
250
+ function getCommandPolicyMode(commandName) {
251
+ return COMMAND_POLICY.routed[commandName] || COMMAND_POLICY.helpers[commandName] || null;
252
+ }
253
+
254
+ function getPolicyCommandEntries() {
255
+ return Object.entries({ ...COMMAND_POLICY.routed, ...COMMAND_POLICY.helpers });
256
+ }
257
+
258
+ function isThinNonCanonicalSkillWrapper(text) {
259
+ const body = stripFrontmatter(text);
260
+ const lines = body
261
+ .split(/\r?\n/)
262
+ .map((line) => line.trim())
263
+ .filter(Boolean);
264
+
265
+ const runSkillLines = lines.filter((line) =>
266
+ /^run skill:\s*`?\.roo\/skills\/[^\s`]+SKILL\.md`?\s*$/i.test(line)
267
+ );
268
+
269
+ if (runSkillLines.length !== 1) return false;
270
+
271
+ const otherLines = lines.filter((line) =>
272
+ !/^run skill:/i.test(line) && line !== "$ARGUMENTS"
273
+ );
274
+
275
+ return otherLines.every(
276
+ (line) => line.length <= 120 && !/^(#{1,6}\s|[-*]\s|\d+[.)]\s|[A-Z][A-Z\s]+:)/.test(line)
277
+ );
278
+ }
279
+
280
+ function getRoutedCommandRows(routingText) {
281
+ const routedSection = routingText.match(/## Routed commands\s*\n([\s\S]*?)(?=\n## |$)/);
282
+ if (!routedSection) return [];
283
+
284
+ return routedSection[1]
285
+ .split(/\r?\n/)
286
+ .map((line) => line.trim())
287
+ .filter((line) => line.startsWith("|") && !/^\|\s*-+/.test(line))
288
+ .map((line) => line.split("|").slice(1, -1).map((cell) => cell.trim()))
289
+ .filter((cells) => cells.length >= 3 && cells[1].includes("`/"));
290
+ }
291
+
292
+ function findPositiveBuiltInDelegation(text) {
293
+ const findings = [];
294
+ const target = "(ask|code|debug|architect|orchestrator)";
295
+ const end = "(?=$|[\\s.,;:)\\]`])";
296
+ const optionalBacktick = "[`]?";
297
+ const patterns = [
298
+ new RegExp("\\bnew_task\\b[^\\n]*(?:to|target|slug:)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
299
+ new RegExp("\\bdelegate(?:s|d)?\\b[^\\n]*(?:to|into|with)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
300
+ new RegExp("\\bswitch_mode\\b[^\\n]*(?:to|->|slug:)\\s*" + optionalBacktick + target + optionalBacktick + end, "i"),
301
+ new RegExp("\\bswitch\\s+to\\s*" + optionalBacktick + target + "(?:\\s+mode)?" + optionalBacktick + end, "i")
302
+ ];
303
+
304
+ const negativePattern = /\b(never|do not|don't|must not|no valid|not fall back|outside zoo flow)\b/i;
305
+
306
+ for (const line of text.split(/\r?\n/)) {
307
+ const trimmed = line.trim();
308
+ if (!trimmed || negativePattern.test(trimmed)) continue;
309
+
310
+ if (patterns.some((pattern) => pattern.test(trimmed))) {
311
+ findings.push(trimmed);
312
+ }
313
+ }
314
+
315
+ return findings;
316
+ }
317
+
318
+ function validateTemplate(rootDir) {
318
319
  const roomodesPath = path.join(rootDir, ".roomodes");
319
320
  const rooDir = path.join(rootDir, ".roo");
320
321
  const commandsDir = path.join(rooDir, "commands");
@@ -329,38 +330,38 @@ function validateTemplate(rootDir) {
329
330
  if (!pathExists(skillsDir)) failures.push("Missing .roo/skills/");
330
331
  if (!pathExists(rulesDir)) failures.push("Missing .roo/rules/");
331
332
 
332
- let roomodes = null;
333
-
334
- if (pathExists(roomodesPath)) {
335
- try {
336
- roomodes = readJson(roomodesPath);
337
- if (!Array.isArray(roomodes.customModes)) {
338
- failures.push(".roomodes must contain customModes array");
339
- }
340
- } catch (error) {
341
- failures.push(error.message);
342
- }
343
- }
344
-
345
- // Validate command references. Commands may either declare a skill via
346
- // `Skill: .roo/skills/.../SKILL.md` or contain workflow steps directly.
347
- if (pathExists(commandsDir)) {
348
- const skillRefRegex = /^Skill:\s*`?(\.roo\/skills\/[^\s`]+SKILL\.md)`?\s*$/m;
349
-
333
+ let roomodes = null;
334
+
335
+ if (pathExists(roomodesPath)) {
336
+ try {
337
+ roomodes = readJson(roomodesPath);
338
+ if (!Array.isArray(roomodes.customModes)) {
339
+ failures.push(".roomodes must contain customModes array");
340
+ }
341
+ } catch (error) {
342
+ failures.push(error.message);
343
+ }
344
+ }
345
+
346
+ // Validate command references. Commands may either declare a skill via
347
+ // `Skill: .roo/skills/.../SKILL.md` or contain workflow steps directly.
348
+ if (pathExists(commandsDir)) {
349
+ const skillRefRegex = /^Skill:\s*`?(\.roo\/skills\/[^\s`]+SKILL\.md)`?\s*$/m;
350
+
350
351
  for (const entry of fs.readdirSync(commandsDir)) {
351
352
  if (!entry.endsWith(".md")) continue;
352
353
 
353
- const commandFile = path.join(commandsDir, entry);
354
- const text = fs.readFileSync(commandFile, "utf8");
355
- const match = text.match(skillRefRegex);
356
-
357
- if (isThinNonCanonicalSkillWrapper(text)) {
358
- failures.push(
359
- `Command ${path.relative(rootDir, commandFile)} uses non-canonical skill wrapper. Use \`Skill: .roo/skills/.../SKILL.md\`.`
360
- );
361
- }
362
-
363
- if (!match) continue;
354
+ const commandFile = path.join(commandsDir, entry);
355
+ const text = fs.readFileSync(commandFile, "utf8");
356
+ const match = text.match(skillRefRegex);
357
+
358
+ if (isThinNonCanonicalSkillWrapper(text)) {
359
+ failures.push(
360
+ `Command ${path.relative(rootDir, commandFile)} uses non-canonical skill wrapper. Use \`Skill: .roo/skills/.../SKILL.md\`.`
361
+ );
362
+ }
363
+
364
+ if (!match) continue;
364
365
 
365
366
  const skillRelative = match[1];
366
367
  const skillAbsolute = path.join(rootDir, skillRelative);
@@ -369,112 +370,112 @@ function validateTemplate(rootDir) {
369
370
  failures.push(
370
371
  `Command ${path.relative(rootDir, commandFile)} references missing skill: ${skillRelative}`
371
372
  );
372
- }
373
- }
374
- }
375
-
376
- const routingPath = path.join(rootDir, ".roo", "rules-custom-orchestrator", "00-routing.md");
377
- const allowedRoutedModes = new Set(["system-architect", "code-tweaker"]);
378
-
379
- if (pathExists(routingPath)) {
380
- const routingText = fs.readFileSync(routingPath, "utf8");
381
- const routedRows = getRoutedCommandRows(routingText);
382
-
383
- if (routedRows.length === 0) {
384
- failures.push("Routing table missing routed command rows");
385
- }
386
-
387
- for (const cells of routedRows) {
388
- const commandMatch = cells[1].match(/`\/(.+?)`/);
389
- const mode = cells[2].replace(/`/g, "");
390
-
391
- if (commandMatch) {
392
- const commandName = commandMatch[1];
393
- const commandPath = path.join(commandsDir, `${commandName}.md`);
394
- if (!pathExists(commandPath)) {
395
- failures.push(`Routed command /${commandName} is missing .roo/commands/${commandName}.md`);
396
- }
397
- }
398
-
399
- if (!allowedRoutedModes.has(mode)) {
400
- failures.push(`Routed command table uses invalid mode slug: ${mode}`);
401
- }
402
- }
403
- } else {
404
- failures.push("Missing .roo/rules-custom-orchestrator/00-routing.md");
405
- }
406
-
407
- if (roomodes && Array.isArray(roomodes.customModes)) {
408
- const slugs = new Set(roomodes.customModes.map((mode) => mode.slug));
409
- for (const slug of ["custom-orchestrator", "system-architect", "code-tweaker"]) {
410
- if (!slugs.has(slug)) {
411
- failures.push(`Missing required mode slug in .roomodes: ${slug}`);
412
- }
413
- }
414
-
415
- const modesBySlug = new Map(roomodes.customModes.map((mode) => [mode.slug, mode]));
416
- for (const [commandName, modeSlug] of getPolicyCommandEntries()) {
417
- const mode = modesBySlug.get(modeSlug);
418
- const instructions = mode && typeof mode.customInstructions === "string" ? mode.customInstructions : "";
419
- if (!instructions.includes(`/${commandName}`)) {
420
- failures.push(`.roomodes ${modeSlug} does not permit documented command /${commandName}`);
421
- }
422
- }
423
- }
424
-
425
- if (pathExists(commandsDir)) {
426
- for (const [commandName, expectedMode] of getPolicyCommandEntries()) {
427
- const commandPath = path.join(commandsDir, `${commandName}.md`);
428
- if (!pathExists(commandPath)) {
429
- failures.push(`Command policy references missing command file: .roo/commands/${commandName}.md`);
430
- continue;
431
- }
432
-
433
- const commandText = fs.readFileSync(commandPath, "utf8");
434
- const actualMode = getFrontmatterMode(commandText);
435
- if (actualMode !== expectedMode) {
436
- failures.push(`Command .roo/commands/${commandName}.md must declare mode: ${expectedMode}`);
437
- }
438
- }
439
-
440
- for (const commandName of COMMAND_POLICY.modelessUtilities) {
441
- const commandPath = path.join(commandsDir, `${commandName}.md`);
442
- if (!pathExists(commandPath)) {
443
- failures.push(`Command policy references missing modeless utility: .roo/commands/${commandName}.md`);
444
- }
445
- }
446
-
447
- for (const entry of fs.readdirSync(commandsDir)) {
448
- if (!entry.endsWith(".md")) continue;
449
-
450
- const commandName = entry.slice(0, -3);
451
- const commandPath = path.join(commandsDir, entry);
452
- const commandText = fs.readFileSync(commandPath, "utf8");
453
- const mode = getFrontmatterMode(commandText);
454
-
455
- if (mode && !ALLOWED_COMMAND_MODES.has(mode)) {
456
- failures.push(`Command .roo/commands/${entry} uses invalid mode: ${mode}`);
457
- }
458
-
459
- if (mode && BUILT_IN_MODE_NAMES.has(mode)) {
460
- failures.push(`Command .roo/commands/${entry} uses built-in/default mode: ${mode}`);
461
- }
462
-
463
- if (!getCommandPolicyMode(commandName) && !COMMAND_POLICY.modelessUtilities.includes(commandName)) {
464
- failures.push(`Command .roo/commands/${entry} is missing from command policy`);
465
- }
466
- }
467
- }
468
-
469
- const allFiles = [];
470
- for (const validationRoot of [roomodesPath, rooDir, path.join(rootDir, ".zoo-flow")]) {
471
- if (pathExists(validationRoot)) {
472
- allFiles.push(...walkFiles(validationRoot));
473
- }
474
- }
373
+ }
374
+ }
375
+ }
376
+
377
+ const routingPath = path.join(rootDir, ".roo", "rules-custom-orchestrator", "00-routing.md");
378
+ const allowedRoutedModes = new Set(["system-architect", "code-tweaker"]);
379
+
380
+ if (pathExists(routingPath)) {
381
+ const routingText = fs.readFileSync(routingPath, "utf8");
382
+ const routedRows = getRoutedCommandRows(routingText);
383
+
384
+ if (routedRows.length === 0) {
385
+ failures.push("Routing table missing routed command rows");
386
+ }
387
+
388
+ for (const cells of routedRows) {
389
+ const commandMatch = cells[1].match(/`\/(.+?)`/);
390
+ const mode = cells[2].replace(/`/g, "");
391
+
392
+ if (commandMatch) {
393
+ const commandName = commandMatch[1];
394
+ const commandPath = path.join(commandsDir, `${commandName}.md`);
395
+ if (!pathExists(commandPath)) {
396
+ failures.push(`Routed command /${commandName} is missing .roo/commands/${commandName}.md`);
397
+ }
398
+ }
399
+
400
+ if (!allowedRoutedModes.has(mode)) {
401
+ failures.push(`Routed command table uses invalid mode slug: ${mode}`);
402
+ }
403
+ }
404
+ } else {
405
+ failures.push("Missing .roo/rules-custom-orchestrator/00-routing.md");
406
+ }
407
+
408
+ if (roomodes && Array.isArray(roomodes.customModes)) {
409
+ const slugs = new Set(roomodes.customModes.map((mode) => mode.slug));
410
+ for (const slug of ["custom-orchestrator", "system-architect", "code-tweaker"]) {
411
+ if (!slugs.has(slug)) {
412
+ failures.push(`Missing required mode slug in .roomodes: ${slug}`);
413
+ }
414
+ }
415
+
416
+ const modesBySlug = new Map(roomodes.customModes.map((mode) => [mode.slug, mode]));
417
+ for (const [commandName, modeSlug] of getPolicyCommandEntries()) {
418
+ const mode = modesBySlug.get(modeSlug);
419
+ const instructions = mode && typeof mode.customInstructions === "string" ? mode.customInstructions : "";
420
+ if (!instructions.includes(`/${commandName}`)) {
421
+ failures.push(`.roomodes ${modeSlug} does not permit documented command /${commandName}`);
422
+ }
423
+ }
424
+ }
425
+
426
+ if (pathExists(commandsDir)) {
427
+ for (const [commandName, expectedMode] of getPolicyCommandEntries()) {
428
+ const commandPath = path.join(commandsDir, `${commandName}.md`);
429
+ if (!pathExists(commandPath)) {
430
+ failures.push(`Command policy references missing command file: .roo/commands/${commandName}.md`);
431
+ continue;
432
+ }
433
+
434
+ const commandText = fs.readFileSync(commandPath, "utf8");
435
+ const actualMode = getFrontmatterMode(commandText);
436
+ if (actualMode !== expectedMode) {
437
+ failures.push(`Command .roo/commands/${commandName}.md must declare mode: ${expectedMode}`);
438
+ }
439
+ }
440
+
441
+ for (const commandName of COMMAND_POLICY.modelessUtilities) {
442
+ const commandPath = path.join(commandsDir, `${commandName}.md`);
443
+ if (!pathExists(commandPath)) {
444
+ failures.push(`Command policy references missing modeless utility: .roo/commands/${commandName}.md`);
445
+ }
446
+ }
447
+
448
+ for (const entry of fs.readdirSync(commandsDir)) {
449
+ if (!entry.endsWith(".md")) continue;
450
+
451
+ const commandName = entry.slice(0, -3);
452
+ const commandPath = path.join(commandsDir, entry);
453
+ const commandText = fs.readFileSync(commandPath, "utf8");
454
+ const mode = getFrontmatterMode(commandText);
455
+
456
+ if (mode && !ALLOWED_COMMAND_MODES.has(mode)) {
457
+ failures.push(`Command .roo/commands/${entry} uses invalid mode: ${mode}`);
458
+ }
459
+
460
+ if (mode && BUILT_IN_MODE_NAMES.has(mode)) {
461
+ failures.push(`Command .roo/commands/${entry} uses built-in/default mode: ${mode}`);
462
+ }
463
+
464
+ if (!getCommandPolicyMode(commandName) && !COMMAND_POLICY.modelessUtilities.includes(commandName)) {
465
+ failures.push(`Command .roo/commands/${entry} is missing from command policy`);
466
+ }
467
+ }
468
+ }
469
+
470
+ const allFiles = [];
471
+ for (const validationRoot of [roomodesPath, rooDir, path.join(rootDir, ".zoo-flow")]) {
472
+ if (pathExists(validationRoot)) {
473
+ allFiles.push(...walkFiles(validationRoot));
474
+ }
475
+ }
475
476
  const textFileExtensions = new Set([".md", ".json", ".txt", ".yaml", ".yml"]);
476
477
 
477
- for (const file of allFiles) {
478
+ for (const file of allFiles) {
478
479
  const ext = path.extname(file);
479
480
  if (!textFileExtensions.has(ext)) continue;
480
481
 
@@ -490,28 +491,28 @@ function validateTemplate(rootDir) {
490
491
  "APP_MAP.md"
491
492
  ];
492
493
 
493
- for (const pattern of badPatterns) {
494
- if (text.includes(pattern)) {
495
- failures.push(`Bad pattern "${pattern}" in ${path.relative(rootDir, file)}`);
496
- }
497
- }
498
- }
499
-
500
- const runtimeFiles = allFiles.filter((file) => {
501
- const relative = path.relative(rootDir, file).replace(/\\/g, "/");
502
- return relative === ".roomodes" || /^\.roo\/rules(?:-|\/)/.test(relative);
503
- });
504
-
505
- for (const file of runtimeFiles) {
506
- const text = fs.readFileSync(file, "utf8");
507
- const findings = findPositiveBuiltInDelegation(text);
508
-
509
- for (const finding of findings) {
510
- failures.push(
511
- `Built-in/default delegation target in ${path.relative(rootDir, file)}: ${finding}`
512
- );
513
- }
514
- }
494
+ for (const pattern of badPatterns) {
495
+ if (text.includes(pattern)) {
496
+ failures.push(`Bad pattern "${pattern}" in ${path.relative(rootDir, file)}`);
497
+ }
498
+ }
499
+ }
500
+
501
+ const runtimeFiles = allFiles.filter((file) => {
502
+ const relative = path.relative(rootDir, file).replace(/\\/g, "/");
503
+ return relative === ".roomodes" || /^\.roo\/rules(?:-|\/)/.test(relative);
504
+ });
505
+
506
+ for (const file of runtimeFiles) {
507
+ const text = fs.readFileSync(file, "utf8");
508
+ const findings = findPositiveBuiltInDelegation(text);
509
+
510
+ for (const finding of findings) {
511
+ failures.push(
512
+ `Built-in/default delegation target in ${path.relative(rootDir, file)}: ${finding}`
513
+ );
514
+ }
515
+ }
515
516
 
516
517
  const requiredRules = [
517
518
  ".roo/rules/00-paths.md",
@@ -710,7 +711,7 @@ function doctor() {
710
711
  }
711
712
  console.log("");
712
713
  }
713
- }
714
+ }
714
715
 
715
716
  function update() {
716
717
  const args = new Set(process.argv.slice(3));
@@ -12,17 +12,20 @@ paths, so this index is not required for runtime execution.
12
12
 
13
13
  | Skill | Path |
14
14
  |---|---|
15
+ | `commit-and-document` | `.roo/skills/engineering/commit-and-document/SKILL.md` |
15
16
  | `diagnose` | `.roo/skills/engineering/diagnose/SKILL.md` |
16
17
  | `grill-with-docs` | `.roo/skills/engineering/grill-with-docs/SKILL.md` |
17
18
  | `improve-codebase-architecture` | `.roo/skills/engineering/improve-codebase-architecture/SKILL.md` |
18
19
  | `prototype` | `.roo/skills/engineering/prototype/SKILL.md` |
19
20
  | `review` | `.roo/skills/engineering/review/SKILL.md` |
21
+ | `scaffold-context` | `.roo/skills/engineering/scaffold-context/SKILL.md` |
20
22
  | `setup-matt-pocock-skills` | `.roo/skills/engineering/setup-matt-pocock-skills/SKILL.md` |
21
23
  | `tdd` | `.roo/skills/engineering/tdd/SKILL.md` |
22
24
  | `to-issues` | `.roo/skills/engineering/to-issues/SKILL.md` |
23
25
  | `to-prd` | `.roo/skills/engineering/to-prd/SKILL.md` |
24
26
  | `triage` | `.roo/skills/engineering/triage/SKILL.md` |
25
27
  | `tweak` | `.roo/skills/engineering/tweak/SKILL.md` |
28
+ | `update-docs` | `.roo/skills/engineering/update-docs/SKILL.md` |
26
29
  | `verify` | `.roo/skills/engineering/verify/SKILL.md` |
27
30
  | `zoom-out` | `.roo/skills/engineering/zoom-out/SKILL.md` |
28
31
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fernado03/zoo-flow",
3
3
  "description": "Workflow control plane for Zoo Code.",
4
- "version": "0.8.8",
4
+ "version": "0.9.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "zoo-flow": "bin/zoo-flow.js"
@@ -17,6 +17,6 @@ EXECUTION RULES (Run sequentially. Wait for user between phases):
17
17
  5. IMPLEMENT (Tweaker):
18
18
  - Architect summarizes issues.
19
19
  - Architect MUST `switch_mode` -> `code-tweaker`.
20
- - Tweaker: For each issue, execute the `/tdd` command workflow (per `.roo/rules/01-command-protocol.md`). After each ships, suggest `/verify`, then `/review`, then `/commit-and-document`. Do not auto-launch.
20
+ - Tweaker: For each issue, execute the `/tdd` command workflow (per `.roo/rules/01-command-protocol.md`). After each ships, suggest `/verify`, then `/review` (requires `switch_mode` back to system-architect), then `/commit-and-document`. Do not auto-launch.
21
21
 
22
22
  $ARGUMENTS
@@ -14,6 +14,7 @@ EXECUTION RULES:
14
14
  - Architect summarizes approved plan.
15
15
  - Architect MUST `switch_mode` -> `code-tweaker`.
16
16
  - Tweaker executes the `/tdd` command workflow (per `.roo/rules/01-command-protocol.md`) — new tests at interface, delete old.
17
- - Tweaker suggests `/verify`, then `/review`, then `/commit-and-document`. Do not auto-launch.
17
+ - Tweaker suggests `/verify`, then `/review` (requires `switch_mode` back to system-architect), then `/commit-and-document`. Do not auto-launch.
18
+ - Tweaker calls `attempt_completion` with: what was refactored, files changed, tests added, status, and recommended next command.
18
19
 
19
20
  $ARGUMENTS
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Review a diff or branch against the requested spec, project standards, architecture, and likely regressions. Use before committing non-trivial work."
2
+ description: "Review a diff, branch, PR, or work-in-progress change against the requested spec, project standards, architecture, and likely regressions. Use before committing non-trivial work."
3
3
  argument-hint: <optional base ref, files, issue, PRD, or review focus>
4
4
  mode: system-architect
5
5
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: "Teach a topic over multiple stateful sessions. Tracks mission, glossary, resources, and learning records. Use when user asks to be taught a topic, wants to learn something, or mentions ongoing study."
3
3
  argument-hint: "What would you like to learn about?"
4
+ mode: code-tweaker
4
5
  ---
5
6
 
6
7
  Skill: `.roo/skills/productivity/teach/SKILL.md`
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Triage issues through a state machine driven by triage roles. Use when user wants to create an issue, triage issues, review incoming bugs or feature requests, prepare issues for an AFK agent, or manage issue workflow."
3
+ argument-hint: "Describe the issue(s) to triage or 'all' to review all open issues"
3
4
  mode: system-architect
4
5
  ---
5
6
 
@@ -8,7 +8,7 @@ Update repo documentation so it matches the current code. Surgical edits only
8
8
 
9
9
  Skill: `.roo/skills/engineering/update-docs/SKILL.md`
10
10
 
11
- Find the target doc in `.zoo-flow/` or `docs/`. If it does not exist, ask once: "No <slot> found. Create a stub at .zoo-flow/<slot>? (yes / pick-existing / skip)".
11
+ Find the target doc in `.zoo-flow/` or `docs/`. If it does not exist, ask once: "No <doc> found. Create a stub at .zoo-flow/<doc>? (yes / pick-existing / skip)".
12
12
 
13
13
  Do NOT use this for:
14
14
 
@@ -21,7 +21,7 @@ Read domain docs only when at least one is true:
21
21
  - The task touches domain language or terminology.
22
22
  - The task changes public behavior.
23
23
  - The task changes architecture, module seams, persistence, API shape, auth, payments, security, migrations, or cross-module design.
24
- - The command explicitly requires those docs (e.g. `/feature`, `/refactor`, `/grill-with-docs`, `/scaffold-context`, `/update-docs`).
24
+ - The command explicitly requires those docs (e.g. `/feature`, `/refactor`, `/grill-with-docs`, `/scaffold-context`, `/update-docs`, `/tdd`).
25
25
  - The user asks for documentation, architecture, product, or domain-context work.
26
26
 
27
27
  Missing CONTEXT.md or ADRs is not an error. Proceed silently when nothing is present.
@@ -22,9 +22,9 @@ Never delegate to built-in/default modes, including Ask, Code, Debug, Architect,
22
22
 
23
23
  Slash commands bypass this — the extension reads `mode:` from the command frontmatter and switches directly.
24
24
 
25
- If a task sounds like "ask", "inspect", "review", "branch review", "pre-commit review", "analyze", "deep inspection", "investigate", or "reason about safety", route it to `system-architect`.
25
+ If a task sounds like "ask", "inspect", "review", "branch review", "pre-commit review", "analyze", "deep inspection", "investigate", or "reason about safety", route it to `system-architect`.
26
26
 
27
- If a task requires source edits, tests, verification, docs updates, prototypes, or commits, route it to `code-tweaker`.
27
+ If a task requires source edits, tests, verification, docs updates, prototypes, or commits, route it to `code-tweaker`.
28
28
 
29
29
  If neither custom mode is suitable, stop and report that no valid Zoo Flow mode exists. Do not fall back to Ask mode.
30
30
 
@@ -40,7 +40,7 @@ Users are not expected to know slash commands. For free-form requests, infer the
40
40
 
41
41
  ## User-facing workflow names
42
42
 
43
- Slash commands are internal routing labels unless the user explicitly typed one or asked for syntax. For free-form requests, use plain-language workflow names only: small implementation, test-first, diagnosis, feature planning, refactor planning, exploration, documentation update, commit and journal, prototype, issue triage, review, verification. Never show slash commands as selectable options for free-form requests. Internal delegation may still use the slash command after approval.
43
+ Slash commands are internal routing labels unless the user explicitly typed one or asked for syntax. For free-form requests, use plain-language workflow names only: small implementation, test-first, diagnosis, feature planning, refactor planning, exploration, documentation update, commit and journal, prototype, issue triage, review, verification. Never show slash commands as selectable options for free-form requests. Internal delegation may still use the slash command after approval.
44
44
 
45
45
  ## Routed commands
46
46
 
@@ -51,17 +51,18 @@ Slash commands are internal routing labels unless the user explicitly typed one
51
51
  | documentation update | `/update-docs` | code-tweaker |
52
52
  | commit and journal | `/commit-and-document` | code-tweaker |
53
53
  | prototype | `/prototype` | code-tweaker |
54
+ | context scaffolding | `/scaffold-context` | code-tweaker |
54
55
  | diagnosis | `/fix` | system-architect |
55
56
  | feature planning | `/feature` | system-architect |
56
57
  | refactor planning | `/refactor` | system-architect |
57
- | exploration | `/explore` | system-architect |
58
- | issue triage | `/triage` | system-architect |
59
- | review | `/review` | system-architect |
60
- | verification | `/verify` | code-tweaker |
58
+ | exploration | `/explore` | system-architect |
59
+ | issue triage | `/triage` | system-architect |
60
+ | review | `/review` | system-architect |
61
+ | verification | `/verify` | code-tweaker |
61
62
 
62
63
  ## Routing decision guide
63
64
 
64
- Read intent, not keywords. Top-down: 1. unknown code area or unclear next move → exploration; 2. broken behavior with unknown cause → diagnosis; 3. new capability needing design, PRD, issue slicing, or phase gates → feature planning; 4. working behavior but structure is the problem → refactor planning; 5. small known low-risk change → small implementation; 6. clear behavior and interface, user wants tests first → test-first; 7. throwaway design/state/UI uncertainty → prototype; 8. docs drift from code → documentation update; 9. finished work needs commit/journal → commit and journal; 10. issue creation, sorting, labels, or tracker workflow → issue triage; 11. diff, branch, PR, standards, architecture, or pre-commit inspection → review; 12. check if this passes, run tests for this change, verify the branch, or make sure nothing broke → verification.
65
+ Read intent, not keywords. Top-down: 1. unknown code area or unclear next move → exploration; 2. broken behavior with unknown cause → diagnosis; 3. new capability needing design, PRD, issue slicing, or phase gates → feature planning; 4. working behavior but structure is the problem → refactor planning; 5. small known low-risk change → small implementation; 6. clear behavior and interface, user wants tests first → test-first; 7. throwaway design/state/UI uncertainty → prototype; 8. docs drift from code → documentation update; 9. finished work needs commit/journal → commit and journal; 10. issue creation, sorting, labels, or tracker workflow → issue triage; 11. diff, branch, PR, standards, architecture, or pre-commit inspection → review; 12. check if this passes, run tests for this change, verify the branch, or make sure nothing broke → verification.
65
66
 
66
67
  ## Routing weight
67
68
 
@@ -69,7 +70,7 @@ Prefer the lightest workflow that preserves correctness. Use small implementatio
69
70
 
70
71
  ## Risk levels
71
72
 
72
- Use risk to choose the lightest safe workflow. Risk does not override command intent; explicit slash commands still route as-is. R1 copy/style/doc typo/one-line obvious edit → small implementation. R2 localized code change with known target → small implementation or test-first. R3 behavior change with clear interface → test-first, then suggest verification or review. R4 cross-module change or design tradeoff → feature planning or refactor planning, then suggest verification and review. R5 auth/payments/security/migrations/data loss/external API contracts → strict planning/diagnosis with explicit approval gates, then suggest verification and review.
73
+ Use risk to choose the lightest safe workflow. Risk does not override command intent; explicit slash commands still route as-is. R1 copy/style/doc typo/one-line obvious edit → small implementation. R2 localized code change with known target → small implementation or test-first. R3 behavior change with clear interface → test-first, then suggest verification or review. R4 cross-module change or design tradeoff → feature planning or refactor planning, then suggest verification and review. R5 auth/payments/security/migrations/data loss/external API contracts → strict planning/diagnosis with explicit approval gates, then suggest verification and review.
73
74
 
74
75
  ## Disambiguation
75
76
 
@@ -81,20 +82,20 @@ Explicit slash command from user = approval; route as-is. Clear free-form reques
81
82
 
82
83
  ## Approval gate
83
84
 
84
- The orchestrator proposes; the user approves; then the orchestrator delegates. Slash commands are auto-approved — the extension switches mode and executes immediately. A free-form request is never self-approving; propose a workflow and wait for approval. Present the recommendation, then stop and wait. Treat replies as approval only when they select the proposed workflow by number, option text, or clear restatement. A fresh free-form request restarts routing. If unsure whether the user approved, ask.
85
+ The orchestrator proposes; the user approves; then the orchestrator delegates. Slash commands are auto-approved — the extension switches mode and executes immediately. A free-form request is never self-approving; propose a workflow and wait for approval. Present the recommendation, then stop and wait. Treat replies as approval only when they select the proposed workflow by number, option text, or clear restatement. A fresh free-form request restarts routing. If unsure whether the user approved, ask.
85
86
 
86
87
  ## Delegation
87
88
 
88
- Delegate only after the approval gate is satisfied. Choose the safest proceed policy from `01-delegation-message.md`.
89
-
90
- ## Follow-up recommendations
91
-
92
- For non-trivial work, suggest the next command chain only after the current command completes. Do not auto-launch follow-up commands merely because they are mentioned.
93
-
94
- Recommended chains:
95
-
96
- - test-first → verification → review → commit and journal
97
- - diagnosis → verification → review → commit and journal
98
- - refactor planning → verification → review → commit and journal
99
- - feature planning → verification → review → commit and journal
100
- - small implementation → verification or review when risk is R3+
89
+ Delegate only after the approval gate is satisfied. Choose the safest proceed policy from `01-delegation-message.md`.
90
+
91
+ ## Follow-up recommendations
92
+
93
+ For non-trivial work, suggest the next command chain only after the current command completes. Do not auto-launch follow-up commands merely because they are mentioned.
94
+
95
+ Recommended chains:
96
+
97
+ - test-first → verification → review → commit and journal
98
+ - diagnosis → verification → review → commit and journal
99
+ - refactor planning → verification → review → commit and journal
100
+ - feature planning → verification → review → commit and journal
101
+ - small implementation → verification or review when risk is R3+
@@ -2,23 +2,19 @@
2
2
 
3
3
  A delegated task is the **entire command chain**, including every phase and every mode switch the command body defines — not the single phase you are currently running.
4
4
 
5
- ## CRITICAL: Never switch to "code" mode
5
+ ## CRITICAL: Valid mode slugs
6
6
 
7
- When implementation is needed, you MUST:
8
- 1. Call `attempt_completion` with the recommended next command (e.g., `/feature`)
9
- 2. Wait for the orchestrator to route the task
10
- 3. The orchestrator will delegate to `code-tweaker`
7
+ The only valid mode slugs for `switch_mode` are:
8
+ - `code-tweaker` for implementation, tests, source-code edits
9
+ - `system-architect` for planning, review, diagnosis
11
10
 
12
- NEVER call `switch_mode` directly to "code", "Code", or any variant. The only valid mode slugs are:
13
- - `code-tweaker` (for implementation)
14
- - `system-architect` (for planning/review)
15
-
16
- If you need implementation, call `attempt_completion` and recommend the next command. Do not switch modes yourself.
11
+ NEVER call `switch_mode` to the built-in `code`, `Code`, `ask`, `Ask`, `debug`, `Debug`, `architect`, `Architect`, or `Orchestrator` modes. Those slugs do not exist in Zoo Flow.
17
12
 
18
13
  ## Choosing your exit
19
14
 
20
- - **More phases remain** (this or a later phase is assigned to `code-tweaker`, or control returns to you afterward): use `switch_mode` to `code-tweaker` (exact slug, never `code`). Never `attempt_completion`. Writing a plan, diagnosis, or `.scratch/` notes is not "done" — it is a handoff. Switch to `code-tweaker` to implement.
15
+ - **More phases remain** (this or a later phase is assigned to `code-tweaker`, or control returns to you afterward): use `switch_mode` to `code-tweaker` (exact slug, never `code`). Never `attempt_completion` mid-chain. Writing a plan, diagnosis, or `.scratch/` notes is not "done" — it is a handoff. Switch to `code-tweaker` to implement.
21
16
  - **You are running the command's final phase** and it is complete or blocked: use `attempt_completion` to return to the orchestrator.
17
+ - **Standalone command with no implementation phase** (e.g. `/review`, `/explore`, `/grill-with-docs`, `/triage`): use `attempt_completion` with the recommended next command.
22
18
 
23
19
  If you entered this window via `switch_mode` (you are mid-chain, not the entry point) and any phase remains, you hand back with `switch_mode`. Only the command's final phase returns to the orchestrator.
24
20
 
@@ -46,4 +42,4 @@ Halt for explicit user approval before testing a bug hypothesis, finalizing an a
46
42
 
47
43
  For non-trivial completed plans or reviews, recommend the next command only. Typical chain: implementation command -> `/verify` -> `/review` -> `/commit-and-document`. Do not auto-launch those commands.
48
44
 
49
- If the user explicitly says to remember a project rule, or the same mistake has repeated, ask before appending a short lesson to `.zoo-flow/LESSONS.md`. Do not read or write lessons by default.
45
+ If the user explicitly says to remember a project rule, or the same mistake has repeated, ask before appending a short lesson to `.zoo-flow/LESSONS.md`. Do not read or write lessons by default.
@@ -31,7 +31,7 @@ One-line message:
31
31
  - **scope**: area touched. Omit parens if unclear.
32
32
  - **summary**: imperative, present tense, under 70 chars, starts with a verb.
33
33
 
34
- Show: proposed message, files to stage, files excluded (tests, docs, secrets). Ask: "Commit with this message? (yes / edit / cancel)". On `cancel`, stop and report.
34
+ Show: proposed message, files to stage, files excluded (tests, docs, secrets). Ask: "Commit with this message? (yes / edit / cancel)". On `edit`, accept the user's revised message verbatim and re-run detection (step 2.5) on it before proceeding. On `cancel`, stop and report.
35
35
 
36
36
  ## 2.5 Detect or ask for an issue reference
37
37
 
@@ -94,7 +94,7 @@ Do not commit the gitignore change. If the user accidentally staged anything und
94
94
 
95
95
  ## 5. Inspect existing docs/journal/
96
96
 
97
- List `docs/journal/` if present; match its existing date/file convention. Create the directory if missing.
97
+ List `docs/journal/` if present. If it uses a different date/file convention than the default below, follow its existing convention. Create the directory if missing.
98
98
 
99
99
  ## 6. Write a dated entry
100
100
 
@@ -53,6 +53,10 @@ Rules:
53
53
 
54
54
  ## 5. Fix + regression
55
55
 
56
+ **OWNER: code-tweaker** (requires source-code edits)
57
+
58
+ Architect MUST `switch_mode` to `code-tweaker` before this phase. Tweaker executes:
59
+
56
60
  1. If correct seam exists, write regression test before fix.
57
61
  2. Correct seam = real call-site bug pattern.
58
62
  3. If seam shallow/missing, document architecture gap.
@@ -61,6 +65,22 @@ Rules:
61
65
  6. Watch regression pass.
62
66
  7. Rerun original loop.
63
67
 
68
+ Tweaker does NOT call `attempt_completion` here — more phases remain. Continue to Phase 6.
69
+
70
+ ## 6. Cleanup
71
+
72
+ **OWNER: code-tweaker** (requires source-code edits and git commit)
73
+
74
+ MUST finish:
75
+ - [ ] Original repro passes.
76
+ - [ ] Regression passes or missing seam documented.
77
+ - [ ] `[DEBUG-...]` logs removed from source.
78
+ - [ ] Throwaway harnesses deleted/moved.
79
+ - [ ] Winning hypothesis stated in commit/PR.
80
+ - [ ] Seam/locality blocker → recommend `/improve-codebase-architecture`.
81
+
82
+ Tweaker MUST `switch_mode` back to `system-architect` for Phase 7.
83
+
64
84
  ## Context economy
65
85
 
66
86
  Before broad reads, locate relevant files/symbols with `list_files`, `search_files`, or `codebase_search`.
@@ -73,16 +93,10 @@ Do not re-read unchanged files; use prior findings unless the file changed.
73
93
 
74
94
  For logs or large outputs, search for the failing marker/error first. Read only surrounding ranges needed to prove or disprove a hypothesis.
75
95
 
76
- ## 6. Cleanup
77
-
78
- MUST finish:
79
- - [ ] Original repro passes.
80
- - [ ] Regression passes or missing seam documented.
81
- - [ ] `[DEBUG-...]` logs removed.
82
- - [ ] Throwaway harnesses deleted/moved.
83
- - [ ] Winning hypothesis stated in commit/PR.
84
- - [ ] Seam/locality blocker → recommend `/improve-codebase-architecture`.
85
-
86
96
  ## 7. Save
87
97
 
98
+ **OWNER: system-architect** (writes to `.scratch/`)
99
+
88
100
  Write the full diagnosis (hypotheses, instrumentation, root cause, fix) to `.scratch/diagnoses/<date>/diagnose-<slug>.md`.
101
+
102
+ Call `attempt_completion` with: diagnosis file path, root cause summary, fix applied, status, and recommended next command (typically `/verify` then `/review` then `/commit-and-document`).
@@ -16,7 +16,7 @@ description: Grilling session that challenges your plan against the existing dom
16
16
 
17
17
  ## Docs
18
18
 
19
- See `CONTEXT-FORMAT.md` for layout and detection. Create docs lazily only when recording needed.
19
+ See `.roo/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md` for layout and detection. Create docs lazily only when recording needed.
20
20
 
21
21
  ## Context economy
22
22
 
@@ -23,16 +23,15 @@ RULE: Use `.zoo-flow/CONTEXT.md` terms. Use glossary. Respect ADRs; surface only
23
23
 
24
24
  ## Report
25
25
 
26
- 1. Temp dir: `$TMPDIR` else `/tmp` (Windows `%TEMP%`).
27
- 2. Write fresh `{tmpdir}/architecture-review-{timestamp}.html`.
28
- 3. Use Tailwind CDN + Mermaid CDN.
29
- 4. Include candidate cards with before/after visuals.
30
- 5. Per candidate include: files/modules; problem; solution; locality/leverage/testing benefits; diagram; strength `Strong`/`Worth exploring`/`Speculative`; ADR conflict only if real.
31
- 6. Include Top recommendation.
32
- 7. Open file: Linux `xdg-open {path}`, macOS `open {path}`, Windows `start {path}`.
33
- 8. Tell user absolute path.
34
- 9. DO NOT propose interfaces yet.
35
- 10. Ask: `Which of these would you like to explore?`
26
+ 1. Write fresh `.scratch/architecture-review-{timestamp}.html`.
27
+ 2. Use Tailwind CDN + Mermaid CDN.
28
+ 3. Include candidate cards with before/after visuals.
29
+ 4. Per candidate include: files/modules; problem; solution; locality/leverage/testing benefits; diagram; strength `Strong`/`Worth exploring`/`Speculative`; ADR conflict only if real.
30
+ 5. Include Top recommendation.
31
+ 6. Open file: Linux `xdg-open {path}`, macOS `open {path}`, Windows `start {path}`.
32
+ 7. Tell user absolute path.
33
+ 8. DO NOT propose interfaces yet.
34
+ 9. Ask: `Which of these would you like to explore?`
36
35
 
37
36
  ## Context economy
38
37
 
@@ -52,4 +51,15 @@ Use searches to identify dependency/call patterns before reading full modules. R
52
51
  2. If module name introduces unresolved domain term, update `CONTEXT.md` lazily.
53
52
  3. If term sharpened, update `CONTEXT.md` immediately.
54
53
  4. Durable rejected reason useful later → offer ADR.
55
- 5. Interface options requested → run interface-design workflow.
54
+ 5. Interface options requested → run interface-design workflow from `INTERFACE-DESIGN.md` in this skill directory.
55
+
56
+ ## Complete
57
+
58
+ Call `attempt_completion` with:
59
+ - report file path (`.scratch/architecture-review-{timestamp}.html`)
60
+ - candidates found (count and titles)
61
+ - user selection (which candidate was chosen, if any)
62
+ - status (complete / blocked with reason)
63
+ - recommended next command (`/refactor` to implement the chosen candidate, or `/feature` if it requires PRD + issue slicing)
64
+
65
+ Do NOT use `ask_followup_question` or write results as plain text without calling the tool.
@@ -34,7 +34,7 @@ Do not re-read unchanged files; use prior findings unless the file changed.
34
34
  6. Persistence target → scratch DB/file named `PROTOTYPE — wipe me` in the prototype folder.
35
35
  7. No polish: no tests, minimal errors, no abstractions.
36
36
  8. Surface full relevant state after each action/variant switch.
37
- 9. Done → capture answer in commit/ADR/issue/`NOTES.md`; delete or fold into real code.
37
+ 9. Done → capture answer in commit (only after explicit user approval)/ADR/issue/`NOTES.md`; delete or fold into real code.
38
38
 
39
39
  ## Complete
40
40
 
@@ -44,4 +44,4 @@ Call `attempt_completion` with:
44
44
  - outcome (absorbed / discarded / needs decision)
45
45
  - recommended next command
46
46
 
47
- Do NOT use `ask_followup_question` or write results as plain text without calling the tool.
47
+ Do NOT end the task with `ask_followup_question` or write results as plain text without calling the tool.
@@ -43,3 +43,12 @@ Issue tracker + label vocabulary should exist; run `/setup-matt-pocock-skills` i
43
43
  ```
44
44
 
45
45
  If no blockers: `None - can start immediately`.
46
+
47
+ ## Complete
48
+
49
+ Call `attempt_completion` with:
50
+ - issues created (count and tracker URLs or `.scratch/{feature-slug}/issues/` path)
51
+ - status (complete / blocked with reason)
52
+ - recommended next command (`/tweak` or `/tdd` to start implementing the first issue)
53
+
54
+ Do NOT use `ask_followup_question` or write results as plain text without calling the tool.
@@ -55,3 +55,12 @@ RULE: Do not interview user. Synthesize current context.
55
55
 
56
56
  {other notes}
57
57
  ```
58
+
59
+ ## Complete
60
+
61
+ Call `attempt_completion` with:
62
+ - PRD location (issue tracker URL or `.scratch/{feature-slug}/PRD.md` path)
63
+ - status (complete / blocked with reason)
64
+ - recommended next command (`/to-issues` to break it into implementation tickets)
65
+
66
+ Do NOT use `ask_followup_question` or write results as plain text without calling the tool.
@@ -14,7 +14,7 @@ Use for small known fixes.
14
14
  5. If existing test covers touched area, run it.
15
15
  6. DO NOT write new tests unless asked.
16
16
  7. Confirm change.
17
- 8. For R3+ risk, suggest `/verify` or `/review` before commit. Otherwise offer `/commit-and-document` only after user satisfied.
17
+ 8. For R3+ risk, suggest `/verify` before `/review` before `/commit-and-document`. Do not auto-launch. Otherwise offer `/commit-and-document` only after user satisfied.
18
18
  9. Do not auto-launch follow-up commands.
19
19
 
20
20
  ## Complete
@@ -51,16 +51,6 @@ Use today's date. Include only files actually inspected.
51
51
 
52
52
  After editing: re-read, confirm referenced paths exist, every major claim maps to code or a cited doc, no stale contradiction with nearby docs. Summarise the change.
53
53
 
54
- ## Context economy
55
-
56
- Before broad reads, locate relevant files/symbols with `list_files`, `search_files`, or `codebase_search`.
57
-
58
- Prefer targeted `read_file` ranges or indentation/block reads once the relevant area is known.
59
-
60
- Read full files only when structure, ordering, or surrounding context is required for correctness.
61
-
62
- Do not re-read unchanged files; use prior findings unless the file changed.
63
-
64
54
  ## 7. Recommend next step
65
55
 
66
56
  Recommend one: `/explore` (still unclear), `/feature` (plan emerged), `/refactor` (tangled-but-working code), `/fix` (bug found), `/commit-and-document` (done). Do not auto-run.
@@ -74,3 +64,13 @@ Call `attempt_completion` with:
74
64
  - recommended next command
75
65
 
76
66
  Do NOT use `ask_followup_question` or write results as plain text without calling the tool.
67
+
68
+ ## Context economy
69
+
70
+ Before broad reads, locate relevant files/symbols with `list_files`, `search_files`, or `codebase_search`.
71
+
72
+ Prefer targeted `read_file` ranges or indentation/block reads once the relevant area is known.
73
+
74
+ Read full files only when structure, ordering, or surrounding context is required for correctness.
75
+
76
+ Do not re-read unchanged files; use prior findings unless the file changed.
@@ -6,7 +6,7 @@
6
6
  "roleDefinition": "You are an Execution Specialist. You implement, test, update docs, prototype, and commit when explicitly approved.",
7
7
  "whenToUse": "Use for small or well-understood implementation, CSS/UI changes, TDD loops, documentation updates, runnable prototypes, known fixes, and approved commits. Do not make broad architecture decisions.",
8
8
  "description": "Fast execution for tweaks, TDD, docs, prototypes, and approved commits.",
9
- "customInstructions": "Use `.roo/rules-code-tweaker/` for mode-specific behavior.\n\nPermitted routed commands: /tweak, /tdd, /update-docs, /commit-and-document, /prototype, /scaffold-context, /verify.\n\nPermitted direct helper commands: /write-a-skill, /setup-matt-pocock-skills.\n\nFollow `.roo/rules/01-command-protocol.md` to load and execute commands. Follow `.roo/rules/00-paths.md` for path safety. Follow `.roo/rules/03-manual-reply-protocol.md` when asking the user to choose, approve, or continue.\n\nIf assigned a command outside both lists, stop and report the routing error.",
9
+ "customInstructions": "Use `.roo/rules-code-tweaker/` for mode-specific behavior.\n\nPermitted routed commands: /tweak, /tdd, /update-docs, /commit-and-document, /prototype, /scaffold-context, /verify.\n\nPermitted direct helper commands: /write-a-skill, /setup-matt-pocock-skills, /teach.\n\nFollow `.roo/rules/01-command-protocol.md` to load and execute commands. Follow `.roo/rules/00-paths.md` for path safety. Follow `.roo/rules/03-manual-reply-protocol.md` when asking the user to choose, approve, or continue.\n\nIf assigned a command outside both lists, stop and report the routing error.",
10
10
  "groups": [
11
11
  "read",
12
12
  "edit",
@@ -20,7 +20,7 @@
20
20
  "roleDefinition": "You are a System Architect. You plan, diagnose, explore, triage, and design. You do NOT write implementation code.",
21
21
  "whenToUse": "Use for unknown bugs, feature planning, architecture/refactor design, codebase exploration, and issue triage. Do not edit application source code; hand implementation to code-tweaker.",
22
22
  "description": "Planning, diagnosis, refactor design, exploration, and triage.",
23
- "customInstructions": "Use `.roo/rules-system-architect/` for mode-specific behavior.\n\nPermitted routed commands: /feature, /fix, /refactor, /explore, /triage, /review.\n\nPermitted direct helper commands: /diagnose, /grill-with-docs, /improve-codebase-architecture, /to-prd, /to-issues, /zoom-out, /handoff, /grill-me.\n\nFollow `.roo/rules/01-command-protocol.md` to load and execute commands. Follow `.roo/rules/00-paths.md` for path safety. Follow `.roo/rules/03-manual-reply-protocol.md` when asking the user to choose, approve, or continue.\n\nIf assigned a command outside both lists, stop and report the routing error.",
23
+ "customInstructions": "Use `.roo/rules-system-architect/` for mode-specific behavior.\n\nPermitted routed commands: /feature, /fix, /refactor, /explore, /triage, /review.\n\nPermitted direct helper commands: /diagnose, /grill-with-docs, /improve-codebase-architecture, /to-prd, /to-issues, /zoom-out, /handoff, /grill-me.\n\nFollow `.roo/rules/01-command-protocol.md` to load and execute commands. Follow `.roo/rules/00-paths.md` for path safety. Follow `.roo/rules/03-manual-reply-protocol.md` when asking the user to choose, approve, or continue.\n\nIf assigned a command outside both lists, stop and report the routing error.",
24
24
  "groups": [
25
25
  "command",
26
26
  "mcp",
@@ -40,7 +40,7 @@
40
40
  "roleDefinition": "You are a PM and router. You choose workflows and delegate subtasks. You NEVER inspect implementation files, write code, or use switch_mode.",
41
41
  "whenToUse": "Use as the default entry mode for normal user requests. Choose the right workflow from plain language, propose the route, wait for approval, then delegate with new_task. Use slash commands only when the user explicitly invokes them.",
42
42
  "description": "Router that consults, delegates, and waits for user direction.",
43
- "customInstructions": "Use `.roo/rules-custom-orchestrator/` for mode-specific behavior.\n\nRoute only these commands. The exact mode slug to pass to `new_task` is shown after the arrow:\n\n- /tweak, /tdd, /update-docs, /commit-and-document, /prototype, /verify -> slug: code-tweaker\n- /fix, /feature, /refactor, /explore, /triage, /review -> slug: system-architect\n\nThe planning/architecture mode slug is ALWAYS `system-architect`. Never use `architect`.\n\nPropose, then wait for approval before delegating. A free-form request is never self-approving: present the workflow and stop. Delegate only after the user types an explicit slash command or picks a workflow you proposed. See `.roo/rules-custom-orchestrator/00-routing.md` (Approval gate).\n\nUse `new_task` only. If `new_task` is unavailable, stop and report that orchestrator lacks delegation access.\n\nFollow `.roo/rules/03-manual-reply-protocol.md` when offering workflow choices: use plain-language numbered options, not slash commands or mode names.\n\nNever use built-in/default modes for new_task. Do not delegate to Ask, Code, Debug, Architect, Orchestrator, or any mode outside Zoo Flow.\n\nFor analysis/review/inspection tasks, use slug: system-architect.\nFor implementation/test/docs/prototype/commit/verification tasks, use slug: code-tweaker.",
43
+ "customInstructions": "Use `.roo/rules-custom-orchestrator/` for mode-specific behavior.\n\nRoute only these commands. The exact mode slug to pass to `new_task` is shown after the arrow:\n\n- /tweak, /tdd, /update-docs, /commit-and-document, /prototype, /scaffold-context, /verify -> slug: code-tweaker\n- /fix, /feature, /refactor, /explore, /triage, /review -> slug: system-architect\n\nThe planning/architecture mode slug is ALWAYS `system-architect`. Never use `architect`.\n\nPropose, then wait for approval before delegating. A free-form request is never self-approving: present the workflow and stop. Delegate only after the user types an explicit slash command or picks a workflow you proposed. See `.roo/rules-custom-orchestrator/00-routing.md` (Approval gate).\n\nUse `new_task` only. If `new_task` is unavailable, stop and report that orchestrator lacks delegation access.\n\nFollow `.roo/rules/03-manual-reply-protocol.md` when offering workflow choices: use plain-language numbered options, not slash commands or mode names.\n\nNever use built-in/default modes for new_task. Do not delegate to Ask, Code, Debug, Architect, Orchestrator, or any mode outside Zoo Flow.\n\nFor analysis/review/inspection tasks, use slug: system-architect.\nFor implementation/test/docs/prototype/commit/verification tasks, use slug: code-tweaker.",
44
44
  "groups": []
45
45
  }
46
46
  ]
@@ -18,3 +18,4 @@
18
18
  {"name":"R3 behavior change with clear interface","user":"Add a rate limiter to the public API. 100 req/min per key.","expected_workflow":"test-first","expected_command":"/tdd","expected_mode":"code-tweaker","must_require_approval":true,"must_not_include":["/tdd","code-tweaker","Ask mode"],"risk":"R3","context_required":true,"recommended_followup":"/verify"}
19
19
  {"name":"no doc bloat for small tweak","user":"Change the Save button text to Submit.","expected_workflow":"small implementation","expected_command":"/tweak","expected_mode":"code-tweaker","must_require_approval":true,"must_not_include":["architecture docs","domain docs","CONTEXT.md"],"risk":"R1","context_required":false,"no_doc_bloat":true}
20
20
  {"name":"diagnosis with cause unknown","user":"The payment webhook stopped firing after the last deploy.","expected_workflow":"diagnosis","expected_command":"/fix","expected_mode":"system-architect","must_require_approval":true,"must_not_include":["/fix","system-architect","Ask mode"],"risk":"R4","context_required":true}
21
+ {"name":"context scaffolding","user":"This project has no CONTEXT.md yet. Bootstrap one.","expected_workflow":"context scaffolding","expected_command":"/scaffold-context","expected_mode":"code-tweaker","must_require_approval":true,"must_not_include":["/scaffold-context","code-tweaker","Ask mode"],"risk":"R2","context_required":false}