wogiflow 1.5.2 → 1.5.3
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/lib/installer.js
CHANGED
|
@@ -583,6 +583,24 @@ function createCLIConfig(projectRoot, cliKey, config) {
|
|
|
583
583
|
|
|
584
584
|
You are an AI development assistant using the WogiFlow methodology v1.0.
|
|
585
585
|
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## Task Gating (MANDATORY — NO EXCEPTIONS)
|
|
589
|
+
|
|
590
|
+
**STOP. Before doing ANYTHING with a user message, you MUST route it through a \`/wogi-*\` command.**
|
|
591
|
+
|
|
592
|
+
**EVERY user message** MUST be routed through either:
|
|
593
|
+
1. **A matching \`/wogi-*\` command** (e.g., "code review" → \`/wogi-review\`, "show tasks" → \`/wogi-ready\`)
|
|
594
|
+
2. **\`/wogi-start\`** for everything else (the universal fallback router)
|
|
595
|
+
|
|
596
|
+
This applies to ALL message types — implementation requests, questions, exploration, research, operational requests. No exceptions.
|
|
597
|
+
|
|
598
|
+
**You do NOT handle requests directly.** Always invoke a \`/wogi-*\` command first. If you find yourself thinking "this is just a question, I can handle it directly" — that thought is the exact bypass this rule exists to prevent.
|
|
599
|
+
|
|
600
|
+
**Do NOT use EnterPlanMode directly.** Route through \`/wogi-start\` which will use plan mode internally when appropriate.
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
586
604
|
## Quick Start
|
|
587
605
|
|
|
588
606
|
\`\`\`bash
|
|
@@ -593,9 +611,12 @@ cat .workflow/state/ready.json # Check tasks
|
|
|
593
611
|
## Core Commands
|
|
594
612
|
|
|
595
613
|
- \`/wogi-ready\` - Show available tasks
|
|
596
|
-
- \`/wogi-start TASK-X\` - Start a task
|
|
614
|
+
- \`/wogi-start TASK-X\` - Start a task (or \`/wogi-start "description"\` to route any request)
|
|
615
|
+
- \`/wogi-story "title"\` - Create story with acceptance criteria
|
|
597
616
|
- \`/wogi-status\` - Project overview
|
|
598
617
|
- \`/wogi-health\` - Check workflow health
|
|
618
|
+
- \`/wogi-review\` - Code review
|
|
619
|
+
- \`/wogi-bug "description"\` - Report a bug
|
|
599
620
|
|
|
600
621
|
Run \`flow bridge sync\` to regenerate this file with full template.
|
|
601
622
|
|
package/package.json
CHANGED
package/scripts/flow-health.js
CHANGED
|
@@ -441,6 +441,117 @@ function main() {
|
|
|
441
441
|
console.log(` ${color('yellow', '○')} .claude/settings.local.json not found (run 'flow bridge sync')`);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
+
// Check hook integrity
|
|
445
|
+
console.log('');
|
|
446
|
+
printSection('Checking hook integrity...');
|
|
447
|
+
|
|
448
|
+
const settingsLocalPath = path.join(PROJECT_ROOT, '.claude', 'settings.local.json');
|
|
449
|
+
if (fileExists(settingsLocalPath)) {
|
|
450
|
+
try {
|
|
451
|
+
const settings = safeJsonParse(settingsLocalPath, {});
|
|
452
|
+
const hooks = settings.hooks || {};
|
|
453
|
+
|
|
454
|
+
// Check PreToolUse matcher includes EnterPlanMode
|
|
455
|
+
const preToolHooks = hooks.PreToolUse || [];
|
|
456
|
+
let hasEnterPlanMode = false;
|
|
457
|
+
let hasCorrectMatcher = false;
|
|
458
|
+
let hookScriptsMissing = [];
|
|
459
|
+
|
|
460
|
+
for (const hookEntry of preToolHooks) {
|
|
461
|
+
const matcher = hookEntry.matcher || '';
|
|
462
|
+
if (matcher.includes('EnterPlanMode')) {
|
|
463
|
+
hasEnterPlanMode = true;
|
|
464
|
+
}
|
|
465
|
+
if (matcher.includes('Edit') && matcher.includes('Write') && matcher.includes('Bash') && matcher.includes('Skill')) {
|
|
466
|
+
hasCorrectMatcher = true;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Check hook script files exist
|
|
470
|
+
for (const h of (hookEntry.hooks || [])) {
|
|
471
|
+
if (h.command) {
|
|
472
|
+
// Extract script path from command like: node "/path/to/script.js"
|
|
473
|
+
const scriptMatch = h.command.match(/node\s+"([^"]+)"/);
|
|
474
|
+
if (scriptMatch) {
|
|
475
|
+
const scriptPath = scriptMatch[1];
|
|
476
|
+
if (!fileExists(scriptPath)) {
|
|
477
|
+
hookScriptsMissing.push(scriptPath);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Also check other hook types for missing scripts
|
|
485
|
+
for (const hookType of ['PostToolUse', 'UserPromptSubmit', 'SessionStart']) {
|
|
486
|
+
for (const hookEntry of (hooks[hookType] || [])) {
|
|
487
|
+
for (const h of (hookEntry.hooks || [])) {
|
|
488
|
+
if (h.command) {
|
|
489
|
+
const scriptMatch = h.command.match(/node\s+"([^"]+)"/);
|
|
490
|
+
if (scriptMatch && !fileExists(scriptMatch[1])) {
|
|
491
|
+
hookScriptsMissing.push(scriptMatch[1]);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (hasEnterPlanMode) {
|
|
499
|
+
console.log(` ${color('green', '✓')} PreToolUse matcher includes EnterPlanMode`);
|
|
500
|
+
} else {
|
|
501
|
+
console.log(` ${color('red', '✗')} PreToolUse matcher MISSING EnterPlanMode — Claude can bypass /wogi-start`);
|
|
502
|
+
console.log(` ${color('dim', "→ Run 'flow bridge sync' to regenerate hooks")}`);
|
|
503
|
+
issues++;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (hasCorrectMatcher) {
|
|
507
|
+
console.log(` ${color('green', '✓')} PreToolUse matcher has core tools (Edit|Write|Bash|Skill)`);
|
|
508
|
+
} else if (preToolHooks.length > 0) {
|
|
509
|
+
console.log(` ${color('yellow', '⚠')} PreToolUse matcher may be outdated — missing core tools`);
|
|
510
|
+
console.log(` ${color('dim', "→ Run 'flow bridge sync' to regenerate hooks")}`);
|
|
511
|
+
warnings++;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (hookScriptsMissing.length > 0) {
|
|
515
|
+
console.log(` ${color('red', '✗')} ${hookScriptsMissing.length} hook script(s) MISSING:`);
|
|
516
|
+
for (const missing of hookScriptsMissing.slice(0, 5)) {
|
|
517
|
+
console.log(` - ${missing}`);
|
|
518
|
+
}
|
|
519
|
+
console.log(` ${color('dim', "→ Run 'npm install wogiflow' or 'flow init' to restore scripts")}`);
|
|
520
|
+
issues++;
|
|
521
|
+
} else if (preToolHooks.length > 0) {
|
|
522
|
+
console.log(` ${color('green', '✓')} All hook scripts exist`);
|
|
523
|
+
}
|
|
524
|
+
} catch (err) {
|
|
525
|
+
console.log(` ${color('yellow', '⚠')} Could not parse settings.local.json for hooks: ${err.message}`);
|
|
526
|
+
warnings++;
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
console.log(` ${color('yellow', '⚠')} .claude/settings.local.json not found — hooks not configured`);
|
|
530
|
+
console.log(` ${color('dim', "→ Run 'flow bridge sync' to generate hooks")}`);
|
|
531
|
+
warnings++;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Check CLAUDE.md has routing instructions (not just product description)
|
|
535
|
+
if (fileExists(claudeMdPath)) {
|
|
536
|
+
try {
|
|
537
|
+
const claudeContent = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
538
|
+
const hasRouting = claudeContent.includes('wogi-start') && (
|
|
539
|
+
claudeContent.includes('Task Gating') ||
|
|
540
|
+
claudeContent.includes('MUST route') ||
|
|
541
|
+
claudeContent.includes('MANDATORY')
|
|
542
|
+
);
|
|
543
|
+
if (hasRouting) {
|
|
544
|
+
console.log(` ${color('green', '✓')} CLAUDE.md contains routing instructions`);
|
|
545
|
+
} else {
|
|
546
|
+
console.log(` ${color('red', '✗')} CLAUDE.md has NO routing instructions — Claude will bypass /wogi-start`);
|
|
547
|
+
console.log(` ${color('dim', "→ Run 'flow bridge sync' to regenerate CLAUDE.md from template")}`);
|
|
548
|
+
issues++;
|
|
549
|
+
}
|
|
550
|
+
} catch (err) {
|
|
551
|
+
// Already warned about CLAUDE.md read failure above
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
444
555
|
// Check git status
|
|
445
556
|
console.log('');
|
|
446
557
|
printSection('Checking git status...');
|
|
@@ -513,7 +513,7 @@ Run: /wogi-start ${coreResult.nextTaskId}`;
|
|
|
513
513
|
// Task gating for Edit/Write + TodoWrite gating + Skill tracking + Bash strict adherence
|
|
514
514
|
if (rules.taskGating?.enabled !== false || rules.todoWriteGate?.enabled !== false) {
|
|
515
515
|
preToolUseMatchers.push({
|
|
516
|
-
matcher: 'Edit|Write|TodoWrite|Skill|Bash',
|
|
516
|
+
matcher: 'Edit|Write|TodoWrite|Skill|Bash|EnterPlanMode',
|
|
517
517
|
hooks: [{
|
|
518
518
|
type: 'command',
|
|
519
519
|
command: `node "${path.join(scriptsDir, 'pre-tool-use.js')}"`,
|
|
@@ -163,9 +163,11 @@ function isRoutingPending() {
|
|
|
163
163
|
* @returns {{ allowed: boolean, blocked: boolean, reason: string, message: string|null }}
|
|
164
164
|
*/
|
|
165
165
|
function checkRoutingGate(toolName) {
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
// Gate Bash and EnterPlanMode calls
|
|
167
|
+
// EnterPlanMode bypasses /wogi-start routing — must be blocked before routing
|
|
168
|
+
const GATED_TOOLS = new Set(['Bash', 'EnterPlanMode']);
|
|
169
|
+
if (!GATED_TOOLS.has(toolName)) {
|
|
170
|
+
return { allowed: true, blocked: false, reason: 'not_gated_tool', message: null };
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
// Check if routing gate is enabled
|
|
@@ -151,9 +151,9 @@ async function main() {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
// v6.0: Routing gate check (for Bash)
|
|
155
|
-
// Blocks Bash calls when no /wogi-* command has been invoked first
|
|
156
|
-
if (toolName === 'Bash') {
|
|
154
|
+
// v6.0: Routing gate check (for Bash and EnterPlanMode)
|
|
155
|
+
// Blocks Bash/EnterPlanMode calls when no /wogi-* command has been invoked first
|
|
156
|
+
if (toolName === 'Bash' || toolName === 'EnterPlanMode') {
|
|
157
157
|
try {
|
|
158
158
|
const routingResult = checkRoutingGate(toolName);
|
|
159
159
|
if (routingResult.blocked) {
|