wogiflow 1.9.6 → 1.9.7

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.
Files changed (31) hide show
  1. package/.claude/commands/wogi-onboard.md +1 -1
  2. package/.claude/commands/wogi-research.md +70 -1
  3. package/.claude/commands/wogi-start.md +4 -3
  4. package/.claude/docs/config-reference.md +2 -2
  5. package/.claude/docs/knowledge-base/02-task-execution/03-verification.md +3 -3
  6. package/.claude/docs/knowledge-base/02-task-execution/05-session-review.md +1 -1
  7. package/.claude/docs/knowledge-base/02-task-execution/README.md +1 -1
  8. package/.claude/docs/knowledge-base/02-task-execution/trade-offs.md +1 -1
  9. package/.claude/docs/knowledge-base/configuration/README.md +1 -1
  10. package/.claude/docs/knowledge-base/configuration/all-options.md +2 -2
  11. package/.workflow/templates/claude-md.hbs +3 -6
  12. package/package.json +1 -1
  13. package/scripts/flow-config-defaults.js +1 -1
  14. package/scripts/flow-done +2 -2
  15. package/scripts/flow-done.js +119 -2
  16. package/scripts/hooks/entry/claude-code/pre-tool-use.js +28 -1
  17. package/.claude/rules/_internal/README.md +0 -64
  18. package/.claude/rules/_internal/document-structure.md +0 -77
  19. package/.claude/rules/_internal/dual-repo-management.md +0 -174
  20. package/.claude/rules/_internal/feature-refactoring-cleanup.md +0 -87
  21. package/.claude/rules/_internal/github-releases.md +0 -71
  22. package/.claude/rules/_internal/model-management.md +0 -35
  23. package/.claude/rules/_internal/self-maintenance.md +0 -87
  24. package/.claude/rules/architecture/component-reuse.md +0 -38
  25. package/.claude/rules/code-style/naming-conventions.md +0 -52
  26. package/.claude/rules/operations/git-workflows.md +0 -92
  27. package/.claude/rules/security/security-patterns.md +0 -176
  28. package/.claude/skills/figma-analyzer/knowledge/learnings.md +0 -11
  29. package/.workflow/specs/architecture.md.template +0 -24
  30. package/.workflow/specs/stack.md.template +0 -33
  31. package/.workflow/specs/testing.md.template +0 -36
@@ -701,7 +701,7 @@ Display:
701
701
  for (const reqs of [featureReqs, bugfixReqs, refactorReqs]) {
702
702
  reqs.push('requestLogEntry');
703
703
  }
704
- featureReqs.push('appMapUpdate');
704
+ featureReqs.push('registryUpdate');
705
705
 
706
706
  config.qualityGates = {
707
707
  feature: { require: featureReqs },
@@ -25,6 +25,46 @@ This command is **automatically triggered** (when strict mode is enabled) for:
25
25
  5. **Integration Questions**: "How to integrate X with Y?"
26
26
  6. **Comparison Questions**: "What can we learn from X?", "How does X compare to Y?"
27
27
 
28
+ ## Step 0: Config Loading (MANDATORY — before all phases)
29
+
30
+ Before ANY research phase, read the project's config to determine depth, format, and verification requirements:
31
+
32
+ ```bash
33
+ cat .workflow/config.json | grep -A 30 '"research"'
34
+ ```
35
+
36
+ **Extract and apply these settings:**
37
+
38
+ 1. **Determine depth** (in priority order):
39
+ - CLI flag (`--deep`, `--quick`, etc.) → use that depth
40
+ - If auto-triggered (no flag): classify question type and look up `research.triggers`:
41
+ - Capability question ("Does X support Y?") → `triggers.capabilityQuestions` (default: `"standard"`)
42
+ - Feasibility question ("Is it possible to...") → `triggers.feasibilityQuestions` (default: `"deep"`)
43
+ - Existence question ("Is there a...") → `triggers.existenceQuestions` (default: `"standard"`)
44
+ - Architecture question ("How does X work?") → `triggers.architectureQuestions` (default: `"deep"`)
45
+ - Integration question ("How to integrate X with Y?") → `triggers.integrationQuestions` (default: `"deep"`)
46
+ - Comparison question ("How does X compare to Y?") → `triggers.comparisonQuestions` (default: `"deep"`)
47
+ - Fallback: `research.defaultDepth` (default: `"standard"`)
48
+
49
+ 2. **Apply format flags** from config:
50
+ - `requireVerificationFormat: true` → ALL assumptions must have `[VERIFIED]`/`[UNVERIFIED]` markers
51
+ - `requireCitations: true` → ALL claims must have an Evidence Chain entry
52
+ - `assumptionTracking: true` → Assumption Stack table is MANDATORY in output
53
+ - `negativeEvidenceRule: true` → Negative claims require exhaustive search evidence
54
+
55
+ 3. **Display header block** (MANDATORY):
56
+ ```markdown
57
+ ## Research Report
58
+ **Question:** [the question]
59
+ **Depth:** [resolved depth from step 1]
60
+ **Flow:** [Standard/Comparison]
61
+ **Config applied:** requireVerification=[yes/no], citations=[yes/no], assumptionTracking=[yes/no]
62
+ ```
63
+
64
+ **If config.json has no `research` section or is unreadable**: use defaults (depth: standard, all format flags: true).
65
+
66
+ ---
67
+
28
68
  ## Research Protocol Phases
29
69
 
30
70
  There are two flows depending on question type:
@@ -199,6 +239,7 @@ In `.workflow/config.json`:
199
239
  "enabled": true,
200
240
  "defaultDepth": "standard",
201
241
  "autoTrigger": true,
242
+ "requireVerificationFormat": true,
202
243
  "maxTokensPerDepth": {
203
244
  "quick": 5000,
204
245
  "standard": 20000,
@@ -210,7 +251,15 @@ In `.workflow/config.json`:
210
251
  "cacheExpiryHours": 24,
211
252
  "budgetMode": "soft",
212
253
  "negativeEvidenceRule": true,
213
- "assumptionTracking": true
254
+ "assumptionTracking": true,
255
+ "triggers": {
256
+ "capabilityQuestions": "standard",
257
+ "feasibilityQuestions": "deep",
258
+ "existenceQuestions": "standard",
259
+ "architectureQuestions": "deep",
260
+ "integrationQuestions": "deep",
261
+ "comparisonQuestions": "deep"
262
+ }
214
263
  }
215
264
  }
216
265
  ```
@@ -269,6 +318,26 @@ When `research.requireCitations` is enabled and `research.autoTrigger` is true:
269
318
  - Claims without citations are flagged
270
319
  - Negative claims require exhaustive search evidence
271
320
 
321
+ ## Output Checklist (MANDATORY — self-verify before presenting)
322
+
323
+ Before presenting ANY research report, verify ALL of these are present. If any is missing, add it before outputting.
324
+
325
+ | # | Check | Required When |
326
+ |---|-------|---------------|
327
+ | 1 | **Header block** with Question, Depth, Flow, Config applied | Always |
328
+ | 2 | **Conclusion** section with direct answer | Always |
329
+ | 3 | **Assumption Stack** table with `[VERIFIED]`/`[UNVERIFIED]` markers | `assumptionTracking: true` (default) |
330
+ | 4 | **Evidence Chain** table with Claim, Source Type, Source Location, Confidence | `requireCitations: true` (default) |
331
+ | 5 | **Confidence level** (HIGH/MEDIUM/LOW) | Always |
332
+ | 6 | **Searches Performed** list (web + local) | Always |
333
+ | 7 | **Negative Evidence format** for any "X doesn't exist" claims | `negativeEvidenceRule: true` (default) |
334
+ | 8 | **Comparison table** (External Feature / Local Equivalent / Status) | Comparison flow only |
335
+ | 9 | **Recommendation Verification** (EXISTS/PARTIAL/MISSING markers) | Comparison flow only |
336
+
337
+ **Self-check prompt**: "Have I included all mandatory sections per config? Is every assumption marked? Is every claim cited?"
338
+
339
+ If the report is missing any required section, DO NOT present it — add the missing section first.
340
+
272
341
  ## CLI Compatibility
273
342
 
274
343
  This command currently supports Claude Code only.
@@ -302,7 +302,7 @@ If violations found: fix, re-run, only proceed when all pass. Violations auto-re
302
302
  **First**: Run `node node_modules/wogiflow/scripts/flow-spec-verifier.js verify wf-XXXXXXXX` — verify all spec deliverables exist. If missing → STOP, create them.
303
303
 
304
304
  **Then**: Check `config.qualityGates` for task type. Gates are type-specific:
305
- - **feature**: loopComplete, tests, appMapUpdate, requestLogEntry, integrationWiring, standardsCompliance
305
+ - **feature**: loopComplete, tests, registryUpdate, requestLogEntry, integrationWiring, standardsCompliance
306
306
  - **bugfix**: loopComplete, tests, requestLogEntry, standardsCompliance, learningEnforcement
307
307
  - **refactor**: loopComplete, tests, noNewFeatures, smokeTest, standardsCompliance
308
308
  - **chore**: requestLogEntry, outstandingFindings
@@ -311,7 +311,8 @@ If violations found: fix, re-run, only proceed when all pass. Violations auto-re
311
311
 
312
312
  **Fallback behavior**: Task types not listed above (docs, style, test, perf, etc.) inherit the **feature** gates. This is intentional — feature gates are the most comprehensive and serve as a safe default.
313
313
 
314
- **Key automated gates** (v1.9.2):
314
+ **Key automated gates** (v1.9.7):
315
+ - `registryUpdate` → runs `flow registry-manager scan` on ALL active registries (app-map, function-map, api-map, schema-map, service-map). Auto-updates maps when new entries found. Replaces old `appMapUpdate` no-op gate.
315
316
  - `integrationWiring` → calls `verifyWiring()` — checks created files are imported/used
316
317
  - `standardsCompliance` → calls `runTaskStandardsCheck()` — checks naming, security, decisions.md rules
317
318
  - `outstandingFindings` → reads `last-review.json` — blocks if unresolved critical/high findings exist
@@ -328,7 +329,7 @@ Reflection: "Have I introduced any bugs or regressions?"
328
329
  1. Reflection: "Does this match what the user asked for?"
329
330
  2. Close out all TodoWrite items for this task
330
331
  3. Move task to recentlyCompleted in ready.json
331
- 4. Update request-log.md, app-map.md, function-map.md, api-map.md as needed
332
+ 4. Registry maps auto-updated by `registryUpdate` quality gate (runs `flow registry-manager scan` on all active registries — app-map, function-map, api-map, schema-map, service-map)
332
333
  5. If `config.webmcp.enabled` and UI files created: run `node node_modules/wogiflow/scripts/flow-webmcp-generator.js scan`
333
334
  6. Commit: `feat: Complete wf-XXXXXXXX - [title]`
334
335
  7. Show completion summary
@@ -163,7 +163,7 @@ Customize which checks are required per task type.
163
163
  {
164
164
  "qualityGates": {
165
165
  "feature": {
166
- "require": ["loopComplete", "tests", "appMapUpdate", "requestLogEntry"],
166
+ "require": ["loopComplete", "tests", "registryUpdate", "requestLogEntry"],
167
167
  "optional": ["review"]
168
168
  },
169
169
  "bugfix": {
@@ -174,7 +174,7 @@ Customize which checks are required per task type.
174
174
  }
175
175
  ```
176
176
 
177
- **Available gates**: `loopComplete`, `tests`, `generatedTestsPass`, `uiVerification`, `apiVerification`, `appMapUpdate`, `requestLogEntry`, `integrationWiring`, `standardsCompliance`, `outstandingFindings`, `preRelease`, `noNewFeatures`, `smokeTest`, `learningEnforcement`, `review`, `docs`, `webmcpVerification`
177
+ **Available gates**: `loopComplete`, `tests`, `generatedTestsPass`, `uiVerification`, `apiVerification`, `registryUpdate`, `requestLogEntry`, `integrationWiring`, `standardsCompliance`, `outstandingFindings`, `preRelease`, `noNewFeatures`, `smokeTest`, `learningEnforcement`, `review`, `docs`, `webmcpVerification`
178
178
 
179
179
  **Task types**: `feature`, `bugfix`, `refactor`, `chore`, `release`, `fix`
180
180
 
@@ -62,7 +62,7 @@ Quality gates are requirements that must pass before a task can be completed.
62
62
  {
63
63
  "qualityGates": {
64
64
  "feature": {
65
- "require": ["tests", "appMapUpdate", "requestLogEntry"],
65
+ "require": ["tests", "registryUpdate", "requestLogEntry"],
66
66
  "optional": ["review", "docs"]
67
67
  },
68
68
  "bugfix": {
@@ -84,7 +84,7 @@ Quality gates are requirements that must pass before a task can be completed.
84
84
  | `tests` | npm test passes |
85
85
  | `lint` | npm run lint passes (with auto-fix) |
86
86
  | `typecheck` | npm run typecheck passes |
87
- | `appMapUpdate` | New components added to app-map.md |
87
+ | `registryUpdate` | All registry maps (app-map, function-map, api-map, schema-map, service-map) auto-scanned |
88
88
  | `requestLogEntry` | Task logged in request-log.md |
89
89
  | `noNewFeatures` | (Refactor) No new functionality added |
90
90
  | `integrationWiring` | Created files are imported/used somewhere (not orphaned) |
@@ -134,7 +134,7 @@ Running quality gates...
134
134
  ✓ lint passed (auto-fixed)
135
135
  ✓ typecheck passed
136
136
  ✓ requestLogEntry (found in request-log)
137
- appMapUpdate (verify manually if components created)
137
+ registryUpdate (auto-scanned: app-map.md updated)
138
138
 
139
139
  All gates passed!
140
140
  ```
@@ -196,7 +196,7 @@ Session review can be added to quality gates:
196
196
  {
197
197
  "qualityGates": {
198
198
  "feature": {
199
- "require": ["tests", "sessionReview", "appMapUpdate"]
199
+ "require": ["tests", "sessionReview", "registryUpdate"]
200
200
  }
201
201
  }
202
202
  }
@@ -122,7 +122,7 @@ Comprehensive code review before finalizing changes.
122
122
  },
123
123
  "qualityGates": {
124
124
  "feature": {
125
- "require": ["tests", "appMapUpdate", "requestLogEntry"]
125
+ "require": ["tests", "registryUpdate", "requestLogEntry"]
126
126
  }
127
127
  }
128
128
  }
@@ -141,7 +141,7 @@ Every configuration decision in WogiFlow involves trade-offs. Understanding thes
141
141
  {
142
142
  "qualityGates": {
143
143
  "feature": {
144
- "require": ["tests", "lint", "typecheck", "appMapUpdate", "requestLogEntry", "review"]
144
+ "require": ["tests", "lint", "typecheck", "registryUpdate", "requestLogEntry", "review"]
145
145
  }
146
146
  }
147
147
  }
@@ -127,7 +127,7 @@ cat .workflow/config.json
127
127
  },
128
128
  "qualityGates": {
129
129
  "feature": {
130
- "require": ["tests", "appMapUpdate", "requestLogEntry", "review"]
130
+ "require": ["tests", "registryUpdate", "requestLogEntry", "review"]
131
131
  }
132
132
  }
133
133
  }
@@ -410,7 +410,7 @@ Per-task-type quality requirements that must pass before task completion.
410
410
  "qualityGates": {
411
411
  "preTaskBaseline": { "enabled": false },
412
412
  "feature": {
413
- "require": ["loopComplete", "tests", "appMapUpdate", "requestLogEntry", "integrationWiring", "standardsCompliance"],
413
+ "require": ["loopComplete", "tests", "registryUpdate", "requestLogEntry", "integrationWiring", "standardsCompliance"],
414
414
  "optional": ["review", "docs", "webmcpVerification"]
415
415
  },
416
416
  "bugfix": {
@@ -433,7 +433,7 @@ Per-task-type quality requirements that must pass before task completion.
433
433
  | `qualityGates.bugfix.require` | string[] | See above | Required gates for bugfix tasks |
434
434
  | `qualityGates.refactor.require` | string[] | See above | Required gates for refactor tasks |
435
435
 
436
- Available gate values: `loopComplete`, `tests`, `appMapUpdate`, `requestLogEntry`, `integrationWiring`, `standardsCompliance`, `learningEnforcement`, `resolutionPopulated`, `noNewFeatures`, `smokeTest`, `review`, `docs`, `webmcpVerification`.
436
+ Available gate values: `loopComplete`, `tests`, `registryUpdate`, `requestLogEntry`, `integrationWiring`, `standardsCompliance`, `learningEnforcement`, `resolutionPopulated`, `noNewFeatures`, `smokeTest`, `review`, `docs`, `webmcpVerification`.
437
437
 
438
438
  ---
439
439
 
@@ -210,12 +210,9 @@ When creating tasks programmatically, always call `generateTaskId(title)` — ne
210
210
 
211
211
  ### After Completing:
212
212
  1. Update `request-log.md` with tags
213
- 2. Update `app-map.md` if components created/deleted/renamed
214
- 3. Update `function-map.md` if utilities created/deleted/renamed — run `npx flow function-index scan`
215
- 4. Update `api-map.md` if endpoints created/deleted/renamed — run `npx flow api-index scan`
216
- 5. Update other active registry maps if relevant — run `npx flow registry-manager scan`
217
- 6. Run quality gates (lint, typecheck, test)
218
- 7. Provide completion report
213
+ 2. Registry maps (app-map, function-map, api-map, schema-map, service-map) are **auto-updated** by the `registryUpdate` quality gate — it runs `flow registry-manager scan` on all active registries
214
+ 3. Run quality gates (lint, typecheck, test)
215
+ 4. Provide completion report
219
216
 
220
217
  ## Auto-Validation (CRITICAL)
221
218
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "1.9.6",
3
+ "version": "1.9.7",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -302,7 +302,7 @@ const CONFIG_DEFAULTS = {
302
302
  qualityGates: {
303
303
  preTaskBaseline: { enabled: false },
304
304
  feature: {
305
- require: ['loopComplete', 'tests', 'generatedTestsPass', 'uiVerification', 'apiVerification', 'appMapUpdate', 'requestLogEntry', 'integrationWiring', 'standardsCompliance'],
305
+ require: ['loopComplete', 'tests', 'generatedTestsPass', 'uiVerification', 'apiVerification', 'registryUpdate', 'requestLogEntry', 'integrationWiring', 'standardsCompliance'],
306
306
  optional: ['review', 'docs', 'webmcpVerification']
307
307
  },
308
308
  bugfix: {
package/scripts/flow-done CHANGED
@@ -76,8 +76,8 @@ for gate in gates:
76
76
  except:
77
77
  print(' \033[0;33m○\033[0m requestLogEntry (verify manually)')
78
78
 
79
- elif gate == 'appMapUpdate':
80
- print(' \033[0;33m○\033[0m appMapUpdate (verify manually if components created)')
79
+ elif gate == 'appMapUpdate' or gate == 'registryUpdate':
80
+ print(' \033[0;33m○\033[0m registryUpdate (verify manually if components created)')
81
81
 
82
82
  else:
83
83
  print(f' \033[0;33m○\033[0m {gate} (manual check)')
@@ -121,6 +121,20 @@ try {
121
121
  // v5.2 verification profiles
122
122
  const { loadProfile: loadVerificationProfile } = require('./flow-verification-profile');
123
123
 
124
+ // v1.9.7 registry map update gate — lazy-loaded to avoid startup cost
125
+ // Loaded inside the registryUpdate gate branch only
126
+ let _registryManagerModule = undefined; // undefined = not yet loaded, null = load failed
127
+ function getRegistryManager() {
128
+ if (_registryManagerModule === undefined) {
129
+ try {
130
+ _registryManagerModule = require('./flow-registry-manager');
131
+ } catch (err) {
132
+ _registryManagerModule = null;
133
+ }
134
+ }
135
+ return _registryManagerModule;
136
+ }
137
+
124
138
  // Path for last failure artifact
125
139
  const LAST_FAILURE_PATH = path.join(PATHS.state, 'last-failure.json');
126
140
 
@@ -338,8 +352,111 @@ function runQualityGates(taskId, taskType) {
338
352
  if (process.env.DEBUG) console.error(`[DEBUG] requestLogEntry check: ${err.message}`);
339
353
  console.log(` ${color('yellow', '○')} requestLogEntry (could not check)`);
340
354
  }
341
- } else if (gate === 'appMapUpdate') {
342
- console.log(` ${color('yellow', '○')} appMapUpdate (verify manually if components created)`);
355
+ } else if (gate === 'appMapUpdate' || gate === 'registryUpdate') {
356
+ // v1.9.7: Programmatic registry scan — replaces manual "verify manually" no-op.
357
+ // Runs flow-registry-manager scan on all active registries, comparing modified files
358
+ // against registry entries to detect missing registrations.
359
+ // v1.9.8: Deprecation warning for old gate name
360
+ if (gate === 'appMapUpdate') {
361
+ console.log(` ${color('yellow', '⚠')} appMapUpdate is deprecated — update config.json qualityGates to use 'registryUpdate'`);
362
+ }
363
+ const registryMod = getRegistryManager();
364
+ if (registryMod) {
365
+ try {
366
+ console.log(' Running registry update check...');
367
+ const modifiedFiles = getModifiedFiles();
368
+
369
+ // Get map file timestamps BEFORE scan (to detect changes)
370
+ const mapFiles = ['app-map.md', 'function-map.md', 'api-map.md', 'schema-map.md', 'service-map.md'];
371
+ const beforeHashes = {};
372
+ for (const mf of mapFiles) {
373
+ const mapPath = path.join(PATHS.state, mf);
374
+ try {
375
+ beforeHashes[mf] = fs.existsSync(mapPath) ? fs.statSync(mapPath).mtimeMs : 0;
376
+ } catch (err) {
377
+ beforeHashes[mf] = 0;
378
+ }
379
+ }
380
+
381
+ // Detect active plugins to check if scan is needed (lightweight, no async)
382
+ const { RegistryManager } = registryMod;
383
+ const manager = new RegistryManager();
384
+ manager.loadPlugins();
385
+ manager.detectStack();
386
+ manager.activatePlugins();
387
+
388
+ // Only scan if there are active plugins
389
+ if (manager.activePlugins.length > 0) {
390
+ // scanAll is async but we need sync behavior in quality gates
391
+ // Use spawnSync to run the scan as a child process
392
+ // v1.9.8: Added cwd, write JSON to stderr to avoid stdout pollution from require() side-effects
393
+ const scanResult = spawnSync('node', [
394
+ '-e',
395
+ `const {RegistryManager} = require(${JSON.stringify(path.join(__dirname, 'flow-registry-manager'))});
396
+ const m = new RegistryManager(); m.loadPlugins(); m.detectStack(); m.activatePlugins();
397
+ m.scanAll().then(r => { process.stderr.write('SCAN_RESULT:' + JSON.stringify(r)); process.exit(0); })
398
+ .catch(err => { process.stderr.write('SCAN_RESULT:' + JSON.stringify({error: err.message})); process.exit(1); });`
399
+ ], {
400
+ encoding: 'utf-8',
401
+ stdio: ['pipe', 'pipe', 'pipe'],
402
+ timeout: 30000,
403
+ cwd: process.cwd()
404
+ });
405
+
406
+ if (scanResult.status === 0) {
407
+ // Extract scan result from stderr (after SCAN_RESULT: marker) to avoid stdout pollution
408
+ const stderrOutput = scanResult.stderr || '';
409
+ const markerIdx = stderrOutput.indexOf('SCAN_RESULT:');
410
+ const jsonStr = markerIdx >= 0 ? stderrOutput.slice(markerIdx + 'SCAN_RESULT:'.length) : '{}';
411
+ const results = safeJsonParseString(jsonStr, {});
412
+
413
+ // Check which map files were updated
414
+ const updatedMaps = [];
415
+ for (const mf of mapFiles) {
416
+ const mapPath = path.join(PATHS.state, mf);
417
+ try {
418
+ const afterMtime = fs.existsSync(mapPath) ? fs.statSync(mapPath).mtimeMs : 0;
419
+ if (afterMtime > beforeHashes[mf]) {
420
+ updatedMaps.push(mf);
421
+ }
422
+ } catch (err) {
423
+ // ignore
424
+ }
425
+ }
426
+
427
+ // Check if modified files include patterns that should be in registries
428
+ const relevantExtensions = ['.js', '.ts', '.jsx', '.tsx', '.vue', '.svelte'];
429
+ const codeFiles = modifiedFiles.filter(f => relevantExtensions.some(ext => f.endsWith(ext)));
430
+ const nonTestFiles = codeFiles.filter(f => !f.includes('test') && !f.includes('spec') && !f.includes('__test'));
431
+
432
+ const activeIds = manager.activePlugins.map(p => p.constructor.id);
433
+ const scanSummary = Object.entries(results)
434
+ .filter(([id, r]) => r.success && !r.empty)
435
+ .map(([id]) => id);
436
+
437
+ if (updatedMaps.length > 0) {
438
+ console.log(` ${color('green', '✓')} registryUpdate (auto-scanned: ${updatedMaps.join(', ')} updated)`);
439
+ } else if (scanSummary.length > 0) {
440
+ console.log(` ${color('green', '✓')} registryUpdate (scanned ${activeIds.join(', ')} — maps already current)`);
441
+ } else if (nonTestFiles.length === 0) {
442
+ console.log(` ${color('green', '✓')} registryUpdate (no registrable code files modified)`);
443
+ } else {
444
+ console.log(` ${color('green', '✓')} registryUpdate (scanned — no new entries found)`);
445
+ }
446
+ } else {
447
+ console.log(` ${color('yellow', '⚠')} registryUpdate (scan error — degraded to manual check)`);
448
+ if (process.env.DEBUG) console.error(`[DEBUG] registry scan stderr: ${scanResult.stderr}`);
449
+ }
450
+ } else {
451
+ console.log(` ${color('green', '✓')} registryUpdate (no active registry plugins)`);
452
+ }
453
+ } catch (err) {
454
+ // Graceful degradation — don't block task completion on scan errors
455
+ console.log(` ${color('yellow', '⚠')} registryUpdate (error: ${truncateOutput(err.message, 3, 200)} — verify manually)`);
456
+ }
457
+ } else {
458
+ console.log(` ${color('yellow', '⚠')} registryUpdate (registry manager not available — verify manually)`);
459
+ }
343
460
  } else if (gate === 'loopComplete') {
344
461
  // v2.1: Explicit loop completion check
345
462
  const activeLoop = getActiveLoop();
@@ -213,8 +213,35 @@ async function main() {
213
213
  // v7.0: Subagents exempt — spawned by main agent which already went through routing.
214
214
  // v7.1: Defense-in-depth — only bypass when an active task exists.
215
215
  // v8.0: Added Agent, WebSearch, WebFetch to close bypass vectors.
216
+ // v8.1: Whitelist read-only git commands — Claude naturally runs git status/log/diff
217
+ // to gather context before routing. These are pure reads with no side effects.
216
218
  const skipRoutingGateForSubagent = isSubagent && hasActiveTask();
217
- if (!skipRoutingGateForSubagent && (toolName === 'Bash' || toolName === 'EnterPlanMode' || toolName === 'Read' || toolName === 'Glob' || toolName === 'Grep' || toolName === 'Edit' || toolName === 'Write' || toolName === 'NotebookEdit' || toolName === 'Agent' || toolName === 'WebSearch' || toolName === 'WebFetch')) {
219
+
220
+ // Read-only git commands whitelist — allowed before routing.
221
+ // These are pure read operations that cannot bypass task tracking.
222
+ // Safety: reject commands with shell chaining operators to prevent abuse.
223
+ let skipRoutingGateForReadOnlyGit = false;
224
+ if (toolName === 'Bash' && toolInput.command) {
225
+ const cmd = toolInput.command.trim();
226
+ const READ_ONLY_GIT_PREFIXES = [
227
+ 'git status', 'git log', 'git diff', 'git branch',
228
+ 'git show', 'git rev-parse', 'git remote -v', 'git tag -l',
229
+ 'git ls-files', 'git describe'
230
+ ];
231
+ // Block shell chaining operators AND control characters that could bypass prefix matching
232
+ const SHELL_CHAIN_OPERATORS = /[;&|`$()\n\r\\]/;
233
+ // Block destructive flags that could appear after an otherwise-safe prefix
234
+ const DESTRUCTIVE_GIT_FLAGS = /\s-[dD]\b|\s--delete\b|\s--force\b|\s--hard\b|\s--prune\b/;
235
+ if (
236
+ READ_ONLY_GIT_PREFIXES.some(prefix => cmd.startsWith(prefix)) &&
237
+ !SHELL_CHAIN_OPERATORS.test(cmd) &&
238
+ !DESTRUCTIVE_GIT_FLAGS.test(cmd)
239
+ ) {
240
+ skipRoutingGateForReadOnlyGit = true;
241
+ }
242
+ }
243
+
244
+ if (!skipRoutingGateForSubagent && !skipRoutingGateForReadOnlyGit && (toolName === 'Bash' || toolName === 'EnterPlanMode' || toolName === 'Read' || toolName === 'Glob' || toolName === 'Grep' || toolName === 'Edit' || toolName === 'Write' || toolName === 'NotebookEdit' || toolName === 'Agent' || toolName === 'WebSearch' || toolName === 'WebFetch')) {
218
245
  try {
219
246
  const routingResult = checkRoutingGate(toolName, config);
220
247
  if (routingResult.blocked) {
@@ -1,64 +0,0 @@
1
- ---
2
- alwaysApply: false
3
- description: "Meta-documentation about how project rules are organized"
4
- ---
5
- # Project Rules
6
-
7
- This directory contains coding rules and patterns for this project, organized by category.
8
-
9
- ## Structure
10
-
11
- ```
12
- .claude/rules/
13
- ├── code-style/ # Naming conventions, formatting
14
- │ └── naming-conventions.md
15
- ├── security/ # Security patterns and practices
16
- │ └── security-patterns.md
17
- ├── architecture/ # Design decisions and patterns
18
- │ ├── component-reuse.md
19
- │ └── model-management.md
20
- └── README.md
21
- ```
22
-
23
- ## How Rules Work
24
-
25
- Rules are automatically loaded by Claude Code based on:
26
- - **alwaysApply: true** - Rule is always loaded
27
- - **alwaysApply: false** - Rule is loaded based on `globs` or `description` relevance
28
- - **globs** - File patterns that trigger rule loading
29
-
30
- ## Adding New Rules
31
-
32
- 1. Choose the appropriate category subdirectory
33
- 2. Create a `.md` file with frontmatter:
34
-
35
- ```yaml
36
- ---
37
- alwaysApply: false
38
- description: "Brief description for relevance matching"
39
- globs: src/**/*.ts # Optional: only load for these files
40
- ---
41
- ```
42
-
43
- 3. Write the rule content in markdown
44
-
45
- ## Categories
46
-
47
- | Category | Purpose |
48
- |----------|---------|
49
- | code-style | Naming conventions, formatting, file structure |
50
- | security | Security patterns, input validation, safe practices |
51
- | architecture | Design decisions, component patterns, system organization |
52
-
53
- ## Auto-Generation
54
-
55
- Some rules can be auto-generated from `.workflow/state/decisions.md`:
56
-
57
- ```bash
58
- node scripts/flow-rules-sync.js
59
- ```
60
-
61
- The sync script will route rules to appropriate category subdirectories.
62
-
63
- ---
64
- Last updated: 2026-01-12
@@ -1,77 +0,0 @@
1
- ---
2
- alwaysApply: false
3
- description: "All AI-context documents must use PIN markers for targeted context loading"
4
- globs: ".workflow/**/*.md"
5
- ---
6
-
7
- # Document Structure for AI Context
8
-
9
- All documents in `.workflow/` that are used as AI context MUST follow the PIN standard.
10
-
11
- ## Required Structure
12
-
13
- ### 1. Header with PIN List
14
- Every document starts with a comment listing all pins in the document:
15
- ```markdown
16
- <!-- PINS: pin1, pin2, pin3 -->
17
- ```
18
-
19
- ### 2. Section PIN Markers
20
- Each major section has a PIN marker comment:
21
- ```markdown
22
- ### Section Title
23
- <!-- PIN: section-specific-pin -->
24
- [Content]
25
- ```
26
-
27
- ### 3. PIN Naming Convention
28
- - Use kebab-case: `user-authentication`, not `userAuthentication`
29
- - Use semantic names: `error-handling`, not `eh`
30
- - Use compound names for specificity: `json-parse-safety`
31
-
32
- ## Why PINs Matter
33
-
34
- The PIN system enables:
35
- 1. **Targeted context loading**: Only load sections relevant to current task
36
- 2. **Cheaper model routing**: Haiku can fetch only relevant sections for Opus
37
- 3. **Change detection**: Hash sections independently for smart invalidation
38
- 4. **Cross-reference**: Link sections by PIN across documents
39
-
40
- ## Example Document
41
-
42
- ```markdown
43
- # Config Reference
44
-
45
- <!-- PINS: database, authentication, api-keys, environment -->
46
-
47
- ## Database Settings
48
- <!-- PIN: database -->
49
- | Setting | Default | Description |
50
- |---------|---------|-------------|
51
-
52
- ## Authentication
53
- <!-- PIN: authentication -->
54
- | Setting | Default | Description |
55
- |---------|---------|-------------|
56
- ```
57
-
58
- ## Parsing
59
-
60
- The PIN system automatically parses documents with:
61
- - `flow-section-index.js` - Generates section index with pins
62
- - `flow-section-resolver.js` - Resolves sections by PIN lookup
63
- - `getSectionsByPins(['auth', 'security'])` - Fetch only relevant sections
64
-
65
- ## Files That Must Have PINs
66
-
67
- | File | Required PINs |
68
- |------|---------------|
69
- | `decisions.md` | Per coding rule/pattern |
70
- | `app-map.md` | Per component/screen |
71
- | `product.md` | Per product section |
72
- | `stack.md` | Per technology |
73
-
74
- ## Validation
75
-
76
- Run `node scripts/flow-section-index.js --force` to regenerate the index.
77
- Check `.workflow/state/section-index.json` for indexed sections and their pins.