wogiflow 1.0.47 → 1.0.49

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 (67) hide show
  1. package/.claude/commands/wogi-research.md +223 -0
  2. package/.claude/commands/wogi-review-fix.md +241 -0
  3. package/.claude/docs/commands.md +17 -0
  4. package/.workflow/bridges/base-bridge.js +124 -15
  5. package/.workflow/bridges/claude-bridge.js +50 -22
  6. package/.workflow/bridges/codex-bridge.js +466 -0
  7. package/.workflow/bridges/cursor-bridge.js +573 -0
  8. package/.workflow/bridges/gemini-bridge.js +614 -0
  9. package/.workflow/bridges/index.js +41 -4
  10. package/.workflow/bridges/kimi-bridge.js +454 -0
  11. package/.workflow/bridges/opencode-bridge.js +825 -0
  12. package/.workflow/templates/agents-md.hbs +127 -0
  13. package/.workflow/templates/claude-md.hbs +66 -0
  14. package/.workflow/templates/codex-config.hbs +69 -0
  15. package/.workflow/templates/cursor-rules.mdc.hbs +142 -0
  16. package/.workflow/templates/gemini-md.hbs +334 -26
  17. package/.workflow/templates/opencode-agents-md.hbs +158 -0
  18. package/.workflow/templates/opencode-config.hbs +27 -0
  19. package/.workflow/templates/partials/auto-features.hbs +125 -0
  20. package/.workflow/templates/partials/enforcement-rules.hbs +164 -0
  21. package/.workflow/templates/partials/user-commands.hbs +154 -0
  22. package/.workflow/templates/research-report.md +153 -0
  23. package/README.md +170 -1589
  24. package/package.json +1 -1
  25. package/scripts/flow-import-profile +17 -8
  26. package/scripts/flow-operational-scanner.js +13 -8
  27. package/scripts/flow-parity-check.js +281 -0
  28. package/scripts/flow-prompt-composer.js +10 -0
  29. package/scripts/flow-research-protocol.js +1022 -0
  30. package/scripts/flow-strict-adherence.js +14 -9
  31. package/scripts/flow-utils.js +4 -0
  32. package/scripts/hooks/adapters/base-adapter.js +22 -2
  33. package/scripts/hooks/adapters/claude-code.js +14 -1
  34. package/scripts/hooks/adapters/cursor.js +421 -0
  35. package/scripts/hooks/adapters/gemini.js +368 -0
  36. package/scripts/hooks/adapters/index.js +99 -0
  37. package/scripts/hooks/adapters/opencode.js +317 -0
  38. package/scripts/hooks/core/constants.js +75 -0
  39. package/scripts/hooks/core/implementation-gate.js +15 -1
  40. package/scripts/hooks/core/index.js +21 -1
  41. package/scripts/hooks/core/research-gate.js +306 -0
  42. package/scripts/hooks/entry/claude-code/pre-tool-use.js +1 -1
  43. package/scripts/hooks/entry/claude-code/user-prompt-submit.js +47 -2
  44. package/scripts/hooks/entry/cursor/after-file-edit.js +127 -0
  45. package/scripts/hooks/entry/cursor/before-shell.js +131 -0
  46. package/scripts/hooks/entry/cursor/before-submit-prompt.js +102 -0
  47. package/scripts/hooks/entry/cursor/session-start.js +125 -0
  48. package/scripts/hooks/entry/cursor/stop.js +135 -0
  49. package/scripts/hooks/entry/gemini-cli/after-tool.js +119 -0
  50. package/scripts/hooks/entry/gemini-cli/before-agent.js +140 -0
  51. package/scripts/hooks/entry/gemini-cli/before-tool.js +189 -0
  52. package/scripts/hooks/entry/gemini-cli/session-end.js +120 -0
  53. package/scripts/hooks/entry/gemini-cli/session-start.js +80 -0
  54. package/scripts/hooks/entry/opencode/prompt-append.js +76 -0
  55. package/scripts/hooks/entry/opencode/session-start.js +86 -0
  56. package/scripts/hooks/entry/opencode/tool-after.js +77 -0
  57. package/scripts/hooks/entry/opencode/tool-before.js +143 -0
  58. package/.claude/rules/README.md +0 -60
  59. package/.claude/rules/architecture/component-reuse.md +0 -38
  60. package/.claude/rules/architecture/document-structure.md +0 -76
  61. package/.claude/rules/architecture/feature-refactoring-cleanup.md +0 -87
  62. package/.claude/rules/architecture/model-management.md +0 -35
  63. package/.claude/rules/code-style/naming-conventions.md +0 -55
  64. package/.claude/rules/security/security-patterns.md +0 -143
  65. package/.workflow/specs/architecture.md.template +0 -24
  66. package/.workflow/specs/stack.md.template +0 -33
  67. package/.workflow/specs/testing.md.template +0 -36
@@ -0,0 +1,223 @@
1
+ # /wogi-research - Zero-Trust Research Protocol
2
+
3
+ Execute rigorous research before answering questions about capabilities, feasibility, or existence.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ /wogi-research "Does X support Y?" # Standard depth
9
+ /wogi-research --quick "Simple question" # Quick check (5K tokens)
10
+ /wogi-research --deep "Architecture query" # Deep audit (50K tokens)
11
+ /wogi-research --exhaustive "Critical decision" # Full audit (100K tokens)
12
+ ```
13
+
14
+ ## When This is Required
15
+
16
+ This command is **automatically triggered** (when strict mode is enabled) for:
17
+
18
+ 1. **Capability Questions**: "Does X support Y?", "Can X do Y?"
19
+ 2. **Feasibility Questions**: "Is it possible to...", "Can we..."
20
+ 3. **Existence Questions**: "Is there a...", "Does X exist?"
21
+ 4. **Architecture Questions**: "How does X work?", "How is X structured?"
22
+ 5. **Integration Questions**: "How to integrate X with Y?"
23
+
24
+ ## Research Protocol Phases
25
+
26
+ ### Phase 1: Scope Mapping
27
+ - Identify all potentially relevant local files
28
+ - Identify external tools/libraries mentioned
29
+ - Generate search keywords
30
+ - Create `research-scope.json`
31
+
32
+ ### Phase 2: Local Evidence Gathering
33
+ - Read ALL files identified in scope (not just the first match)
34
+ - Extract relevant code snippets and documentation
35
+ - Log findings to research notes
36
+ - **DO NOT SKIP FILES** - partial reading leads to false conclusions
37
+
38
+ ### Phase 3: External Verification
39
+ - For each external tool/library:
40
+ - Web search: "[tool] documentation [feature] [current year]"
41
+ - Read official docs (top 3 results minimum)
42
+ - Extract quotes with URLs
43
+ - **ASSUME training data is 2+ years stale**
44
+
45
+ ### Phase 4: Assumption Check
46
+ - List ALL assumptions made during research
47
+ - Tag each assumption:
48
+ - `[VERIFIED]` with HIGH confidence + source
49
+ - `[UNVERIFIED]` with LOW confidence - **MUST be verified before proceeding**
50
+ - Loop back to Phase 2/3 for any unverified assumptions
51
+
52
+ ### Phase 5: Synthesis
53
+ - Generate research report with:
54
+ - Answer to original question
55
+ - Evidence chain (every claim → source)
56
+ - Confidence level (HIGH/MEDIUM/LOW)
57
+ - Caveats and uncertainties
58
+ - List of searches performed
59
+
60
+ ## Critical Rules
61
+
62
+ ### The Negative Evidence Rule
63
+
64
+ **FORBIDDEN conclusions:**
65
+ - "X is not supported"
66
+ - "There is no Y"
67
+ - "It doesn't exist"
68
+ - "X cannot do Y"
69
+
70
+ **REQUIRED format for negative claims:**
71
+ ```
72
+ I searched the following sources and found no evidence of X:
73
+ 1. [source 1] - searched for [terms]
74
+ 2. [source 2] - searched for [terms]
75
+ 3. [official docs URL] - no mention found
76
+
77
+ However, my search may be incomplete. Before concluding X doesn't exist:
78
+ - Check if there's a different name for this feature
79
+ - Verify with the latest official documentation
80
+ - Consider that the feature may be in development
81
+ ```
82
+
83
+ ### The Version Paranoia Rule
84
+
85
+ For ANY external tool (npm packages, CLIs, APIs, frameworks):
86
+ ```
87
+ ASSUME: Training data is 2+ years old
88
+ ACTION: ALWAYS web search "[tool] latest documentation [current year]"
89
+ BEFORE making capability claims
90
+ ```
91
+
92
+ ### The Assumption Stack
93
+
94
+ Before answering, explicitly list:
95
+ ```markdown
96
+ ## My Assumptions
97
+ 1. [VERIFY] Gemini CLI version supports hooks → Confidence: LOW (training data)
98
+ 2. [OK] Project uses JavaScript → Confidence: HIGH (read package.json)
99
+ 3. [VERIFY] settings.json format → Confidence: LOW (haven't read docs)
100
+ ```
101
+
102
+ Any assumption marked `[VERIFY]` with `LOW` confidence **MUST** be verified.
103
+
104
+ ## Evidence Chain Format
105
+
106
+ Every claim needs a traceable source:
107
+
108
+ ```markdown
109
+ | Claim | Source Type | Source Location | Confidence |
110
+ |-------|-------------|-----------------|------------|
111
+ | "Hooks are supported" | Live Docs | github.com/x/docs/hooks | HIGH |
112
+ | "Settings format is X" | File Read | .gemini/settings.json | HIGH |
113
+ | "Feature Y exists" | Training Data | None | LOW - VERIFY |
114
+ ```
115
+
116
+ ## Depth Tiers
117
+
118
+ | Depth | Token Budget | Actions | Use For |
119
+ |-------|--------------|---------|---------|
120
+ | `--quick` | 5K | 1-2 files, no web search | Simple factual lookups |
121
+ | (default) | 20K | All relevant files, 1 web search | Most questions |
122
+ | `--deep` | 50K | Full file audit, multiple web searches | Architecture/feasibility |
123
+ | `--exhaustive` | 100K+ | Everything + user confirmation gates | Production decisions |
124
+
125
+ ## Output
126
+
127
+ The command generates:
128
+
129
+ 1. **research-report.md** - Full research findings with citations
130
+ 2. **Console summary** - Key findings and confidence level
131
+ 3. **Cached verifications** - Stored in `.workflow/state/research-cache.json`
132
+
133
+ ## Configuration
134
+
135
+ In `.workflow/config.json`:
136
+
137
+ ```json
138
+ {
139
+ "research": {
140
+ "enabled": true,
141
+ "defaultDepth": "standard",
142
+ "strictMode": true,
143
+ "autoTrigger": true,
144
+ "maxTokensPerDepth": {
145
+ "quick": 5000,
146
+ "standard": 20000,
147
+ "deep": 50000,
148
+ "exhaustive": 100000
149
+ },
150
+ "requireCitations": true,
151
+ "cacheVerifications": true,
152
+ "cacheExpiryHours": 24,
153
+ "budgetMode": "soft",
154
+ "negativeEvidenceRule": true,
155
+ "assumptionTracking": true
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## Examples
161
+
162
+ ### Example 1: Capability Question
163
+
164
+ ```
165
+ User: Does Gemini CLI support hooks?
166
+
167
+ /wogi-research "Does Gemini CLI support hooks?"
168
+ ```
169
+
170
+ Research output:
171
+ ```
172
+ ## Research Report
173
+
174
+ **Question:** Does Gemini CLI support hooks?
175
+ **Depth:** standard
176
+ **Confidence:** HIGH
177
+
178
+ ### Conclusion
179
+ Yes, Gemini CLI supports hooks since version X.
180
+
181
+ ### Evidence Chain
182
+ | Claim | Source | Confidence |
183
+ |-------|--------|------------|
184
+ | Hooks supported | https://github.com/gemini-cli/docs/hooks | HIGH |
185
+ | Configuration in .gemini/settings.json | File read | HIGH |
186
+
187
+ ### Searches Performed
188
+ 1. Web: "Gemini CLI hooks documentation 2026"
189
+ 2. Local: .gemini/settings.json
190
+ 3. Local: .gemini/**/*.md
191
+ ```
192
+
193
+ ### Example 2: Architecture Question
194
+
195
+ ```
196
+ User: How does the authentication flow work in this codebase?
197
+
198
+ /wogi-research --deep "How does the authentication flow work?"
199
+ ```
200
+
201
+ This will:
202
+ 1. Search for auth-related files
203
+ 2. Read all matches (not just first)
204
+ 3. Trace the flow through the codebase
205
+ 4. Generate a comprehensive report
206
+
207
+ ## Integration with Hooks
208
+
209
+ When `research.strictMode` is enabled and `research.autoTrigger` is true:
210
+ - Capability/feasibility questions automatically trigger research
211
+ - Claims without citations are flagged
212
+ - Negative claims require exhaustive search evidence
213
+
214
+ ## CLI Compatibility
215
+
216
+ This command works across all supported CLIs:
217
+ - Claude Code
218
+ - Gemini CLI
219
+ - Codex (OpenAI)
220
+ - OpenCode
221
+ - Cline/Cursor
222
+
223
+ State is stored in `.workflow/` for cross-CLI persistence.
@@ -0,0 +1,241 @@
1
+ Comprehensive code review with **automatic fixing**. Runs the full `/wogi-review` process, then automatically fixes all identified issues and re-verifies.
2
+
3
+ **Triggers**: `/wogi-review-fix`, "review and fix", "fix all issues"
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ /wogi-review-fix # Review + auto-fix all issues
9
+ /wogi-review-fix --dry-run # Show what would be fixed (no changes)
10
+ /wogi-review-fix --no-verify # Skip re-verification after fixes
11
+ /wogi-review-fix --commits 3 # Review last 3 commits + fix
12
+ ```
13
+
14
+ ## How It Works
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────────────────┐
18
+ │ /wogi-review-fix │
19
+ ├─────────────────────────────────────────────────────────────┤
20
+ │ PHASE 1: REVIEW (same as /wogi-review) │
21
+ │ 1. Identify changed files (git diff) │
22
+ │ 2. Run verification gates (lint, typecheck, tests) │
23
+ │ 3. Run AI review (parallel or multi-pass) │
24
+ │ 4. Consolidate findings │
25
+ │ │
26
+ │ PHASE 2: AUTO-FIX │
27
+ │ 5. Categorize issues (auto-fixable vs manual) │
28
+ │ 6. For each auto-fixable issue: │
29
+ │ → Read file │
30
+ │ → Apply fix │
31
+ │ → Verify syntax (node --check) │
32
+ │ → Track result │
33
+ │ │
34
+ │ PHASE 3: RE-VERIFY │
35
+ │ 7. Run verification gates again │
36
+ │ 8. Report: Fixed N, Manual M, Verification PASS/FAIL │
37
+ └─────────────────────────────────────────────────────────────┘
38
+ ```
39
+
40
+ ## Auto-Fixable vs Manual Issues
41
+
42
+ ### Auto-Fixable (will be fixed automatically)
43
+
44
+ | Issue Type | Fix Method |
45
+ |------------|------------|
46
+ | Unused imports | Remove the import line |
47
+ | Console.log in production | Remove or convert to proper logger |
48
+ | Missing try-catch (simple) | Wrap operation in try-catch |
49
+ | Naming convention violation | Rename file/variable to match convention |
50
+ | Missing null check (simple) | Add optional chaining `?.` or guard |
51
+ | Dead code / unreachable | Remove the dead code |
52
+ | Duplicate code (small) | Extract to shared function |
53
+
54
+ ### Manual (will be listed for user attention)
55
+
56
+ | Issue Type | Why Manual |
57
+ |------------|------------|
58
+ | Logic bugs | Requires understanding intent |
59
+ | Security vulnerabilities | Requires careful review |
60
+ | Architecture issues | Requires design decisions |
61
+ | Breaking API changes | Requires coordination |
62
+ | Complex refactors | Requires validation |
63
+
64
+ ## Execution Steps
65
+
66
+ ### Step 1: Run Full Review
67
+
68
+ Execute the standard `/wogi-review` process:
69
+
70
+ ```bash
71
+ # Get changed files
72
+ git diff --name-only HEAD
73
+
74
+ # Run verification gates
75
+ npm run lint 2>&1 | head -50
76
+ npm run typecheck 2>&1 | head -50
77
+
78
+ # Run AI review (parallel or multi-pass based on file count)
79
+ # Collect all findings with file:line:issue:severity:suggestion
80
+ ```
81
+
82
+ ### Step 2: Categorize Findings
83
+
84
+ After review completes, categorize each finding:
85
+
86
+ ```javascript
87
+ // Example finding structure
88
+ {
89
+ file: "src/utils.ts",
90
+ line: 45,
91
+ issue: "Unused import 'lodash'",
92
+ severity: "low",
93
+ category: "unused-import", // Auto-fixable
94
+ suggestion: "Remove the unused import"
95
+ }
96
+ ```
97
+
98
+ **Categorization rules:**
99
+ - `unused-import` → Auto-fix
100
+ - `console-log` → Auto-fix
101
+ - `missing-null-check` (single line) → Auto-fix
102
+ - `naming-convention` → Auto-fix
103
+ - `logic-error` → Manual
104
+ - `security-*` → Manual
105
+ - `architecture-*` → Manual
106
+
107
+ ### Step 3: Fix Loop
108
+
109
+ For each auto-fixable issue, in order of file (to batch edits):
110
+
111
+ ```
112
+ For each file with issues:
113
+ 1. Read the file
114
+ 2. For each issue in this file:
115
+ a. Apply the fix using Edit tool
116
+ b. Log: "Fixed: [issue] in [file:line]"
117
+ 3. Verify file syntax: node --check [file] (for JS/TS)
118
+ 4. If syntax fails:
119
+ - Rollback edit
120
+ - Move issue to "Manual" list
121
+ - Log: "Fix failed, moved to manual: [issue]"
122
+ ```
123
+
124
+ ### Step 4: Re-Verification
125
+
126
+ After all fixes applied:
127
+
128
+ ```bash
129
+ # Run verification gates again
130
+ npm run lint 2>&1 | head -50
131
+ npm run typecheck 2>&1 | head -50
132
+ npm run test 2>&1 | head -50 # If tests exist
133
+
134
+ # Syntax check all modified files
135
+ node --check [modified files]
136
+ ```
137
+
138
+ ### Step 5: Summary Report
139
+
140
+ ```
141
+ ╔══════════════════════════════════════════════════════════╗
142
+ ║ Review + Fix Complete ║
143
+ ╚══════════════════════════════════════════════════════════╝
144
+
145
+ ═══════════════════════════════════════════════════════════
146
+ FIXES APPLIED (12 issues)
147
+ ═══════════════════════════════════════════════════════════
148
+ ✓ src/utils.ts:45 - Removed unused import 'lodash'
149
+ ✓ src/api.ts:23 - Removed console.log
150
+ ✓ src/api.ts:67 - Added null check
151
+ ✓ src/components/Button.tsx:12 - Removed unused import
152
+ ... (8 more)
153
+
154
+ ═══════════════════════════════════════════════════════════
155
+ MANUAL ATTENTION NEEDED (3 issues)
156
+ ═══════════════════════════════════════════════════════════
157
+ ⚠ src/auth.ts:89 - Potential SQL injection (security)
158
+ → Review: User input not sanitized before query
159
+ ⚠ src/api.ts:134 - Race condition (logic)
160
+ → Review: Async operation may complete out of order
161
+ ⚠ src/utils.ts:200 - Breaking API change (architecture)
162
+ → Review: Function signature changed, check callers
163
+
164
+ ═══════════════════════════════════════════════════════════
165
+ RE-VERIFICATION
166
+ ═══════════════════════════════════════════════════════════
167
+ ✓ Lint: passed
168
+ ✓ TypeCheck: passed
169
+ ✓ Syntax: all files valid
170
+
171
+ ═══════════════════════════════════════════════════════════
172
+ SUMMARY
173
+ ═══════════════════════════════════════════════════════════
174
+ Total issues found: 15
175
+ Auto-fixed: 12
176
+ Manual review needed: 3
177
+ Verification: PASSED
178
+
179
+ Files modified: 4
180
+ • src/utils.ts (3 fixes)
181
+ • src/api.ts (5 fixes)
182
+ • src/components/Button.tsx (2 fixes)
183
+ • src/auth.ts (2 fixes)
184
+ ```
185
+
186
+ ## Options
187
+
188
+ | Flag | Description |
189
+ |------|-------------|
190
+ | `--dry-run` | Show what would be fixed without making changes |
191
+ | `--no-verify` | Skip re-verification after fixes |
192
+ | `--commits N` | Include last N commits in review scope |
193
+ | `--staged` | Only review staged changes |
194
+ | `--skip-manual` | Don't show manual issues in report |
195
+
196
+ ## Dry Run Mode
197
+
198
+ With `--dry-run`, shows the fix plan without applying:
199
+
200
+ ```
201
+ ═══════════════════════════════════════════════════════════
202
+ DRY RUN - WOULD FIX (12 issues)
203
+ ═══════════════════════════════════════════════════════════
204
+ • src/utils.ts:45 - Would remove unused import 'lodash'
205
+ • src/api.ts:23 - Would remove console.log
206
+ • src/api.ts:67 - Would add null check: user?.profile
207
+ ...
208
+
209
+ Run without --dry-run to apply these fixes.
210
+ ```
211
+
212
+ ## Comparison with /wogi-review
213
+
214
+ | Aspect | `/wogi-review` | `/wogi-review-fix` |
215
+ |--------|----------------|-------------------|
216
+ | Reviews code | ✓ | ✓ |
217
+ | Lists issues | ✓ | ✓ |
218
+ | Fixes issues | ✗ | ✓ (auto-fixable) |
219
+ | Re-verifies | ✗ | ✓ |
220
+ | End state | Issues listed | Issues resolved |
221
+
222
+ ## When to Use
223
+
224
+ **Use `/wogi-review`** when:
225
+ - You want to see issues before deciding to fix
226
+ - You're reviewing someone else's code
227
+ - You want to understand the codebase state
228
+
229
+ **Use `/wogi-review-fix`** when:
230
+ - You want issues fixed immediately
231
+ - You trust the auto-fix for common issues
232
+ - You're cleaning up after a large change
233
+ - You want a "fix everything" single command
234
+
235
+ ## Safety Guarantees
236
+
237
+ 1. **Syntax verification** - Every fix is syntax-checked before moving on
238
+ 2. **Rollback on failure** - If a fix breaks syntax, it's reverted
239
+ 3. **Manual escalation** - Complex issues are never auto-fixed
240
+ 4. **Security issues untouched** - Security findings always require manual review
241
+ 5. **Git-friendly** - All changes can be reviewed in `git diff` before commit
@@ -141,6 +141,15 @@ When user types these commands, execute the corresponding action immediately.
141
141
  |---------|--------|
142
142
  | `/wogi-guided-edit` | Guide through multi-file changes step by step. Shows each edit for approval. |
143
143
 
144
+ ### Research Protocol (Zero-Trust)
145
+
146
+ | Command | Action |
147
+ |---------|--------|
148
+ | `/wogi-research [question]` | Execute rigorous research before answering capability/feasibility questions. Phases: scope mapping, evidence gathering, external verification, assumption check, synthesis. |
149
+ | `/wogi-research --quick [q]` | Quick research (5K tokens) - 1-2 files, no web search. |
150
+ | `/wogi-research --deep [q]` | Deep research (50K tokens) - full file audit, multiple web searches. |
151
+ | `/wogi-research --exhaustive [q]` | Exhaustive research (100K+ tokens) - everything + user confirmation gates. |
152
+
144
153
  ### Planning & Documentation
145
154
 
146
155
  | Command | Action |
@@ -312,6 +321,14 @@ npx flow onboard # Analyze existing project & set up context
312
321
  ./scripts/flow figma confirm <f> # Interactive confirmation
313
322
  ./scripts/flow figma generate # Generate code from decisions
314
323
  ./scripts/flow figma server # Start MCP server
324
+
325
+ # Research Protocol
326
+ ./scripts/flow research "q" # Execute research protocol
327
+ ./scripts/flow research --quick # Quick research (5K tokens)
328
+ ./scripts/flow research --deep # Deep research (50K tokens)
329
+ ./scripts/flow research --exhaustive # Full audit (100K+ tokens)
330
+ ./scripts/flow research cache # Show cached verifications
331
+ ./scripts/flow research cache clear # Clear verification cache
315
332
  ```
316
333
 
317
334
  ## Command Execution
@@ -109,26 +109,64 @@ class BaseBridge {
109
109
 
110
110
  /**
111
111
  * Safe JSON parse that checks for prototype pollution (fallback when flow-utils unavailable)
112
+ *
113
+ * NOTE: This is a fallback implementation. When flow-utils is available,
114
+ * safeJsonParse from flow-utils is used instead (it performs recursive
115
+ * validation of the parsed object). This fallback only does pre-parse
116
+ * string checking which is less comprehensive but better than nothing.
117
+ *
112
118
  * @param {string} content - JSON string to parse
113
119
  * @returns {Object|null} Parsed object or null if invalid
114
120
  */
115
121
  safeJsonParseContent(content) {
116
- // Check for prototype pollution attempts (case-insensitive)
117
- const contentLower = content.toLowerCase();
118
- if (contentLower.includes('__proto__') ||
119
- contentLower.includes('constructor') ||
120
- contentLower.includes('prototype')) {
121
- this.log('Warning: Potential prototype pollution detected in JSON');
122
+ if (!content || typeof content !== 'string') {
122
123
  return null;
123
124
  }
124
125
 
126
+ // Check for prototype pollution attempts
127
+ // These patterns look for dangerous keys that could be used for prototype pollution
128
+ const dangerousPatterns = [
129
+ /__proto__/i,
130
+ /"constructor"\s*:/,
131
+ /"prototype"\s*:/
132
+ ];
133
+
134
+ for (const pattern of dangerousPatterns) {
135
+ if (pattern.test(content)) {
136
+ this.log('Warning: Potential prototype pollution detected in JSON');
137
+ return null;
138
+ }
139
+ }
140
+
125
141
  try {
126
142
  const parsed = JSON.parse(content);
127
143
  if (parsed === null || typeof parsed !== 'object') {
128
144
  return null;
129
145
  }
146
+
147
+ // Additional check: verify no __proto__ keys in parsed result
148
+ // (JSON.parse could still create them in some edge cases)
149
+ const hasProtoKey = (obj) => {
150
+ if (!obj || typeof obj !== 'object') return false;
151
+ if (Object.prototype.hasOwnProperty.call(obj, '__proto__')) return true;
152
+ for (const value of Object.values(obj)) {
153
+ if (typeof value === 'object' && value !== null && hasProtoKey(value)) {
154
+ return true;
155
+ }
156
+ }
157
+ return false;
158
+ };
159
+
160
+ if (hasProtoKey(parsed)) {
161
+ this.log('Warning: __proto__ key detected in parsed JSON');
162
+ return null;
163
+ }
164
+
130
165
  return parsed;
131
- } catch {
166
+ } catch (err) {
167
+ if (process.env.DEBUG) {
168
+ this.log(`JSON parse error: ${err.message}`);
169
+ }
132
170
  return null;
133
171
  }
134
172
  }
@@ -164,7 +202,8 @@ class BaseBridge {
164
202
  ensureCliFolder() {
165
203
  const cliFolder = path.join(this.projectDir, this.getCliFolder());
166
204
  if (!fs.existsSync(cliFolder)) {
167
- fs.mkdirSync(cliFolder, { recursive: true });
205
+ // Use explicit permissions (0o755 = rwxr-xr-x) to avoid relying on umask
206
+ fs.mkdirSync(cliFolder, { recursive: true, mode: 0o755 });
168
207
  this.log(`Created ${this.getCliFolder()}/`);
169
208
  }
170
209
  }
@@ -181,9 +220,9 @@ class BaseBridge {
181
220
  return;
182
221
  }
183
222
 
184
- // Ensure target directory exists
223
+ // Ensure target directory exists with explicit permissions
185
224
  if (!fs.existsSync(targetSkillsDir)) {
186
- fs.mkdirSync(targetSkillsDir, { recursive: true });
225
+ fs.mkdirSync(targetSkillsDir, { recursive: true, mode: 0o755 });
187
226
  }
188
227
 
189
228
  // Copy skills
@@ -214,9 +253,9 @@ class BaseBridge {
214
253
  syncRules() {
215
254
  const rulesDir = path.join(this.projectDir, this.getRulesPath());
216
255
 
217
- // Ensure rules directory exists
256
+ // Ensure rules directory exists with explicit permissions
218
257
  if (!fs.existsSync(rulesDir)) {
219
- fs.mkdirSync(rulesDir, { recursive: true });
258
+ fs.mkdirSync(rulesDir, { recursive: true, mode: 0o755 });
220
259
  }
221
260
 
222
261
  // Copy any existing rules from .workflow/rules/ if present
@@ -244,9 +283,9 @@ class BaseBridge {
244
283
  // Knowledge files to sync
245
284
  const knowledgeFiles = ['stack.md', 'architecture.md', 'testing.md'];
246
285
 
247
- // Ensure CLI docs directory exists
286
+ // Ensure CLI docs directory exists with explicit permissions
248
287
  if (!fs.existsSync(cliDocsDir)) {
249
- fs.mkdirSync(cliDocsDir, { recursive: true });
288
+ fs.mkdirSync(cliDocsDir, { recursive: true, mode: 0o755 });
250
289
  }
251
290
 
252
291
  let syncedCount = 0;
@@ -359,6 +398,76 @@ class BaseBridge {
359
398
  return results;
360
399
  }
361
400
 
401
+ // ==================== Template Utility Methods ====================
402
+
403
+ /**
404
+ * Load a partial template from .workflow/templates/partials/
405
+ * @param {string} partialName - Name of the partial (without .hbs extension)
406
+ * @returns {string} Partial content or empty string if not found
407
+ */
408
+ loadPartial(partialName) {
409
+ const partialPath = path.join(
410
+ this.projectDir,
411
+ this.workflowDir,
412
+ 'templates',
413
+ 'partials',
414
+ `${partialName}.hbs`
415
+ );
416
+
417
+ try {
418
+ if (fs.existsSync(partialPath)) {
419
+ return fs.readFileSync(partialPath, 'utf-8');
420
+ }
421
+ } catch (err) {
422
+ this.log(`Warning: Could not load partial ${partialName}: ${err.message}`);
423
+ }
424
+ return '';
425
+ }
426
+
427
+ /**
428
+ * Process partial includes in template content
429
+ * Replaces {{> partial-name}} with the partial content
430
+ * @param {string} content - Template content
431
+ * @returns {string} Content with partials included
432
+ */
433
+ processPartials(content) {
434
+ // Match {{> partial-name}} pattern
435
+ const partialRegex = /\{\{>\s*([a-zA-Z0-9_-]+)\s*\}\}/g;
436
+
437
+ return content.replace(partialRegex, (match, partialName) => {
438
+ const partialContent = this.loadPartial(partialName);
439
+ if (!partialContent) {
440
+ this.log(`Warning: Partial not found: ${partialName}`);
441
+ return `<!-- Partial not found: ${partialName} -->`;
442
+ }
443
+ return partialContent;
444
+ });
445
+ }
446
+
447
+ /**
448
+ * Get nested value from config object using dot notation
449
+ * @param {Object} obj - The object to search
450
+ * @param {string} path - Dot-separated path (e.g., 'hooks.rules.taskGating')
451
+ * @returns {*} The value or undefined
452
+ */
453
+ getNestedValue(obj, path) {
454
+ if (!path || typeof path !== 'string') return undefined;
455
+
456
+ const parts = path.split('.');
457
+ let current = obj;
458
+
459
+ for (const part of parts) {
460
+ if (current === null || current === undefined) return undefined;
461
+ // Security: skip dangerous property names
462
+ if (part === '__proto__' || part === 'constructor' || part === 'prototype') {
463
+ return undefined;
464
+ }
465
+ current = current[part];
466
+ }
467
+
468
+ return current;
469
+ }
470
+
362
471
  // ==================== Utility Methods ====================
363
472
 
364
473
  /**
@@ -366,7 +475,7 @@ class BaseBridge {
366
475
  */
367
476
  copyDirRecursive(source, target) {
368
477
  if (!fs.existsSync(target)) {
369
- fs.mkdirSync(target, { recursive: true });
478
+ fs.mkdirSync(target, { recursive: true, mode: 0o755 });
370
479
  }
371
480
 
372
481
  const items = fs.readdirSync(source);