wogiflow 2.4.1 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -15,8 +15,10 @@
15
15
  * v1.0: Initial implementation — pre-commit blocking gate
16
16
  */
17
17
 
18
+ const fs = require('node:fs');
19
+ const path = require('node:path');
18
20
  const { execFileSync } = require('node:child_process');
19
- const { getConfig, getReadyData } = require('../../flow-utils');
21
+ const { getConfig, getReadyData, PATHS } = require('../../flow-utils');
20
22
 
21
23
  /**
22
24
  * Check if a Bash command contains a git commit
@@ -120,25 +122,34 @@ function checkCommitLogGate(command, config) {
120
122
  return { allowed: true, blocked: false };
121
123
  }
122
124
 
123
- // Check if request-log.md is in staged changes
124
- const hasLogEntry = stagedFiles.some(f => f.endsWith('request-log.md'));
125
+ // Check if request-log.md contains an entry for the active task.
126
+ // We check file content instead of git staging because .workflow/ may be
127
+ // in .gitignore (intentional user choice to keep state files out of git).
128
+ // Checking staged files would silently fail when the directory is gitignored.
129
+ const task = readyData.inProgress[0];
130
+ const taskId = (typeof task === 'string' ? task : task.id) || 'unknown';
131
+
132
+ const logPath = path.join(PATHS.state, 'request-log.md');
133
+ let hasLogEntry = false;
134
+ try {
135
+ const logContent = fs.readFileSync(logPath, 'utf-8');
136
+ hasLogEntry = logContent.includes(taskId);
137
+ } catch (_err) {
138
+ // File doesn't exist or can't be read — no log entry
139
+ }
140
+
125
141
  if (hasLogEntry) {
126
142
  return { allowed: true, blocked: false };
127
143
  }
128
144
 
129
- // Block: active task + code changes but no log entry
130
- const task = readyData.inProgress[0];
131
- const taskId = (typeof task === 'string' ? task : task.id) || 'unknown';
132
-
133
145
  return {
134
146
  allowed: false,
135
147
  blocked: true,
136
148
  reason: 'commit_without_log_entry',
137
149
  message: [
138
- `BLOCKED: Active task ${taskId} but request-log.md is not staged.`,
150
+ `BLOCKED: Active task ${taskId} but no request-log entry found.`,
139
151
  'Add a request-log entry before committing.',
140
- 'Append a ### R-[N] entry to .workflow/state/request-log.md following the existing format,',
141
- 'then stage it: git add .workflow/state/request-log.md'
152
+ `Append a ### R-[N] entry referencing ${taskId} to .workflow/state/request-log.md following the existing format.`
142
153
  ].join(' ')
143
154
  };
144
155
  }
@@ -296,6 +296,33 @@ function checkTaskGate(options = {}, config) {
296
296
  };
297
297
  }
298
298
 
299
+ // getActiveTask() returned null — check if a task EXISTS in inProgress
300
+ // but was rejected for missing routing proof (routedAt + receipt).
301
+ // This gives the AI an actionable error instead of the misleading "no active task".
302
+ try {
303
+ const readyData = getReadyData();
304
+ if (readyData.inProgress && readyData.inProgress.length > 0) {
305
+ const task = readyData.inProgress[0];
306
+ const taskId = typeof task === 'string' ? task : task.id;
307
+ if (taskId) {
308
+ trackBypassAttempt({
309
+ filePath,
310
+ operation,
311
+ reason: 'task_missing_routing_proof',
312
+ taskId
313
+ });
314
+ return {
315
+ allowed: false,
316
+ blocked: true,
317
+ message: `Task ${taskId} is in inProgress but has no routing proof (missing routedAt and no routing receipt file).\n\nThis usually means the task was inserted into ready.json manually instead of through /wogi-start.\n\nTo fix:\n1. Use /wogi-start ${taskId} to properly route this task\n2. Or remove it from inProgress and start fresh: /wogi-ready`,
318
+ reason: 'task_missing_routing_proof'
319
+ };
320
+ }
321
+ }
322
+ } catch (_err) {
323
+ // Fall through to normal "no active task" path
324
+ }
325
+
299
326
  // No active task - should we block?
300
327
  const shouldBlock = config.enforcement?.taskGating?.blockWithoutTask !== false;
301
328