wogiflow 1.0.41 → 1.0.42

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": "1.0.41",
3
+ "version": "1.0.42",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -27,6 +27,8 @@ const {
27
27
  outputJson,
28
28
  getConfig,
29
29
  getConfigValue,
30
+ safeJsonParse,
31
+ withLock,
30
32
  color,
31
33
  success,
32
34
  warn,
@@ -126,7 +128,7 @@ ${discoveredFrom ? `- Discovered while working on: ${discoveredFrom}` : ''}
126
128
  /**
127
129
  * Main function
128
130
  */
129
- function main() {
131
+ async function main() {
130
132
  const { flags, positional } = parseFlags(process.argv.slice(2));
131
133
 
132
134
  // Handle help
@@ -215,12 +217,52 @@ Examples:
215
217
  const content = createBugContent(bug);
216
218
  writeFile(bugPath, content);
217
219
 
220
+ // v4.2: Add bug to ready.json so it can be started with /wogi-start
221
+ let addedToReady = false;
222
+ try {
223
+ await withLock(PATHS.ready, async () => {
224
+ const ready = safeJsonParse(PATHS.ready, { ready: [], inProgress: [], completed: [] });
225
+
226
+ // Check if already exists (duplicate prevention)
227
+ const exists = ready.ready?.some(t => t.id === id) ||
228
+ ready.inProgress?.some(t => t.id === id) ||
229
+ ready.completed?.some(t => t.id === id);
230
+
231
+ if (!exists) {
232
+ if (!Array.isArray(ready.ready)) {
233
+ ready.ready = [];
234
+ }
235
+
236
+ ready.ready.push({
237
+ id,
238
+ title,
239
+ type: 'bug',
240
+ priority,
241
+ severity,
242
+ discoveredFrom,
243
+ status: 'ready',
244
+ createdAt,
245
+ specPath: bugPath
246
+ });
247
+
248
+ fs.writeFileSync(PATHS.ready, JSON.stringify(ready, null, 2), 'utf-8');
249
+ addedToReady = true;
250
+ }
251
+ });
252
+ } catch (lockErr) {
253
+ // Non-fatal: bug file was created, just couldn't add to ready.json
254
+ if (process.env.DEBUG) {
255
+ console.error(`[DEBUG] Could not add to ready.json: ${lockErr.message}`);
256
+ }
257
+ }
258
+
218
259
  // Output result
219
260
  if (flags.json) {
220
261
  outputJson({
221
262
  success: true,
222
263
  bug,
223
- file: bugPath
264
+ file: bugPath,
265
+ addedToReady
224
266
  });
225
267
  } else {
226
268
  console.log('');
@@ -234,6 +276,12 @@ Examples:
234
276
  console.log(`Discovered from: ${color('yellow', discoveredFrom)}`);
235
277
  }
236
278
 
279
+ if (addedToReady) {
280
+ console.log('');
281
+ console.log(color('green', `✓ Added to ready.json`));
282
+ console.log(`Start with: ${color('cyan', `/wogi-start ${id}`)}`);
283
+ }
284
+
237
285
  console.log('');
238
286
  info('Edit the file to add description, steps to reproduce, etc.');
239
287
  }
@@ -241,7 +289,10 @@ Examples:
241
289
 
242
290
  // Run only when executed directly
243
291
  if (require.main === module) {
244
- main();
292
+ main().catch(err => {
293
+ error(err.message);
294
+ process.exit(1);
295
+ });
245
296
  }
246
297
 
247
298
  module.exports = { main, createBugContent, getCurrentTask };
@@ -156,17 +156,79 @@ function getRegistrySummary(registryPath, type) {
156
156
  return null;
157
157
  }
158
158
 
159
+ /**
160
+ * Triage a request that isn't a task ID
161
+ * Outputs classification context for the agent (Claude) to decide what to do
162
+ * @param {string} prompt - The user's request
163
+ */
164
+ function triageRequest(prompt) {
165
+ console.log('');
166
+ console.log(color('cyan', '━'.repeat(60)));
167
+ console.log(color('cyan', ' REQUEST TRIAGE'));
168
+ console.log(color('cyan', '━'.repeat(60)));
169
+ console.log('');
170
+ console.log(`Request: "${prompt}"`);
171
+ console.log('');
172
+ console.log(color('yellow', 'Decide based on your understanding:'));
173
+ console.log('');
174
+ console.log(color('green', 'OPERATIONAL') + ' (execute directly, no task needed):');
175
+ console.log(' - Version control: push, pull, fetch, merge, commit');
176
+ console.log(' - Publishing: deploy, publish to any platform');
177
+ console.log(' - Build/CI: run tests, build, lint, format');
178
+ console.log(' - Maintenance: update deps, bump version');
179
+ console.log(' - Reviews: code review, check something');
180
+ console.log('');
181
+ console.log(color('yellow', 'SMALL FIX') + ' (execute + log for learning):');
182
+ console.log(' - Trivial changes: typo, color, text');
183
+ console.log(' - Single line changes');
184
+ console.log(' - No behavioral change');
185
+ console.log('');
186
+ console.log(color('red', 'IMPLEMENTATION') + ' (create task first):');
187
+ console.log(' - New features: add, create, build');
188
+ console.log(' - Bug fixes: fix errors, resolve issues');
189
+ console.log(' - Refactoring: restructure, reorganize');
190
+ console.log('');
191
+ console.log(color('cyan', '━'.repeat(60)));
192
+ console.log('');
193
+ console.log(color('dim', 'Based on your classification:'));
194
+ console.log(` ${color('green', 'OPERATIONAL')} → Proceed with the request directly`);
195
+ console.log(` ${color('yellow', 'SMALL FIX')} → Execute, then add to request-log.md with #quick-fix tag`);
196
+ console.log(` ${color('red', 'IMPLEMENTATION')} → Use /wogi-bug or /wogi-story first`);
197
+ console.log('');
198
+
199
+ // Return triage mode indicator for programmatic use
200
+ return {
201
+ triageMode: true,
202
+ prompt,
203
+ awaitingClassification: true
204
+ };
205
+ }
206
+
159
207
  async function main() {
160
- const taskId = process.argv[2];
208
+ const taskIdArg = process.argv[2];
161
209
  const forceResume = process.argv.includes('--force-resume');
162
210
  const skipSuspensionCheck = process.argv.includes('--skip-suspension');
163
211
  const usePhasedMode = process.argv.includes('--phased');
164
212
 
165
- if (!taskId) {
213
+ if (!taskIdArg) {
166
214
  console.log('Usage: flow start <task-id> [--force-resume] [--skip-suspension] [--phased]');
215
+ console.log(' flow start "<request>" - Triage a request (agent decides)');
167
216
  process.exit(1);
168
217
  }
169
218
 
219
+ // v4.2: Check if this is a quoted request or non-task-ID input
220
+ // Task IDs match pattern: wf-XXXXXXXX (hex hash)
221
+ const isTaskId = /^wf-[a-f0-9]+$/i.test(taskIdArg);
222
+
223
+ if (!isTaskId) {
224
+ // This is a quoted request, not a task ID - run triage
225
+ const prompt = taskIdArg.replace(/^["']|["']$/g, ''); // Remove surrounding quotes if any
226
+ triageRequest(prompt);
227
+ process.exit(0);
228
+ }
229
+
230
+ const taskId = taskIdArg;
231
+
170
232
  // v1.7.0: Check for session resume context
171
233
  const config = getConfig();
172
234
  if (config.sessionState?.autoRestore !== false) {
@@ -278,15 +278,41 @@ function checkImplementationGate(options = {}) {
278
278
  };
279
279
  }
280
280
 
281
- // Route through /wogi-start instead of blocking
282
- // /wogi-start will intelligently decide: execute directly (operational) or create story (implementation)
281
+ // v4.2: Block and route through /wogi-start
282
+ // /wogi-start will triage: operational (execute directly), small fix (execute + log), or implementation (create task)
283
+ const config = getConfig();
284
+ const mode = config.hooks?.rules?.implementationGate?.mode || 'block';
285
+
286
+ if (mode === 'off') {
287
+ return {
288
+ allowed: true,
289
+ blocked: false,
290
+ message: null,
291
+ reason: 'gate_mode_off'
292
+ };
293
+ }
294
+
295
+ if (mode === 'warn') {
296
+ return {
297
+ allowed: true,
298
+ blocked: false,
299
+ message: generateRoutingMessage(prompt),
300
+ reason: 'route_to_wogi_start',
301
+ confidence,
302
+ suggestedAction: 'wogi-start',
303
+ matches
304
+ };
305
+ }
306
+
307
+ // Default: mode === 'block' - strict enforcement
283
308
  return {
284
- allowed: true,
285
- blocked: false,
286
- message: generateRoutingMessage(prompt),
309
+ allowed: false,
310
+ blocked: true,
311
+ message: generateBlockingMessage(prompt),
287
312
  reason: 'route_to_wogi_start',
288
313
  confidence,
289
314
  suggestedAction: 'wogi-start',
315
+ suggestedCommand: `/wogi-start "${truncatePrompt(prompt)}"`,
290
316
  matches
291
317
  };
292
318
  }
@@ -323,6 +349,22 @@ function generateBlockMessage(prompt) {
323
349
  return generateRoutingMessage(prompt);
324
350
  }
325
351
 
352
+ /**
353
+ * Generate blocking message (v4.2 strict enforcement)
354
+ * This message appears when implementation is detected without active task
355
+ */
356
+ function generateBlockingMessage(prompt) {
357
+ return `Implementation request detected without active task.
358
+
359
+ To proceed, run:
360
+ /wogi-start "${truncatePrompt(prompt)}"
361
+
362
+ WogiFlow will triage and decide:
363
+ - If operational (git/npm/deploy) → execute directly
364
+ - If small fix → execute + log for learning
365
+ - If larger task → create story/bug first`;
366
+ }
367
+
326
368
  module.exports = {
327
369
  isImplementationGateEnabled,
328
370
  isSoftModeEnabled,
@@ -333,6 +375,7 @@ module.exports = {
333
375
  generateWarningMessage,
334
376
  generateRoutingMessage,
335
377
  generateBlockMessage,
378
+ generateBlockingMessage,
336
379
  truncatePrompt,
337
380
  IMPLEMENTATION_PATTERNS,
338
381
  EXPLORATION_PATTERNS