wogiflow 1.5.11 → 1.5.12

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.
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "PreToolUse": [
37
37
  {
38
- "matcher": "Edit|Write|TodoWrite|Skill|Bash|EnterPlanMode",
38
+ "matcher": "Edit|Write|TodoWrite|Skill|Bash|Read|Glob|Grep|EnterPlanMode",
39
39
  "hooks": [
40
40
  {
41
41
  "type": "command",
@@ -346,7 +346,7 @@ Last synced: ${new Date().toISOString()}
346
346
  'Bash(python -m *)',
347
347
  'Bash(python3 -m *)',
348
348
 
349
- // Git operations - all safe read/write operations
349
+ // Git operations - safe read/write operations
350
350
  'Bash(git status)',
351
351
  'Bash(git status *)',
352
352
  'Bash(git diff *)',
@@ -358,8 +358,13 @@ Last synced: ${new Date().toISOString()}
358
358
  'Bash(git push *)',
359
359
  'Bash(git pull *)',
360
360
  'Bash(git fetch *)',
361
- 'Bash(git reset *)',
362
- 'Bash(git restore *)',
361
+ // git reset — only safe unstaging operations
362
+ // NOTE: git reset --hard intentionally excluded — destroys uncommitted work
363
+ 'Bash(git reset HEAD *)',
364
+ 'Bash(git reset --soft *)',
365
+ // git restore — only safe staged-file operations
366
+ // NOTE: git restore <file> / git restore . intentionally excluded — discards changes
367
+ 'Bash(git restore --staged *)',
363
368
  'Bash(git show *)',
364
369
  'Bash(git rm *)',
365
370
  'Bash(git ls-files *)',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "1.5.11",
3
+ "version": "1.5.12",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -36,25 +36,36 @@ const HOOK_TIMEOUTS = {
36
36
  };
37
37
 
38
38
  /**
39
- * Claude Code Hook Events
39
+ * Claude Code Hook Events — ONLY officially supported events.
40
+ * Claude Code rejects settings.json with unrecognized hook keys.
41
+ * Do NOT add hooks here without verifying they pass Claude Code schema validation.
40
42
  */
41
43
  const CLAUDE_CODE_EVENTS = [
42
44
  'SessionStart',
43
- 'Setup', // Claude Code 2.1.10+ - triggered by --init, --init-only, --maintenance
44
45
  'PreToolUse',
45
46
  'PostToolUse',
46
47
  'Stop',
47
- 'SubagentStop',
48
48
  'SessionEnd',
49
- 'Notification',
50
49
  'UserPromptSubmit',
51
- 'TaskCompleted', // Claude Code 2.1.33+ - fired when sub-agent task completes
52
- 'TeammateIdle', // Claude Code 2.1.33+ - fired when teammate agent becomes idle
53
- 'ConfigChange', // Claude Code latest - fired when config files change mid-session
54
- 'WorktreeCreate', // Claude Code 2.1.50+ - fired when a new worktree is created
55
- 'WorktreeRemove' // Claude Code 2.1.50+ - fired when a worktree is removed
56
50
  ];
57
51
 
52
+ /**
53
+ * Extended hook events — NOT part of official Claude Code schema.
54
+ * These were speculatively added and cause schema validation errors.
55
+ * Kept here for reference in case Claude Code adds them in the future.
56
+ * See: https://github.com/anthropics/claude-code/issues (check for hook API updates)
57
+ */
58
+ // const EXTENDED_EVENTS_NOT_YET_SUPPORTED = [
59
+ // 'Setup', // Speculated for --init/--maintenance
60
+ // 'SubagentStop', // Speculated for sub-agent stop
61
+ // 'Notification', // Speculated for notifications
62
+ // 'TaskCompleted', // Speculated for task completion
63
+ // 'TeammateIdle', // Speculated for teammate idle
64
+ // 'ConfigChange', // Speculated for config changes
65
+ // 'WorktreeCreate', // Speculated for worktree creation
66
+ // 'WorktreeRemove', // Speculated for worktree removal
67
+ // ];
68
+
58
69
  /**
59
70
  * Claude Code Adapter
60
71
  */
@@ -503,16 +514,8 @@ Run: /wogi-start ${coreResult.nextTaskId}`;
503
514
  }];
504
515
  }
505
516
 
506
- // Setup hook (Claude Code 2.1.10+ --init/--maintenance)
507
- if (rules.setup?.enabled !== false) {
508
- hooks.Setup = [{
509
- hooks: [{
510
- type: 'command',
511
- command: `node "${path.join(scriptsDir, 'setup.js')}"`,
512
- timeout: HOOK_TIMEOUTS.SETUP
513
- }]
514
- }];
515
- }
517
+ // NOTE: Setup hook removed — not in official Claude Code schema.
518
+ // The setup.js entry script still exists for manual use.
516
519
 
517
520
  // UserPromptSubmit hook (implementation gate)
518
521
  if (rules.implementationGate?.enabled !== false) {
@@ -531,7 +534,7 @@ Run: /wogi-start ${coreResult.nextTaskId}`;
531
534
  // Task gating for Edit/Write + TodoWrite gating + Skill tracking + Bash strict adherence
532
535
  if (rules.taskGating?.enabled !== false || rules.todoWriteGate?.enabled !== false) {
533
536
  preToolUseMatchers.push({
534
- matcher: 'Edit|Write|TodoWrite|Skill|Bash|EnterPlanMode',
537
+ matcher: 'Edit|Write|TodoWrite|Skill|Bash|Read|Glob|Grep|EnterPlanMode',
535
538
  hooks: [{
536
539
  type: 'command',
537
540
  command: `node "${path.join(scriptsDir, 'pre-tool-use.js')}"`,
@@ -578,62 +581,21 @@ Run: /wogi-start ${coreResult.nextTaskId}`;
578
581
  }];
579
582
  }
580
583
 
581
- // TaskCompleted hook for post-task cleanup (Claude Code 2.1.33+)
582
- if (rules.taskCompleted?.enabled !== false) {
583
- hooks.TaskCompleted = [{
584
- hooks: [{
585
- type: 'command',
586
- command: `node "${path.join(scriptsDir, 'task-completed.js')}"`,
587
- timeout: HOOK_TIMEOUTS.TASK_COMPLETED
588
- }]
589
- }];
590
- }
591
-
592
- // TeammateIdle hook for task dispatch (Claude Code 2.1.33+, experimental)
593
- if (rules.teammateIdle?.enabled === true) {
594
- hooks.TeammateIdle = [{
595
- hooks: [{
596
- type: 'command',
597
- command: `node "${path.join(scriptsDir, 'teammate-idle.js')}"`,
598
- timeout: HOOK_TIMEOUTS.TEAMMATE_IDLE
599
- }]
600
- }];
601
- }
602
-
603
- // ConfigChange hook for mid-session config detection (Claude Code latest)
604
- if (rules.configChange?.enabled !== false) {
605
- hooks.ConfigChange = [{
606
- hooks: [{
607
- type: 'command',
608
- command: `node "${path.join(scriptsDir, 'config-change.js')}"`,
609
- timeout: HOOK_TIMEOUTS.CONFIG_CHANGE
610
- }]
611
- }];
612
- }
613
-
614
- // WorktreeCreate hook (Claude Code 2.1.50+ worktree lifecycle)
615
- if (rules.worktreeLifecycle?.enabled !== false) {
616
- hooks.WorktreeCreate = [{
617
- hooks: [{
618
- type: 'command',
619
- command: `node "${path.join(scriptsDir, 'worktree-create.js')}"`,
620
- timeout: HOOK_TIMEOUTS.WORKTREE_CREATE
621
- }]
622
- }];
623
- }
624
-
625
- // WorktreeRemove hook (Claude Code 2.1.50+ worktree lifecycle)
626
- if (rules.worktreeLifecycle?.enabled !== false) {
627
- hooks.WorktreeRemove = [{
628
- hooks: [{
629
- type: 'command',
630
- command: `node "${path.join(scriptsDir, 'worktree-remove.js')}"`,
631
- timeout: HOOK_TIMEOUTS.WORKTREE_REMOVE
632
- }]
633
- }];
584
+ // NOTE: TaskCompleted, TeammateIdle, ConfigChange, WorktreeCreate, WorktreeRemove
585
+ // hooks removed — not in official Claude Code schema. Registering them causes
586
+ // schema validation errors that block Claude Code from loading settings.
587
+ // Entry scripts still exist in scripts/hooks/entry/claude-code/ for future use
588
+ // if/when Claude Code officially supports these events.
589
+
590
+ // Final safety filter: only emit hooks that are in CLAUDE_CODE_EVENTS
591
+ const filteredHooks = {};
592
+ for (const [key, value] of Object.entries(hooks)) {
593
+ if (CLAUDE_CODE_EVENTS.includes(key)) {
594
+ filteredHooks[key] = value;
595
+ }
634
596
  }
635
597
 
636
- return { hooks };
598
+ return { hooks: filteredHooks };
637
599
  }
638
600
 
639
601
  /**
@@ -170,9 +170,10 @@ function isRoutingPending() {
170
170
  * @returns {{ allowed: boolean, blocked: boolean, reason: string, message: string|null }}
171
171
  */
172
172
  function checkRoutingGate(toolName) {
173
- // Gate Bash and EnterPlanMode calls
173
+ // Gate Bash, EnterPlanMode, and read tools (Read/Glob/Grep)
174
174
  // EnterPlanMode bypasses /wogi-start routing — must be blocked before routing
175
- const GATED_TOOLS = new Set(['Bash', 'EnterPlanMode']);
175
+ // Read/Glob/Grep allow codebase exploration without routing — must also be gated
176
+ const GATED_TOOLS = new Set(['Bash', 'EnterPlanMode', 'Read', 'Glob', 'Grep']);
176
177
  if (!GATED_TOOLS.has(toolName)) {
177
178
  return { allowed: true, blocked: false, reason: 'not_gated_tool', message: null };
178
179
  }
@@ -203,11 +204,11 @@ function checkRoutingGate(toolName) {
203
204
  blocked: true,
204
205
  reason: 'routing_pending',
205
206
  message: [
206
- 'BLOCKED: You must route through /wogi-start before using Bash or EnterPlanMode.',
207
+ 'BLOCKED: You must route through /wogi-start before using Bash, Read, Glob, Grep, or EnterPlanMode.',
207
208
  'ACTION REQUIRED: Invoke the Skill tool with skill="wogi-start" and pass the user\'s request as args.',
208
209
  'Example: Skill(skill="wogi-start", args="<the user\'s original request>")',
209
210
  '/wogi-start will classify the request (operational, exploration, implementation) and unblock the appropriate tools.',
210
- 'Do NOT suggest the user run commands manually in their terminal.',
211
+ 'Do NOT read files, search code, or execute commands without routing first.',
211
212
  'Do NOT try alternative approaches to bypass this gate.'
212
213
  ].join(' ')
213
214
  };
@@ -167,9 +167,9 @@ async function main() {
167
167
  }
168
168
  }
169
169
 
170
- // v6.0: Routing gate check (for Bash and EnterPlanMode)
171
- // Blocks Bash/EnterPlanMode calls when no /wogi-* command has been invoked first
172
- if (toolName === 'Bash' || toolName === 'EnterPlanMode') {
170
+ // v6.0: Routing gate check (for Bash, EnterPlanMode, Read, Glob, Grep)
171
+ // Blocks tool calls when no /wogi-* command has been invoked first
172
+ if (toolName === 'Bash' || toolName === 'EnterPlanMode' || toolName === 'Read' || toolName === 'Glob' || toolName === 'Grep') {
173
173
  try {
174
174
  const routingResult = checkRoutingGate(toolName);
175
175
  if (routingResult.blocked) {